From cb110cfbfe27d2f71afe98af7463e8636ae4f2e1 Mon Sep 17 00:00:00 2001 From: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:04:15 -0700 Subject: [PATCH 1/4] Create telemetry Signed-off-by: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> --- moz/telemetry | 2484 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2484 insertions(+) create mode 100644 moz/telemetry diff --git a/moz/telemetry b/moz/telemetry new file mode 100644 index 0000000..bc5e9d6 --- /dev/null +++ b/moz/telemetry @@ -0,0 +1,2484 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { BrowserUtils } = ChromeUtils.importESModule( + "resource://gre/modules/BrowserUtils.sys.mjs" +); +const { TelemetryTimestamps } = ChromeUtils.importESModule( + "resource://gre/modules/TelemetryTimestamps.sys.mjs" +); +const { TelemetryController } = ChromeUtils.importESModule( + "resource://gre/modules/TelemetryController.sys.mjs" +); +const { TelemetryArchive } = ChromeUtils.importESModule( + "resource://gre/modules/TelemetryArchive.sys.mjs" +); +const { TelemetrySend } = ChromeUtils.importESModule( + "resource://gre/modules/TelemetrySend.sys.mjs" +); + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); +ChromeUtils.defineESModuleGetters(this, { + ObjectUtils: "resource://gre/modules/ObjectUtils.sys.mjs", + Preferences: "resource://gre/modules/Preferences.sys.mjs", +}); + +const Telemetry = Services.telemetry; + +// Maximum height of a histogram bar (in em for html, in chars for text) +const MAX_BAR_HEIGHT = 8; +const MAX_BAR_CHARS = 25; +const PREF_TELEMETRY_SERVER_OWNER = "toolkit.telemetry.server_owner"; +const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled"; +const PREF_DEBUG_SLOW_SQL = "toolkit.telemetry.debugSlowSql"; +const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled"; + +// ms idle before applying the filter (allow uninterrupted typing) +const FILTER_IDLE_TIMEOUT = 500; + +const isWindows = Services.appinfo.OS == "WINNT"; +const EOL = isWindows ? "\r\n" : "\n"; + +// This is the ping object currently displayed in the page. +var gPingData = null; + +// Cached value of document's RTL mode +var documentRTLMode = ""; + +/** + * Helper function for determining whether the document direction is RTL. + * Caches result of check on first invocation. + */ +function isRTL() { + if (!documentRTLMode) { + documentRTLMode = window.getComputedStyle(document.body).direction; + } + return documentRTLMode == "rtl"; +} + +function isFlatArray(obj) { + if (!Array.isArray(obj)) { + return false; + } + return !obj.some(e => typeof e == "object"); +} + +/** + * This is a helper function for explodeObject. + */ +function flattenObject(obj, map, path, array) { + for (let k of Object.keys(obj)) { + let newPath = [...path, array ? "[" + k + "]" : k]; + let v = obj[k]; + if (!v || typeof v != "object") { + map.set(newPath.join("."), v); + } else if (isFlatArray(v)) { + map.set(newPath.join("."), "[" + v.join(", ") + "]"); + } else { + flattenObject(v, map, newPath, Array.isArray(v)); + } + } +} + +/** + * This turns a JSON object into a "flat" stringified form. + * + * For an object like {a: "1", b: {c: "2", d: "3"}} it returns a Map of the + * form Map(["a","1"], ["b.c", "2"], ["b.d", "3"]). + */ +function explodeObject(obj) { + let map = new Map(); + flattenObject(obj, map, []); + return map; +} + +function filterObject(obj, filterOut) { + let ret = {}; + for (let k of Object.keys(obj)) { + if (!filterOut.includes(k)) { + ret[k] = obj[k]; + } + } + return ret; +} + +/** + * This turns a JSON object into a "flat" stringified form, separated into top-level sections. + * + * For an object like: + * { + * a: {b: "1"}, + * c: {d: "2", e: {f: "3"}} + * } + * it returns a Map of the form: + * Map([ + * ["a", Map(["b","1"])], + * ["c", Map([["d", "2"], ["e.f", "3"]])] + * ]) + */ +function sectionalizeObject(obj) { + let map = new Map(); + for (let k of Object.keys(obj)) { + map.set(k, explodeObject(obj[k])); + } + return map; +} + +/** + * Obtain the main DOMWindow for the current context. + */ +function getMainWindow() { + return window.browsingContext.topChromeWindow; +} + +/** + * Obtain the DOMWindow that can open a preferences pane. + * + * This is essentially "get the browser chrome window" with the added check + * that the supposed browser chrome window is capable of opening a preferences + * pane. + * + * This may return null if we can't find the browser chrome window. + */ +function getMainWindowWithPreferencesPane() { + let mainWindow = getMainWindow(); + if (mainWindow && "openPreferences" in mainWindow) { + return mainWindow; + } + return null; +} + +/** + * Remove all child nodes of a document node. + */ +function removeAllChildNodes(node) { + while (node.hasChildNodes()) { + node.removeChild(node.lastChild); + } +} + +var Settings = { + attachObservers() { + let elements = document.getElementsByClassName("change-data-choices-link"); + for (let el of elements) { + el.parentElement.addEventListener("click", function (event) { + if (event.target.localName === "a") { + if (AppConstants.platform == "android") { + var { EventDispatcher } = ChromeUtils.importESModule( + "resource://gre/modules/Messaging.sys.mjs" + ); + EventDispatcher.instance.sendRequest({ + type: "Settings:Show", + resource: "preferences_privacy", + }); + } else { + // Show the data choices preferences on desktop. + let mainWindow = getMainWindowWithPreferencesPane(); + mainWindow.openPreferences("privacy-reports"); + } + } + }); + } + }, + + /** + * Updates the button & text at the top of the page to reflect Telemetry state. + */ + render() { + let settingsExplanation = document.getElementById("settings-explanation"); + let extendedEnabled = Services.telemetry.canRecordExtended; + + let channel = extendedEnabled ? "prerelease" : "release"; + let uploadcase = TelemetrySend.sendingEnabled() ? "enabled" : "disabled"; + + document.l10n.setAttributes( + settingsExplanation, + "about-telemetry-settings-explanation", + { channel, uploadcase } + ); + + this.attachObservers(); + }, +}; + +var PingPicker = { + viewCurrentPingData: null, + _archivedPings: null, + TYPE_ALL: "all", + + attachObservers() { + let pingSourceElements = document.getElementsByName("choose-ping-source"); + for (let el of pingSourceElements) { + el.addEventListener("change", () => this.onPingSourceChanged()); + } + + let displays = document.getElementsByName("choose-ping-display"); + for (let el of displays) { + el.addEventListener("change", () => this.onPingDisplayChanged()); + } + + document + .getElementById("show-subsession-data") + .addEventListener("change", () => { + this._updateCurrentPingData(); + }); + + document.getElementById("choose-ping-id").addEventListener("change", () => { + this._updateArchivedPingData(); + }); + document + .getElementById("choose-ping-type") + .addEventListener("change", () => { + this.filterDisplayedPings(); + }); + + document + .getElementById("newer-ping") + .addEventListener("click", () => this._movePingIndex(-1)); + document + .getElementById("older-ping") + .addEventListener("click", () => this._movePingIndex(1)); + + let pingPickerNeedHide = false; + let pingPicker = document.getElementById("ping-picker"); + pingPicker.addEventListener( + "mouseenter", + () => (pingPickerNeedHide = false) + ); + pingPicker.addEventListener( + "mouseleave", + () => (pingPickerNeedHide = true) + ); + document.addEventListener("click", () => { + if (pingPickerNeedHide) { + pingPicker.classList.add("hidden"); + } + }); + document + .getElementById("stores") + .addEventListener("change", () => displayPingData(gPingData)); + Array.from(document.querySelectorAll(".change-ping")).forEach(el => { + el.addEventListener("click", event => { + if (!pingPicker.classList.contains("hidden")) { + pingPicker.classList.add("hidden"); + } else { + pingPicker.classList.remove("hidden"); + event.stopPropagation(); + } + }); + }); + }, + + onPingSourceChanged() { + this.update(); + }, + + onPingDisplayChanged() { + this.update(); + }, + + render() { + // Display the type and controls if the ping is not current + let pingDate = document.getElementById("ping-date"); + let pingType = document.getElementById("ping-type"); + let controls = document.getElementById("controls"); + let pingExplanation = document.getElementById("ping-explanation"); + + if (!this.viewCurrentPingData) { + let pingName = this._getSelectedPingName(); + // Change sidebar heading text. + pingDate.textContent = pingName; + pingDate.setAttribute("title", pingName); + let pingTypeText = this._getSelectedPingType(); + controls.classList.remove("hidden"); + pingType.textContent = pingTypeText; + document.l10n.setAttributes( + pingExplanation, + "about-telemetry-ping-details", + { timestamp: pingTypeText, name: pingName } + ); + } else { + // Change sidebar heading text. + controls.classList.add("hidden"); + document.l10n.setAttributes( + pingType, + "about-telemetry-current-data-sidebar" + ); + // Change home page text. + document.l10n.setAttributes( + pingExplanation, + "about-telemetry-data-details-current" + ); + } + + GenericSubsection.deleteAllSubSections(); + }, + + async update() { + let viewCurrent = document.getElementById("ping-source-current").checked; + let currentChanged = viewCurrent !== this.viewCurrentPingData; + this.viewCurrentPingData = viewCurrent; + + // If we have no archived pings, disable the ping archive selection. + // This can happen on new profiles or if the ping archive is disabled. + let archivedPingList = await TelemetryArchive.promiseArchivedPingList(); + let sourceArchived = document.getElementById("ping-source-archive"); + let sourceArchivedContainer = document.getElementById( + "ping-source-archive-container" + ); + let archivedDisabled = !archivedPingList.length; + sourceArchived.disabled = archivedDisabled; + sourceArchivedContainer.classList.toggle("disabled", archivedDisabled); + + if (currentChanged) { + if (this.viewCurrentPingData) { + document.getElementById("current-ping-picker").hidden = false; + document.getElementById("archived-ping-picker").hidden = true; + this._updateCurrentPingData(); + } else { + document.getElementById("current-ping-picker").hidden = true; + await this._updateArchivedPingList(archivedPingList); + document.getElementById("archived-ping-picker").hidden = false; + } + } + }, + + _updateCurrentPingData() { + TelemetryController.ensureInitialized().then(() => + this._doUpdateCurrentPingData() + ); + }, + + _doUpdateCurrentPingData() { + const subsession = document.getElementById("show-subsession-data").checked; + let ping = TelemetryController.getCurrentPingData(subsession); + if (!ping) { + return; + } + + let stores = Telemetry.getAllStores(); + let getData = { + histograms: Telemetry.getSnapshotForHistograms, + keyedHistograms: Telemetry.getSnapshotForKeyedHistograms, + scalars: Telemetry.getSnapshotForScalars, + keyedScalars: Telemetry.getSnapshotForKeyedScalars, + }; + + let data = {}; + for (const [name, fn] of Object.entries(getData)) { + for (const store of stores) { + if (!data[store]) { + data[store] = {}; + } + let measurement = fn(store, /* clear */ false, /* filterTest */ true); + let processes = Object.keys(measurement); + + for (const process of processes) { + if (!data[store][process]) { + data[store][process] = {}; + } + + data[store][process][name] = measurement[process]; + } + } + } + ping.payload.stores = data; + + // Delete the unused data from the payload of the current ping. + // It's included in the above `stores` attribute. + for (const data of Object.values(ping.payload.processes)) { + delete data.scalars; + delete data.keyedScalars; + delete data.histograms; + delete data.keyedHistograms; + } + delete ping.payload.histograms; + delete ping.payload.keyedHistograms; + + // augment ping payload with event telemetry + let eventSnapshot = Telemetry.snapshotEvents( + Telemetry.DATASET_PRERELEASE_CHANNELS, + false + ); + for (let process of Object.keys(eventSnapshot)) { + if (process in ping.payload.processes) { + ping.payload.processes[process].events = eventSnapshot[process].filter( + e => !e[1].startsWith("telemetry.test") + ); + } + } + + displayPingData(ping, true); + }, + + _updateArchivedPingData() { + let id = this._getSelectedPingId(); + let res = Promise.resolve(); + if (id) { + res = TelemetryArchive.promiseArchivedPingById(id).then(ping => + displayPingData(ping, true) + ); + } + return res; + }, + + async _updateArchivedPingList(pingList) { + // The archived ping list is sorted in ascending timestamp order, + // but descending is more practical for the operations we do here. + pingList.reverse(); + this._archivedPings = pingList; + // Render the archive data. + this._renderPingList(); + // Update the displayed ping. + await this._updateArchivedPingData(); + }, + + _renderPingList() { + let pingSelector = document.getElementById("choose-ping-id"); + Array.from(pingSelector.children).forEach(child => + removeAllChildNodes(child) + ); + + let pingTypes = new Set(); + pingTypes.add(this.TYPE_ALL); + + const today = new Date(); + today.setHours(0, 0, 0, 0); + const yesterday = new Date(today); + yesterday.setDate(today.getDate() - 1); + + for (let p of this._archivedPings) { + pingTypes.add(p.type); + const pingDate = new Date(p.timestampCreated); + const datetimeText = new Services.intl.DateTimeFormat(undefined, { + dateStyle: "short", + timeStyle: "medium", + }).format(pingDate); + const pingName = `${datetimeText}, ${p.type}`; + + let option = document.createElement("option"); + let content = document.createTextNode(pingName); + option.appendChild(content); + option.setAttribute("value", p.id); + option.dataset.type = p.type; + option.dataset.date = datetimeText; + + pingDate.setHours(0, 0, 0, 0); + if (pingDate.getTime() === today.getTime()) { + pingSelector.children[0].appendChild(option); + } else if (pingDate.getTime() === yesterday.getTime()) { + pingSelector.children[1].appendChild(option); + } else { + pingSelector.children[2].appendChild(option); + } + } + this._renderPingTypes(pingTypes); + }, + + _renderPingTypes(pingTypes) { + let pingTypeSelector = document.getElementById("choose-ping-type"); + removeAllChildNodes(pingTypeSelector); + pingTypes.forEach(type => { + let option = document.createElement("option"); + option.appendChild(document.createTextNode(type)); + option.setAttribute("value", type); + pingTypeSelector.appendChild(option); + }); + }, + + _movePingIndex(offset) { + if (this.viewCurrentPingData) { + return; + } + let typeSelector = document.getElementById("choose-ping-type"); + let type = typeSelector.selectedOptions.item(0).value; + + let id = this._getSelectedPingId(); + let index = this._archivedPings.findIndex(p => p.id == id); + let newIndex = Math.min( + Math.max(0, index + offset), + this._archivedPings.length - 1 + ); + + let pingList; + if (offset > 0) { + pingList = this._archivedPings.slice(newIndex); + } else { + pingList = this._archivedPings.slice(0, newIndex); + pingList.reverse(); + } + + let ping = pingList.find(p => { + return type == this.TYPE_ALL || p.type == type; + }); + + if (ping) { + this.selectPing(ping); + this._updateArchivedPingData(); + } + }, + + selectPing(ping) { + let pingSelector = document.getElementById("choose-ping-id"); + // Use some() to break if we find the ping. + Array.from(pingSelector.children).some(group => { + return Array.from(group.children).some(option => { + if (option.value == ping.id) { + option.selected = true; + return true; + } + return false; + }); + }); + }, + + filterDisplayedPings() { + let pingSelector = document.getElementById("choose-ping-id"); + let typeSelector = document.getElementById("choose-ping-type"); + let type = typeSelector.selectedOptions.item(0).value; + let first = true; + Array.from(pingSelector.children).forEach(group => { + Array.from(group.children).forEach(option => { + if (first && option.dataset.type == type) { + option.selected = true; + first = false; + } + option.hidden = type != this.TYPE_ALL && option.dataset.type != type; + // Arrow keys should only iterate over visible options + option.disabled = option.hidden; + }); + }); + this._updateArchivedPingData(); + }, + + _getSelectedPingName() { + let pingSelector = document.getElementById("choose-ping-id"); + let selected = pingSelector.selectedOptions.item(0); + return selected.dataset.date; + }, + + _getSelectedPingType() { + let pingSelector = document.getElementById("choose-ping-id"); + let selected = pingSelector.selectedOptions.item(0); + return selected.dataset.type; + }, + + _getSelectedPingId() { + let pingSelector = document.getElementById("choose-ping-id"); + let selected = pingSelector.selectedOptions.item(0); + return selected.getAttribute("value"); + }, + + _showRawPingData() { + show(document.getElementById("category-raw")); + }, + + _showStructuredPingData() { + show(document.getElementById("category-home")); + }, +}; + +var GeneralData = { + /** + * Renders the general data + */ + render(aPing) { + setHasData("general-data-section", true); + let generalDataSection = document.getElementById("general-data"); + removeAllChildNodes(generalDataSection); + + const headings = [ + "about-telemetry-names-header", + "about-telemetry-values-header", + ]; + + // The payload & environment parts are handled by other renderers. + let ignoreSections = ["payload", "environment"]; + let data = explodeObject(filterObject(aPing, ignoreSections)); + + const table = GenericTable.render(data, headings); + generalDataSection.appendChild(table); + }, +}; + +var EnvironmentData = { + /** + * Renders the environment data + */ + render(ping) { + let dataDiv = document.getElementById("environment-data"); + removeAllChildNodes(dataDiv); + const hasData = !!ping.environment; + setHasData("environment-data-section", hasData); + if (!hasData) { + return; + } + + let ignore = ["addons"]; + let env = filterObject(ping.environment, ignore); + let sections = sectionalizeObject(env); + GenericSubsection.render(sections, dataDiv, "environment-data-section"); + + // We use specialized rendering here to make the addon and plugin listings + // more readable. + this.createAddonSection(dataDiv, ping); + }, + + renderAddonsObject(addonObj, addonSection, sectionTitle) { + let table = document.createElement("table"); + table.setAttribute("id", sectionTitle); + this.appendAddonSubsectionTitle(sectionTitle, table); + + for (let id of Object.keys(addonObj)) { + let addon = addonObj[id]; + this.appendHeadingName(table, addon.name || id); + this.appendAddonID(table, id); + let data = explodeObject(addon); + + for (let [key, value] of data) { + this.appendRow(table, key, value); + } + } + + addonSection.appendChild(table); + }, + + renderKeyValueObject(addonObj, addonSection, sectionTitle) { + let data = explodeObject(addonObj); + let table = GenericTable.render(data); + table.setAttribute("class", sectionTitle); + this.appendAddonSubsectionTitle(sectionTitle, table); + addonSection.appendChild(table); + }, + + appendAddonID(table, addonID) { + this.appendRow(table, "id", addonID); + }, + + appendHeadingName(table, name) { + let headings = document.createElement("tr"); + this.appendColumn(headings, "th", name); + headings.cells[0].colSpan = 2; + table.appendChild(headings); + }, + + appendAddonSubsectionTitle(section, table) { + let caption = document.createElement("caption"); + caption.appendChild(document.createTextNode(section)); + table.appendChild(caption); + }, + + createAddonSection(dataDiv, ping) { + if (!ping || !("environment" in ping) || !("addons" in ping.environment)) { + return; + } + let addonSection = document.createElement("div"); + addonSection.setAttribute("class", "subsection-data subdata"); + let addons = ping.environment.addons; + this.renderAddonsObject(addons.activeAddons, addonSection, "activeAddons"); + this.renderKeyValueObject(addons.theme, addonSection, "theme"); + this.renderAddonsObject( + addons.activeGMPlugins, + addonSection, + "activeGMPlugins" + ); + + let hasAddonData = !!Object.keys(ping.environment.addons).length; + let s = GenericSubsection.renderSubsectionHeader( + "addons", + hasAddonData, + "environment-data-section" + ); + s.appendChild(addonSection); + dataDiv.appendChild(s); + }, + + appendRow(table, id, value) { + let row = document.createElement("tr"); + row.id = id; + this.appendColumn(row, "td", id); + this.appendColumn(row, "td", value); + table.appendChild(row); + }, + /** + * Helper function for appending a column to the data table. + * + * @param aRowElement Parent row element + * @param aColType Column's tag name + * @param aColText Column contents + */ + appendColumn(aRowElement, aColType, aColText) { + let colElement = document.createElement(aColType); + let colTextElement = document.createTextNode(aColText); + colElement.appendChild(colTextElement); + aRowElement.appendChild(colElement); + }, +}; + +var SlowSQL = { + /** + * Render slow SQL statistics + */ + render: function SlowSQL_render(aPing) { + // We can add the debug SQL data to the current ping later. + // However, we need to be careful to never send that debug data + // out due to privacy concerns. + // We want to show the actual ping data for archived pings, + // so skip this there. + + let debugSlowSql = + PingPicker.viewCurrentPingData && + Preferences.get(PREF_DEBUG_SLOW_SQL, false); + let slowSql = debugSlowSql ? Telemetry.debugSlowSQL : aPing.payload.slowSQL; + if (!slowSql) { + setHasData("slow-sql-section", false); + return; + } + + let { mainThread, otherThreads } = debugSlowSql + ? Telemetry.debugSlowSQL + : aPing.payload.slowSQL; + + let mainThreadCount = Object.keys(mainThread).length; + let otherThreadCount = Object.keys(otherThreads).length; + if (mainThreadCount == 0 && otherThreadCount == 0) { + setHasData("slow-sql-section", false); + return; + } + + setHasData("slow-sql-section", true); + if (debugSlowSql) { + document.getElementById("sql-warning").hidden = false; + } + + let slowSqlDiv = document.getElementById("slow-sql-tables"); + removeAllChildNodes(slowSqlDiv); + + // Main thread + if (mainThreadCount > 0) { + let table = document.createElement("table"); + this.renderTableHeader(table, "main"); + this.renderTable(table, mainThread); + slowSqlDiv.appendChild(table); + } + + // Other threads + if (otherThreadCount > 0) { + let table = document.createElement("table"); + this.renderTableHeader(table, "other"); + this.renderTable(table, otherThreads); + slowSqlDiv.appendChild(table); + } + }, + + /** + * Creates a header row for a Slow SQL table + * Tabs & newlines added to cells to make it easier to copy-paste. + * + * @param aTable Parent table element + * @param aTitle Table's title + */ + renderTableHeader: function SlowSQL_renderTableHeader(aTable, threadType) { + let caption = document.createElement("caption"); + if (threadType == "main") { + document.l10n.setAttributes(caption, "about-telemetry-slow-sql-main"); + } + + if (threadType == "other") { + document.l10n.setAttributes(caption, "about-telemetry-slow-sql-other"); + } + aTable.appendChild(caption); + + let headings = document.createElement("tr"); + document.l10n.setAttributes( + this.appendColumn(headings, "th"), + "about-telemetry-slow-sql-hits" + ); + document.l10n.setAttributes( + this.appendColumn(headings, "th"), + "about-telemetry-slow-sql-average" + ); + document.l10n.setAttributes( + this.appendColumn(headings, "th"), + "about-telemetry-slow-sql-statement" + ); + aTable.appendChild(headings); + }, + + /** + * Fills out the table body + * Tabs & newlines added to cells to make it easier to copy-paste. + * + * @param aTable Parent table element + * @param aSql SQL stats object + */ + renderTable: function SlowSQL_renderTable(aTable, aSql) { + for (let [sql, [hitCount, totalTime]] of Object.entries(aSql)) { + let averageTime = totalTime / hitCount; + + let sqlRow = document.createElement("tr"); + + this.appendColumn(sqlRow, "td", hitCount + "\t"); + this.appendColumn(sqlRow, "td", averageTime.toFixed(0) + "\t"); + this.appendColumn(sqlRow, "td", sql + "\n"); + + aTable.appendChild(sqlRow); + } + }, + + /** + * Helper function for appending a column to a Slow SQL table. + * + * @param aRowElement Parent row element + * @param aColType Column's tag name + * @param aColText Column contents + */ + appendColumn: function SlowSQL_appendColumn( + aRowElement, + aColType, + aColText = "" + ) { + let colElement = document.createElement(aColType); + if (aColText) { + let colTextElement = document.createTextNode(aColText); + colElement.appendChild(colTextElement); + } + aRowElement.appendChild(colElement); + return colElement; + }, +}; + +var StackRenderer = { + /** + * Outputs the memory map associated with this hang report + * + * @param aDiv Output div + */ + renderMemoryMap: async function StackRenderer_renderMemoryMap( + aDiv, + memoryMap + ) { + let memoryMapTitleElement = document.createElement("span"); + document.l10n.setAttributes( + memoryMapTitleElement, + "about-telemetry-memory-map-title" + ); + aDiv.appendChild(memoryMapTitleElement); + aDiv.appendChild(document.createElement("br")); + + for (let currentModule of memoryMap) { + aDiv.appendChild(document.createTextNode(currentModule.join(" "))); + aDiv.appendChild(document.createElement("br")); + } + + aDiv.appendChild(document.createElement("br")); + }, + + /** + * Outputs the raw PCs from the hang's stack + * + * @param aDiv Output div + * @param aStack Array of PCs from the hang stack + */ + renderStack: function StackRenderer_renderStack(aDiv, aStack) { + let stackTitleElement = document.createElement("span"); + document.l10n.setAttributes( + stackTitleElement, + "about-telemetry-stack-title" + ); + aDiv.appendChild(stackTitleElement); + let stackText = " " + aStack.join(" "); + aDiv.appendChild(document.createTextNode(stackText)); + + aDiv.appendChild(document.createElement("br")); + aDiv.appendChild(document.createElement("br")); + }, + renderStacks: function StackRenderer_renderStacks( + aPrefix, + aStacks, + aMemoryMap, + aRenderHeader + ) { + let div = document.getElementById(aPrefix); + removeAllChildNodes(div); + + let fetchE = document.getElementById(aPrefix + "-fetch-symbols"); + if (fetchE) { + fetchE.hidden = false; + } + let hideE = document.getElementById(aPrefix + "-hide-symbols"); + if (hideE) { + hideE.hidden = true; + } + + if (!aStacks.length) { + return; + } + + setHasData(aPrefix + "-section", true); + + this.renderMemoryMap(div, aMemoryMap); + + for (let i = 0; i < aStacks.length; ++i) { + let stack = aStacks[i]; + aRenderHeader(i); + this.renderStack(div, stack); + } + }, + + /** + * Renders the title of the stack: e.g. "Late Write #1" or + * "Hang Report #1 (6 seconds)". + * + * @param aDivId The id of the div to append the header to. + * @param aL10nId The l10n id of the message to use for the title. + * @param aL10nArgs The l10n args for the provided message id. + */ + renderHeader: function StackRenderer_renderHeader( + aDivId, + aL10nId, + aL10nArgs + ) { + let div = document.getElementById(aDivId); + + let titleElement = document.createElement("span"); + titleElement.className = "stack-title"; + + document.l10n.setAttributes(titleElement, aL10nId, aL10nArgs); + + div.appendChild(titleElement); + div.appendChild(document.createElement("br")); + }, +}; + +var RawPayloadData = { + /** + * Renders the raw pyaload. + */ + render(aPing) { + setHasData("raw-payload-section", true); + let pre = document.getElementById("raw-payload-data"); + pre.textContent = JSON.stringify(aPing.payload, null, 2); + }, + + attachObservers() { + document + .getElementById("payload-json-viewer") + .addEventListener("click", () => { + openJsonInFirefoxJsonViewer(JSON.stringify(gPingData.payload, null, 2)); + }); + }, +}; + +var Histogram = { + /** + * Renders a single Telemetry histogram + * + * @param aParent Parent element + * @param aName Histogram name + * @param aHgram Histogram information + * @param aOptions Object with render options + * * exponential: bars follow logarithmic scale + */ + render: function Histogram_render(aParent, aName, aHgram, aOptions) { + let options = aOptions || {}; + let hgram = this.processHistogram(aHgram, aName); + + let outerDiv = document.createElement("div"); + outerDiv.className = "histogram"; + outerDiv.id = aName; + + let divTitle = document.createElement("div"); + divTitle.classList.add("histogram-title"); + divTitle.appendChild(document.createTextNode(aName)); + outerDiv.appendChild(divTitle); + + let divStats = document.createElement("div"); + divStats.classList.add("histogram-stats"); + + let histogramStatsArgs = { + sampleCount: hgram.sample_count, + prettyAverage: hgram.pretty_average, + sum: hgram.sum, + }; + + document.l10n.setAttributes( + divStats, + "about-telemetry-histogram-stats", + histogramStatsArgs + ); + + if (isRTL()) { + hgram.values.reverse(); + } + + let textData = this.renderValues(outerDiv, hgram, options); + + // The 'Copy' button contains the textual data, copied to clipboard on click + let copyButton = document.createElement("button"); + copyButton.className = "copy-node"; + document.l10n.setAttributes(copyButton, "about-telemetry-histogram-copy"); + + copyButton.addEventListener("click", async function () { + let divStatsString = await document.l10n.formatValue( + "about-telemetry-histogram-stats", + histogramStatsArgs + ); + copyButton.histogramText = + aName + EOL + divStatsString + EOL + EOL + textData; + Cc["@mozilla.org/widget/clipboardhelper;1"] + .getService(Ci.nsIClipboardHelper) + .copyString(this.histogramText); + }); + outerDiv.appendChild(copyButton); + + aParent.appendChild(outerDiv); + return outerDiv; + }, + + processHistogram(aHgram) { + const values = Object.keys(aHgram.values).map(k => aHgram.values[k]); + if (!values.length) { + // If we have no values collected for this histogram, just return + // zero values so we still render it. + return { + values: [], + pretty_average: 0, + max: 0, + sample_count: 0, + sum: 0, + }; + } + + const sample_count = values.reduceRight((a, b) => a + b); + const average = Math.round((aHgram.sum * 10) / sample_count) / 10; + const max_value = Math.max(...values); + + const labelledValues = Object.keys(aHgram.values).map(k => [ + Number(k), + aHgram.values[k], + ]); + + let result = { + values: labelledValues, + pretty_average: average, + max: max_value, + sample_count, + sum: aHgram.sum, + }; + + return result; + }, + + /** + * Return a non-negative, logarithmic representation of a non-negative number. + * e.g. 0 => 0, 1 => 1, 10 => 2, 100 => 3 + * + * @param aNumber Non-negative number + */ + getLogValue(aNumber) { + return Math.max(0, Math.log10(aNumber) + 1); + }, + + /** + * Create histogram HTML bars, also returns a textual representation + * Both aMaxValue and aSumValues must be positive. + * Values are assumed to use 0 as baseline. + * + * @param aDiv Outer parent div + * @param aHgram The histogram data + * @param aOptions Object with render options (@see #render) + */ + renderValues: function Histogram_renderValues(aDiv, aHgram, aOptions) { + let text = ""; + // If the last label is not the longest string, alignment will break a little + let labelPadTo = 0; + if (aHgram.values.length) { + labelPadTo = String(aHgram.values[aHgram.values.length - 1][0]).length; + } + let maxBarValue = aOptions.exponential + ? this.getLogValue(aHgram.max) + : aHgram.max; + + for (let [label, value] of aHgram.values) { + label = String(label); + let barValue = aOptions.exponential ? this.getLogValue(value) : value; + + // Create a text representation: | + text += + EOL + + " ".repeat(Math.max(0, labelPadTo - label.length)) + + label + // Right-aligned label + " |" + + "#".repeat(Math.round((MAX_BAR_CHARS * barValue) / maxBarValue)) + // Bar + " " + + value + // Value + " " + + Math.round((100 * value) / aHgram.sample_count) + + "%"; // Percentage + + // Construct the HTML labels + bars + let belowEm = + Math.round(MAX_BAR_HEIGHT * (barValue / maxBarValue) * 10) / 10; + let aboveEm = MAX_BAR_HEIGHT - belowEm; + + let barDiv = document.createElement("div"); + barDiv.className = "bar"; + barDiv.style.paddingTop = aboveEm + "em"; + + // Add value label or an nbsp if no value + barDiv.appendChild(document.createTextNode(value ? value : "\u00A0")); + + // Create the blue bar + let bar = document.createElement("div"); + bar.className = "bar-inner"; + bar.style.height = belowEm + "em"; + barDiv.appendChild(bar); + + // Add a special class to move the text down to prevent text overlap + if (label.length > 3) { + bar.classList.add("long-label"); + } + // Add bucket label + barDiv.appendChild(document.createTextNode(label)); + + aDiv.appendChild(barDiv); + } + + return text.substr(EOL.length); // Trim the EOL before the first line + }, +}; + +var Search = { + HASH_SEARCH: "search=", + + // A list of ids of sections that do not support search. + blacklist: ["late-writes-section", "raw-payload-section"], + + // Pass if: all non-empty array items match (case-sensitive) + isPassText(subject, filter) { + for (let item of filter) { + if (item.length && !subject.includes(item)) { + return false; // mismatch and not a spurious space + } + } + return true; + }, + + isPassRegex(subject, filter) { + return filter.test(subject); + }, + + chooseFilter(filterText) { + let filter = filterText.toString(); + // Setup normalized filter string (trimmed, lower cased and split on spaces if not RegEx) + let isPassFunc; // filter function, set once, then applied to all elements + filter = filter.trim(); + if (filter[0] != "/") { + // Plain text: case insensitive, AND if multi-string + isPassFunc = this.isPassText; + filter = filter.toLowerCase().split(" "); + } else { + isPassFunc = this.isPassRegex; + var r = filter.match(/^\/(.*)\/(i?)$/); + try { + filter = RegExp(r[1], r[2]); + } catch (e) { + // Incomplete or bad RegExp - always no match + isPassFunc = function () { + return false; + }; + } + } + return [isPassFunc, filter]; + }, + + filterTextRows(table, filterText) { + let [isPassFunc, filter] = this.chooseFilter(filterText); + let allElementHidden = true; + + let needLowerCase = isPassFunc === this.isPassText; + let elements = table.rows; + for (let element of elements) { + if (element.firstChild.nodeName == "th") { + continue; + } + for (let cell of element.children) { + let subject = needLowerCase + ? cell.textContent.toLowerCase() + : cell.textContent; + element.hidden = !isPassFunc(subject, filter); + if (!element.hidden) { + if (allElementHidden) { + allElementHidden = false; + } + // Don't need to check the rest of this row. + break; + } + } + } + // Unhide the first row: + if (!allElementHidden) { + table.rows[0].hidden = false; + } + return allElementHidden; + }, + + filterElements(elements, filterText) { + let [isPassFunc, filter] = this.chooseFilter(filterText); + let allElementHidden = true; + + let needLowerCase = isPassFunc === this.isPassText; + for (let element of elements) { + let subject = needLowerCase ? element.id.toLowerCase() : element.id; + element.hidden = !isPassFunc(subject, filter); + if (allElementHidden && !element.hidden) { + allElementHidden = false; + } + } + return allElementHidden; + }, + + filterKeyedElements(keyedElements, filterText) { + let [isPassFunc, filter] = this.chooseFilter(filterText); + let allElementsHidden = true; + + let needLowerCase = isPassFunc === this.isPassText; + keyedElements.forEach(keyedElement => { + let subject = needLowerCase + ? keyedElement.key.id.toLowerCase() + : keyedElement.key.id; + if (!isPassFunc(subject, filter)) { + // If the keyedHistogram's name is not matched + let allKeyedElementsHidden = true; + for (let element of keyedElement.datas) { + let subject = needLowerCase ? element.id.toLowerCase() : element.id; + let match = isPassFunc(subject, filter); + element.hidden = !match; + if (match) { + allKeyedElementsHidden = false; + } + } + if (allElementsHidden && !allKeyedElementsHidden) { + allElementsHidden = false; + } + keyedElement.key.hidden = allKeyedElementsHidden; + } else { + // If the keyedHistogram's name is matched + allElementsHidden = false; + keyedElement.key.hidden = false; + for (let element of keyedElement.datas) { + element.hidden = false; + } + } + }); + return allElementsHidden; + }, + + searchHandler(e) { + if (this.idleTimeout) { + clearTimeout(this.idleTimeout); + } + this.idleTimeout = setTimeout( + () => Search.search(e.target.value), + FILTER_IDLE_TIMEOUT + ); + }, + + search(text, sectionParam = null) { + let section = sectionParam; + if (!section) { + let sectionId = document + .querySelector(".category.selected") + .getAttribute("value"); + section = document.getElementById(sectionId); + } + if (Search.blacklist.includes(section.id)) { + return false; + } + let noSearchResults = true; + // In the home section, we search all other sections: + if (section.id === "home-section") { + return this.homeSearch(text); + } + + if (section.id === "histograms-section") { + let histograms = section.getElementsByClassName("histogram"); + noSearchResults = this.filterElements(histograms, text); + } else if (section.id === "keyed-histograms-section") { + let keyedElements = []; + let keyedHistograms = section.getElementsByClassName("keyed-histogram"); + for (let key of keyedHistograms) { + let datas = key.getElementsByClassName("histogram"); + keyedElements.push({ key, datas }); + } + noSearchResults = this.filterKeyedElements(keyedElements, text); + } else if (section.id === "keyed-scalars-section") { + let keyedElements = []; + let keyedScalars = section.getElementsByClassName("keyed-scalar"); + for (let key of keyedScalars) { + let datas = key.querySelector("table").rows; + keyedElements.push({ key, datas }); + } + noSearchResults = this.filterKeyedElements(keyedElements, text); + } else if (section.matches(".text-search")) { + let tables = section.querySelectorAll("table"); + for (let table of tables) { + // If we unhide anything, flip noSearchResults to + // false so we don't show the "no results" bits. + if (!this.filterTextRows(table, text)) { + noSearchResults = false; + } + } + } else if (section.querySelector(".sub-section")) { + let keyedSubSections = []; + let subsections = section.querySelectorAll(".sub-section"); + for (let section of subsections) { + let datas = section.querySelector("table").rows; + keyedSubSections.push({ key: section, datas }); + } + noSearchResults = this.filterKeyedElements(keyedSubSections, text); + } else { + let tables = section.querySelectorAll("table"); + for (let table of tables) { + noSearchResults = this.filterElements(table.rows, text); + if (table.caption) { + table.caption.hidden = noSearchResults; + } + } + } + + changeUrlSearch(text); + + if (!sectionParam) { + // If we are not searching in all section. + this.updateNoResults(text, noSearchResults); + } + return noSearchResults; + }, + + updateNoResults(text, noSearchResults) { + document + .getElementById("no-search-results") + .classList.toggle("hidden", !noSearchResults); + if (noSearchResults) { + let section = document.querySelector(".category.selected > span"); + let searchResultsText = document.getElementById("no-search-results-text"); + if (section.parentElement.id === "category-home") { + document.l10n.setAttributes( + searchResultsText, + "about-telemetry-no-search-results-all", + { searchTerms: text } + ); + } else { + let sectionName = section.textContent.trim(); + text === "" + ? document.l10n.setAttributes( + searchResultsText, + "about-telemetry-no-data-to-display", + { sectionName } + ) + : document.l10n.setAttributes( + searchResultsText, + "about-telemetry-no-search-results", + { sectionName, currentSearchText: text } + ); + } + } + }, + + resetHome() { + document.getElementById("main").classList.remove("search"); + document.getElementById("no-search-results").classList.add("hidden"); + adjustHeaderState(); + Array.from(document.querySelectorAll("section")).forEach(section => { + section.classList.toggle("active", section.id == "home-section"); + }); + }, + + homeSearch(text) { + changeUrlSearch(text); + removeSearchSectionTitles(); + if (text === "") { + this.resetHome(); + return; + } + document.getElementById("main").classList.add("search"); + adjustHeaderState(text); + let noSearchResults = true; + Array.from(document.querySelectorAll("section")).forEach(section => { + if (section.id == "home-section" || section.id == "raw-payload-section") { + section.classList.remove("active"); + return; + } + section.classList.add("active"); + let sectionHidden = this.search(text, section); + if (!sectionHidden) { + let sectionTitle = document.querySelector( + `.category[value="${section.id}"] .category-name` + ).textContent; + let sectionDataDiv = document.querySelector( + `#${section.id}.has-data.active .data` + ); + let titleDiv = document.createElement("h1"); + titleDiv.classList.add("data", "search-section-title"); + titleDiv.textContent = sectionTitle; + section.insertBefore(titleDiv, sectionDataDiv); + noSearchResults = false; + } else { + // Hide all subsections if the section is hidden + let subsections = section.querySelectorAll(".sub-section"); + for (let subsection of subsections) { + subsection.hidden = true; + } + } + }); + this.updateNoResults(text, noSearchResults); + }, +}; + +/** + * Helper function to render JS objects with white space between top level elements + * so that they look better in the browser + * + * @param aObject JavaScript object or array to render + * @return String + */ +function RenderObject(aObject) { + let output = ""; + if (Array.isArray(aObject)) { + if (!aObject.length) { + return "[]"; + } + output = "[" + JSON.stringify(aObject[0]); + for (let i = 1; i < aObject.length; i++) { + output += ", " + JSON.stringify(aObject[i]); + } + return output + "]"; + } + let keys = Object.keys(aObject); + if (!keys.length) { + return "{}"; + } + output = '{"' + keys[0] + '":\u00A0' + JSON.stringify(aObject[keys[0]]); + for (let i = 1; i < keys.length; i++) { + output += ', "' + keys[i] + '":\u00A0' + JSON.stringify(aObject[keys[i]]); + } + return output + "}"; +} + +var GenericSubsection = { + addSubSectionToSidebar(id, title) { + let category = document.querySelector("#categories > [value=" + id + "]"); + category.classList.add("has-subsection"); + let subCategory = document.createElement("div"); + subCategory.classList.add("category-subsection"); + subCategory.setAttribute("value", id + "-" + title); + subCategory.addEventListener("click", ev => { + let section = ev.target; + showSubSection(section); + }); + subCategory.appendChild(document.createTextNode(title)); + category.appendChild(subCategory); + }, + + render(data, dataDiv, sectionID) { + for (let [title, sectionData] of data) { + let hasData = sectionData.size > 0; + let s = this.renderSubsectionHeader(title, hasData, sectionID); + s.appendChild(this.renderSubsectionData(title, sectionData)); + dataDiv.appendChild(s); + } + }, + + renderSubsectionHeader(title, hasData, sectionID) { + this.addSubSectionToSidebar(sectionID, title); + let section = document.createElement("div"); + section.setAttribute("id", sectionID + "-" + title); + section.classList.add("sub-section"); + if (hasData) { + section.classList.add("has-subdata"); + } + return section; + }, + + renderSubsectionData(title, data) { + // Create data container + let dataDiv = document.createElement("div"); + dataDiv.setAttribute("class", "subsection-data subdata"); + // Instanciate the data + let table = GenericTable.render(data); + let caption = document.createElement("caption"); + caption.textContent = title; + table.appendChild(caption); + dataDiv.appendChild(table); + + return dataDiv; + }, + + deleteAllSubSections() { + let subsections = document.querySelectorAll(".category-subsection"); + subsections.forEach(el => { + el.parentElement.removeChild(el); + }); + }, +}; + +var GenericTable = { + // Returns a table with key and value headers + defaultHeadings() { + return ["about-telemetry-keys-header", "about-telemetry-values-header"]; + }, + + /** + * Returns a n-column table. + * + * @param rows An array of arrays, each containing data to render + * for one row. + * @param headings The column header strings. + */ + render(rows, headings = this.defaultHeadings()) { + let table = document.createElement("table"); + this.renderHeader(table, headings); + this.renderBody(table, rows); + return table; + }, + + /** + * Create the table header. + * Tabs & newlines added to cells to make it easier to copy-paste. + * + * @param table Table element + * @param headings Array of column header strings. + */ + renderHeader(table, headings) { + let headerRow = document.createElement("tr"); + table.appendChild(headerRow); + + for (let i = 0; i < headings.length; ++i) { + let column = document.createElement("th"); + document.l10n.setAttributes(column, headings[i]); + headerRow.appendChild(column); + } + }, + + /** + * Create the table body + * Tabs & newlines added to cells to make it easier to copy-paste. + * + * @param table Table element + * @param rows An array of arrays, each containing data to render + * for one row. + */ + renderBody(table, rows) { + for (let row of rows) { + row = row.map(value => { + // use .valueOf() to unbox Number, String, etc. objects + if ( + value && + typeof value == "object" && + typeof value.valueOf() == "object" + ) { + return RenderObject(value); + } + return value; + }); + + let newRow = document.createElement("tr"); + newRow.id = row[0]; + table.appendChild(newRow); + + for (let i = 0; i < row.length; ++i) { + let suffix = i == row.length - 1 ? "\n" : "\t"; + let field = document.createElement("td"); + field.appendChild(document.createTextNode(row[i] + suffix)); + newRow.appendChild(field); + } + } + }, +}; + +var KeyedHistogram = { + render(parent, id, keyedHistogram) { + let outerDiv = document.createElement("div"); + outerDiv.className = "keyed-histogram"; + outerDiv.id = id; + + let divTitle = document.createElement("div"); + divTitle.classList.add("keyed-title"); + divTitle.appendChild(document.createTextNode(id)); + outerDiv.appendChild(divTitle); + + for (let [name, hgram] of Object.entries(keyedHistogram)) { + Histogram.render(outerDiv, name, hgram); + } + + parent.appendChild(outerDiv); + return outerDiv; + }, +}; + +var AddonDetails = { + /** + * Render the addon details section as a series of headers followed by key/value tables + * + * @param aPing A ping object to render the data from. + */ + render(aPing) { + let addonSection = document.getElementById("addon-details"); + removeAllChildNodes(addonSection); + let addonDetails = aPing.payload.addonDetails; + const hasData = addonDetails && !!Object.keys(addonDetails).length; + setHasData("addon-details-section", hasData); + if (!hasData) { + return; + } + + for (let provider in addonDetails) { + let providerSection = document.createElement("caption"); + document.l10n.setAttributes( + providerSection, + "about-telemetry-addon-provider", + { addonProvider: provider } + ); + let headingStrings = [ + "about-telemetry-addon-table-id", + "about-telemetry-addon-table-details", + ]; + let table = GenericTable.render( + explodeObject(addonDetails[provider]), + headingStrings + ); + table.appendChild(providerSection); + addonSection.appendChild(table); + } + }, +}; + +class Section { + static renderContent(data, process, div, section) { + if (data && Object.keys(data).length) { + let s = GenericSubsection.renderSubsectionHeader(process, true, section); + let heading = document.createElement("h2"); + document.l10n.setAttributes(heading, "about-telemetry-process", { + process, + }); + s.appendChild(heading); + + this.renderData(data, s); + + div.appendChild(s); + let separator = document.createElement("div"); + separator.classList.add("clearfix"); + div.appendChild(separator); + } + } + + /** + * Make parent process the first one, content process the second + * then sort processes alphabetically + */ + static processesComparator(a, b) { + if (a === "parent" || (a === "content" && b !== "parent")) { + return -1; + } else if (b === "parent" || b === "content") { + return 1; + } else if (a < b) { + return -1; + } else if (a > b) { + return 1; + } + return 0; + } + + /** + * Render sections + */ + static renderSection(divName, section, aPayload) { + let div = document.getElementById(divName); + removeAllChildNodes(div); + + let data = {}; + let hasData = false; + let selectedStore = getSelectedStore(); + + let payload = aPayload.stores; + + let isCurrentPayload = !!payload; + + // Sort processes + let sortedProcesses = isCurrentPayload + ? Object.keys(payload[selectedStore]).sort(this.processesComparator) + : Object.keys(aPayload.processes).sort(this.processesComparator); + + // Render content by process + for (const process of sortedProcesses) { + data = isCurrentPayload + ? this.dataFiltering(payload, selectedStore, process) + : this.archivePingDataFiltering(aPayload, process); + hasData = hasData || !ObjectUtils.isEmpty(data); + this.renderContent(data, process, div, section, this.renderData); + } + setHasData(section, hasData); + } +} + +class Scalars extends Section { + /** + * Return data from the current ping + */ + static dataFiltering(payload, selectedStore, process) { + return payload[selectedStore][process].scalars; + } + + /** + * Return data from an archived ping + */ + static archivePingDataFiltering(payload, process) { + return payload.processes[process].scalars; + } + + static renderData(data, div) { + const scalarsHeadings = [ + "about-telemetry-names-header", + "about-telemetry-values-header", + ]; + let scalarsTable = GenericTable.render( + explodeObject(data), + scalarsHeadings + ); + div.appendChild(scalarsTable); + } + + /** + * Render the scalar data - if present - from the payload in a simple key-value table. + * + * @param aPayload A payload object to render the data from. + */ + static render(aPayload) { + const divName = "scalars"; + const section = "scalars-section"; + this.renderSection(divName, section, aPayload); + } +} + +class KeyedScalars extends Section { + /** + * Return data from the current ping + */ + static dataFiltering(payload, selectedStore, process) { + return payload[selectedStore][process].keyedScalars; + } + + /** + * Return data from an archived ping + */ + static archivePingDataFiltering(payload, process) { + return payload.processes[process].keyedScalars; + } + + static renderData(data, div) { + const scalarsHeadings = [ + "about-telemetry-names-header", + "about-telemetry-values-header", + ]; + for (let scalarId in data) { + // Add the name of the scalar. + let container = document.createElement("div"); + container.classList.add("keyed-scalar"); + container.id = scalarId; + let scalarNameSection = document.createElement("p"); + scalarNameSection.classList.add("keyed-title"); + scalarNameSection.appendChild(document.createTextNode(scalarId)); + container.appendChild(scalarNameSection); + // Populate the section with the key-value pairs from the scalar. + const table = GenericTable.render( + explodeObject(data[scalarId]), + scalarsHeadings + ); + container.appendChild(table); + div.appendChild(container); + } + } + + /** + * Render the keyed scalar data - if present - from the payload in a simple key-value table. + * + * @param aPayload A payload object to render the data from. + */ + static render(aPayload) { + const divName = "keyed-scalars"; + const section = "keyed-scalars-section"; + this.renderSection(divName, section, aPayload); + } +} + +var Events = { + /** + * Render the event data - if present - from the payload in a simple table. + * + * @param aPayload A payload object to render the data from. + */ + render(aPayload) { + let eventsDiv = document.getElementById("events"); + removeAllChildNodes(eventsDiv); + const headings = [ + "about-telemetry-time-stamp-header", + "about-telemetry-category-header", + "about-telemetry-method-header", + "about-telemetry-object-header", + "about-telemetry-values-header", + "about-telemetry-extra-header", + ]; + let payload = aPayload.processes; + let hasData = false; + if (payload) { + for (const process of Object.keys(aPayload.processes)) { + let data = aPayload.processes[process].events; + if (data && Object.keys(data).length) { + hasData = true; + let s = GenericSubsection.renderSubsectionHeader( + process, + true, + "events-section" + ); + let heading = document.createElement("h2"); + heading.textContent = process; + s.appendChild(heading); + const table = GenericTable.render(data, headings); + s.appendChild(table); + eventsDiv.appendChild(s); + let separator = document.createElement("div"); + separator.classList.add("clearfix"); + eventsDiv.appendChild(separator); + } + } + } else { + // handle archived ping + for (const process of Object.keys(aPayload.events)) { + let data = process; + if (data && Object.keys(data).length) { + hasData = true; + let s = GenericSubsection.renderSubsectionHeader( + process, + true, + "events-section" + ); + let heading = document.createElement("h2"); + heading.textContent = process; + s.appendChild(heading); + const table = GenericTable.render(data, headings); + eventsDiv.appendChild(table); + let separator = document.createElement("div"); + separator.classList.add("clearfix"); + eventsDiv.appendChild(separator); + } + } + } + setHasData("events-section", hasData); + }, +}; + +/** + * Helper function for showing either the toggle element or "No data collected" message for a section + * + * @param aSectionID ID of the section element that needs to be changed + * @param aHasData true (default) indicates that toggle should be displayed + */ +function setHasData(aSectionID, aHasData) { + let sectionElement = document.getElementById(aSectionID); + sectionElement.classList[aHasData ? "add" : "remove"]("has-data"); + + // Display or Hide the section in the sidebar + let sectionCategory = document.querySelector( + ".category[value=" + aSectionID + "]" + ); + sectionCategory.classList[aHasData ? "add" : "remove"]("has-data"); +} + +/** + * Sets l10n attributes based on the Telemetry Server Owner pref. + */ +function setupServerOwnerBranding() { + let serverOwner = Preferences.get(PREF_TELEMETRY_SERVER_OWNER, "Mozilla"); + const elements = [ + [document.getElementById("page-subtitle"), "about-telemetry-page-subtitle"], + ]; + for (const [elt, l10nName] of elements) { + document.l10n.setAttributes(elt, l10nName, { + telemetryServerOwner: serverOwner, + }); + } +} + +/** + * Display the store selector if we are on one + * of the whitelisted sections + */ +function displayStoresSelector(selectedSection) { + let whitelist = [ + "scalars-section", + "keyed-scalars-section", + "histograms-section", + "keyed-histograms-section", + ]; + let stores = document.getElementById("stores"); + stores.hidden = !whitelist.includes(selectedSection); + let storesLabel = document.getElementById("storesLabel"); + storesLabel.hidden = !whitelist.includes(selectedSection); +} + +function refreshSearch() { + removeSearchSectionTitles(); + let selectedSection = document + .querySelector(".category.selected") + .getAttribute("value"); + let search = document.getElementById("search"); + if (!Search.blacklist.includes(selectedSection)) { + Search.search(search.value); + } +} + +function adjustSearchState() { + removeSearchSectionTitles(); + let selectedSection = document + .querySelector(".category.selected") + .getAttribute("value"); + let search = document.getElementById("search"); + search.value = ""; + search.hidden = Search.blacklist.includes(selectedSection); + document.getElementById("no-search-results").classList.add("hidden"); + Search.search(""); // reinitialize search state. +} + +function removeSearchSectionTitles() { + for (let sectionTitleDiv of Array.from( + document.getElementsByClassName("search-section-title") + )) { + sectionTitleDiv.remove(); + } +} + +function adjustSection() { + let selectedCategory = document.querySelector(".category.selected"); + if (!selectedCategory.classList.contains("has-data")) { + PingPicker._showStructuredPingData(); + } +} + +function adjustHeaderState(title = null) { + let selected = document.querySelector(".category.selected .category-name"); + let selectedTitle = selected.textContent.trim(); + let sectionTitle = document.getElementById("sectionTitle"); + if (title !== null) { + document.l10n.setAttributes( + sectionTitle, + "about-telemetry-results-for-search", + { searchTerms: title } + ); + } else { + sectionTitle.textContent = selectedTitle; + } + let search = document.getElementById("search"); + if (selected.parentElement.id === "category-home") { + document.l10n.setAttributes( + search, + "about-telemetry-filter-all-placeholder" + ); + } else { + document.l10n.setAttributes(search, "about-telemetry-filter-placeholder", { + selectedTitle, + }); + } +} + +/** + * Change the url according to the current section displayed + * e.g about:telemetry#general-data + */ +function changeUrlPath(selectedSection, subSection) { + if (subSection) { + let hash = window.location.hash.split("_")[0] + "_" + selectedSection; + window.location.hash = hash; + } else { + window.location.hash = selectedSection.replace("-section", "-tab"); + } +} + +/** + * Change the url according to the current search text + */ +function changeUrlSearch(searchText) { + let currentHash = window.location.hash; + let hashWithoutSearch = currentHash.split(Search.HASH_SEARCH)[0]; + let hash = ""; + + if (!currentHash && !searchText) { + return; + } + if (!currentHash.includes(Search.HASH_SEARCH) && hashWithoutSearch) { + hashWithoutSearch += "_"; + } + if (searchText) { + hash = + hashWithoutSearch + Search.HASH_SEARCH + searchText.replace(/ /g, "+"); + } else if (hashWithoutSearch) { + hash = hashWithoutSearch.slice(0, hashWithoutSearch.length - 1); + } + + window.location.hash = hash; +} + +/** + * Change the section displayed + */ +function show(selected) { + let selectedValue = selected.getAttribute("value"); + if (selectedValue === "raw-json-viewer") { + openJsonInFirefoxJsonViewer(JSON.stringify(gPingData, null, 2)); + return; + } + + let selected_section = document.getElementById(selectedValue); + let subsections = selected_section.querySelectorAll(".sub-section"); + if (selected.classList.contains("has-subsection")) { + for (let subsection of selected.children) { + subsection.classList.remove("selected"); + } + } + if (subsections) { + for (let subsection of subsections) { + subsection.hidden = false; + } + } + + let current_button = document.querySelector(".category.selected"); + if (current_button == selected) { + return; + } + current_button.classList.remove("selected"); + selected.classList.add("selected"); + + document.querySelectorAll("section").forEach(section => { + section.classList.remove("active"); + }); + selected_section.classList.add("active"); + + adjustHeaderState(); + displayStoresSelector(selectedValue); + adjustSearchState(); + changeUrlPath(selectedValue); +} + +function showSubSection(selected) { + if (!selected) { + return; + } + let current_selection = document.querySelector( + ".category-subsection.selected" + ); + if (current_selection) { + current_selection.classList.remove("selected"); + } + selected.classList.add("selected"); + + let section = document.getElementById(selected.getAttribute("value")); + section.parentElement.childNodes.forEach(element => { + element.hidden = true; + }); + section.hidden = false; + + let title = + selected.parentElement.querySelector(".category-name").textContent; + let subsection = selected.textContent; + document.getElementById("sectionTitle").textContent = + title + " - " + subsection; + changeUrlPath(subsection, true); +} + +/** + * Initializes load/unload, pref change and mouse-click listeners + */ +function setupListeners() { + Settings.attachObservers(); + PingPicker.attachObservers(); + RawPayloadData.attachObservers(); + + let menu = document.getElementById("categories"); + menu.addEventListener("click", e => { + if (e.target && e.target.parentNode == menu) { + show(e.target); + } + }); + + let search = document.getElementById("search"); + search.addEventListener("input", Search.searchHandler); +} + +// Restores the sections states +function urlSectionRestore(hash) { + if (hash) { + let section = hash.replace("-tab", "-section"); + let subsection = section.split("_")[1]; + section = section.split("_")[0]; + let category = document.querySelector(".category[value=" + section + "]"); + if (category) { + show(category); + if (subsection) { + let selector = + ".category-subsection[value=" + section + "-" + subsection + "]"; + let subcategory = document.querySelector(selector); + showSubSection(subcategory); + } + } + } +} + +// Restore sections states and search terms +function urlStateRestore() { + let hash = window.location.hash; + let searchQuery = ""; + if (hash) { + hash = hash.slice(1); + if (hash.includes(Search.HASH_SEARCH)) { + searchQuery = hash.split(Search.HASH_SEARCH)[1].replace(/[+]/g, " "); + hash = hash.split(Search.HASH_SEARCH)[0]; + } + urlSectionRestore(hash); + } + if (searchQuery) { + let search = document.getElementById("search"); + search.value = searchQuery; + } +} + +function openJsonInFirefoxJsonViewer(json) { + json = unescape(encodeURIComponent(json)); + try { + window.open("data:application/json;base64," + btoa(json)); + } catch (e) { + show(document.querySelector(".category[value=raw-payload-section]")); + } +} + +function onLoad() { + window.removeEventListener("load", onLoad); + // Set the text in the page header and elsewhere that needs the server owner. + setupServerOwnerBranding(); + + // Set up event listeners + setupListeners(); + + // Render settings. + Settings.render(); + + adjustHeaderState(); + + urlStateRestore(); + + // Update ping data when async Telemetry init is finished. + Telemetry.asyncFetchTelemetryData(async () => { + await PingPicker.update(); + }); +} + +class HistogramSection extends Section { + /** + * Return data from the current ping + */ + static dataFiltering(payload, selectedStore, process) { + return payload[selectedStore][process].histograms; + } + + /** + * Return data from an archived ping + */ + static archivePingDataFiltering(payload, process) { + if (process === "parent") { + return payload.histograms; + } + return payload.processes[process].histograms; + } + + static renderData(data, div) { + for (let [hName, hgram] of Object.entries(data)) { + Histogram.render(div, hName, hgram, { unpacked: true }); + } + } + + static render(aPayload) { + const divName = "histograms"; + const section = "histograms-section"; + this.renderSection(divName, section, aPayload); + } +} + +class KeyedHistogramSection extends Section { + /** + * Return data from the current ping + */ + static dataFiltering(payload, selectedStore, process) { + return payload[selectedStore][process].keyedHistograms; + } + + /** + * Return data from an archived ping + */ + static archivePingDataFiltering(payload, process) { + if (process === "parent") { + return payload.keyedHistograms; + } + return payload.processes[process].keyedHistograms; + } + + static renderData(data, div) { + for (let [id, keyed] of Object.entries(data)) { + KeyedHistogram.render(div, id, keyed, { unpacked: true }); + } + } + + static render(aPayload) { + const divName = "keyed-histograms"; + const section = "keyed-histograms-section"; + this.renderSection(divName, section, aPayload); + } +} + +var SessionInformation = { + render(aPayload) { + let infoSection = document.getElementById("session-info"); + removeAllChildNodes(infoSection); + + let hasData = !!Object.keys(aPayload.info).length; + setHasData("session-info-section", hasData); + + if (hasData) { + const table = GenericTable.render(explodeObject(aPayload.info)); + infoSection.appendChild(table); + } + }, +}; + +var SimpleMeasurements = { + render(aPayload) { + let simpleSection = document.getElementById("simple-measurements"); + removeAllChildNodes(simpleSection); + + let simpleMeasurements = this.sortStartupMilestones( + aPayload.simpleMeasurements + ); + let hasData = !!Object.keys(simpleMeasurements).length; + setHasData("simple-measurements-section", hasData); + + if (hasData) { + const table = GenericTable.render(explodeObject(simpleMeasurements)); + simpleSection.appendChild(table); + } + }, + + /** + * Helper function for sorting the startup milestones in the Simple Measurements + * section into temporal order. + * + * @param aSimpleMeasurements Telemetry ping's "Simple Measurements" data + * @return Sorted measurements + */ + sortStartupMilestones(aSimpleMeasurements) { + const telemetryTimestamps = TelemetryTimestamps.get(); + let startupEvents = Services.startup.getStartupInfo(); + delete startupEvents.process; + + function keyIsMilestone(k) { + return k in startupEvents || k in telemetryTimestamps; + } + + let sortedKeys = Object.keys(aSimpleMeasurements); + + // Sort the measurements, with startup milestones at the front + ordered by time + sortedKeys.sort(function keyCompare(keyA, keyB) { + let isKeyAMilestone = keyIsMilestone(keyA); + let isKeyBMilestone = keyIsMilestone(keyB); + + // First order by startup vs non-startup measurement + if (isKeyAMilestone && !isKeyBMilestone) { + return -1; + } + if (!isKeyAMilestone && isKeyBMilestone) { + return 1; + } + // Don't change order of non-startup measurements + if (!isKeyAMilestone && !isKeyBMilestone) { + return 0; + } + + // If both keys are startup measurements, order them by value + return aSimpleMeasurements[keyA] - aSimpleMeasurements[keyB]; + }); + + // Insert measurements into a result object in sort-order + let result = {}; + for (let key of sortedKeys) { + result[key] = aSimpleMeasurements[key]; + } + + return result; + }, +}; + +/** + * Render stores options + */ +function renderStoreList(payload) { + let storeSelect = document.getElementById("stores"); + let storesLabel = document.getElementById("storesLabel"); + removeAllChildNodes(storeSelect); + + if (!("stores" in payload)) { + storeSelect.classList.add("hidden"); + storesLabel.classList.add("hidden"); + return; + } + + storeSelect.classList.remove("hidden"); + storesLabel.classList.remove("hidden"); + storeSelect.disabled = false; + + for (let store of Object.keys(payload.stores)) { + let option = document.createElement("option"); + option.appendChild(document.createTextNode(store)); + option.setAttribute("value", store); + // Select main store by default + if (store === "main") { + option.selected = true; + } + storeSelect.appendChild(option); + } +} + +/** + * Return the selected store + */ +function getSelectedStore() { + let storeSelect = document.getElementById("stores"); + let storeSelectedOption = storeSelect.selectedOptions.item(0); + let selectedStore = + storeSelectedOption !== null + ? storeSelectedOption.getAttribute("value") + : undefined; + return selectedStore; +} + +function togglePingSections(isMainPing) { + // We always show the sections that are "common" to all pings. + let commonSections = new Set([ + "heading", + "home-section", + "general-data-section", + "environment-data-section", + "raw-json-viewer", + ]); + + let elements = document.querySelectorAll(".category"); + for (let section of elements) { + if (commonSections.has(section.getAttribute("value"))) { + continue; + } + // Only show the raw payload for non main ping. + if (section.getAttribute("value") == "raw-payload-section") { + section.classList.toggle("has-data", !isMainPing); + } else { + section.classList.toggle("has-data", isMainPing); + } + } +} + +function displayPingData(ping, updatePayloadList = false) { + gPingData = ping; + try { + PingPicker.render(); + displayRichPingData(ping, updatePayloadList); + adjustSection(); + refreshSearch(); + } catch (err) { + console.log(err); + PingPicker._showRawPingData(); + } +} + +function displayRichPingData(ping, updatePayloadList) { + // Update the payload list and store lists + if (updatePayloadList) { + renderStoreList(ping.payload); + } + + // Show general data. + GeneralData.render(ping); + + // Show environment data. + EnvironmentData.render(ping); + + RawPayloadData.render(ping); + + // We have special rendering code for the payloads from "main" and "event" pings. + // For any other pings we just render the raw JSON payload. + let isMainPing = ping.type == "main" || ping.type == "saved-session"; + let isEventPing = ping.type == "event"; + togglePingSections(isMainPing); + + if (isEventPing) { + // Copy the payload, so we don't modify the raw representation + // Ensure we always have at least the parent process. + let payload = { processes: { parent: {} } }; + for (let process of Object.keys(ping.payload.events)) { + payload.processes[process] = { + events: ping.payload.events[process], + }; + } + + // We transformed the actual payload, let's reload the store list if necessary. + if (updatePayloadList) { + renderStoreList(payload); + } + + // Show event data. + Events.render(payload); + return; + } + + if (!isMainPing) { + return; + } + + // Show slow SQL stats + SlowSQL.render(ping); + + // Render Addon details. + AddonDetails.render(ping); + + let payload = ping.payload; + // Show basic session info gathered + SessionInformation.render(payload); + + // Show scalar data. + Scalars.render(payload); + KeyedScalars.render(payload); + + // Show histogram data + HistogramSection.render(payload); + + // Show keyed histogram data + KeyedHistogramSection.render(payload); + + // Show event data. + Events.render(payload); + + // Show simple measurements + SimpleMeasurements.render(payload); +} + +window.addEventListener("load", onLoad); From 9ad93c8f59ccf27b94ce8572f2f53b5f9179da56 Mon Sep 17 00:00:00 2001 From: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:07:53 -0700 Subject: [PATCH 2/4] Add files via upload Signed-off-by: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> --- ...om_static_dist_components.js_v=c21e03b.pdf | Bin 0 -> 1264606 bytes docsify.txt | 10233 ++++++++++ gerritinstall.txt | 122 + lit-utils.mjs | 618 + maybe_tampered/FUCK.md | 3 + maybe_tampered/JavaScript.js | 18 + maybe_tampered/Server Not Found.htm | 97 + maybe_tampered/```JavaScript.txt | 16 + maybe_tampered/eventemitter3/README.md | 94 + maybe_tampered/eventemitter3/index.js | 336 + maybe_tampered/eventemitter3/index.txt | 134 + maybe_tampered/eventemitter3/package.json | 56 + .../eventemitter3/umd/eventemitter.js | 1268 ++ .../eventemitter3/umd/eventemitter3.js | 340 + .../eventemitter3/umd/eventemitter3.min.js | 1 + .../umd/eventemitter3.min.js.map | 1 + maybe_tampered/eventemitter3/umd/lit.all.mjs | 4467 +++++ .../eventemitter3/umd/moz-button-group.txt | 112 + maybe_tampered/eventemitter3/umd/ua.css | 586 + maybe_tampered/gamp.txt | 669 + maybe_tampered/lit.txt | 4467 +++++ maybe_tampered/profile.txt | 7 + panel.js | 270 + respecv3561.txt | 1253 ++ rumgooglesyndicationpagead.js | 133 + ...chromestatus.com_static_dist_components.js | 16665 ++++++++++++++++ 26 files changed, 41966 insertions(+) create mode 100644 chromestatus.com_static_dist_components.js_v=c21e03b.pdf create mode 100644 docsify.txt create mode 100644 gerritinstall.txt create mode 100644 lit-utils.mjs create mode 100644 maybe_tampered/FUCK.md create mode 100644 maybe_tampered/JavaScript.js create mode 100644 maybe_tampered/Server Not Found.htm create mode 100644 maybe_tampered/```JavaScript.txt create mode 100644 maybe_tampered/eventemitter3/README.md create mode 100644 maybe_tampered/eventemitter3/index.js create mode 100644 maybe_tampered/eventemitter3/index.txt create mode 100644 maybe_tampered/eventemitter3/package.json create mode 100644 maybe_tampered/eventemitter3/umd/eventemitter.js create mode 100644 maybe_tampered/eventemitter3/umd/eventemitter3.js create mode 100644 maybe_tampered/eventemitter3/umd/eventemitter3.min.js create mode 100644 maybe_tampered/eventemitter3/umd/eventemitter3.min.js.map create mode 100644 maybe_tampered/eventemitter3/umd/lit.all.mjs create mode 100644 maybe_tampered/eventemitter3/umd/moz-button-group.txt create mode 100644 maybe_tampered/eventemitter3/umd/ua.css create mode 100644 maybe_tampered/gamp.txt create mode 100644 maybe_tampered/lit.txt create mode 100644 maybe_tampered/profile.txt create mode 100644 panel.js create mode 100644 respecv3561.txt create mode 100644 rumgooglesyndicationpagead.js create mode 100644 view-source_https___chromestatus.com_static_dist_components.js diff --git a/chromestatus.com_static_dist_components.js_v=c21e03b.pdf b/chromestatus.com_static_dist_components.js_v=c21e03b.pdf new file mode 100644 index 0000000000000000000000000000000000000000..30a4a9026573adae57265c92e8ad2e8f8b74afa5 GIT binary patch literal 1264606 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 k0}gPX4$Gow9% z>_oXnq*T!uR{@WsL;Mav9m;*4L$+FC2Nd~ay)^lvR-zO$Up3kP<4i}D0d!pOxNb|z znHBAlKqIfk>E|9(3Noaix9Mp`dO=IS^z3lodRE<-Yol{PgGyzAWl|-3-{OF!v1Z(` z)~K$NyqaIP%(_p}Y?!46wVCvq4x*9=s6t8R40H*nh>eL>(M5k`CT#Az*Jg~EoabKu zvEe~zx`(N;vX^rZ2}P~ls2Q}PGU=K6G_PLH6j5ulJ!a9sA)?(^HLH}dVk3jwPUF1E z^ugavQtO18^D)QOFC40H=?H41dx6~cjN<6Q(#X)DJgC6Hz4@zn8)%fs8jW9db^KA4 z1eS~OfsRIGTO#F4AK}tmgB$L1^{I(fc_p3}bacAiWcvnT*eK_ycJ*efUP7#W6aS7SwfXE{OND=@A$SgOyNW(Pq1Q_*Wf zR1<(=Sk<3l$%Av=(oNhGHWt9ecvc*0l?I7wWBc%0qQjrDl?o?-^jHr?ABLQIcO2kA zR})Hn#6h$0;I>}*Zj9^b*NLqg*{vcPzl3h|oReOYRDt_C;fx^&Jg0QkZBwKr(fR_% zE^qNvDXO3elAnR6r6}&>D9vqO)8>IBF*X~0^KYm48*`GV)?YbYD<*oqxmagL(_5?c z6i+bKZG5>Dm^tLuCO*F(b)n{ag<`*AcD5R-n!v5u@yQ( z_+gLZ?IH-EkX&n~=Yi=}_z#je5=EW^lm#FTglW(EVz;}4TcI6HNQ3|pjf7&f)Ux^_ zD~N-9BW7JTkOC>NMsP|HIA3^dCb?yv2x)=?&+R!tKOE8V3~UWITK|%1ccQ*!F*qHDPfP4F z8kcyrOMfI=$_RXtzz4cxmQ4xy4zRlf)E|X@8o6lQial06yTiQ1{ft}0VmN_?lFhe| zn@owP&5d3vHb-I1ecRZVL+!Z^_FtmGGTSo05$w)Fh|o*PXtNROwpdf@UDv-M+Vku0 z?YPN-JVU4Zs*%#;aLgEr zn!Iywvr}(qYMRXRaVk(k|2rKHGzHIbV?d#$EGTR=F7+*s5sn*!li$}5I!iZYF}}*- zEW&k6?rO-oRS(}!G@wNkC3@e`5dO8b6NWsrDE=%@$=*Un9^%C_t3JkcBk|4dMK%Ft zI6h^JM>#G4@-gJq=tx({>N0PYc)K)bSR@@-9%f0QH7AEGz!v8!nc-4ujxE`_TSm3* zIaJ~h-GaWkIVmJMbc_lx7eg*s@8IKk*WN4NB#{LE!f|m=zlf#MHeaAjEKSxhBzsYs zaSkn{VaflYk2_*m%(d%NcK(85YV|-?>_O%yyFvA6Y^Y3x>NH|2D22HNuh@G%5i%nz zboI0^&47)l!Q;)mq-5n&SsLF&6M&x~D|DxtzRvCLS_I4djw0qd1bRL?8j+k^_r z9ZDKNEL#R6RENFrLE)gJ(%~bf%!JMI6`2hnH`kBqQwj1Dd_?=d0$NI34y6XVjN+4+ zG!PYfte31t>)vE+D15;Xhrq&!@e7PFE%r8(N&W*wWO(jhjDZ|zX z(O@DF<$7!WK%BExp9LnF|A(=6Y7!-2(=E%pY}>Z&+GX3eZQHhMmu=g&ZQHI>U!RDH z>6yOhKaf`$nXlHfAV=i*LZrA#ijr5UXn3~4V&WuJXh2-O2&;;P1DnWuIZ!d#7v6>M zZoD^f@wH~$qr)S_j}ZL~%58!BclXaeRUI(cOwMNY8C30htu5`YIP5!Jy#ve3I4c#* zmu(fKrWTQW- z_;Se#-~FfamHo2_v9K=GRI9E?`El>-v-e8Z)8A3_bLafM=j6uj>lP|c*ZM|hY_aIGD1V3o)iE^g zDUF<} z%B_vx#D#rQuBt#KW0vuc)J5lC#6-lZy7Wec>+SKFw~B?yJ!RXkJ%TpNGb||k6O>YF zbY>Z&GGW5V`2HOG3VNAr2M$ig(p4$6pJloNQnlk>b;lLu`zoc2g0bAnwVfa`55r8r zK6W0jvaQ_0Ryn*q3^}!h&=8~g?JYFXB7($im-gq;!H8*V zs&k3*%}%F5Pg}mN&1ojq`*FziNl4QCgH2dP#MmeuvP~(vgc5DkmfR!XG!{bBNVnb= zhJaV>;i?H2;~%A$U1QWj-r_u-{HSsRC7>?#N09XA&(GtGfj_er`1JMfbQN!+-2X!Z z{J+d5VB%o-@A?RB&Df1r6rY!xSx5h+Tf%KWe7~!@7Vp)94V=80GaFVhf9dwKOQ9cc zf&1IIB;oM(RVD$X-msB+H;&XBEsB;Xtd|-B81rt+L_P|F_P4i|ftx=P&K1JIKMXP* zDRR}AHbyImW5T}m7;#@H${b*Qc8uw(qG_xX{oW_lG^c z&|i7P_v6AtDxZ&!&332z>)z+D$&1-`CkJ;XbYWp{Z=EHHO|}QORF~S?X&@-S(*6DF zHUypqd`?twDH(nWf}y|XF&y3+oFNFl3Vd$9n?P6>oC~2}W^3d4OgD65VUb$uO}!MS z51lWt8@>P!ZAy%VK*{o_$L|Im)KD8d8AJu;x(l9in*JK$I5`OYd_@4XvxQEaoUa`X zX^-i6gkjJdby$a|`>VS9z31wsv7ck)tlj`N5223kMg5Oq@C`yMbTa~j>XcqmV{-p+g#+wA6bk#K73On%aie#&&nOcX!=)oS1j&c z$L5YG#3&hXdZJxbpsJhi-AnM@7P{(YWCz@FVFpq;m*5b?TFqm<)eoytM!Vo?3eVeJN%8~Lt3%1z$!YxJ){nwe zn8Da>uf7z5RG<{}yh4CBgrGR4=`%Z`ec_?$vWzv3PFD>ELSX%2v$Bz4@D%7$W15js z89QpK$Vdv{pUlJ)xmy6K{dkZz(6!N7=J8MFB~BVm>##$LCkr_xL|BF4cE8KM_KPs` z@ElHvGf(R-9=8nc{cYfRsRsqFY&f%!QzR$1q!n%-UCCSCVfo4)x{grkdKRt~K}qtC z>LRH^?y>{Dl7uh-)wv_quG&lrzFtSRCIQIq5=1`DN?bgOwS!6anYk3>XO~H;q=oITn9Z{J{On2{gnv?) zQ)Y1yVQWebwP`UbC|XKov>G7TO*JJFT-*_a@Kn~Z=8Ri8$x-QU`NS9tI`Eeaa$aBr z!N^s4{hAz2qvIGVf$_$C#Wy84h`MKa6!hPtT4iJy+<~9A4p>L3@Y`BB%T^PO_!G{N4UOkia*f{zYx>_<#?i&rQYjKJaX0S zOIvS)815z%oW!WKgk6A6@%%%9dto z#Lk-RRl*Ftp9^<}Isa22t)euk%#*6b{>TnhWzf|{Q1?j3+yBAsh~VfUez8?D@GLIa zK)DBPlS}pWN`F$dV_5cg?RCzU`(x4AT|ngV7OGf3K<`q?Ropb}&G^n`^mK(EQdQwd z&!BqJsvK|-#d$$sr zLchDRy)+X2k$FN$b{blfFI*XC{3TF9Az#hf4PBD>g>iFYwT-rGeMthj)Kj3NVuwIg zEXkba*sK$1SZ$EM9Gb=8c1$t#z{`^3HnDZuR2k8M%JCcpHs9T=p)O(x{vp{_ObK(n zhzjFVq{b?pTmw@@*-HNLl%1M4K1E;MOe9csDNWpdB&C=mUr(Ajs=Pkc1Tyh>4_lo+ z$u!u%<<)G9xN_{>*(Q_h0cCK^+39i_ZI2KUWFeY;q*cGcbt5n$v;Q7un?r;%)_I?v zlN79N_JAY$;ly8cG0=o#v!{bnQ->Mu5^w1Hsqvdsn)aenmMwn0eDpp zX|`%EF(nM8Q~#nDHKAibq*~cL_!K-N>YzA=$wMM5jz%z5!A11;jp+T!*+Bg%m0MJm zW#L&*#aJNoDs;w7{2D1qN%HxRp)`#q>GfHHR~FG;5a33oyZ4`g-sX+=bQUWV3O18E zr)xA(^;R1VU8YGm0xC08KV7Cz6|MLrhFlQ!1Yrh=@m+g%s+Qp^x|ys|QjE?9YxBPu z%v(cj!!f|DNqi!2%GR*ZC&3JGX`WM1)~00t<t9nYmSFi54v(*Q5!EcD8r5G=ROJCe3J zUH1Ty0buvkQ=-KpgjZs`0KZc8!?e4{u&9yTViVd2}T-G z&(f6m_|W_M2ZadBr0~nI$Pa>)NWR82<$c`PBxu;US@z~eC6&f&h<`Ne8Cl=;I<&v= zpI9ms#6VD%bP;?4hd-ig6CG*)Z82jSw|qQBU3Qc5n!xXi+O^lsevOdmeUH8FY7(Li zg27$8^f%x2zSX1v9iyvpp2cN;+R9*M2@mCBFv!m6QknN;=ZiZ=)_wo`O zqU}(acNrvng4%>q**EHKvED+8PyAE$7@@!b6*q{PK?aVA6ute>!*3vuTyQ_(hnkrf zt&oliU#hwPBAMQpS5@~i;B?R0qaWtP#{Wh#vd5XPd5o7GFIN%KEJ2e;!|@kcRuUr1tF-LBqnH- zl(F+_Cyydngd|3aqp{8hc{r4=_zt^gfpqf&&bcQ{W86@74x9Kn;@$aDOi#j0m*I{~ z`>jww@6Rf3p)06G*>qC2%ECcz->D+OlO_oR6p&{t0EpE;Nf7+`ShH}4=q6VVh?|2q z2S(Hbz=K)azUByU4ZNyO<;>7K@f4yid=+T2=N8%&TFsqDw4G4f>oNj@g(5V&y7KCKAuU!kgn||33oS7mO{LkHSw|GqqOOs4$;56 zFi}jIss>e-v#O?mNHqfOhKg+qo|0;NXiS5L=tZjO0dJkdzYo+0UgGD&=MdhU*(J-m zeM4?x4n^E1i&`no83!~{EA=w(HO)ZjQMKig}-7#MR)V^L2y8|js{z-j8c z3n1Ka)EaQ)4D`BG#?AXIVC46`ppw9yeqSBguQw6o9Y7ojrFOt0w10zUe-vgv8YQf~ zYF5RfZa9X(>hnV)j?MhBu>0GhtsGI+Q_kQ9<87IumYNpK3?x5 z#^c1x{m(3mHHDk|UyT4@;T6$MKvrdMJ2U@T9?C3`C|~EwTO2SZpVJ`01>TJ+lO4s0 z_kI6~Hw);iDnvYbY)tB-h(Th^bjRaabfFS6Xm*%>6k&_YB>i~X;?``$9(H}|x)%+8DCsTehb4OL6IurQEx|W=t znV@O5B5ZA(upvxD++^bmMD#Z_Vk?AU48UKaFRjC;LvA&Gj)R^swOlDd4#F~JnpJ@f zHgDz*0ScY&6g(cOzh_3Jy-MqJ9_((H6#po(mIx^YiJ7L%4xqrG%z$c1Bx6R3N8L+H zXNqxAC8DfR-(=U1Ry$@}B6$@fXE4QIa5@}QdpmB;^dR*lwx|1nPxR$+$G688_xt&JU_|yNhtKDGk^A#;gfDk1^glsv zsV}5DjUC0&z9>1=A*e^=2;mRNCD3mA7mW1y5`2}o3bgVD009axBP zH+#z44DIK+`+Tg(0C^9kSSBx+BtvFsa6ccb^wgC;7Mp> zp|SqpZVbVXgDQjt&q2_K;nLw}asf>&Nis0A>44DQPVVAEngg7bwbIIGlQqVEiWwVP zjL&-w_i-S}U*d_@<4E*>XvzP#$T)GDw_H6xm{?7M&yWgKWPMv^lSFH(|nEK7v(Y`bq5q5pDA0iD=55-}_mU4YE zenJEg{(dR%c(-ioqLhQ&qN4g6&Iqsxln2NUQj3{}iH*JjnWlmF$Enh8dsG6X7E8~< z$P}O!z|X^As+ves4*_6A6=L#o^93hbStjZ1iy^D(=ZAhTYJX$y9u*x(-iTr4+a7Y- z(}qQ+9!w%cY*keC28ld<9r@_U;pDs5p+@nxy4IPCkr@QHZs`*Nzm_9ozOM1f3TEu{ zUn*Fv^KoI?L^Ey*cx{XKv9yZE6@_bD@l4u+g@La7RjdknPshUr2m^@aq7x84Hgh#i zJk56L7KmQei{cfF7{|*Wv(gi_QI+Vwesgg#UC!xMn-Kl-!bgL9nA(HRzLs1#d`;T$ z_ez|@uzYIE?N4(VWBM%!wpw^JH%fn1GA)|iK-?->wLX}b-IkXd3Lk$|v(10=+5H#| z-y94~jV6Mzk!GF-U2t7i3u8neocRQ#TBEt+mO`p<(E#O!uM}4kbtds;!nTLY^yACR zZ(F{J)7~(zPbm{-Pt_stBWkAyHOZE@GPF+xNTROJ21F2Zmr^9+6OIp zwUehm%`-MbwaUe}&Iu9laqX_AScO#*HTf%ji)ScIn3v93BqvMrTyn+6qJTnlRQTy^ z=_6}EvvHlqEx#SB@iT1Ru@hv3wj)I+7J@SvXZ)|ZxFab&QhE%=un84DzdcMcMX80``y91$F6Y=V~yJf}*h51^J-JMoRgM)U@O-{bd4;&wlTc4m? zx}2lmHm^bG!n4mx6-l2TSwl+BUSa<6!NXT@jfjn*?98B^!ZkoOP+o{QWJfApit@}) zs8s(^g^G4wHp+D-|M*$D1uwTVopJMM8}a)O=;J<=`5ei^oQqFwq(Ku zG?QOc@odmWtYWFzB2&P1OjoL{MRxuycJ; z0~rnOx#5JxOL!8E^MH|#{VlJ> z-0Env&MmQ@(26N57N{^>hn9`XhKATi1KNCZQ=AOI9~Se4u(kWkOTO={ev1nc5ujda zOyyw=R1a$tG+^Gh!mx~!?N3JkexHkA0U*2lSM?QDG#vee%&^}~0D^?! zML%#7uk2x!}1DC`_9i?(&7gke0 z*#)EMG{Y38RXM0qYzR`CgJS^GtKLM+&5jto>Gj0*!z#4EVRwsYH*>o}$HX0PBy{EK zkP@)s`dxKH697JHkt;56(Us33MDhvyOcma&wDR-&immw>#Yu;5y_lkR7`+%Lq@$R* z(Gvh-cl;(AD&4bWwPRSh-V*>B?MH1)-0JcJSelj4z1eq{%k1nk2cfJMS;1`0Y7qF^ zte7{*scZDslJJIHJ(tk3s8fI0+eCyk*zWGrN$bmDnBo(Vr`c6*0wep?#el6+wnp`( z8(pv`*!l%34foI15($AH^N7SMLia8yBH7t}R|aVXsq9I2)k580!Aocno#u13PcByJP6(Ae-DAhkqZvrd^q^-}i<~ z8IRS2&kU(|-{>deQbb{;vuW7ocQlndjVqBv9wApr>^`?Afo!~^eO-_$xilRKw2nAb zD7@uZ-Kr9?%R6NCUjVlHn4DB<-u}W7!GI*#tbO0wi_Bd|N5>zJ2vfr8#tHfMQ_i8_ zf)cbURjHDp%bwRk-je(i=Etm%oQ2sJNujW3J4^*NaE!NpYM7}!C;dHp%!oJB@xR!) z1$6A$QRHnS=XHvaTAU~Y$Fm^lJaYs0^Q!oAc6)?BfQ7{Jij?AQ3X|H|@>g0o{pVLScGHhH zg9i(@GjToO3k&D_^?6p3da~o|bM{|Lg2&X67-!p^nAnnmS0}etXq?oog_=LO=*QVt zLCR82vOPH4^uvdb9veJg7j`~^D&TWaC1igilC`qY8!{NU7)?kFpC{8Y>FuPT(SGiK zTv8Y;(H(_eCm+?>-m}|SHn==>+S2bN4%E+eI55;?K(YW*l=Lasg0s5*g8< zP^YT|Ap+XYldejka8{$>s1_XX*fZXYO z*WB44{S5PP&DtIgF=BdUq>qcGs5n?ce2kuZ?@QzdwJf76C>&-H=C}Dl*!L=;%U{*BdEy;iW{-5n`=uO3eQNuX;sb6HA7P+m=8!oE)g; z2sR5gyjpt>6}3jF6^JL}$2B#mhMwQ`>KkbvAylk%3X|S?9(=T2iI~b3f6Ew-PDDCV z>!4uAia28!H}Vkp`kvyosS(FuB8_sZ;WK@sDWHq{RWV2p;;#S((>Ow`80N`xU)xwx zvbPiKnJeHM<@X6+HKv95&Ri(-lw}Eyl;eXTAt*efV%J`8gQq}>`EA?>Jd81~|0NfM zz~c+He0Xs?TB2Aha}qGD$&;7SX=G%uFP}>WM~q)-aUiI1CR9tu=YE`>K^bKZ9hlBP zX_f<8NA6)j2zC&o4n*id8!^3Bc}YZ*fVH7kZ30x~tn0k*@wnVY<-c}L%Th&bj7(MW z65kMDdL1l&M5QCvth2E`VGPs^E^*C%p)~$OR`SQiyxijIju9{+kwzrHc6I&17^tow zI@?~sg~kt%8GD`DqC7R$BdL{7Sz(_#6E`7tPC`p31qGHSV6e=0rsE8l_-$!~D~@m_;Qf5s zKyWlB$}I*58lHlsq=KE4k_&}9Nzt-XWi!?|)ys0m!}Zv7qFKL0VB1v@4wJHc)7vgR zG7h~{*Eqs0LvoXwj(TY9l(l-gcs9);rl~_0tIuLiU)``v9scdox`_NHjds1{z>|P< z$ElljN1AGaR@zE)q`Pr;IHBmLuM*Q?bd{yR?vF{x2_)0v(s90PdVa>lFW##)G3mD zax{#nz^=)F{NRpSy`V4hwkt7of@0_5LM1M*e#og9^pMBOtKbOW-$?Cvwqio72_Yy%kjg3@i##+`b8&OcYn z5;-H(FKf#51X>?XGV`TzDo`0-WR)q^+Tue-bX(NB21tF+$mMRBrHr+R5B2lvChL$< zXFiK$#;kdrGG@WGA#(VKKxeAEY$nUB;M##0nJ!SmozR@Lk*EC^kpboa`6a9_#+BdG zp1LbdZ!F#+24hSWx#NsV4Z~x79fMtyLTi#lvMr8Uq={0;;-wyoNsz@$uhB|h+R6t{ z{n|C#x4FqIBp*%6LER#ek>y0GI}}t_KeZswOUmBRBj28E+-O1#qmpf!t7`6M2V+EZEh#`c?~B@ti#B}HddF; zc!hCqw-$wnJT2U=tKs7+U_(}-lBXUAZ|ic8?setZ_d5*@>^fOzwU6mpP@3_7j}gn` zWgZPqAUKZTaJpbRYPyU)#&G|>K7;2cWD+RHwH;afaX`=P3kvynuKeA+}X6lB_g^MJMyszEHf~YD@5}b zqIKJMun%-nu-q}H5@Xyqg;|UdcHys$V;DC%Rd_=S2p(#pEFos3UsunZoResAq)#D! zyS?7s9`$n4c(8oQg#K*7n7_ZtI^RA@;@s6#%yxcC_{CM5je!u$x2HdXKWCK z*J>}1l59M3tH67BVcX`_Rfs_-2VY|9hkzaUg}n|c&vvW0v8#|)j!OJaju^OUIsawh z0L;WvY9zK*38>Ixk9Kh$;4TcbB_N~1Ugu@i@kCX!nGr1=Vdqvtf97r>vn2o1p zma^b65B)02a55wKC9uiWDP)tU<8H z=pb89E^pGHN?sv5DTjsKD&(fiOXlf;&MGKn-hj%lfPyXvQG+7jEpH8=K^s{(h9bf; zDoMlS)t_k@g5uS(P32hX!6=6gy=cTv8r z`RUVqT$2qC3`Jy6)P3J??J8z|*vAM{^odj-U;Ar>RVvn9nwBECfT_-?)7@qRjayk@xaeVshsuDslIf4uIs-0->R`n=sv9nr<& zoOQojxOHZQq%I6JoRZ(@_;Aa^(O*f8R5rJJz8yW15CpC8>N?Z?aPo99tHc$uE&FFw z4T9BuF1Oa?TiNSweoH(rMg>V<)cGSBkPsY)%e@JQVSqCvz)M2ZfdFD?7LT%mH(doI zY!0BSvf}a@0H{zwV1er=$n1e)gAk}78K8K5GLhzNnZCm&BKw#0+Uxzvu{W0Fjxh<6 z2aW;G|I4K|lAG>9tiMKP05%iTKsK(&DEI|Mu9UTWlB#w!=Iq%6j?>v_zQmgf zmfk~((So*t$1DHK3{vL+eHyO_L=ep*^rK%y0Cd5Y&N4Q4g>SP*Gu_wZ;(UN3w15t4 zc;2atkTX9C*xfeoNZRtm*n8O!nkzM--peV=aZMMJF(;GK!TC2!R9X{&Kb1|I?_ef) zb2MZk!zM@QMTTzk$|KK2#)m07wx{E2{mW;Tw=jic&H`U3gQzJ`3umHg!! z#_hOhPcR9Dec+n(bc-z_O$BMOjke+#V6N4B=AfntmW80z*q4PTg9EhKwwcSh0B~!9 zXorTq(#q~pm=~$6t`3gz(?hYa>w`+$jr$3&WyG+`J}bdq*?Hn6vdA8{K?zk%<7VMZ zrG=n%$XS%18%0UV-J%DR+be4Ka_LF|0Z58O{9P7I77)q!Iy690K!py?4+^OjaEi9= zx;XL3&XWpn4HwfYB|geG`$M|S?_)gpm)y%2t=rcf`UVjHs$DyFhn_j-f!Z^_l9 zKRn<%1AisF8z(WRJjBgLkg3$5_Z*3_%raRR@;=-IK9WSddf`dy&eSs>*&9PFlG}6+ zD(i&ZIFD+AwYdi^4P9B(et0;C+$bZkHh(k1qg^oWY~;`l22eX`fozy3$6F{%0C&`~ z!R-+0;(Nr$ljwW<)1SNwasyf2Fw88PFwV1OJx8678$xn(L)x0Y<%@9TaeU`xQIn-m zKyiTvQi`02^c9jrj6$x79~_pPn4{{2@>{ODacevZaJ7+-;9l#QJ1ZJfKmkc$Ue;am z-t|z29vL4Q0w=$akUrG4KKVlhJ+aY+_jQdnI1g{+&Wigkz}#TxnB>D`L|Q{bQEEfH z@!h#qcR=|&%7PjPF*Ou|B-F_}%0R{}@JWzN^gOKgRke2zNF7ms&$b-kK^cn;%L*w0 z`>ewvA9o>q&d$Rg>UyCCB9}zk2qErd_8s)onW|jz z_PavhnbB+=-78Cw+Rp>*Asc1uUP$9)-zC(-Y85Kq>lSz+V}3xV~0$W+^_TT@bf zxXVFSo&><{h-gZa6R%Ss-x8;;5Z87UowmBHuGVq+jaLFCucXcd74A}GX<9KF!Pzx)asC1Hud63p)HwGx0RJ%?R+-p~`3ThVOE zJ@sLBlZ8us1<=*2`zJm-ipLDe5uLg;gHaoRe6XdAuA?Oi*I^D6P1J?JYmkPC!a=1S zv2vo2UiO}T0EuEQ*t42r7wZgh<4Mw3mN~oe;*gg7)aBWn2`BwAq#M7+k2nhR&`@OE z9pa~^p{|J84Mq_gsBhU0tUulG5A_?c5adN~(w(8KgrHr80v^56FH(iy`})d*U@DA? zfdVGd5RtYbWW;|)iq5}!zng57js4Q#{~~tJZ1W?T!Mui~L}~8PS4zA;A`n zO~zW0U#cTuFM-kF0;`&`=2RQbakJ^Tld0i5Q|vZ*-bnUX+pjfWF0Ym=xEIu5&S6dh zL`lFpm%wFZMjDJd4!yU-oaXP&48gJq%(6fnOEN=F!7-lsHk~#3oFxA)C~7meQP4X4 zKr8$h-bbtCk+6z*n6H$!4s&)%kO1kndCLH>s+%Ic58ygHf14nT!XbOg2G^QEliC)O z@6g{Ul>TDEb<%~1$vH;&uT{FesilU|L4cQI<~T;ZaW~8p%pASMN*x-elbO5ZjooS{ zWQ5i<*|a&UIt)W5Sysm-roVV_u<9&;$eDBzI<(JolvDMjY>gUVXVLYz?#7F%=9i2M z%z2pfJ?8P$yhm^Bd*E$}+}3%+^)YMi&G)AtsK`aLcVy7;VjYfF*5vA z-1a&AS2p5kG)M+o+a6k6Ek&~OsHGS!K~cvJcEA(?t0t5rdX>EpSLA4$;%Y2X4Py$* zAaMq+DFj7pJnaAsMzpSMiDq2og<~%=O$Z-EMy=JA`mn;^h4XwnrL(k@EOc1xQJiwE zet4VeS3rZnz)G1+1qa?NK53YW7HlGIow@@>c{{c+jKXfXd$P>CqE7q={M?Oz^kFY2 zxeFTy%To_X7~y^HfS|^0`_clCnSZZ=kNdd2P*qO>9V!t{Ki~l(P>2%@ouap)tb-fF z>4^duq*R2kc-|2+Laq@SHc)`%P42=`W1w#fyn0`Jbdw`eFAYI!K|~PQqht>sy^@&j zP7(R|>Nn#3Fn-*Il+QL3XB}b@mH=&Rd>nxbbIaSWjPqJNq++EiH@Ar*xS1IW4lo7% zx#<>WKGCxO^%K#0u6kC$DuV^SjO(Wpd`7uZqfls7b;z4-FJ}fbOu7M#v3X1gGO@1~ zBX$>x{}>}n!-?dC1cN>?--~@FOM?p~u;eGT?x1-eC8rz)W40VSIeRP@S5uw@U$&R#CTe zO6EhRsnBYxP{H;32X_Gh4_MTkJc-!Er&anpP`%qYhsn?1cGKbz_b#crf$^`Sto^{iC!k$ zszn%FNtmP;@A-~iP72CN1yfd_CDTts0`>alP?~k~=T0JiOL|<8V%a?)irNxoNQkOW zVqi8Y5W@aaG(LTLsnohYWW&kA4X;QNryP0%G*;_wcP_I^9I!pS+pwT3eU18UNGey0 zSS_A^lLacPR6UR@3VA%AU|^zc!HSt-L3?rcBt;#q*t#Yx_d&%<^1A4Cxvj9A#c1tg zW17^8vpGoH)){u3`jAK{sj`0?7iC5m=I{a+KiY?sH@{T_H|AJo-HVoK1;H1+Y1t3q z?6{3Q`FB3JADO6~&&YAT@C@k~*$tv;RxZOl)Q9m`81cKUYxF{K@x-{oeu8z?MO9|8 zSZI;5NxkLniJUvJIlf&~r{^^S$+%vNFnS_9q^eDbmpqhsD;jgKj)Szc)k|hmm zQP$+HDAo=^ODcL>yY4n2`H?ewtzK2nbQXrRsVuhq%;?)G6=DGVrmx|sMkUUWinx`g zZQm*V>dQF}gUzl}60ME(HoYt;!)rwbDAvIZQ@KC*7@FcDfw*OqOwl^6u3 zcu@@sJM=c|eC&aF1NG!Yj?`BtNZTrIt0yRUw_s9sQ(K#~Y}(n>+|c6tT|MHSm3t(; z)BVr=2J>FBIw4%obSu3r7a^_Dk#I?~A?W+8#Y7&SY-}>p^#?Bew4HD*`ew0RxP(1%$C>^9v=2~1I? zSAt^Y>fYB>$l|nScB#fmf%u=QmKh!CL{KHbL@mUls~|`en2vHkjH_cWx}VN`=`@Gr zvCO0niEI%J3p{673eNLe_wMOq{b4^T&J(X9=PGx9H&<*+!>!vo=V@lh*d>FFY&}Zq zFKKSHAA#SLYxqeIC8fPzLs}pg%BtlZ&p2mU2in3_fvT5xlJ@Pc zs(iQE`*uZi9m}<$))VG61Vg6G31(zEqwSD)i<$l9;(>KblXl&R29;4=RY3lPRKiM| z*@R=;0Kt35*LMfii-t90mB?NiI^wkQNJLogk{PvT#heivvv8OF52`uyCW_95kZI&o z%+x{ZAEhE{It$yf@D`0^PLrgA@%$oq1lzJttHyT0jGVq-eP~&>*%6D%3tXc0O&dK` zN8Xf;#n;+f`id&H__7ls(u~>zM?xoU!lv}w8q9DFPeP;SyH!%&G}Sh7g4X`(4Lxi` zi%Issnaaf*cx*#Up~Xz6e3gyC?Vvl+X*ATf@Lhvb-2FFN)wk{PFzekHY0F~=g7;1p z6SSC>%VJ42CgIi!;AL>yl+;h$O+)H(_vGp8zO8+BnHC2&0UzPf0d^w}Q0*RSH^7=J zw1T3xkSMG%RUgk^^XEml)A-h&RdO!(qW4=%nE9vT;9f~l56|c0)X}5e_wC&Y-p(r@ z-{<}BiO<#ViO+FK?oQX+>%)iZ)_`lz*TcV$quibDx4o;-PdcQDm;{}%yBf00F`fk+ zvOaH5Btp-Ls6{R3LeIB+EWFWW;A7m{ZOZZ}qcFCRgA~T-KZk8~$abamq1IP-s~-QF z+>!c@k2m>dd2oa%iWh(tAeG{X$yA~w=-5@qmm=KkHkb}-%t0s+AmI-uHU1$66a=?D zVjp%PFN+Z_055wC82;b9i4qT0^JD#zfuXOC?*eEwEsvYL^~r(?v}?uskV@_j{}Pf z+1gf|N~CXk)D8JM@@H&L8?fFl|AX8_)j6{fOAif3g7yHShU_AT~%;$swl zO#VMiCjPgv6Z9PaeKMi76}#CAd6U&X zpH^)(D5(=s<++BO7OU(HtnY`=!+&;a{b(^7pG>eHeG+p0Ur)~mfS+*R?}kXMxH^EUh-sIAl|Z#PerJGD(Rf!qhW8+P(0K$ZAS4cO!V$x^n~-OOIas^ z6G1myt@OEfczn}ybup|U+xR{w!yf6@`wz|!udxGf_J4_>oo2zAAb61eQl+I#&-4*TV6_Wv_x>YjI3U^Eex0_>r4K}c8_P~)V*sI3km01QIA z#H~=#Hu)%3n_kaqeApO!AuF0qDq9NGy*)fV*Pw|PY_Wq>IOKzM<f>DT%9fON*2Xg;i^BBa<$(Ti>^6Qk^&=U# zXwwX2t>eFS-cYU9xQ9AGx0-rHQ@dF(-H;j-IDv%1dLtfJEI!duTT}+Y+mJ7Ue#-Bg2lKO|%ug*$Vo zRao6sb(}>yqpqec$5I{;zR&q;=70@tJxIe8*lch3vTe z$)H7C#R+#F(; zhD}3qBVR5C*U?S|5rXrnAqA4N^jNu$wTz6WCP{aPbM&jjuADewwen}`T}t+y^0Fr?zQ48oi#&Qb zV>%$ky*=R1k`)7!==cV`FYC}X%8Qkp4bh0&INb*h&!M$|X?)D5HEBdK$yP(lRf2XR zVvvO!7#pgRtJLN~Vqaq`GKOCS-^@h2uO34_C~I^ekL&MI%cRI$pWc(&#M|Qr6V_vL zBMB%hun) zQ)X<;^J*$VY(ZSI8;nqk5o?p%plIY3sU(}(AT_U8?*wauO!&8!r4fcf{+dWzk%W+fX94V3pSH|a0AiG0QWX``^s6Z2|GO+10 z*s#xJtqzWx-BxNOy6W3o1o;9BaOUfoYN$G=PF%A08qHe~Hs+T1Ohq!a{8W&z3^Yje zRT?)aK|PGqZGzjhQug3E#JmtE92Os_t?3BI#)C~zBNQKbnFefNhQP{RCS#GyrTtlu z!tN-%4(l2}{ByK?35uf5{!O$vBJfmdr$}no?Pgm7)0+XolHr5n^mHr2=4MnM2sBs{ zIZ2N&eeYSc7eh5tpdYf!Wssc@NA7OCBd~gG9!kkM)3RtE7X-}}sW2rrmk2@AJ($x& z`DJ0FT^2o$K&&vcUM=jum{-WZz1MmpCR1OrG zZ1$$YL=WDLkAU4HHL693P{n81l5L=gSWRCcbONGDT#!TH1)wT6S@I-6XP=qo|3{n|lv15qf~5z+G2R9OP2FSMIi5UOw5#e_kl8^1+H=86f?Nd=i~iql^f7 zVraKGUX?|YmzsRuMEiDEWfb_~(pmSS!t!Wiajx9gKRW;%4pl$Q69KswSu9{t)Ml@u z?F{(Kr0M52M57yq0@{!?chpbkf^x>}&5}?!q+||L@xkk`l?s+_L4+-_($!M7$eqy; zo}?<8)P**RCUSJzOKhRmZjuq2)i7_Cp`IZCRjejiz-B)q(@pTw!&W7LJdoVsTSiDrHJ{>EtbZ&>#r1C|FS?11DqmG!CRM*pOa8L8kEnrj$tAn=JL_b_Gl zkFCZ1^D6&r#Hgjd2(o&z=xFN7Va9vWid_WoQ_=c6vR6Lr$@ws=`ncem2H?XMEU1S> zB4eo6q_GmHl)LBzO|Y(NmNQU@^=Y~jSlT{<;TO{$NLKP8Spk)s5#*&-F9)YHyu9v~x&d`PECFFV}WeLx3{Y9T=cC1OTmjQ&7lw~y}|{`%SNs7^uk!>H zCp;7;#4Z=7>!}Yf*uLl3nnP~F`tFOelCFX7#6@tyj;$^^+>9e#;kN=V9oXhE#1*CR zqo71OZ5o7^*yiem4FuY zxGCpuxx>8kp`xaINUf_vY2}P^94?1X;KVMVTA8Qe^$VnK>;%<0qNm1issV?q7mJMak`5Wk6N6Hdycm!+`rG9TDf?6d|$7m-B?Zz zdVb!j+dd{TU+{Rl+`n(%6dhkCZhU>8b-(YnGIe)&mTa$*U;W4b#XJG+C)$?4QPd)kQ-p}eU}CcZwQN0+di0>W#6X(WApi<5IncHxBGeUbvcFkzJ9)?tsTAE${xS19KhT27n zg+RlmpAOoeuhPEipXCl8Mgq?EIV&{A0l&p8VW6Kd2)35?e}~sCE^1fzeQE1{`uRWK z-tHckjlMmeSGk{W*IJivcc0cStG3nDvK5+X*!QW}sAMd5ip6!-v~5={0|ExmWqUrm z&f1`$rg7|2>`ZCLoB8NiCrLC;dGwOTSp(DnVgL(J25^D4C+6fH-@qk6CkR88qs_VH=2HHFgJL!PF_Wpwc3;(hJb!mU~`p zwPd_hRh3^lH@y$6(FL{DdL(-tzx!}HW;w>9dHWAGi}app5p{-H692CX9ov(s@=#nL zjBj3E1#-kL0$??ht9$6B%g{z)x%ukZRu7Vlg03ErPr+JpZ*twedP!T$H!*;VmUyO# zP|xm5Q1MG=_7Exl+C$5J!y^tW>C6%#L6M-HDbtFo(w(<|2M)*KShH)0tL*|D&G?bU zfoyb{T3uE4F&|<@RaJi2PhmMGFP6B{x;*z0u!dGc^!@NyzL!wP#;=_RT14d-$Fv-k z&Jz1c%&~{;I%Z29g;azKcqrbYW^z89RIr<*b&-cIif^oV<}hY!ftfrWs)honv0koc z*ZFmsX{+jPGter_3dSa_keMm7GFy!hjXo!1*=>yFu&s1K9+uNdd)B2-8vUxw81)`k zS~Buw4q1Ow?Yx=rVVehL>;~#zhBzEp@KhZf0NJ)~%9Pgb_PtHgG_(=D4omyRVFh*RUbM2jH0c8%P*E5rl?BotS!vOGrZRv7m{#P3OFaP(KvAD&awc6| z$KR1a5;z6MoC1m=B+!^Xd#Y%h>2VfkPjCm00!zO8>rKa9( z6K1w`ZO=4Et0;@{Y{dg0KTxr5Pxyd6rlBVyZ1{mWK-5L$Ho!yxGpe$jj_im)Ith8i z6j#W^0n9hb2PNWLf=pFecS`uUq)pU?&q!hz{GxuUB73)Ppbn)~TM@%51nIc;Bx(5e z5aZqCY_F1F`X=GgQaT|0dXxi|QQsJ;`o&4B00!MI$K@^|a#=EWG~K214SOe*;-p1D zec4{%UB|(I6*~Uq9yK&I5j+6G5>iY?iLhXCm1U99xr+>9O4bRJi+`w~$)Zc{M@zY9WAN*I4I8p6I(%ZV2o zEY$-dK=?U8mfiKm3Hk{?eb_Kn1sESNJxoKIY5)-soXetEC^Bm2y?tCRMYaeeP&den zsEofBHa}&rk+tdHxbD3#YZCW1RP+SdpO&Q?Z?;vPQkmP>#tt>T+;8T`Eo&E=I<)@^ zNm!H!`}bB8CyI9KXiRkUv(f`0-zn~0Ua{wRqvUr@u>(~>PM-4$W3nNCnj1a6=hGFL zF0Y$kM$V~BJVNttCw{p1#0|QN@?|Pu0jE6DW9fR6yyEip4uHUU(skAIVm!3fFb*fr z_x#F%G5K#hUELad{660fth~3?ujd(C-^bCZWqWt_`0cCfv#NOh zZ?9(kFRvf`=M#}1p~Mm_Hd%Oh+QWvI9tlTLW!71o9InMVdfWsnW{n-R*= zFdX*Wv=cdq5)_bnNr4U(4u){aDaV{73E5m022Rd65Zgh_`rV87whH&%p-{o-O}bH z+ks2s)JsXI4iBdhrDTdl-HW7yfsT-$NC{m2KS&uKTLUHCIdXFO>4uH|hl8@{@SzkD zz@Avl9MoV%CV=()RoMNiVLt=4I;AL-DL4}*A50#SE?HJTG3r***&hCd>8;I5<8PRLsvU zxYIFQbPxz*-c=ctKaX;R1lRvWh+e$Nk_7zmJv;NlQwr95 zT`+v-_1l3waDJD*AHOdbQlU2)*EfM_$g@DkSw>*Z;l|0!QKUrxr4ZQ!Wy z&2Sqje1xwo-rfKEW%ro=2jO%m{d~5#iICp6=|0=z z$Gf2~_rsLEn&2Mj9Nm^1Qk3D^WF%+3#P{d#0S2V`>AA;$^YQYai!rUj45o~c&%z4u z15SVhZ~!0zA>Zo~fEvI9T0bPAkpqn7ZY@s43?{rt_A*p`F^+43OSXVDKsW(bx)mw+ zA({+El5Ne_l~h^xvgy|IyT_^*Vif)_`sp<%Iue{KtpaKK)*Gahw^ebg_h_QXd6etR zmFs{6F`ZprnD-YJD*K`OJJ1x~_JwoYwn!E9+mN7Y1WHU{lNL{sn^=Q#Mbq~tddj?( zF!gW=JhpZ=fK?2Dc_wL=W?g%W6eSZL+^ye*HHaLqC1RH6Z z>h9GlR%}p^Y6z-2)_TEM1>c)@br0Wk?jRr40eF6xo>JSUVvpz%cQa;cfC5|{&s&OgpbA9h7Bghy}L zP$m{~N^ySx3jQ_Dbb5O-98-at6;fQyveK|?+3-v(i`qxx766eaC`0k<+8Ho}5>9~x z+u;c~c3{Fux*>C_D{lF|0t!t1?c{_F;#fn5<*4v$9~8X_42H3s59w@Rh!MQ{*zjts z7M-@EwD#$X6U$k)`mI1P=g^KdS@z7vt{;iw8* zWfV%IX#FFl8_VB);9VK>Bm3KSlqkzqKEXrIfjLj$6C{G1F@$66y9z{9%_SsFhQD)Qu$L%< z*ex9JOPR&4?;J9|8aRr_72csV%B6|9Et;gt2)V?2`A?$jtcXd8$Y?y|uge!L38&~6 zu~osv2oxSP+5)3C3z1~#lg;yxM3q@jG!5?3wPI*R()i&!G?={KaT36dBL@|F8xYYK zjzL^-kCE_J&%(SF)qsq13G`WO<8``I8BFXBjQA{$M-fmp7vy>=8{X}Xtyg;R`0z29 z$udr_;oIKW$dW!-<6(KLl^h8p1tgI@0N9kk%7fFovg^GV&JL z2(pD%!k>4ytEM(#v}4FxjHD|ChxLN-vPDuY3R<{S2N?m5#_fvGh_j6H`LVB?@hCa7 z-d@*FHMp4VZLGm69D-=vu|dGQ;1Q*<+M&Eh^w*e8L{@}ekYUF|r3qg0{4T@PG;P@j zg8y5)%XdAE%6RdLMK?=BQR&u4dCJZB63s^&0Pvf6c0aViPn=luJ9e6iGeI}2Gkt`tesE8mp5R7b~OTy39`J)xdT{Eb}ZU`cgr$^k=5Y%2dq zBH22p(sy9;g`!A7F7!}po*&n`4`K-|E)err!O7ZEo;Bm(H@t^@aY-k9t4+l0@!rzh z+T^^eA0YZ?kbl|rcyE9hn!i`HFt~3*sO|g};1LOE>7dZM&Z|klb`x1_=@w2NA%zC` zu}f1)-o%HHiH6T+FpM)xUeaIGm;VKV_v8p`n0A+(pYmFDyz?StNx-QiyKFH$NV>%oSTSntk`reIYA!V4uo zLQkGZT-g%CvaVs*3NO7Pj$QLe$qM%{@AR^`8=i14dnDTO+(d+GiHs{NRhWqmY&t@Q zA8C5u%hR!5&tJ8)4@QFJWie(| zdMFQRamN0H2#ezJ&0dmk=otTyiwdI7=py|@c7Nxn3vYap1HA?cv|hsOp< z_a-w*gThY;pE*MZ3iPCT#G355)}tZhI@I16{)&KTYF*D^tn5Fb%1es~XX(Ju zFhx!zZPf9D2&^l6i)OlRy=clVvPJLU{CoSf5xxDaDYKRzKS`gwmN|gPmCkvaQx8DT z)m6!MkvR#Lps*Va48tpvPPmV)P3r<=YAQ;>OANH4ZEN(+T1tF3IwZ*yLuVc{W|GnL zgcGZST>HD|M1iW}d+QX}T#2UXq)QcKb*l4uQDigA{F5NniH2Xa1Z`CVLIq7g>3j{ct^))USH&@CJ z)^2YZrTEi{tgUZcRlJ4Ry^}1S+ELg{AB-DAe(M}w!7XguX4{?`X9hDv*JuP|*K6b5PD4uzaO={1mWwNVkWGTE(uKR$L>zre#_`#;q z59d=)|E~MN;m+^b!@bTcyk-sc3d&&V@eFM-&@Kkhkczd*{bOGpQ1aC|@Y^AKwn{Y% zMHQZLx%bUAs%aLCl3$ZWqLKJ2C$H_~RTFSkjMdN4SZL zspfslu>8@Fgx_BBLwnl||9g7%@%s0Dd#jxw%yv9`zvJ5X6Q7^|Dqo+WNlAQYl-~Vz1r_d#M4X2qs zX$+~sJ|5GK{XcEb)`ryd1);1mma*^uBL3|S!=YoCUxl4P0SQ$^u@kD7=S!;9P$J1W z!k;aMc`=}DVZmz+lx+W}?HP-GOqv@*E~pw~!vctSE58KE?znS#!a`6}r)bDcvG50g zvhFFl9!(;0zZa5%PM@?snN+yT10nq~ylvpbgFDv7u0fh!HLy3#y2h@d_u+PjSj|$% zfkt)NUG7kVWV&gqKKHKHI==@lYZ+o(ctM4x0EAVHjX) zTwa#=O3aZ$Jgmy%4uTo6UmgB9BZ!<{h-xU|+||9)Utno%q@|sX*au(tB-Wh_H}ihH z5xtg8-%Nn{kB9TCHaz3f#l}BHoe{3pZD}rWt;ZgyY#S4yZnwT z?64`S)u~djO+oJy2-|F51p0gzSG{Oc;Xn0%Uth2D@$&k9-=`Ix_eWPjQHSl=c?n^H z<)b8`8gYX=NCVL6x<=M`OS=6!g#8b%5#JAAAOoO2=ZAf)`(`GAEVNojPyj2|@vDg5 z7F+!H79K%*u~|ntHjIQkr<;WH0qKvEfRd2Z@du)Q!$;^vJ=q|Y11gY%{gSDFxeJQo zuS-Y<-Di(TlDfZt$g_j#@@E4iK*o6uAGgY`7QT+)c3yna{8W3s1h{d%XyUb_yija8 z-g z=F!hG#nL}+R?X{y(L9}J;;p03+HZ7cr!M}mZZ0!?YArsM!P>o>y-Ltq9$awntsRxuvXqqW!_k*ZZ&&D&7 zX;*w&M%V*N=8)QHZn)Fk)i9Q<1i=LJ9ty?}@<#WxMRDijj%M8=%9DPZ+n{ofjd`V` z(2nF=?jf#IuDtfy_Q(|mpsEpAxIyH^89Z!fj1ge+dQ03}yzL04esrF#VgyYcJX#qw z!`T{xh=R}rf@WF!*4TnDrjy{5mf2nj*gozEYs?ERQGYMC>E%e>u#kexuqP=ir<5e2Ji9B?U^*#Ugop7=Dil% zIe*i)WY8Ut5{H+Kb2q*)GWnZDIxo%cBA6jQ1+jbdd26i5HleqEnQ(*hf!c)nXL+W@ z^LVQ>2H~38q)bXi9uySe8uM|DCy1@gcDL+kk8@7(M9(lbO>-qX_lFs>dG{$O4rp;d zXbv-1g;6TT!BJShkI`ha=Wl@PSCaDHAsI32qC|JPO~}W5;Ns^z_x#?`?x$V;tH22J z6p0POA#-TK4(I!m{4tn zZvVfWA&HLMQeaO_F~3T|LK)R1q0o=WsbogaP>+NRLakCCp!9S&ceqgLF&t?#lA{@Q zvX_6ivSM3k+@Dk0ll{jU0(PH&FOwN=BvftLUU9R5=d_(Ehw|cpXfhb7yK-8%qa4iO zdWPb#jdn^(yrOMgh;|#`J{~T*d&T^no@aN2qd=AgP8P*^@#1n6!mqKqvb!+6ET(Ql zo?HV=QwmH`E}ni&T|_OnBOWKG4Y3yVVF68itDU{`hu5S1+M34<%%$&2HSsa@UXFnlwz@jJyoKj=hnjmW~qgrW^!@`tqnxy z`HvBW0{I6%IxW*!6)XcPGS6i6%MK(xN&V6XZ?p>yc@sJJ?@z3;sxlTVI(0hr{wrRA zB<*(?UP_B)qrr?_1u@iP+8MC}-MUYbM#KhkyW*wO!sTrIbo4(g(-W15GAvLrn)7UR zGmY^j<}NK%)(+GL4L!5$G?R&mpi{NUs=3o={GybLAv@rSm5~^3+H8;-Fq*X@=1x`< zQ&%?{#7C=Sh+)FK9}h}F<3bl2WMWK`V#|B=mT0wc)x_Ji*d!T~8cd!!zS(hPg6CMA zn|Vu+UVw5c*j^1lX7Rvy0&(B%=T}tlT{QD1;BsO?#Gs=&ycxACFw#VDyyRU6eOXC+ ztp|0$qZUaz38t6I2=hxodFbsXHDjs~wnVP6XhPXeRa2KQ`KbF1JAG2Qb2W-0G7#qP zC{0MPr6A5ibv-Hy#G2b|>YY9lSI7QoHbxn5XJeyk;AXjj>Pf2B zNd1PsD`(nahh=-sgLO`L9-8e6xYi75a5Jq}VhhY-Nu!8r0bLncIWPe#7hD6WD6b5Q zgOMzaZh$7$`t}2I1KysHz+o* zH(Xf3g@#Ed?06)xGOl5v6>R92xMN9k=CM^rJ$)Oqc#v8{n|`>ua0TwBM?N2njO>zH zSo!$^+I>tb^`9>|YB~r7eF^OHwDC(bd6w0e^Ba_^R7jFc>94QPdZC8a{TrlS z08EK_dI*AG)UD@{6{&jp2CyPb#0e3vx~q_WUT*3X7h~|k=Y4R&j&bArN_ZZBJev1q z+rN>H<90a*?exMQex5C&ACU!GT(*6gCC08mf)Vw#?)=&>e&NSX^@_FQ6H*CAUeDgA z=G9mQ1mk5-sap>=Ja--86IS2VmS>yrP>wjV=VZUz15rZOBs!7q<%-Pje`&pW>lDbt*=aJ)5b!_BDGw$?Fp@yG0EujShP?2lWWz{^_C}J2O#Af9 zNj%eT&jL7no_2f4$>+K{dpW&*eS`ol$gE7&?DJQHCh`fuGtWumTSts#ATQvM+e{G> zV)PUgzam%Pp+<60Dv+Oaytq8y$1j_&X;14=!@Ft^2{Xn@Bu__F5Z?mDvqYB;V%`2N zvS|CoX7PGnC;7W0#t=V1Pm$;2#_6}V^v@W(%DXc4Pyp||T;y5~lOPqFizP19DClgg z>M#4{cooincG8K0^R&6p514O`hs!D!OQYiUrOy^ zIY6$T zXLIhnl%?mje;BfkpHCAbqtw2xE+1!*_LkrkBO{b>H{7-u_H?-S$^sxBmy-$oGS8 z-1vNX@5|j7?(6k`zJI5GoiP{-6RbM8(Z(~|0GYr6(ugwcwUlg4!>I_h%J=-}z_J_r z2X|$6vqW7Qa}a{``B=&nigTlo0c}0SY`yXi`?&52z>&w>9aQOK`fF$F!_@P+PwHW!n}y_nRW%|#nd(s6$SIO!^YJp_Bwrfu3FaYGIRoxWCa#=!IT zd|Wu{U&NkD^^m9Ht`x~cr*>W8b4&d_ad0ckKybO%f6hM03uPy8Qk~kMiK(DJwy8>w z0W2P$Q2;g_M^{U<|BvA!@@h}h3&wO+3PZKbqp18;^b~E=a_(LIdPSZ6;VevVbG8bn zGY5xhWV(yU5}KT(kI_lEs6u6TWC2d}d%p*XeR&LKDF%ONM?*@Be zeZ;FULj4M?5s?%t5MLgfUHVu2ZWwi%-?!UWd&^zxZ3xdlPM!yPeZB70FQ--E@3TdZ zj>{2WcgJDxfw#}_I1W$AI&bod!p|?~XXFSqKo|fMIv*#t8zH)mP#PvA=RB&v@{Huu$>+G$GBkR(q+BRDzU6u{O19rJXE{sJx~Zc)@4F-wAS%}ANZuI z%v43a-QLDDWnM;Yy_5BwUE>-cu@PMC1RdC|_z49-b3;9v0mG?RxF|kU3Ye(NJ~#>Ff|Q0 z(I!lV<)S?oJQau)xip^`|4n3EaA7c~QQxOD{$=XKzzI2+jY-XT9zi@SzRSTik`?Y` z^~aBsvrj-q*_M1iSd;#G(DITmm&ul-H&mm+n#0;f)_@^%voKh^@OB6NoGFNIFa~P! zh&tVx?Ik;25$9OhX8lFZh<7j4yVD%-tZJDT?LtQYH7TwD4nt>A6v-1@{R2KPXC4q< zqi2_f`_`pozRl{@G9+G&BE~8jQ?HO-|EoP$qqV|p?Fj(0o>Yx4WIdUyIk|=HwG?$B z?G#MCQ7GF7XJ&&5F|xzCLq?0KoKhF78H)~Dy4t5ozbgzE)Dd@4VLqayoXQJg?__7t zIGNL_MfKQPOY4w}uu6_nt({+dKM`7%%}G3uW7}0BAnPznm$Y!vG*DQGJt_aQp3)(k zG~$De`7-|;(SgbU5aYjWIOV5f{pl+d^cW#eM4r>Ea$RMtEa9iMDfBs2p;HcS^Xg~5 zVf;nnIG9q|uH~69{AzgQ970TI`r{V|DJl%+idRuoOhY?~4Vxg%W*TPqKUrGB+3&yqKAC{|BRB<3G}=psw)yf!9>gQL);Kz^!=CC>;OE9EcpIM;uf1 z*5ah8(4%5$P{Ke#soM&%+N7oHfLcSPtt9sjv)YQK#<_6ipE14uF~=z4Q$ zM^1M$)q8^2{p?I_Q8{-ahwjYP#RzjAMYy3$wW@28+C4ox(E04Hd64pwxY>?&Jn)Yo z+VN|y7}~%xuq6(6Ti*a&ECJl_lOxblF4A?A5hZ2p@*EUw4d!^3pC?q~h}Utw;#(G+ zZGL(Q{9{zbN}-1}!lHJ`(3>f%03Lf5*;_^%EcPg|q5LH=%i$WN4zNv#!ptturOCHt zr8L?>IQdPfX&1EkY0xOTv3A6-kVdF0XuFI}89iqi!k>CcVujCk zcHsZ5TI^W+%Q?>y4svEkWROi1+xsTsPiDAn)WXwIU?U}mgsnY3Wjqq@R@yxVd-9YN zNEpl07E-WHf5gFeWdKp^r}NN`3Xm`k#0gTcGX$(HZnZdUZnqd`bdFvy6~S%V9S_fy z>$~H&(}+5E4%EDKqG@RrFB#}Wp^mV%_PT)PhSOW!hRPV(Hn;rTNT%BmAqY@j9csJI z;WbXC5amKHG_WZWs>Y>grhq0)s1p~y)&l_$U-hk!{Ez_<-xIaSuaJy#w;ByFBHf;N zJ|VW-^z-AvzP>ypI(Iqsw{n1f@MpTuxN15o{QSL#W>Y_SOYogQhfOdep3@4nI+j=G zh}-R9W5-N^V(8!XdX8p~b3q~ojyZSwD0KqJmr4+zIzGgk$3ZU{VXazjqWh(=yt2V3 zVfMPCC6-=Tx*{W`z0NfnmcYg_*Pw-;f6iZB3^WFk`PQC=*uq;O$)TN)^zc**Tyk+( zziJqgKKDL%eXbKSyrGAq-(48|Ju~QiA7UR}_V@PTTW;$;t8N&--^1kzYByo*-@m^) zPU-!+zFtnB-gf6VZT)Yb&h-(V2J`G|x3@P&uLmM?`w531I&uT zLQUpNaXJaCW2!;aoVzl3@YFu3c)&J8ow1qS0mh05 z9HNAVP6)OTLkdG96#^nhQj5OxXHuYL(@YF1z5Kr8giKe1XS>{0LMPtV9ydw0=Svh8CES%8hBAg1;<*0=KzE!J)LA#|0 z(ql?u=jx$-=pTVp9*gXl?pEF19pR8HH>5#_q@l3b4u-d5$RngEcfrM zGnN;f@G*_B*6*^v3A33gNc5zpl!j!?F!6sA>iBDa^wAjSKTeF)6}(ajhFn$RV3hiQ z=9e4qdB|`m_hl$_EU6lBDH#Tk_jLZu{GBkukZFA**v*OW`X8o@|7~!LmEpe!$8ShD;UzAg(SpNU!?usdSU#1{M_5$bKS4MyxZT8M-lk>{lCuB zkFOT1x(M*UZdVeo9?y4gcYpedujC4gx_|nL1wcldnempDPOnbm2Wf;L-Sd_==dZ)} zQ5+zQd7CCIG`A&VGyDF=8*6lD@gq|IB2qyziVH!MjhGA3c+NpF3Uk zHaC6Y(EH?lzU6yv>rzX-&+X-wAAA)VoS(ni^O(%xM#EM^I*T87sN*LeT`UsW7$Z{&2C@j zRyrATq4I_AfrbXJB0b0vli|@r$>AXL>PTXS0v;=+p^=tbI8My;HkwUN#Tg0bI0EG< ze8i>WO~8o>Tq#o@6A)rLt~d;p%rY%z?$Twf0{`V-YVr{`4}SQ(%UrTp9clSDZ}}?8 zwciEGRI!$+C{82!ThEkJDG8BD58aFRv}#=q)1{1}6Ov>Uv$Inty@u*=kq2+IRIVa8d>6<# zL4;esPIFB}SBN417G}KliIGQ%qZ}i)&bnXufQ10LudG%(E#u-E^78?}0kcnBPCA=( ztL@5k*z>8Mb)B?x2d?|U<#Imp#pNH3-;~K|b7E!d;z^zoIx84{#wt%(B>TA&HG*T9v#z+WvBPs8X4Tq_2!owV{^e zTxcy?r6K7mi{Y5=aB9!UVDV`bc~R$SWhB+R8mUH7>yBw_B;>{7KR2Lg_PVr2Zy!F> zC$UtoA?c0Sr#`-JVy_4rX1Pq9x|>Ye>6Gp@F?+_lf^~*u zrz;{0n!7VHaN|*uf%VMjFuTtbmfXg&rU=OVQJ$mQWUN_*ulXDnnXm?)xV zhQ?dnX2HYPvwQ7@v20xvFQ!^#pQXN?wwNoZ)TrgPf!AL--MAX3M(vEgxT<|ol0^t+;nR>=#AO&FS2f~d>wYaM2 zqN>T6W2c9o5^wWOHl*Bv211-MA1M@AO1db_K=w7HQXbN*HB&xy`pXrEL&55j&)O}- z-1XMglL^_Mi>kWlJ-Cq{c@ti>wKGF8u&RB3ow>z*`_*oPh)PQymF|L=&WP^Vhoc$i z=GO{AhImSk4UBV4CG&88{jDEqL>4zH&1KMkwo^we)YP^WLw8=R)*zU{-A@>9`aTK( z&qhFKz=|b~2WXnYm$BtRBnXc&XcEDnP@-)kIyXq@D7HM66D)oLLYo)E~YoWAWCj5Jp)0R&8ekrE; z_W@t=DJXReKhb+4tm#l@3B6K+S2fvU`Cf(S>|IR-jYI{EP|c5R@!a_Ez{`5h1SQrU zYMt8Ao?E3<9Ic3R#@lfk%)+*_HGDR~hUaO*OSUqnqJy{IGgi0H$-&rmYDF^>r{ZI< zJp7!;UE>6_pizD3PRzUgq{R6limSj9<59yWH{G9yt+qmsIp}?Jn{%^EE`sPJ)wsLU zvI}N3&l5W7VI(QR)=bJ~$Jx&}kz$#L=`TtgJK1|ejmkqe*iCf}a)Zb%5>PB8-D&rM znserOHR=s5!Q|AqV__m}5LQ8C1de zhF&uS$5^y-g*Y#*uCz?*d+A9%2Rf9&e70L`x_xpds~skOHuS!z6H`%gZHZ)cp;Gaz zarV8x_0~Gw&wTdh2+mj9@@$GG2APh)J!X*3bmVm1)Y7x*-RO?r^i;9nIEePaZudTYXz=dD1<4|bg(1`de&7l!B)wMrx5f-gPqq?{eHkWnyWyR$5 z=D_)B(#9`^?#2#FHX+kEF_W%0YKo;(QHD$cA@)2VQi^+^pboEED^=X`{CLPXPaly4 z({*JWYqrj<2b}8+7O`$KwL{`u|_7nhh zAUc0IRyf;gschtxM4lU7Nx?Vl(=X0NH}R#=I0)`7yy_jvjXE4J1LZ`yc<880#1BLH zcVaB7ay?nZPnlft&0gB9#le0WeBEwt2WKeLKSPC1s$q<4%?$S#h|b9}+kTKBSGJc` zi7fKC%%c!P29F#gb5lt5EX$07{9`J5_0rUBta00oXW6y?(yUDzjzQV(rAi1rj^CsP z;WxXv*DrN}-0)om!YX|Yc;=qQ8D>yQeG+YKS6WnMurq5*`pMsa84`PB7g^8vSan~g zn&X+ANE|MaDgrmpJTjSZne*SCY-Fh?>~xGrHk>QIjz=?`0;@hE1(u-amIz0mv@}8E zibBuu{kAETtvrE9oc3_`p1O6<`Y1ORs${$k^Gx`Uj*Any4P6bl%q(hr6f%9o* ze)LknNziOf<1E)Czg#Ty3xCG6dyj4)jjgV=gTNVPS?RBaC5a~0>O;AfQ_k!6nJ7v` z&B4OiQQMKR@s?bp#!}&AU7cpq+8y~iTrn5(lPzhdkleB4gxD)#a|TS4g`}Lr^P(i8 zK9P_oZ6?gve(?_Z3K*M=_!eWl?tN>x8Es^iCncPad3RTAkVqHlQsnn6Y6kMbo2X5L zqW@hgWfPN_g(91yc@Z1=dYT>4VUA*}!c8Ai5~9|^?1p?%OE@N2xxEgtU(IIm~Z-3QlX0a*r$m66wbaBBV)=(wKAww&#c# z5f&V3t@ZEJhBn{tE@ZP)4cMdWyPv`4c8gb+9Pe_lj+hZ20@dIbjTlt622qr&o!|=+j`NNNDz!nlp)6c6 zfS(GgTg7FgH8)cqLorO2>CYtnXXZHRqG>d^jLw{z-VUfUGN$%3SQ*A$>2iAvEUD!X zTvZVURyFV{WSRRs3Vb;^Q7rGH4%)HwZqpj?c!{7{vi69wpo)8UQo6lYGOajWD|3}A z+or;8BL7$~Mnk8z!6?)-yU^gm>Vj~Su*H+~imd=K^$~;m^L%)`xDe(T^|G zuM&K`ue0~{e(HSt1Yb~|rn>Yo8fv*T#U(#*-PT`{|G)T;~hLdHBo?gGKVD4-C>yCGLpWDBem$0)^MDnd!&XhlqbV+1@7Xntm zLfmfPJG>mE3jPSXsYipdWNSx=@C>2oaJv6WqkwFrVPW9l7 zBsnZ=F{*>n{|)tJT35rQ1tXC^Sx9=Tb5{T(V(MCIYX(^UkVEL&Ez6lMrl`Lz(4)v0 z)^}Q5dQ`na_>)7uVHV1K!I&IM7l zERVpn+#aSL;gc5==fO6F4|<7ZD`kWE63mK#@j{^nt(tH3Ta-=5@j$yjp3AK7ytzIW zz^(7Y@5RRe_Fd3*7Xd@&sefn|s>l=}tLkcZbGOXjg#aNBVPL!d-+<}K6P$6x#DkH7 z8g;w4-$&~`2EsK0`*zgTCqejcf8V#4qubpXef%!U)waM%pu68&*niInePuv?!$O=>vS-HoF;}1hsL=RYflWQ`t!@a3+|{oAP1>y zmyqp`+%>+qe`Gzk@pXD2eyb2d9bC^abaimfDjY-;kQ?~Rv}3tB+(kQ22f`}L+5{-% zxD^IYf-T)NXnQJy*YXi0yYUg<>Gk?4$HBI0$85lwtyar;XuCJ=#-Wg$^uQmlN_V_q zvE{^oX5=P9)9Vg^D>UTqqgs{>;5az8)_DCt6TH7oXb(HxqJY^5RRseY3LHBn1r&cp zZx!7Sxt3=B{Y^Pimb$m^*8?R|H9AZd{~M7%xA;j-IpsiZmvaIL-*Fy1c}z`(6bN(q z+?K6oJs-JdTlR=@BBSwzQu(Ad&&?Pv2})u<4Jd;z*yE9`0w2hF`GQ>JBGEr~n5mhV z1S*1uIss|svC*>KI{UV*BQpR!G#ZTc45ybFr6gAsEB?M`zc^P_hf|QG6+(N}=2;0V zIa*92A>f#lTZfg-4tX|8Cnm+aQpMN)P?Yyvp)38LvOJr{9n#Ubop3g}%7{S z)y-$7=?3(^MltIu*F4Bp_N3xml_@$KT*v5!#wnD^fg>Dh9TE>?5kjE3;YhxaGc;GH zDXXn&2Pj^Q*VhbN@-Y=64A+RG21;k!SFu1D9IT-o>a-q<8e+-*e=$gN+LEU&vYP+) zH77f|*3f=e>M{(#df?J_f;%f zy1+41g5&=P$GFtRLN&J3$^jo4q+tDtBolzVmEhK2Z-4CgLP;!Y29T<%SpnA~wX2;f zPgR&&!{vfjXO$|%JNshHdTLiVSqEl-f(|G!niOzo6R1UP#aEz&#)F!UK}KnjdUoV5 zGG4?y_(;8Qu11`2n!@BFU!nvhwpNiaj!P6-&qz#g3OS7|Itvw2g_MTi8}^@g{{u4* zN#l4H2*CgWk~ThCe`JxbwGH3`b^z2~QmsklV{=?X)HG|nbOGa4R8RVLlKL=OD4vxk z*kn1HqqjTH3F7JAJk1S=BM?`0ToY&FRh0MR{)AT2B3xFs3FO8h_^?I$LRHQkkl2*d zjQRg)4kg}v$&+doJKf^WJ$CNOT^#k!i%=+$rjc#vJ;ks!nu83M_%F}p|64uRyqJH} z8176~;|Q%DRZCLPRVZI_;)PntwJlY}RE(`|gCjbXWn$uB7&g!&gzRjKE} zre;mJswMoN*+6)L@#6dTGt}cdD>egJ0BtQ!4+-5`l_yRl_ z))I2fL{q4hd^0)^X+Lf-mvL579lPbPQIbfmMYp`zOj&bdvu7%mGtT!=pdp9oXt+Nw zIJbz$d+{FU@>@0ezL~V=o{>JYlGvwm{Fh#p?`lp>x_&&+!bXHwnbl_H6r%s^_}lt< zF>ZK@C4etz2^w?J>eB(-9j;6FS+%w9hU;~oPCzr-y(^wic(_57?}0dOZ_h*}kS$Ra~~mL>++17sciTZ?NNPDSli( z4j(>&GS6$aXs`5>FuyN4a_Kswkt*prJ-KZH1ok$BcmhA~^X=a5@AJOv&forhzTdn1 z>!S#Hd~WRaUmve?n;%!3>pxf21A4Q{IKjG9UvJdoro)^7kKVJHB^7&)O2HHO&Ubz8 z^?WI~4c412i&ERvwk_lCTuNG&{t80s_OD6IQkD_j3USMuJ<#Z2m~DoKm{l+a1&~P~ zw8R60;mo^!%b`VRo{&?{PD5g;Vt5qP4a@}=LCvg=JABlhBycoJtDO>jzoV6X19k+^ zSVg8TYRi(apjA_-%VB)0`<<9naQe!wRnp24Bgd_vK-S) ztp^>6K<0|>)~2f;D8iWvbt7D2SO40XJ@FV4=>IT3{V$`LEKIDd|80K48;{!>ln8lUl=H!Uj2Xa!gSycc?ClV9fJp)<$4%Z$gPT^BUg0iqom7FcEw^ia} zu|I7KfHV0p2i2t@{=oazPX{BFc&Qm*zA?+@B`DQF*qyK=O^jY%jvm_hVXx%~D(*z@Z_v*IcuHxhSa`k*h!}Y&iy>5@6ul+tAZlCk`;OO;xU%qzb z>wZ4u{qo~%mxVt^Pp35SZuc}D#T76wh=5Wc1Sj8@qlYZS@!`YG^SS@XxIkASP7AO`V#0DWz;656s`aa!n90;VMvttJOA89kk|ufka-=> zSuQ&>(OUa;7-A(IWW6g^FvkrTR!hTB7zx&;p)R^>!_7MDNmIBiw+j99<>UC5?f=8r zIYbE-G-9 zytflBIZg+`BZ-$pip@L?G3*Hlgj_5IBs5-GmkDHA;9kYeW%TKq6$_=H@-*j9`88q>X;le;ByMr=`~NqWNydD52c=d&aPB7JUd1g95LTI-Z5H zVN1utK-io~*(KgAGFAA;=u6*!3d7viEF1y0918m50EQLcs(wDH3i?&>B}%yAdxn~@ zX?H(dUFvU{1D%<=Z|hxErmE+t|Htf7+V6)tYsj5cX&+|I9y+|!)nc5GE|3I{}DO=9=^ z3F=Y!z0)w9u~tCBRl_3X9PW@o&;51w@v7wIJu}bt=Cy2y#0>{c44Fja#$>SL-8gft` z#Ue$x)|l9hC*2%-jxook^lz;R$>^DAx*$oFno3C=o!b1Go%6-f#|UvtZSxu?+dbp` zW+|FxGQt^ml5&`v;VHA~Sb$j$?nb_=qR)BBYk~Pa3#re#fH_Spy63G+Q8^Kz*kDea zW;Dg5XKFw8Ps;)Q>C19A7{b6vUZA6?i470z@$bgQ(Xp)V&P=2}>>z*&v&65AhYt9p zIB*RAN&$VndlV|TBJ z*2NUW%Y$I*Yb|&#T$>!b)B14s^(O|!%ycqp2ALNS>kACSg8VaIbBw4`P%lA7h2uUl zh!9k~aE#5KE@GtfgxuaYeyX`GIAg&{98}Yk8v|^pWi~aXlji8d1zVy92e{r}T20}6 z6JVJ??W-}q;I`Qy!a|)I&Oe~(uOHBB4Myi3Bn=BDqlnyi0MGfW&5!zf5=}dJP10^k zL=(dbI28TO@hetsRD?4$4>x%JLZucY zWfFM1fL(~9=9%H%yJ|~1Wo}1E`O%|%4V}QL{lV-lGTj###Zcas(xr9cEnlrY`;g_# zKL%KyUdH2qokbpzC=w!)Hm>sm(5du|^L`%9H+TyX5dx)?vd(-BVCVUfrMXzB9iY$% z(~`W3YL?mti~;%~cxG_YM&|tQ)^wbUWifd3?Lr^90kAW)lrk%1u5_uE?B6|Kq0I24 zqAE1=O1fe8V#hhw*>*;H%*Z~reIa@Nk^)MSBf4W0wX-^qWtALCWO@)e+JZgQfG)H8 zHw}r$CWX6qkB6mM3!meo?$F8;^n}`f2`I%1IXV_(2)*|A6N6?(aP#~vI}eqiBL^%moAZA6MmuRZmxE13Y*Z25Wr zlBG^m4Bw3z-b;#gnV9#-7!I$I?On*}BqynJdM&K1?xP8G;wjfhq(CJ4Z4MJp-@!`y zIu(dpfFel~OP#Jhfbyv{WslElY4e6+=2|kV^&EbQH0bKgr_ou!k@!Vv^z8ec!l!*= z_bXMc#4FqX>GN>R8$UKfU&b(zcc_gR?mCsJzk(r1XDB2JIi=*U&fF%9&|;0IK`<&O zR~q*?Ed8@fy&F*0Nb&xOrBi;(G=`MFNRMKYKUEgB#6BYbG%jfpJVXK0q5fz4)_QrM z7s}^Z&;+W1rF+1$yDVVDGVfg_fZ!=(=FX>bo|Q+@jN|1M6&E`91@j3o8?bzy1mTY` zi@e3b8+4I_4bc5|3L0-{XY4J2^;9ebOi}>sNrZhyAuD>tr%vGf$E^;dUh29P+2fXg z2W2273xzI2wUGXrjjrJ|Y|JoH~54^NC^J0ID>HzT^g_{(?)6z;9lmTl=eB zzui^5KRin%zQre3@HaHV2?1*k=YqXUj15Xmiqq7NxJ^IgorY>NIK@I$N5e+uUcLjU zHehK}SL;X*_R9y=Ej|tt3qLM&rx1&iVfCVYo-6U|y z4K=s5uwZvARErg3BoYGzSf`CSXj?W&vaAgw#4leZckKX4fwma%KIJ_%{RR z0j>#yw6XdEv-WIWV#HPrHIO;0RT9bVt&-w13FU|O6!;)W}=FFVL zTtg79+y3GTPFP4u72DS^^qngWV=3vDv$HsL`&`^z!A0o2OWQXk^8y zkyf>kSG77hzR3k8%qE1xw~_LiX&W)~pZnt%F*wIy%+iE}HjSCwURiwy!1ho@ z@z;Www`@r=A%_5wR{fLlI%stmrb8txQBBeV>(I?x8uD2A zh)`iy^CBa}Q7d_MU~%JwJLm6FL3qFCg%5nZmTa3M(%#_ZI&;6`I(;+sC}3rrwjjPx z_sKC=ZOAq)0M4ZwQustpj8sQ+URBg5`RC3&Z)&1I3=q@UeBs~ew(xlIe$3e`e#@a= zapf<0TE^}3E5~7)%rdKfJlSGgg0`F-XXMY*DSJ|aChf3>?miwo4=<lqrdVr~%^@GYj{+@=nQ34$EQKVnv>Dy3D4*UQO-lcym|_6amF#}l1n^j&$vFDq-znUVmjxrXLxSxSl8X2+3Mb1s5h zAY_;5Xo>#Z8@(1k#*qdIE`F^dJO$+`sMr5vCQ&(ma(GfcQ-49FaoN-d!@PYWXh(wg zb&sj2gL{@HYt>6u?BvY`Fv14LiSij{UVjX{3$HZF2UD|DyF9OECUr+;?UY350(3-2 zL>VJLmq=VyJpko;C9yw-dWF3o7eURUDn<`!>qx#Ew~+5d;hgj{8_fI2f~hA+LQxw5 zr)x0glw{gqlPwMdkn$*)(2$)~#pJO)Jt-hZpIn@~ju+`dk(~{?m_hS3aFw0_u^0zr zCCZh==tkC1esSRS_-)a1MK|nr;96Ul5v{N$hylq=kP6Fx*`KSAs zOL!_?6GqF3CI3f@t$_VeVct3pe7B3_Tf>>lJ_|S6c-&IwTru9*_%dxoCOA_GHPHN` zj#Xdg6IhRuCY_-&US*%YQ4a^#0mr!-czgpEnuN%!n`yKgvMy+~|DPljm?(Od904ij z*IKQUNp@{9LQ{|n7#3Gr%S={e7$K^E$)?E;(q7F$(1!w*;@#A_%yN2dmDr<&)J17El)OH z%XY?wbJ;U%PntZ%nFA)R0>=g}AmTh~KU)OjkmRmBWv~23CX+HBJ)oqTX6oXm2J7_l z=|*LAq~uuYv~(lQe4{}!RmME^<`=}+1>}ZYKTWa^SJqGzkY4USbP=u;j+9~Sc#6U1s119( zZ#nI^hb@|y7Wc>EJE!g1nbY^{=_PfwX8HPj_t%TD>uvHBLRhvyjEz*?)Pwy)$2=gGrPz*(NS4{|~8pi-8i`NPB!O z$5sFISW`BM-8j+rA9hBO$)>*Y7KeSZF;RL9>M$`@wQHDG2W|`FCOxicdBM&yeqtq% zYsKizO53pML`99vF31~`Bqfkjb~y&_H!Llh=Zo^*K8m))3Mrjz!_PmLiFl%L{g$>$ zp#{y!su(pdBH6C3jc1kBW~R#^85>xz;SNSpbmYJR-W4l(Bb~}b3z+$3RWK;Nx_{N) z!VwwhX3iWl-zGm_bMHuUN_K0iEzc<~m28#RyCu3S*sC>urx8Dwp}m;}b*JZ48K1mN z#4HtA1O-%;K)d48^R39#+v`~b=YQBNhn^7Z`FGLvtzr?Kv>I^w0F}5oa@ItL53dM_?AP z;8?gwtdEW^W83*Nu0R}htnrd91Zt>;H8b?b8-GVU{vf|7z0D6us*4dbA@tOTu#{A( z;+JD7|K^j&EfN87yK`4oR|Y-O$0++fRF3Nje6hYT0gn41=wDc~Y_HdZT_h8&g;x5lLw5@w02Tb?e9QpC%XCfE7CLoF+e!abk}+}L zWcn#~YoT3NfJ&M(m?8dAhZFl07bZ>9mSqoZ@#xzZZgjtfl6^*r6{w}upE{N}cuQlk zZ<|MklDAMsxOhy;uBb8k5SjUo0a|w*KDVQf;vJ~#Z1O7zMp}kT?y}Sq>!u!Fe-&=7 zUYSCz#`veKX;>>i>ohIKN)VPamTp~)GpdamJQSKqOUqd`P`3K4*=iZUD+g$Hx+K|P z`^n#s0TD%EPC-FE?jnDhW&=T{&|P)mmu*=SrRSgR@ z>Q}`-c#{_P+&fc+IjdA~@!jZWV*(a^Y)V4d9VKA25IK6E5*?>ixQ#knZ|CMmwhaX)B`#jjd%W8aQ7n1cEY4J~=HV?3TU|JZL5{_-TqMGR|W$oc=#ak?*)W8NmjOLTRO5BzxqK;w;lP`wz9 z?AFYG=o1oCdwomGir+AH_Rf*NvG$X*TB9AIMBOJjwv?>asQLg3Vn@D ztJ+J7McdaFe$tRJFs8FT+*E>NTq5M9kxTmZ9`pnr`d`yXy}NLI%j6oQ8F?D?@r>S; zp2rI9DJ9PI`-&)%F$JsR8`ydnn`1cw++J-!U_!@*blAN7j zw>ET1R%rgxJp-OLvmAi~Dn(VK&RyjPHw4+^8Wln&wKz`Y>}wUaoA?kUG2b>GAElnO zN19%#%kxUvX&0~|5LhxagQz~!TS+O5^VW`y;I1#M?Fi&2eDNYXjWn^8$e{Q$wh%@@ zs#?+(Z%r&^At=1J;vg>~pN5BIT-c=;c?x5t>Z=uxOlZJM#LM}(=$WsG-567LYQAe( z@&P>Ab32a0D&gS0QzRYE2Elr|7<+(hX+)p}g|4eRUb;dNVvSw?@Hr}5Rt&gQ9ve#^ z*Bn@den@R*56L9204PQT8xE~W8kuWDh5fr`$midokZK~j=7+F0eaH1d`44xW6du(T|aLQ$x#EDU3>8&U4_ zEge0i04UzW_Yyb?$uVR|&VT;m{Gs%QsYEiKib!G!p z!X~_w+mYV_at@+3a!4-$^<4J2-a?5HUDjOH%Ed`L3ooDbu<|DoO2Bzuhd*I1!9dpCRS3}b zKD2|ZzC}qhB^Xnsj*Wn!74flVk$WW@Mi2>{qOG$R#MngF#=*w;Q+7sCCcG2d9oNQd zo9@5RKGU&#!5H@hZ#Amr0594>qtS)gYr~1-r#=gMOb?<2;3fqOLF&GFaBVQMysQ@! zvyT8Ci!W=oW$M8P=ty-i4N>hr4iGgdSolm7+rz0K>oCaJlKRtG$yVm|v;Teu6~;i# z9RqyWxB2)5Z=}m&q~Pre1h5exToFAy;|gmazgkN6Xb05LP(!e=b4vCZ&nP2U72pIz zV#wngKaIsF6IHxYalEv45k5a8Qop&lwlezcJ`HHayK;)?L!-zV%^3GQ0p2f|gl4^z zB{Iu)*})I=xj~RL0k2Jf9n$OyThxMncsovBRyc~$(M~z$0`{JhAXg#pnVrD6h2($Q zbLhwL*Stx2de9mk?jlK(iVBJ_KeWivU|O+>G-LLpQ4$*~(?rU zb1XuYVh{S&ObNxV*AU$_{3vP2neFP}+JSHX?y7wyTkILBy=EdwGOt}<4?6%P3aOE2 z40MfU)1D?2_mc58$KdY=;*mi}A4_M|1^5H61-)Ob?}{bcB+?+3H$f`ty3TLdqj zoPv>ypnRED%rjnPV~ix#%HK`1>G&@;JK2Y~%{6TuPV7X;E;MeEeCeX6t#m`4kb2Yt z0%HOB_2BQ{Aunqu7jW6^>_Baf-KsWWZse^YAz>jKSM95bfua%mS`z8pgvtTGGBzZ}9u!BmGT^Kh&-e;&0eDYd|Ou3rp51P}P{}_WacXa04$E7p~pGP!7bX z_zV{Bk&(r9pmpRh7|hKz_>~j)JE>K>#nEIEiKVJ*`_xPcjP*3%Zifq7Cw2Y0LPzC* z4Tec=b^ahWVqSjV9M{6pu)6PMlEg;1X0$LCVv*scPF$eOp&#YLpJ^?FWn3i*tP|hY zPBUvAiDE=3_y8*EOZ)SEz$GpqEM?67U`t<=IHNX^ zIF+}86;auYK3gj&eK&}H5nN983ZoP*X;ZE}Jg*|TD6o5ars$;qN=1qMYxC)g4X-FZ6fa?K0DB|+$yJ;>a(R<<)s_wx(lfb~eQLQB&X*tY1O#wO+g z9rI(ab~+2nqkZw1)0$?NDjW~LA#R{63O%#%TR%#lRXE%4-zHf` z5|0U@=sM`bi+xL*+@6noFur_!!Nh@z0jAmqXguvyDTG$*l_v3vaX?^*<>Sl6OhviTk6Qdv zgSU=LjaFc_zA5gCo?%_uP(0{R+}cG+;G;JOsHFl6MaU>MEY+jUu1>1D;j0hOg!osy zo?2Th2IqBrnOuQLtPzO0I?A?K_&#|C59d33mQEoyfiz(G0#`t%n$>(MSMcww5~Kfu zf#wy^3YgGT0`Tp@2H@gHYr0@-8)}s1*~--6y4OGe*4f6Hpet zNMvt;09&qJSbc>TR!iqMZ-sP^%^sA*A#6CYnHL$xPVEz|I50EplTk!^qoh|aN8V{z z?7cKsqNFDhYQ{4z)OVt^=VjYC)R9qM!#M9fPf7wVqcx)6B3{MYr#z0G z3<8`&RJ|YIIWgg`X31LS7(z1LG+aBlgCH8|Y!;X1>DV*Y!q{+Q6YH-G z>YjOxIfswx2BZytMt8Lkawlf5?jX=;IO<}-TK+h%?yP^+FT1`-__cwdc3R*=ZopgF zYxiyHv_&~si0?4J-}5kAHYj|DHYMT#Ks$}Y)Y^3#^k{%S)Zh7CBBS3A91!uQf}4R` zyfo4aUW8^Uv3pu^q;r0J2DQdt(RP9Wq*YnkVsMq!fl~!j>uYU^8kD~so{ui3B3-bZ ztBVrf4v%qgyi|Gm_oz$n!WDFE)K$_ zE^fcSA0OJinzHUU_djJAHe;@9q~jQ)6>^on3i<-)qsH_jh-Czn{MyUq7Cm zeCMf#IifsfijowDzT=7t$6mzEriVSmfw9PMmUD1oA#m)2b(F>}}C|C*8Ek-pa)>2&Y7qfR> zwHfW11SW}*x9#r9ZLlvQ7ja`1>4m+66)_3iYCRbw1t46klI3S7=NT9RUJHi*Gc2e* z9-yb9(gtisB^2y!{UIJ4=F0Pmi3|AvjogDZ)W1K#yvCxU^}*≀a9*36|ufWzaGg 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�=|gkM~#e@UJCi|^j^>Z5DgkhK=oF{DhPbkdI$ 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�G zZfd8ZXg<~maKy@pz{2{mLyUQ8W``#=_wyY`C(pzzuB~AFZ|>zkm5%j8#YK6i>*i00 zEN>i0UZ?Wuqad40M?=FgAfY!kiH9;IERdz|aj4y;(sIFPEaSX^i+pIikhTP#MHbkD z@HKi_o*=cSfV(E>&Pg2M&X5D3KJw{X}96B^jHOn+HI)vvQ(8jlx zJI$T+`1Oq1ml_HA_-sWt$}9|1f?DwMWN~2h9ES^)5C3$xFiuC@C`d|H6Ms));X`*C zm@!*-QbGCJF%)@4?vOsbR=eW2xI37=iL=rMEoE$kSggLQ>v{xYDk?f7a^|!zE~9Py z;8Ea1Wwe*kvm~5G9PVU0o-03Ciswa~UN<{F1{f40BTjEXx0ZMOcbX^4{7AgC;5kI| z(B}N2FO0&J1uTPv^H2dz4H2iRG)xT8BU96rhsUdYtXgpR*q`;At}uy@Tjh1F2huPN z`MflF!^PPjP#dpG7yX$rU#B@i&v>J>>8SidD#=n7m)D<^3cO8={3=ZUvHFB&f0HI{ z%pkA1h%l5Au5Wtlop-QuQwi=F)qTjAQyQ_X*uW_ExL#Qds-Az}9*=AEBD+RmJZ7K%c*^ZT1u#<3-+wPo;(ZC&n$e+?^xR&};Jx6GtK}id2GlDR zMJ1P^5=D|%zfZ9B%O=SD;ybwn+$E&8QTjA)5I1C)@@(9wcLejD#lLcKZOUPW{jSDaRxO%q4ZLXBQ3iNk>gs|)$ z(amQif>F9y_TcZ}SXtdM*_mHEL3=~A z6T5-eIK^3;z{;&zIgrL;_M45BpIHXAR7MRtpQJCcq~)h>G}u33)S@yXWY5XS(Xh~X zp}pa-ZLhf4;nnL>Pb{+r&b{H1R7o1E~T$26n!%Qd{lr`4gizKS&* zJb#X>o0oWbe1C8BU6;4JJpZ2Co9~yKp)vW}Tt2_=<(;q3G5*}ocz?hDsSZx05md+W z*Cu<)7nWn~b|E8_TL&O3cb$sB3b@bl{I0h_S33K@KzFrgniaF_jdb9XEp-BZNx@d@ zp}aQM@gJ*EtEaL+Sy|BzhUb{Tqwfjy0yPSXf4a3COM?!#%hj3x657o5OpwwhVnL#8 zYZWmEHi~vYA^p}?s}u_FK=w5d$yvKFs}yt(c(komXlhm#^}4OiJsm={yV(uDk9I+C zDz@aHA3*Z#hZgE0MCFt>K-T4CVY9z!$nJkRy_^t^T#X{5SS{?XaHv7G-O;Tre3jmq z%>vn6jp`TKajtDwi^}Jlv6x@nAw$-bR*-2EC~4#p^OykOqBB5M?Y z;;z0f$*NrHo?m_{eabv&#{5FpzOu&ff))PN8?eIk=wL97>cI(5vgn9;7C;H3QtY%l z;DsrDLM}-3D)dN3@&>E$zO*ZWSfypm1n9tDHM=hro)Pho{AoK{9_c(I_%yKB+m-^| z^o*bgJ!*f`KPnsW_}_Z)|7VyQBl~|<2)feoIBkf%bH8Q-fLF9US)ic6>kUkDaPWp6 zf!QcpY&Zi-wPWFL-+3RDiCi;x$5MASFcO3O48Mfx%J^ra#4TsTojy3O^WMKrc`*Gh z{NHYGU;XJ9;47g&?FNnDWMOg|wBGYNuK0Vn-|uNRUk9(jcj%?7gKKx2>Pe1-GW_jg z1HZ~h_Fw77ecI3vd*R1PUwC+*zsJu|*>4~It-|~9^kC~~FZcHq-(Egkc%x@SLz-?f zE_3|&>G%wnGGigjsqS-qxVr!W7VkbgygwffUbQT?qWl_1)Ilm6=)^zdMIs!r{-_IjV?c!LMj z>y;Dhmk6*M-m7g01rP&}H`r}{aJTgQm~|<*%VP4xR+ufdI%0(+2(OR{y{}kTK;+O( zdAH?&5*2fB;+K$3Q^|3 z^~@AR$cRj4dNuG>%RPy!*(VFa3F`_{GtC@NA-(zam^S^G20ln3H9OB>29#mQEHmy5 zW{+8-190r*?U7r847<5*p%;i8s-D#6wSZv$Fq;ER&<-A$iLiOggzBdQFe{5UdN|H& zCK9l3{oJ!1-j9dFSD=T>$4E8|sbQ=azIqsiE76T_Qg1rOuvo}pR+DIJ3K&K%hO`*i z!q7j@7`O-o>zB0Z9?mSnM9)pEBAL_3LGGZGcbbRbT<*0@LE-r_g)y~BK|Ze-(phSk zJai06Wtz07pXIer`eYq5xaq|6!Z_nqA1e3#r}8L01tP2 zf4h*%RsX;wi>m>8CofdJ>=HWDgKmS_I5$B&sSY4y0p9=u0KT^-XdeJ~alq7Yo$;49 zA@&iK7~3;DAS33Py$wC9`W`=zr>_A&8aVQLo-QCP)|XY!S!^4?QapO#-$P$TAUYE$ zr#LlCq8i+HV7A%My!<&?p?a8FznL{tWom-Kzh4doeLl69hGfsW>9-^e-FHXzwGKz|OHH$_K(OvmE|Q$3C2_1QC&1!e z?SGH6G{h)QkApPgC3cuTiurCwWuhY{xt{dL9*$k?JQGP39fyJ#og22#}0Fh zo6>cw=Q(E&^*s&*panyOAq{%{>n3?7%W+IvyWcEAO$l}OU0*}WI&JGBDKM-;&1;A z`j{N5L18&~_dg~nw@Lnqaf?cZqfI9c2&Agfb1mDm15|R#c!=X#KCEiN^yMVmDtS_T zi5kwEq~qZY-Zgy1&34Mo5bMWUXwm0vx>(jrBNrCRz`#kRje^P=6R{2@ZjU^EQA9IQ zgAwL>`h#DL|K-pj|0k;4onzKDJ5NwD21u za_r5a^Za|!pU2kthxmq50pn9K@;1U`_*Y3psxXrp00vluc+Y$id& zauM$Y+kBWhj+MW`eD%~?1+6FrzSUYb)9{8ud9q+r-ckz_(t>|;xO%l9AJ`QUc{}rR}{RlQ-scTuqY(r5y)_8xsJ6Ux15P0 zcU6^ZXGqu5xZYrwJ-Js8U6B!7B(xmUt293`GKX8zQMQP=Qoo}gV(GR=gEwl>ATLV7 zf=iw2R|_{P@q15nY8c#iftM3AeGR)C)}y`KZBmq2E81u-L>UAv++xeI zDXQmg1v0HM$EX=EYJy$d1DqA2B z5)>%3FqHp?R#9i3nCzEt!^}^r85U)xg2|}NGU~{U*&X!9E@sF-`Wmg(4j^-6jy%`Y zK6Qmba~R=I;3Eo<7bVB>j3$*rU=xX^_*MnqEia2(V@WLsZL5XHdYfk+AbYtv5z`be zXf=Xi%F%F%JJKNvCZWvlpUgV28-2amet)B!zfkgk6rf|Nejqo5!(f@a+t+HYqHgm# z$%}nU6XQ{4>m?xGFSgD5B;M3Vc&m}TQH+e(|IEyiy3v+@(-^GhM%B$UD*$d;t$&C9 zV9DvGH@yjx$~+k1#k9pp1I~Q0CPGb1W(1Q(Y_NT!48WEgcc8?}SSm~h3K~Wj4AjtR zF5TCmV@}HWu>oQ2#M9;Z%#@12>BT_iPb044Qp!Yp1GU(YN7TmHwH$F+@X=Y-Se%Vz z?T$x%TN@HeF$oU#$l=y}v_qBui$u@?@N&wtVwzz?qj$3Yj~GxQlwY`oM^88ve79zz zm~%`Lz(i}_sPrO(>35jni1j_Lvea3=zu12?3T|F4u!b zLUB|fG?)tkn&My+CP^eyi?fsV3~R;MFor*`<;O(=F>tDG2%v;aPA>I&K!JMn=wg2= zsu-2k$3?>poz0GKN+<5fQo=@|k!W4;j*f<1Rm8fs+?5T3#fN94Q}jycRTd&@iFjZg zBOQfJ+%T_eV|HfAv8xz}FdO^nQiN3XVPg)st|mfU4(Wn#q^s-~yT)P8l8(KM4}E*z zKHJ%mu>GSjJ@h72AuQ*QHq57%da5!LZ~}P~iRwoMHdoZyu*XO>(7CNR!HXem$Q;dA zBY4+IC0Fzc*iw9rIj0}KJYa8&vKgv7(;t02ed;K5!4TPzD=JlDE!TP7C3p;k%?&)V zvpD*}R$q9oO#xD8Kr8M~E*gE7_@wq)?`d}3!?~M)%ckNMgL$>w{Sc$u3{-6{EM@TQ z%UJP1g>W2td^w-aLvc3fV}rG+i1LlsiUrZU5L-AwDabqPTAwFa4)C_^Th`U();)d< z0~B(J6QrHWn|Fl}SP!RwCDL<2&?xCFpULYcId$l`Lh3+x(NQ<3>CL^0j2`R`kU>EKi9Lt#fB zI|p4ucj4#EcPh_k@gEga1Yo@1&=D}c0fSzxuj%lzdbsiM@OXXRpH5r9WAV6tZh3Dz zLVdfwj#po7dB5KGyQm8Bh&6XM-#6ZWZ0~mt7Ki&5rxF zFx-ZHZ1@YXy3WCAc4I$4L*cI)LBNo}Jp_@|)7enpfl1B_%2p$^eNt+-l zp;Vy~r^`GWkX5cdxm-zQ-SXBE%jC5{HP0fro!1E77RH>lNM@F{Zlo7Ej>F9gAg@Z* z{IH$MqzxH)X*GX?CG+M7B*EtF0XxeM(2#w<@Ai?mhZ>tsD{6`>=gN1=2)ik}E7+?w zeoinyhGD!J1a+t8(3zZgnT(>eSp+APltg?A=>>%qI~)vcLgv2REQxPXY!$3#36$|$ zO!Gi1LerH4wP>N1Jb(4<0KRx!$Kg`yUp&A>otkzaXI`PBf%LXl-z1xF=l`T;|BvJ} zMpoAUjRx1!jNNKM^~wEBlmX4-?flmC(Qjn`;z$d`(ast(*+QU)YPP2Zf4uqsg%z0y zg?G#hsR0AeN*wIBB3Fv)-Byp!F|LakNd4Is1@wxyqJOMHbN~3b0RvPW zJ+ydyzwAF|{VA84{%fjo6vV6_%f}2b@8Q;VECw{k9}^-DQPzCFAt^Q=0w@o}Cke0( zfC1aIPqG!~^92KM+<-Px`A6Z-Vh$h#*bGz;08`-`OANp;`xHj6?B^z@-!!_L&aaHA zLXo8Diu-eu$FiMSG_L@VvN^j`NUbI3LcQQ!={hEzR_ zV5TpA9$A51x4o|WCiqkZ0KJX4Z4@!LwdR`*gRr{^Tx(#SDa|c_D#!0%qiR?+Xtx@Wkdytk2|M*9r80j-+ZCTeVqmUJQrz(RPhGTCI54$rPBZqL0~=<9}Nj#uuxt?-1B$E+pA3QeiH;WVs2iD zH3%G)5#<1}Ix4v;gkNbQPI}Q zzdu%-IR_1|K)s!FEsauxrg^DV2%VXw&OjX@aTb`n-9B~UcbifS6xHf|HG^6Gog!7I zG~YpZc7Sy4C*h=c0coz4q?|l@n>xwe$z@@o%@x3z;m9-pD4V;qq=Ys~Y8eM$7F(R% z{*0+;p|fdGS}t>pK-} zemOV%yuCfe%L;v^7%}$n!i<>?_(@(EradT338a_;xiP7mHlzT(n7X5{3nJD0Sa_=! z%5PL`-o~n;?nWOnjW!#{CR^AMYP6PsNw?6MC%^!@MH@cHjk{o@h>?>L`cR2e=CK6m zGmGMFoGq=zy(AaJjU}jJZ((eyqZA2UrO)kE7=YtxF&dC(L=+rU{4MJzX)!DhL+)>t z7J}i*18)83lNZ_$hve~!6wV6UvnDjy>u-8fFCZdIA!gKAt9FzzztttYkaDwCmRB}g zHB&HVz+Dd(OPJeKp`s-RLzBD7alNSw{smEopfRpi7o6`BA&=DJ;6#&B8<(RXZ@@Dk z9%8Yz*mg;SCEkjK%?qEy-ve6h44m%V{fLA4#`yxJ0Q zvg9(C)d9(zx=q?6N-lE^FH4%NC_JY3Cv=48?9-Fp;Yfo2?%M3{V(<)|%JSN=_al|4; z$W1|zkb&C{#i+M(H+K{lBBp;87m^-I_qv8LG-%gftN8ev)u#99c-#_YUOce)2Z&5m zLq%S#NkvLZUZ0ky?cEv6#^FV)=TxH*9+p5_ZB+?PDLYns`|{yD&Vl$)!f?%|5Hjwn^}~KJNEIli9^&5C>C8J(Km{u z2&z{teVQ_@%5*$^!~#6CZkJ=qLuy&bewk4;7XYZ|)vUJ~04(mBk{py$6K#mwjIJ@> zHKINu!PFA*4`3l`O|eNuU*DK?81GMQeQS;~_{?7o6J-I?Vaj~&dJoC#P8Pd(Rq-w# zr`4`tp?I#ILOoT+x64ME2TBJ1phs&h_)4n*u*F!=eqQgIsvn@YjI^*@RoAxS} zF=XMqvZZ2@@Qb$93A7D_6PPr&)HPjy<-hqmj_M!mWz6ya$X$flxAMC$_`^mUJP^Fs zK`C#II8+qQ6LUXR0k51t40i>aKv(BpED&tPx;BCQvpq)W56Y?O_r$8DGS%2X0hnd^ zFhDQEbQ#&+=HA>7Q9^0yNr07()My_ttb-nL)ze_WF<2fc6IwFc;{04|(L{@fZ%e~h zFoN!Nt=VS^9FEa;+UqHE=O8^H*9-KxbDwpYFX4M?+BU#Y>NHFwE&qqD_>t^UZ)uqb zT_?0%U`e{l$vp3s@0(_wU?+E$Crq*Ib-HuO5-VhTHz-^{jbT3;!ZRrhAkJ z0IiYrGCs%OXvFF%U1MJ`p>D+qn#*v&S3Is@yP`bDc2mu|p07<0DfMF`^joy;z zlsM4f(Fsp|TygeSc^3z5RjqmPe7L;W`AE!ZuF?-?4AUz*MF0V2?@6UZLy6b)I?e5q6x24BeTN%WX!dl>* zb8CJ+YG4b^J%#d8h(&%{Ri4Lpa|5f;4VW{lnKf~|##{j6v`3NC30M|W5xwl=l)i%_ z*RjYE=`2)QcGeqq1t~}vHwN97UyWe%FPAC;X&=`#UpKl9oawK#XIZ~wn-C!8Uy(_2 zf?09eE>Lxvws|0-E`CR%uA`2X2{V56ETU4E_(O@Zs15i3ih>OtjYE!0=NP*-NHq92 zhDy8=?dUDEM0jcSQFm$?lg`dCX!m^{U9Jn(ZG}-&BqVZO+O;FP?`Gc=$SN+&Gy-L8 zLDUMVD^ixB6!dvFEEAk|s*@yS<%dnhLzVutpynX^MKG$7pvqF*pU&p$PDpa;?{~*} zrOb55Jd3O>Hm*#jELuI~;?&m~pEbjDr{u3PHtAw6Y&@p^$!DS<>Yk?%#8qH)JZyjo zem|^4+%4bzjeK4@h$M52IT)EABKsY_5WM(R9HrmfK5g^xG5)LD03#VwzG`_H4#%Pj9T@0HIcWY?Ytw60)dtp}WzU}@4N z$|v&At4pjd&sUe{tICz{_wCJoEk3W;&)ecHuh)+6*VEuHVutHR|7V(Ybae6NwaK&X z(UbI9miHP1Y3kWzHs~beHrHp{8+OVJ02)99APw4YzV8UJ&1vx*u$WGe@itQ&S`QC!iXp1@vkd^u4-nuHzz)a{`tBPD!1Ob- zJ(HtJRbMLI94vbj=J3xK*CJd&-stRh1s}Aa$ClQ%qm9pb29#IAcV})WLrjY8v+U1K zcCLxK%~J|>>X=UD!lUW>je5+L2m}hiB0v;)N+y*)#-jffyyKnI9e`}nIM|BrT}CMR zWAZzouQe`6fHmP0VLi((?|W}+a9-`geE`CpbQ1w(!&b_1jqmQWu=otz7nr3O8;t4J9(f@VbUIpuKwFRB_|k0)B> z+_Toq>MoIufc1FHtcaQy=foz@pz2)S>Hb0=M}O9;upBS~4Z&reDMZi=atp^Bx{wVE zLI?ysPir(^lA#Rbu*5b)=DRp4-wHUgpF_uyWIkllI?1DV_<}I;>-SSt>D&T4WZwsu})v}rD^Sllym*B27HrtTpd=94XjdGvh7njMX&kl>- zlcrhhu<oFUb}`Tu~jvjzdebOF zWkIz^v;vfOD5B3@@B{>`No69(qtsa!uO;6X6+$8;~djNFkxSuv3#nK^W!k!z^ws&%-7^aNqSg8>{R`DCu;aouE zFB?TgCmm0m-g3%j<}{OxQXXjutUhAK_k2yqHV{}^7uNOcz0-);wL;air!Gy$INx0? zic#cbhvN>GR>=ViBrccFE_-g-!t!=al6@@G7H(OCeOkn8;jJxJht?`Q-(mJoCz>^& zxA|+Q047+D3}J&rZ2}C_4_L`jY4VM+7-hyr?fyj=%$SNpK*D$a8pIK1k|Fi5&hd}l ze$SLj);WLAnl|~BB#WShz8n#F&g!>osOMg1OU{ZHdflQ3Mcm<_FPk@^Gj(7H%mwRK z>4Np{X1Zu|yfZ(}3}X7bvuL68I9|7H0AlIO@0y8k^zhIhlgDNJQGs7K=2XhNTJm|; zJP~H&Bf{+BK<36hR*4IxfebL>-n-c&0zFORU*^$>2p_~Q2`?J(&INb&tD}k?AtyU) z79=X2IcgNUBJ<8&Un7L>tVMX_y=Ahd#4!bPIN{!jDTEe*6GN|3!NMJ~goDm*f}`b~ zwv@rzJV0)g=Rs=tBOH)s!P0cjn1-K-3B?V67$}ZcFUkLGe9S{WDg7gw$05GH_oh}e zv*BEXrjcaZm}}$`rHV%mvfxB46t`Ss*JWiHC!Xnf@wRsc@VT;Ak(jb05n*(aSbclm zXF7T*8_j&swuKt;gE z<%&^902!s?mqS^lvte30+S=+KTHt?W%wTXTGAtX2lhfXdWqXx{0+}V39(1E(iNu^C z?Psa4Fmz#QLaH;M^aA0Acx?RG*oYcCBh8u|f)KyYXHGF$%2y-bA*^-;+us6Gt$Mao zS&yGiR#ZY9VXRVgI&hpr^@}6jPgiSxZGDiprfO>CtPe zd0r|7l-v-FZ82@qXeK|0o9z&}iZ2vPWHXk7%8cVntis=&LZF9OG+rT(iNTf?DO|{P zOK+$lzxa{oRD12$O=&5QT7LM{wZ)L(e`7}sC)c5jgptlfngxMfqcQ)pX(Oq;9u;jk zKR~8pLEFO|YqTS3eEnn17W&b+Ull+e6+z=K z;p}NlqibGD_62%N$KD@?U&X>6;wBQ7Hb}rbF`*%(v>^6_na0-K$4AL@!Xrrngv-?S zcLukka0TiC$EsWd#QaY)C`~TtdXsi8%T>FjBjzjJ8JQl4IEqY%D6QMT`XTNr(Cf#J z(~t+h@FykqMlSeah;(dZDf#IZolsc3;J+2KV^&6LD`b1G?GU+-SC6KpnASEb;<2Xt zQ!GdcZB>#psZW$dL)w=F%B?_Z$6nYr(sO!(8)IFuRXP)0 zIQQX)`px8)VLo5Wr1!rq!+ssjNfk}1Hp1a$vJa!KyivojQ*!p(@2w-rgg?_7`Cddk$4Piy-tV31s`=YW?SoK4|G zN_ya+DwQSBwJ>Eh=d{qM1|Eyu(X%Bhq?;?ueAX|7$nrh^!<*18jd@eDf2g(VW&{1( zr%|`gW%Pk4a5_aTG>G8;&uj(TaQv|e_z|_^D?Y4k49)=5TqXrX{Ltk#feF_9Lp>)V zll(zri?INat%%ri(Pft2k#jg)`;Fd-4Q)6U+FYq5aUTE)Ur5sSKt!x0JmwH7{H>|zYE>y)M<={5w~UM zkx)7zx|Ken@_|sXMAaoMRz2ETA;Lh^8Y5#V!{#ZsKROL2BOP+}9!*8@4I^UWosjfI z$XxdCJ~(+5cp4|&L*okFdpst+@-SMmd4dWerUPG}p~Zpa(QS2?t{0 zAC^gT7c-2ya@_aa^5v&RgzSaVoVfPC%MKUJL&nYVn`)gU)+elbHAAy`T672RUHixj z<%!zy2mhe}T%c)ZZVP{g;mHb0RyXf~BhDP~TERTf+MLggeUyI!VIk;hT7O zT^tL$llLZ*IHp#wGUY-_5?~fbA@Edcvc-nSv>$I>B#ea`6ZC$#*KyXVl1qDaml&P9 z(~(I0gO}h}7%v6F+M|LQ7Qalx^^c;dEazkA)s=luWh&RRvQ{mMu!-td320bekSS61 z&byOXez_(b+?{-lw=W7=+ydg&Nf^rS!pJh`wpDUW-n78D zvVUtq3TqZG{C442Gy5^okXE@fdr&qj-Vg?X9giR+=TpVXl7DmE}rSQ~cyi+9F5?D}UDySD*l^RVtbkYHdt?`U<2To_RxJ{^Z z{%};H3po^!TM$#3*g+jWT*dh)>plS*aXeU$%E$d$09s z-N?4#JzZ?_Q9G!7Hxr9*>p_kJnH5_d@9w(^-;JuZYEj74|N4*eE)~1U2Vm^pe1}{?Fs# zPOfFu_TD$xZI!`9Hl&7)eV4Xsi32cga!mk&RFuA@A=iq=5?HNF9YvoXcb!gNp}dLWu$6S+oHrWrspC_MkC&HE$c%6ZSQ$<_g~SB<+y+ zKTU^<&8dq3ExggP*kAPm+M`4aKdOmciBdKZZCS&&4UdR|GdlbOJl3&N_8$~Im zi3(BLlhBam0fm|ZOam|@v|sA$I84T3aa-&Qp;FM>1D2rp-QXx<0Vv(_x&lo3vKTbI zV4UD@zr0`Fz#FW@_Jv^6gZ2$PJlD3b{@C7tyV9ka?sYSA$&pUOD~b~vD;by!euxsi z|FfbQb#NJxuMUSZW-(ZQwKO4$TgTVaa!{XHw!wtt_-0Fv%|XL6`-JJZRzk1hjlW5- ziS$69@dy;g#-`uZgk-XXUy$68-2QBy&G4)G{367kjB$L+ zx1Ai>JHz_z!gF-tL9r&!P_~*EA+|0)WmjR82pNwgnhbFdU-J}>ps}Eayls{kW!|eX zukD`^2eIULRivrhlWo^^$D>eK0x#_nqbEVH@P+-<(;@8V;KlFgR97LK#_OJiAqPhF z!qbdw21wQ%idv>G7wy5Mu9Ez=HXL(C!EcHMRDH1=g+7$@{fT3A*dzNF&1i`x+JM17 zAJC=QBwe&>g4WiukbLQbbv6tELC#T$qFwFuArRzUB)+19ukiemPB2U=RqA@kw-+wo zOusdY9zs3wzNP2eZ6rv$euzGw;)#-c`U!Gej38~j)QjX5<@xo4>UK|GLkrQ?wMI@w2EPo&}VV2OZLJ;NEdC31-K}Vd!ktS!~TgDsFb6^l--8=cnCugRMCRN1lozU(UM znBhbNpq9Duc7I|$%gV&g-+D-khbv%CC*l-Q8PG2zq>KZR4j@((0+1wxA>bTH%!CTZ zd1N%{#Ufbt%>G4`Gba8y6M`OON^hNV3;!Epso<9`+Qq9#E{rK;W)jMH0Kw0euMjCv zp|l{x=T~JH(mMpqr8X;D%yuFeD{O29ZRT}Ft1KVsw1S16dB7n* zB0?X=cad-5sF@AinW3u$r=8(y7UO6{A)+8jV$Cv8VF4o50aiVW`DT2;fOLX?zVlS> zAur4kPhX(6Ty!81(HdKU;ReIuB#x$x1J8sWmC_(TAL(f$FUa54N}5?IfX7*iQI3X~ zW%=Z6AgpXw#)aKhSWQU8FeJkR=E$V)oY}L~txh2)x)M&ydZ^(R4cV*$id<5!unoxU zQ$b;5Jhj2A1as3=ICBYklv)H`scX81@}wZ&or%c6N0bc)xf2Rh1rqwkpn3CVGdXSj z&&c90=-&EvzEC*HygGh_&l>0XUcq9x+>u>GZb=a22~JrSN3j?eQj5`6`w#K6{$%2H zhNF|YN36RK);9_z?7aT~r-N9}FZhbAj z4}fcLx7>sYY^rEVJJkSrrFum5o#F_#5~$7bj!y)@9T^r!xIt}2a%?adk0vK{M!dXh zQpDT*6lVjXnNCR|{i$L44g#K??T7=%KdROctr4W}1}V6$Kf>P>7VBZ3HwuzHhz&c8 z;bfero#$u+STH@6Lb6n7kA&yZ1)OeyhJCrLo_vJ zTL?VNB2Fb~FNC%(NX)U~5l<7$wd@ zct)(-x0O8QFH|45*pq`UE>;q+d>Bt!Aw8PlX6oVX9~D>fnmrqkNGj)Keix%IqdrJ6 z4*x)te#U37xVEv4CL$Ev4_$X@k}2egBIWKAP{%o>IdaH1+BaL2gglI+iw^w6Bak9T zIo)nN?JfE55Ythk*f~h%uq1rE;?bgs5gUn5$tXtNGP4Sgpya!97eW8yvpK6|=j^9>;0rjl8OaRP?IvszZbTD22y4 z9Fd6FoQjUa(9zFwAkN|qb#n7vd<@BGDjr`pvDQyVeLdkz65BdHR>s%_%H{f9#Gjlk z8;=J<81Fl?JEV&qQuE`K9a+CV|C954y)q|(u40cQ?w5+#`MBr@%dz!8OwBg1N%@X3}Z=Tf2 zu7?zGg?V&z23**+5|xBMw$L+e!J}e_yj^{efi3%oam@=3K1yr+-RG~?qe10Yj@Qlo zyQ*~m7EFUy&9$YQNZY8lVjZjhSns{AyZvy><#nZKeKML z_Oqagki(_WkCZ??LeDlOsH95-|763WSKq~o(5n9=FaECt3D&>=o6&}=9lP0fzuhY^ z3o0{d8_$Q(_wPpM!%n!il`nU(Q!5TAmD&6z|EGr_l!@3_zQC%Qj)KLnzJ&yqeODK! z6n!Ds7xz-_MLXB~C~E!YbQdlcE^E_gPWzLHSe5(G;jDD8*WDoD z5%mkpiH+LyXQ;tAOkps=Jj`HlF^HlVN%Q@|=s}AGTs^s8_&E4W}JFZ8q_qCw2VAUO<-aeMDBZ+q!K+^u6BO=0hW5op}uK$wA1+DMLB z8p4f<&!}>C^~(7bGZKrI=)*AtcJBYKH1vKD*6I9%d-XbFGcaH`Fm9 z2ryHmCGgv^Va5#yVn;m#?B)GBL(ik*I7QyMzy<@M&{qh<0p4|*N;fvXJy}g2!N(_7 ztnz!!neMM2SrrF;s^_0Xcz84|)RBD#8@#ONv-B-Yn6Ax}Tv%nVVZmVjRAJVgGK%yw z-v}+`PsNwsM6e^?}>CY4B6>XA!MLs9FDbb&txG?{xOdEc`2y*{f%C@TbHWF#n1&`Ab3iYK-aNwh{rrA2pHW&*qLb{4O*CWTwwm?{Eg3Dtc*&~C5Op?I@ zC5Cu+lL;VapBBS+hoP&Jo|IUu+mRTS zD%YVOHy)p1=`Y#XMq=^boGc++Ix67Pg}q!c5js`TEv@@&N1Hmb5amIO7SY|nD|0s0s)`j5VV4;a&Lnm@jzWfH3cJQ?XGp6SI( zPZP}c;X%z6SIUhRR}9;4zRC^0A=T~iEwv- zu>x!}|BeuZv<`$w4)1o}$P|j~+R7!?-)_pRA=eQUqc*CpWpa&k2*R2AWnZm=$wRYZ zd&+fkHtY~%QTr47+JyLR{o$>dPX%?D7~P+oRLaEdVu%GC49ZS9JgDvs2Hl9IJZDB(go+uu#l5gEgZ~j2O)6-Ev`(q;Wo6zIKG)d5 zHpviQiQjF+P~-*YYpHhmA2^Dvx*FvqhdezyMozVz1m`kSRe4wy_rgH=lC@bCF!hRR zyav2FC^gstQ?nU42KR1<-U67J+c7G;<-$9U9bEjr8f!Ehdu8MqvqNR@)Dp<}G81$p z5V?1Os-lAI{+!mmLqazwAh*e_bUZd-q(V9gqycOXb@FJmQU>V*%S%>tw@6I z`pKPf84M8yq;AeA_vj!J>a#V2qfO#Ju?wnrx|o>&oTT!k;8+x6zd`omY(rHRuEIpd zSHBF##VSjzwtVPgz{S+RB0$bYR&iMvhd6uuv;sKLtKIIHl}5& zU~YtgRF*F-aV&p_L#B|qL~I?RoTX63L)}H27;MNBF0*ioaQGo{;s{^9((=#SM)LM+ z$163*8mLA4qizJ``%dj^DQ5U{ZOEV)jNDVHzr1U@K&V=^4M=$-9|;htEXxsfpfBsB zQx&={trBII_SrL&lS7ASor>DO$Y&VoFKGG7F%^}a@Smf)h#3_dWQU8(4)fIfsWf6+ zX7>e~a23s31#GOPZ=I@I#M>!^63Z>k73iaZ4Df49p!8y56qEIn1N~UZllwQ$8ooGt zdqtcxla)@m;__#SU-x@HgQT!`P?FGbOoZcuu2`AGJqD>#ItMylumd2?Lz49fUCCB$ z_@9p_MfBX=3>G8+LT{ zOiybQP41Rp1VXk3KzXkvAbj$dEbUhh9RgC(8S$AUl#CFUD6u39OfcI>7ktPL-}FEi zsPt!C*M&NFK;Q15&=qRy>9$cUG$u#tOsV74^q7+X1?y6j%0|1;$=6)K@NW}r7=+ zlU|AH2rWQ;;~SW1Q=*1(hh`l3<-_s-QZ{Q_QFZ=_oC`Sy=E42 zQ=n#BG;HMwfZlw0r#QO1c~|~D^F|S~-3QaThjElqq(IrH)O*QcXl0gpztOIL6pS86 z_9UV6wvTY}$zq#_F@Yhc4~U(}Z=rRM6Qw&TkmX<@Fk+&(6YQxh(q{0Wd2U%7PAs`NsDa2prH$hm(U#*Ph6~Cmk0zr?xGgZ}sZT zD2+nu3j=&OMz36hCefPONXt(cNV~awjie5JO{r4>sNLig;+-uq(Q|i3;;6BrKJ$I2T~8nP)CSo+Q*J7nKBJQGH$#3}W$<6bV`WCUG`qL&{>&RH={N7?&+xLm+95$ zp*V9ILo=*s;m9yzvP0Bx5Rri$y;;;H-uZ_e&DJPYA&%1w){0A4n*LyWOW!~VyNc*? zCIBVg^@<@3sZonC23DS6u>L=jtT*BGR~Rrn*eY^0J;#L8?zagLIiI!p`>S=xa>7i% zM`=Yy#MB_<>ADf;idWN9$g)|FAk}q^9wUg&aOr4Y(cq%#7O?g&<=9%$h@W2AG)~I1 zZkRMt)fXE0G|p~m^KzFrM!j!Xm^9A!_?%S02kVjjb+D=I?Gn4kL&4ogzc=EOb)u~i z^_;8E*)7O~iM_2~qvEU2g6jTUN+--#hCORG*OB!eUZre6D~^i3 zx0zCE?>$IK6S-YhuR(OKP{pLZ}Hm!I?AAD_+b zuj}c~7ySRn*gH0N5`X*Jzu2~I+n8vQOl;e>ZQHh!iJggU+qSKf|GrP1x_8xnuwOt| z_k-@P?^^4#u4~K7{rgtf^?CmK`vdvk$Nf4-cjsr;H*xnB=Xvzgx49qP_)9?|EDHnW z*vS@DC4@Qm65r=sa8i}auOOHL*ASda(SDSDpFFEWV9zSQ2m{83kjiR%UC)AMH?-cf zJ!E=VzGtEw%sDU>XjDlBM4DbU$f;z9CSv@#$G#9_Imx7ONXgwSHmG09{aPRp#($F= zGESX-E#v?u{x6q28hh2*TGgX0PJ6Ma>n&)jlk>P~uyTD^d;mH#&#@$#!^mMz#iK~C9tYz0e#21=z|Z#*cshWyE*ISo?PYG^w-?o$^2r=fh>k|Ll*~6{M4_AtzaR>bn zw^2XHOeRcamjl@Vl4uQ)`ZvOw*>?<55WK3;VcYK^M% za43&m(j#or{@6#<9h9!{b|;zVl%qvZDs3s;5(=osd6Zc1Dbv{ava@lbB`{g6wuUVr z!J;iV&vQILqel@5ooJj8nh)!Z$%7Zb`ySc+b!X@#FV+K+6%XXwY-fFEc*j|ZptKOc zU9%w>_wQNZn6WUOo|v>YZzo|3V(ct$KSlD+pRqU_!p;YlEZ30i8e{3Vq~U;h)Ag2`g`o2=w2uo^duPgF8yCDXBBG{pW# zB36+)0FOgjx(LrMzGj!!^(POBiI>0R$i&trgPezSWNHo;kPa;`9!0K2OWt5+Anwu? z*PidcAAo0~iEK8KAtVK6p8}f}97XNHNf-G-r5_Ow*^7|43;KqDr3&MY`}YuBARy8x zz}apAn^{utDEzr59hSdQ4px1>$FjxZP8nF8sb~6c>fWUgLMWke#b5;CIglnPj9_;K zTKoufKX??f*^N(K$PMCy{zPrq7Snt%w$=}L* ztVQKJM3Ll0lvJG8?Ha~vG$0B2-Sm;W4izLnOE?bs<@DI@hMOqa z|i{q~= zjupS-EZb`&va7{nyprefUHE(|Bp?gr8$4m1%0n$Nf8nBE@p#tkVpk>4$D+Y=Zi_(^?4GexH`Kt~EBLr{51PKNC_~*e zS>DtQatld&qH?Nb=&i&-M}ugHcX~<_6`0NgpXp(j5FMw{`QGeGT%};>ae-MdKIbHn zq`=BuM=6&}H;Z0{)tKGe95WR}_T-yvYb^Qtm7&U8AbB>rp)MZD=Y@3i-XRk+Uk%W5 z4CKg5T7f4Rc8M{C!9<9|1dd5=wh{#bPo@C6pSOp@uXKL4z|{?8t1I6 z=V^7#na(31JZ_cd9W@T0`z~2DL2AD{ETc<^>Jy?$^(zQ+8~8-=PB_4MvJ0}6v=#Va znex$(yky)$>*MN9l*nM;jcV7UD>z_joOi%2f$~-;8CkBifx!JF`dCw-X_U9nsndv7 zrE;aKpM7^IOH`>_;3`4oB!Jfo@GAZ1sr?Y963Ew12H$#LKq92J?H55zfsuJpw;v>% zT7rp@P~`^Xf`)4jZ4GNJ4FVyShn1y)9(?e%NoY!}E7>~<3}n(xI41@zjoz1G;xIM5 z_{|P64Lmk?`kf4Im%)u5{QZ9^ZLz2pq&q<3PDs;nH;j3;Si~=>; z4Ru~4n~CfUtTqL(G0Qf_#PyeZmj)sLX%nR?cRiAcRwM{u1h6ZNCBa@JfsJLMm z{XB+VMjB)F>`Xeq)@m||Y z5`$@RaaSL>KyoG2mY^Vd#%)Jj9lx=v4_=bj<%tZj4E+^I<=Jl@%?kCG1RFy+O{#|G zR*Gy0>D8m{ddrB{py>@FNTF-@DzCPFd9Ejq?1mrv>6o%=dRvX17}XD^TMH5wA&0D0 z7WUEgOHvcKbs|u+F?;`XiX=oXuf9C8NB-i2tQFL*yIR$L#rz!hLEp1xua>_9_JOu7 z{l$8w+b)N&`eS%L_UG_6N450loo!<4E*`=A^_LX%c7K#=3%}p%P5+^jtB=Rm%Q??C z+{Ezr*SojtbBikhzmLcB$L)RT)m7>C_v?kt*Xw78?v}t|?r;(wSy#dnN=`d0zWT5P z@5o`W=2M6{m)&Cg)otn&e_Rv91fO1)yps7SBFWIF;OQ8ML$x1tKrLfv`J}xrj(lck zgr2j*6#*`^uY0~$br=N4ZV;h(xE#>0si;|MB1((2KhwXq z{^&Q7GV|#*A>li2p7)xKx@8oKxu|O<<5C-8u$ljjiJMGR)X3~?|1qp9p&he{6VvYk zsW#8hFCkUYtHLIaR{j{))pETAe8hEd1j6vS;guCo1)4DMQ=H@ z2kQHZt;VyDOthy=jJKoUfA0CVIwy~vaZ4tvFcR8KSg(P7Flc#7hrJ6hqR;!@@jIWE zq?wr0ERc&V^j2-WT!eXuhk=9&w23yovcnHu{Mmaj^Gp|di!9$m~z+dIR5_g>cFL5`Nc}wI= z5I0z=VU_GrG-?cvSfXi#rhW|(dDd3@_5Y))|BwrP1Q<=;emU zUab%R*GP=(!w1o={}&8Fzu~q-etKNjjbQKh-p@$vM_p9f-~U|j{*c?>uiNeOdiuIf zARyp+y~X!o_cm?_vHAYIzkkZekB3iRZ&={@_Sj?BTg8HxsAaLm_vzvW0SIvDy3YA> z<`iHPgl|q2gAR3oTB8Iwf-?g5Q2X8@`O%>NvjqI0*JDz@X*XXkPZ0z4SKtCc*Kj{0 zKE|S;Dhd2wlbOHM&wuOnlj$M(Si%8VcHdWhjfUiE>)&t50!%ajn7`kVUUyy$jdm7y zhApJl(_XiO$79t)?C`u0dzy$1YV=*+^lC3apWa3VBSRH*cQ#DU8(Gm&w`V) zXuGhfXdZcV7IrrAYX}I*t#DCg9?)kGlWZ}KKkZLZx zPp~>f?#HUjUK@QZ3%I^B{$VfL(2E;hZy$MYa{IE6RNE&D?@lL#V1hQ9O}h1nCZ|k{ zYbDeHlgH=6aE(|aLVFl8=~4@J>9Iw7?L8F=J&%DaOChFlaPmRwVs)*J z3OaPgk}m_64G}S%w%oo^uS6H|5)Jh&L>60qp+-wt^*M9aCH5pG>Ss%LbC{(XVWPZm zat0yN)l9>yqfyV|2U>{m4xtX^zuoYvGIPv7uH&W+*du&LolEa>4KM=i%cJiC7D4C# zSd&+27%`5CNoCI*fYiK1SBlhBOvryvWaBOfJuivNHv|p+N>u3KfZyu@k{NzAAh`o;y3dT$JY;!;pZFcSZ2YCu>|Nem+b%#cHp2CPkDljzvVu<+>B4?OX*IULr^ZYwWQHN*+rG zuVXb;Fe?;Ww!;0JJwn2*p0_NRqO%|!!{qmrhL#R3s)kDO&8TFb++?C8{Z_pRQ7>o) zC85sDuq85R@2%ucb>*l_Kg~9q4QAf(LsRp`ixlKnx}>OI7CFRQSYh`J|E3CdpBGF3 zo$>T9M)`(B@|E&0R~Ve>%k`2zdqU`kNd2y6tlK%Hq_L2u_lGH|qB{1%n8@Tkx|+w7 zUxe-inSFI}#O76<`^-b6CsV7h<3^R87Ukfx_d4UfkigMKg6y868Ef>VR=XVXRJR-k zM;tUODm|K?UMn8@flsO-%1U>V2pvj`<-it(s#ICVRG>6v$YtlM=mOiUUF~wUC*Pr> z^PU2W`=%(Q7g^;;^PhAE8IQ)wqu6 za-v~sdfS{V3|C8OB#i^SRmu==(t3A|)nwQO%6TXax&cUwBd;A2DXwh_mxy3QKl&|= zs<)KpX{tiyPeR1GCdmpW!>ZSlG!o5ZN-P7g>t#ZpG*nt>s8m)Mk=W=VOf5tabP5{Q zgH$R&VF5AL9-s^7VOL>3ao`!vEHaz;t;L60E>pL7aQ|>HQ02%ujtS-0)f@pmBZhwX zF|3EaC)uDsy>jS=1ZTe@Nv!W(G9B6r8!U-q3uf$BbcqFIpy^Es@W`l{0RkGRF7PB3 z(?JV&%16L_WssCW13wv)E^OQg@Psj#8D?DboXSmZ5nE?kkQ}T z^iZ~0Pp`{~l|eJu$JKTTb#527vM-#rrDzZI;X`c^(hD>0BR(NH$5^jsss>nFADN96 z$xGJSmEUkHd_w-@GH5}H?9;=ei)le<+i*#$)dJgd#|OmPJX^B_J?RM)PjWsFAJILV zk>b3}=^gAUP)|OMIQ*MSWM)WY1181B(JozOgeq33NZ&-N*lnK10pa!1RtG;1aGhi= zt6Cp*zp3%^1J@V#x5TM97{2kA+BQe-38(Whf+zK3h1wYa=X?8bm^CXvu+mDOe9Ct|+ZYEKU`ApScDc`1#VHVKufLl$M+ znROKL{jd=0q4Hhy*95_JFSUP6hnSA0=+;|MJs*$W)v!3tHut?0z`UN8-9~BxFuR9m z*`CBCoHsA|y2$`Bk%z&uqNd4;LbXC801Yc0q-TjP$} z;1-qvn7>hQ@MEh0s$y^!m@cA8AT6D2yF1wfWwcR>jmj$S>#AlsEBD#^?}t``si8EF z8yvLxXRR zQb{U%*gC}5BpKoiGY7m#TmFs{7&_g${>EH-W zcBgGTgg0jC)(9pJi_c5!3O5jCEsm8XmT+ce9$623f=GjmDUmoPA1AIgNm)f(<~DS` zoif={fD8y=vqg5Zlz$oE)c8@%i&B!J;F>^ofe9U6_(I}RzMUR(qVtGKFMO^PmfrvC zt_Q2C=L(r_6b_fL6xnRg@&x)@`P#yicQqT`<~6<+z`xL~rpy8zS*|S1D8g z#;RzQcv7-q>jbB-bw4fUSDc4WkWLwE_02Za!s9sV2osU-^y++U_65T9~1ygtQJlOslY~%x5a=-H+^IR zIiarNkli(-x%b}N2OTs5=^@qIiD z3*>%I3iy89j1Su$dcG?C7yq4SMk=9JMv!+RM5w}JJQ_RbD$nz+_`Y;Q17ri?X3L^v z(|-DpV(3yZeF&h1{j;TEa#UN*g|8{wNN!8KlBKoNGs6Nt(G*eyR0c*ZnSenvg$g|d zb7=94H|VnMc3y-ko}2JLz&uk>V;IL^-2V>%@9x)ttABtQ}k&&kc zb6?Walw&r2<$>g_^~YsPWTrVskof-s^KQ*O0#h#7!$<4BEjYrTIFI0C*UBp11Av zUw4n^ESrNY@xc4d$uX=4{wL=z4a^wFFC*9`4|rs4le?bqth@+Dcz+zhXf}^*5}P< z9e1~xDwzF9erg)oVaLn=Y4GvCB!jRrvHy2f6y9pg#?Yi2vb5RpNhP;B(M4*>QUmszwlA-}7S60*w+EvsU9l#d`!Bc-zlw&MMAw z;_c7B;fx6TRSj<`$Od2qK7HQyMar?7aQA$p6q%669($^hN#v#AueY;)DDb@Lul@ShD2u=KK_y(o@77Byhu7+NwgS%FjDDxp6h(6xp;N>-R#?HkS zD)YaM^39RJ&NaRz*-InW;=mAS_KcAp@a@|`u=kNDo3tx=KL)KM0Ke+%@_P`9?TUoA`u^GA;|}l7KdhW@?{;1ewX!z+aJdo_G9s_{ zrkhriTl@DouBmB!OZHoFFmxs&f9#z3R5xkzD!x)$U2#wp*?5C<1td<2zN{SL_Q*XQ zA(Bp|aj*%-=F}_63>s>PjiUqtGBc{h`2GVT$5s2~Kdse&{hjc3YnVMqm8f+ZV1~65 zgLaAZ1f6?k><2!jl{#I>gVwxaCBON!c!sYLZt*)4haHy#Vt`DI@=f&^4!E5+Jo7AJ zD$-xPiZmi&;K|(t__hsg(LK7Qb*LssiVq!`4On&C<_SDa)>ioIv z#>@1)8yyH>Ur@6|nYCO*yOtM03<;OFpmxNZ9|DrI5h0ZszY2a87+Tl?m_nU6|LL~9odTvK(D_2E&9Ze)md;qM-bz`))1#RLyc$xK15n*^ z8T{!}8852Y;JYy-d+HN8ZCG9BNxpV?P6skXFC7~I=+3khi89Nkgb0&;jq+7nr(IPz zrWTpigyEzcqVhQZVr>N#osYHeI45#k_dbavk!`lsBtAbF6Kgj~^z%rDqq z*DkG7k8p~wp|&A@8{lpBcA9sNf)#0tc>j@QMB!oob&+sW{`*0xrzbG1=vl(d(CPk{zON?5@k7ib9p0 zKn*!K`kUY?C3a1Yp~pRhu!or<{1f_!iUeV6EqLLsKEb8);JK@o2{r(Bc)~DD!9XlQ zKDf<6tqZ>?bmKkc%gR^~iJ3Nxb7)!EEYg9k4qa9GWJ{q~z9`N$37{^~6OjUpg^mV+ zO8pk2H5p8f6?}{Qow_bYLx1ZU{ISz2u8?l1bI#5rGq z;zTQ2Qj8|IWD02x34Cfv0wQ2?vfzOtH>Cf~bm)p9%Y14-ChPWn@XowOOaUFF#;dNC z7Oo4=V7mbZQ8Ye#Laim!@a*g)?($&d2cONlkU!M~-Xi2}Pciy0(fVYHd4sn{pGUn3 zpL(5{;*1G|+Uk*O32RHPe!`!TKWld+3ri!!J)1ZZM5!x@d>6^cE6`B`ogZ~w)7!Rm~9th7a63JK4@wrpMfdRv{nl%7fg;V~}RXQq;4rthY z%j$g~>s;|hgWZZ@Loz5LHeq&C1!*~tizxVOL{0c}P=Jw?axVwMjj~*kjn%x|m}jy< z;udR|UtGK#V40FrW8+gfO@M-I(OW|Y+QK- zMW-60Iu5%=s*&d!Yc-^502*cULEwAe$X0906+?~hUdy?!U3FSVZ_MvBKuRdw!}oY; zb95@kyF@H4LL>1nV~ocirFyLM$~r#+dbSZ%87v(xE*!iR=04UCA?l)3%AGnz%kE%% z{Lr|dK9#$D6PB;NC=ate#H9yQ1$ov{N>E6j_ER3ZexJAya^P6BZZEgJf8vFq*)~S! zsB+;LlG-$59&_G}j4-e;`{frwwY#y>R=0V;w09=ZqY;&91!{#z`5eMJW{=O0 zRHV!|FbTz+a;jlBOcoEO-Ccz2?q?nn*jFoE;<0++EKp=C;H;NLGhc5NXQZ>k>z0He zH01ycGLdTONq00_$){4sgc=`5`w+lSCxNJrv7lnl7yjs8xv;^+`$1L9jDfB?oDL0q{&Gq>r8lAQKa z2r+#bW5Khc89MhNs2J0a)MHwjjYiXoUV_wV04=vGKT=l!bNS{P*?BKHRSpi2c8~5f z^oUi&`mP3^0(Fc8a;=JQm&jRa7dNSOJ1mXns*k`SB;$S>94Grz zY6vu3h-mqPb`EnLv`ZanV2vp7GV`mDTTAd4uW^8T=x-H&2ibB!a;j5w+gwPp-G!uq zBX%U(ZJLy1>z}Vz6U5w6(@{IT00uTUB{zc=$R=mp6$loUM<5&~Ql%z7?d(KSX_zYZ z-bmXzUbZ12e)4*XEBHTi*Y5^-_A}@jpuNgSE(I%+efNkn{-XZYOZeal8;LZT_dMY{4rTGbEM|nGIKLDn7ZsHM z-a;`n%AjT_fy#i-je8)idnS2zPDR@JnHnmAn<}faU{dH<4iIC~#5e{T>1#B}BKhP9 zr}q@ZU{_q7bI+D<5*aJhZ#pcDBvU3@Rz0s&q%!M52CIRZ1s8OHd5(FfWq3B2=SsTV}2wvH(oNx4_kvp$ZTIo%)9a>9z0`;wBz(L1U zpeZ#LZg`~~!HqOJ^c+iP;Ef9l=#oNG-9E_!0-{5b*r-QLrc;hyqZ9#5;Aojli%rf2 zj|IcjxW>V(bR&Jcc_XO3&R`jq>Z+4adn<;z(z+;N64Hc=@hHKiwTklh$qkSm-l4_M zGseY8@LdlSyMu{eP`F-L2xCRZaYmA*@9PEF9>1>USV!QNPCnhtdx}NMP?3VRx~uF? zNwZe(wxwmB&nAFkQ`g&*^V6$o(T3 z>w0Q^EaA^LmmVSmRiqHGap^A z??<3n@BvTFg|)ZzFbk{d6xp+`e~Pbag^=k-WaPeYar$e%-z;Z*Tqk zx>@gN>8~XC{#b_az5Q#e^Zjw;{R$K4kY}Vc_X%B4E=!^ZLNT+8FPZ4jI3Yf{C>U~_ z3$gvS)s7@{Y+R_U)RyM{9ewH|oIV71w}44q?`#aep0Qu|C}w#_9xyrT-kSeg63STW z7^euGGLDo%C2EY2Q*~@H#?21LwSkNZiJEvMy-Ca%R20S$i*w{RRaLym5l+>kSkFe3 zm?jChBjs9OCzV|_$6Eb5LqTkpk*PGO^?9_Q2pcnbdIB;LzqIX4!X`PA zd8E8jQ-~y&*v(A0J zQzXXQUhqG+d9LQOC1F(NXW# zd8wgflThZlgHAhrU5Xw25y1hh7BB z|B`9K%*M&}-=uUuOp|qX#DDLqCt7)HyP2Q?fRtq$PqW!!V7^jo>>|NLlMcRzZ458P zX3A)z(NkcYo{_6DTn8P3P=a9_DwZo<5I9!d=E1+9f*jpnZSRdFA}x}vy8>g7w*HKZ zj3n+b2@yxPmsiIO83-M+JV)Pp#lZyqwG3RxgvNh@(V(yJ1bh}>2=KQrul^ZKcKleY zx4l1Z=I8eXy7}4u>TG&@z8wAYKYBdB`l>z0cX6fILR{kg_($T?TQm!|3k+(F|FzKt z3}Aoq*yR1FHXtzF6%{xr0tLYhwb=QQFs z^<`}yz)m9vG|U1|o6OQ5SzQdG;Q;!9V1XE+d;Bz=ADUx>x?;ggOhpkyk2I$gfHOk%b9wx=*UAA%cr5Gqx#Oo?L#8{+(*OueZ;3c8M-KF>1+z-2)Vbyo1VfkKP&=suTGVSdv$E6bCmD$&#R#>~U}%Si)7Y4{ ziA09&wb-#yD0SBrz0k?!xUPcjk$^RZdbT`ZhignP z_pOlKZ~%Jic%F$TU;sbfB^@9@20sU&^_kEP2OyYpo*ER4CCTYzW_MtYpKT|x!wlFN zx##rZdniEzY+s4wh)hEOVtA1lApBVS?}7ZTLeK!e6@dTr327?>*&XZ>D@lB)XQS%jPCWkgYBKo%E2|k*-e+^gE`#fZZ5916?B4(A2bS8~ZC^=mIku}dsxV)GY4p$ z4NE>c39lP#%q99&v4!=PP;#f}0^cLy$KOlm-}=|dr( zYh3FV{{U!}%_MDy>5%=!vC^0PI#23fJRFlv6z`gsW2kv!O(l*or%sgn)P(Y4<8(Kd zVyyC+woqqOfTClpQ>0m18J*{2{(I)%dFW@^Y(0;fDe>#)*3RW;&xHEuTh!XEnDhCM zZ@0<41GFtRV^ey9lh^f7Q^n8qd|8RyBQ=6iQ~J6uvW7Nx*{bC$zqzw4JbH(rrKo=y zcWhP~ohWcsmLux6*Cx$Fw9$UoA*dH&pYCnd##UqEEgxk?_Y6Uz zhc>mujw5xjl-|y_;ts!I&VAmh>OU^l1s^Qmx}-LZO=4Ssmjj zY#%Lf)?z~_Lqhnyx#}(0yI#s2I~W2L#lHSHXgqtnfy`N(HGj)n7zxd0De_9?#V?VK zr-&xQ1C{BmP=lB)V|Z6jPf;ZsU8Jaa(5mKdVG?7K`4h%A(_T>1$Yq)%y{;F z{PK#>DFlQF*RMQGFCn_y;~LG5o;vSlx|GlOJ0WT6zgUCKOTCAv z-8YuoJ`T(w>hyE7w;Dum8j)1c)qgF5nY3@%A_62oz;^4U1=TQoQHQxwc?=Sc)r)z* z;1l%`ZHlnl5ovbAjrtSoI8Q0hq$3*FYh(WwVVio5VO{j57ZGxa;y<=~lCsTx1941; zqK9VVU~|HJ!_zLS0rr0m!gGeZU`5Mgjy6d} z@5EqSK*n^gbW5sYjT%$bbgjI2$ z=Ham=H1)ed{x&%>FFtjH#}?W4MhZlGUvA#6_g~q3zdU?Bb9`l9<9~ggTRT2~X1ZPr zbh>-|EcrM-&kJ<(wh8!rK26%%5{xqpqQLp9K)(-qx9i5vhx}p$z3pMp5N?u_VxQst zSXzN7c=Bt9Xk<$er=v6wY006~b_bM3lp*4SIHs-PJ~tsXjaEXdP?&!CTR;H`m5(9h z5y&wmXsO8)d+lgpsiN%mO8wdVjiH!ihlOgifJxU7&{@)UgKt#5BL;)`3RE3^lX0#> zQwV149+R;uYOO4!JTYZCtAj^mA}b?qeRt+ynpu>=*}@1V5CkD*0Ujhvqoz%-`kxHn zglaAStH&2&6?*}7!~*MIa4l;QK9}RrlTWRN`HFxN_C6f><|Jt9V8I|+XO6N#o5irA zBT8b+0tG{hja@DvGfI%>>L!kjU0DJF{#{qMgl@HR__@WAa{e-Kk45*zACvm)w9HDX z_K7iu$7-;SOaA($kVfXNw)hFOQ4)ejhn#Fu6))#@@ZQt@Gx5}#CN4V@PwZZOanw3a zVkZz83{nXvB)?U=|0O5>+4;N#J0sp8dqzUTb7{CH{a`awtCZ~EJIHU6_XX-JeSJU%bYj=KEaJR4r)?XKT^8z1-k zp#%g!{)KtN=d;C0*J0lc=b0`az70Ht{{G#g9M>Rcgl^n0;WVdq5-sMM_Rt@+1;CHa zTgMfl8(#(iOitlJBsQo75Dm&W@c9?Zj~__zMH&dRcKHM#I0z7-@x7+=!v{nGh+`J* z!j{Ixxjo3Vi(IjS{B&?AGC@)C+$IwjnM*Zua0O@m|6`Sc8RqE6(|zFU8IiqoH`#Fh z3EF79TTa}owApL4oriev<1j#kJ+F0#e^w`0uuNYc=1V>GG5(bU0@fdv9|@}xmU_F! zy+9!ATli$&#qI-_82G*aD(p%$Nd#eysf%{AHu|jI%|Ay?t%e1 zlko;zlb)%TWE73FV`bWc0TfeT$IQjmDYmMHLAIp5*|#FuKCpEM1qg@rVB=iYtDZi` z#qIi|=6E>1Ph+0sIZh8~WYt(V*g9)!DbJ@@qKm37lD?)B$X;6>`9>70-nyaLKg%$DfWBAa9}JTpTwGUfX1w=|S=PxR!AblXthI%$t@ExTN#zrLe# z7kGtEg@lUtfYbkmm3CLW*kgY6{_*^Bk|qUB`gUkD6v3u5752zOhwQ@>;v_$9|~Jg|!L8>L1`r>kLI)Nj2A z;lv_)HY7d5wcCGPa&5YEogT-n^LR_Qv@#LmoEu`R%sf>_#ez+;&jvdHL2iCV(t zo*dF5lfSNFwI+EKUArO`rGr(RFbI+K;`avd;qy~qP^f!|DC^J#B4QcqR$Nx3bN4n` zO%w>yP+LbtS$ofWj2>%vqXg6l>_3rwT6m?P*SXGh{J)x7(NE7&_XuqTxNp109n73AYtWI>IiL9tnvc8uZ^Nb5l_?;s%X|Mf-ctJFNlAic;nWd3b5*gTyKO3aYdbBBky~|kU5(!AqQ)Ssr#!8;u>&c}}s!p2@ zM^zb?$?hNA_)0I(j`_f@2iU9|EWQ#rI5=;EbBd%@{+KfauHLaXpe?7+>sHU0U`Nnb zGMLYr7@n;~bS+a?RP!lj4p50QBt7XUHeu!Zgr`5^H!K8qNLYwG7@!K0hj5o;xrIAN zH@D6hcG7L7>o{(c>*tLg!Mdm0G#^%=hxmSBHeTA6!c=&sKZs{u)?uxCQroPG)kd-k zzin&t7*2dXooQv8FJqJ4;bs`Q`<|0tSNL0kfy^7mrkbDkGOYy8)52L7n{i<+oigF1 zH3ri44zNM*KJu0O8*~_yJ#M{rLwvhRVg6pJ%U1o3x#L33sfE&-<~)cWxKiN~(S7bW zUp*YlbD7*ylWgx*V+7-dAc1saBv1o~%qxR}ZIrxH+hD}J5kQ+V9*bo$b@;OLOKq>+ ztjY=O8I0OfM#|QVd}!rUl}M=aq@N3>)2tdvt);XuUQ?K-)Vec-HoH}eW9X54zj2$} zk2jp`V#%kL%j{P*P0q3$GNX005V)p#N*U6yvLQYhBI=ug+O+kF3Xjl_e$yseTei{u z3^rurM#Wy+0kRa^eo%#Y+n74o8rH=Ow(P|4ppF3V(*&hrE#8!50kWT_(J&CDfvu?g zdJg#-O6>GXpXHe~jLv_Vm%q`*(34x1c>lsBIwVvp3lE%-XJMwJ|# zeIUzw@X_YjKwwO^@k*jI&{;)Ysv!&ETu&Ngj^i12RcqO42 zE+HyLD+n771DK@LTpC&{8Ct*9Z$q0bk%wy~dxLIcvCl;9PSEt+tOLi3cYw?K%=*{EiX<2up{5v55+;a}|s z7EOL!VN0ciHSvFr?SDXIReTcgn;H`I+rSQTy6pdS1EglH#jbFm6-Q!M60MA?ga8a zQX!_DF)l#FL+W^_&KAgsk_PQEn8;v>N zk5q@Q_7|*P5@w1bVtOPvtC3}P!SQLYtN%_NkIKfdKfr0VLfdATMR}?ISo$#(nu(bf>OJ9C&XBf32_lqx zJCg*0QHY4Pfl;(X@C^z|Zlfv7-05Cb7H6cBg1yvS#B1y~k6z)eetF~3bz!~;1a zT#bsac%8lQvr6jqZ8N7U9Z#@@yvEvnuxKjIj_fAITE%TH${K0WFm{Wiz~#R9 zfI5XYZ!X)Tn`w-1!?Tu{zxZzZAqwx=%#e1NX^i`}9^&#lLsVt2^5lTBlAlvBe)1e0 zUlqPCy37q~335uQe#E$tRW4`|HdA_IiU*Vi8=ZN?F!mS!Sk(B!KmP8@A|chWn%0mz z$2rsZ_O#8Lt^`7lL ztA_dD&aj;dQ(YS)Q*1HwD#iP|L)yeko0(kd^O!YKHaWdTAg{3 zXiP`g??Hi& zjeT^gJQ@_SJg4H;G3&A>MLqmSN0hl3V!fT_YVuB{yFTDG$d|uc_HI#;tovXLCO+de z81P&+<1@RQN!fN^nM^E5eS-C+zP{S%LE48)s#H$Bz2IWLNPTzu-v1mb3vohvIr!4d z>p29g=>65l`+pew$0keLaN8D5+qP}nwoz%@w(UyWwr$(C?MnOPJ7b?6v3AT4>pzTm zV)VQBtF^$}N$A}a-M?<{H|}liU!Skvsq8nn9`HXOUp8(Jwd}V$e(n#i--ls0C!_q| z59WTKADis_yj5q|Y++7{l{CelKF6dP2D=J6Xc)*};%E3wF z@g*aQmXuAmdf~XvdM=~*A^mTB-;7=?#KUir&j$RG5O;tLDvZSb;gO(jA8u~<{;c?{ z`D`%y4JtwN51Q>d2u9EI#-~uUvHQOFJn;Wdtzov^`Ezsg{dPY%D<9|g^>68aNQ(RT zFSyRNdhjn{+jn)H-1o6{H~X!)_qb%)HxTLxi#Pjm+tdL1%Bz<*`!Cz~`GQiBIp*AR z33-SBnt*3UuX+F&n7+~gYry6yxBdOwrN98FzzANmyp6Z8v3Q7K%gzxii$Qmv2$n{^ zB!MmREwdxR-*1e7`2d<>ldk5%Cv<(NhSJkECF$XkWt8!YM81*+?>%vOjQaX z&}NR`&N8g^jy4{Xm64Akzfx18Jtkk6%}1(^ToC^ul%FL*2^HLe>xE*ySMid za-0HNi@_bvjBlH}|M6EY*k?$`!8Cm?IB%=E!(&qn$6L`cyyZ!MF>Of0OPsssp^Y`| zO9xu@I2pOT#UJQ47YjA+${r_V+B!`}eEF)A*%Juvrc_+S1kmM(ge>VicjRPM6Z9`0 z{5$+((i_8013S3?ZWR-MS;{Qtv{CEjOBbVo>3QE6ZcfQFXnmR^Y>!}(VEA>^`@v&P1Ru=FS;Cd(AXGX8g(^_)6!Kqbp5nZ-T)D|Jg0D#-VN%7G0K#0QON zFI`tVr#gEddeAEzx@O3;sOYt|hOGo6(`U3A(*o;-D*|F+5yOemJN+gceS2IofFSvD zI|6a?QOM`P6L37H>W~kSjz_x@dEDo#0N9MH&nee*Lzn#vbOBtwHkBe0>~#f|w8O4b z*Og`3c*dz}y0Q>T14g1e-cGk)s95MKN(a8vYm|D0K4f#2MocPrTPDt%grFL+Wqi{p zG^ruRh|+g*j~Trojefy|>x=mEnD>=GOvxKCC0_!1*!ZSN?pL00Z$|Ux!Czg08Y~HCB z#PL??+Eyh&*4~7|bQcd%wR(m#jKtKOgtTLp&y7TDUZ1^bi}jXNcFeeO;O|HzW=;%c zSw%L^MINdIPFfv+g8)9A27>=#QXi&LwoQm~$7Fpnslq8-pC2+6pTrdDS(LYsjw@?5 zOZcL%K?KGRTT(PUTw+Kmg!Kw@G%xG?q&HSCYBYmW$_=% z9c#T(7@(2Pzgh0^%Sba!jdL-CfZJRwZs*p?=q{=s`9#g7NDxNZBhGVI3N9W&J4HRVd1FC{U;itm1Z&eKQvKj;nb!Uk|ICFzT6*b5mRC> z26tmkHUgT$+*bX2w#Q9 z8egnEC~X8f#Uw#|9slUmI5lej7bc#gn8&^BP!%B?COeUBZ)w)z!^Rl`To z+J+H~aE^J)($)#{ptCJ0j(EIg=$(6}Pc7YAD| zk2{bhQIZN?EWwBjW&`c3=qD53C|fe}%1{A<-`E#MWhMYxWJaQIsTg02MoGkk3;rb( zlxcWbCrR`NpU0u2Nq>g@hWV_*XKrn;v`yy^X=06>83$T79?+0s-@+zaYmn~9=PMp& zRnnLOgeFo10o@=oli8#zhvW1xj|E(5`8i1UNo} zt7tkX(J=%t-AG5wNH)GxBIGX4Uml2_jB1iu%MsLH&@rJw{q2)f^XmP9d3BTj0T*oqMr@G&GYG7h!-O1iWUjf$e&?o;zsEE|8kct`7v zy0>D?AZje2XK9bt3$5CQ6;sYbSIDbn43oQb2QZH)i>x?^D_m44AM#hC=~r~Ej;K6f z-Ts}IAa6yWt`b`X&rV?;y<=ZXA_-=ZGi#N$BlmO4pLl5RM4?%idFXj{;k)tQ@LlI6 zHlaVOob0qrs_5ZQ$t<)_-LEbQPL1Njb#{IoE`IFpyf&ucf4`h=-rVTf?R5X#ot%G- z!f$WS`hA^_Z~vD&dV73m;w;c`19YLhlA3Ciahi+}qNaVwL?8e2JzwQ{y*4|ko>hY{ z@#b~Mi)<7oob+O}5Eo;^?=2Ca5-=@HG(G}Y3W$<$ z{x)4a_BBJxFg$7J<=h3V`N5M60%9@qOz?kO#pt>~H0b{mKKlx2>Al8Z>i*Yswa1`s zidL!%v98T%ncMjiqOr?KRNkAqp*Q}{sb>3;d?Db|n)Yq@`1?%V+AUdjtc~6PHe>9_ z;rli9SR~_D#xnh_eC9`P9K(0$O}K5~=9+r$WRiG`1EmNN?tZVk&|EWRNN5ES*NKw< zrOXdH0nI6bHT3Qv(cj;d#^LAQ;pNn!7+GPTlR0LC`(Da1;*V48wwV z4l6NL4+jH1+gZlM(~4K4Ot!0Ze73S68;uBR6C(}xKbq}P*8f}b_`ju9u&^-vA8RTd z>A0;C#GcvOJx>4jM7hpn96+?)h!st6h2xVaAggAn748CsO z&qMjau)$mK6aKoTf!h6++ct#nkKf#3_xbhF|MTyBd;i9Zt?OfU|K`{B{Q3B{h|lkb zr`z4}vHzMH1{k_pTN-v~;K{X>{VK3__jnob3Y#bhA8a+aboaQqj|#vrHG8>#t`|01 z3MFYGR>RpylUmdaHWvplA{7dV0VyJrQ?w7@2{Z>Lup4Ieayj{$4ei;OO}_As;yN`5 zM-BiiFl1zMnnO(`4-g8J=0(H)&(%|+s2PA^;`Y}B4nGL3GnYp^TYL=B1hp&Zkng~y zK~6d>;k@QWBGF`9Yv+H}=}RUt#5fiQQpo|j?#`)b`*X720m7hLB0@dYb6(w~_qS!E zxy9P;)Hg7tnUY3;+>89;=xS@-^T^v26~X$uUhrf7BdqiLtN?J{zmWp?Q%zU*FI#`m zb`7sv4z;2^*}!RW?cG5q+2?gFVLLKM_u(}wlE{11j+c*)CiccRw^Zo-HDex+at-_6CwvM#jdi+h{3#5& zDHyC$9gSGo%a;Qegq0({U=c0zNGsc4Gq4*G2acnGt>&Q zVanoA>jAg5W0BmZ4GnxglyD=k_yLGiDMF)X6a^ymgXto*%-7Ms)BjlZ&h&;FFU}g1 zXJ{fZTJNcR7BGuWrdNDO@@oRvu&AL6LQU1SRkdX^m(})1wPIBQ@$-%^h=^=o!Av~JFyXhojx9J*IbEaDyUJNvEAy5;bUEq9U(`p ze#v`M{Q`Rr<;!#O(k3p2MZZ|9q{QvhmWJ_zGqwrdd~r)43?(RxLU^@-15}8LSd1Nr z3rn=8Mj?w?f8EXdCRDepo-!nA9lJ4I2AU$=ft|MoiZ#e`*UW{Jzf$i%^Lj&% z*dC!%#;ezuXKY14%eDjy3Pcz>Ni|0vIOg`5j#VTqUG=G;Qe}}W2)wjNgxJ^9vT$|p z>II$Q#P>OvtyQ@ESu8@V&zhGegu6AK$)!Mqrqi}o*il6*OdDBj@BKlAf)I^Qt5#40 zWdIDM|B9fnLTN!9V1h=V?@WsgGM&fd^s>K_vFKb`?F{x`l>AAwqJxNCS;}M2rG^MbE zAVNXwq6}9^aD8|17ZD8^bv8*TdKyKQdZ0yS0QIhU*hvUqXRTevJz0c+C>0)*ZDH3) zgVe?;Iohq!B075|{1xX2ptTfE_u-7`$kStrDuY9uD(MwY z2jjrf>4zbs17k{nj^v>BeohbCsk>Y&ry30!2X>RaQ;;rYX+hx-@$C4@0-is>NV-|{3L_lO2?C5x< zf-kpSno_Ssbh_~~NEvinRe@`Sq@e&;PwnxdS&5c~OzF@FU=wpejPr?&Kb^S?T=&hX zf%zg4H~m<%UuH@m6IzhP`Wry%3HFsl>>~0}&%gTPQV?+!Rd7dXKhk(Dh)f(Ds(VxaM>v$%KewgTJ5WUR3J=yYO^8PGAiAXgQAHIfa(0aYP%o=; zy6|?yj*yS1#HT=-Ain!WV+iNDRKDE>Z*Ip7#Yx9CT;NZ<*&&DgIR+H|VlusRU`DQv zD*XVlno2X?uiq!J?!lv8WO+{2=^P}0zqN#5frOJa_(LzcMNKQHTXVsYB@mGfnOjNv zDvIlND9oEa2`trjkPk$bH=Q}x#@bq9f7So70pQcXJCFS_v~2%oIu87J!3Na zJShmlY}8mCI4ZVOn&t9g_H*hL<&!E9$jk^g;1K8OpOMTlGylA$xt#G$`j*jqI&Y>e zm0D88jw|d5^_Iz(TICetxHVLE0aZ-0nIeyW5TehOAp&^dKU7z01H(X`!Ce~m$@_jD z^2M%RZ@__r`^EJyTRZ|RulZale^H#oDE)!AK^a@wDd6;s>FMzpF4>)Z33nmTfwdxF zWK;l7&#=Z-363_>L_d*(C(qkhMY6T0y?Qa%h?=ts;|0Boey>O2XVcqNGLk?J;~ka` zcHA=~B37^PcBg~dRlm$c-&8ygX99fsgjLXv5W5pN+H8Ih=1n*Gbm8E}6=qm{l#wXI zrZ4SV&%bfAg117{mQ)tp;)k-DMEL-**`dk2?wZP)W;$Nk%()5SibF`lcQpq~MPPrp zh)|pm>+dwN>EU^kcRtVXKf0AN9lUvXBT*uERrJ|c1(tz2ZSFnIxx}ypSz)Q~!qg3%#7!D zJsa+oU9Y6}jDnnC`JQ&WxuyKX&8PHh8ka5IS_rQz-=!`vYX>_Fh2-1S>UyzH)?p8b zPJQOhequFKct`*r8p{O8*dUAA#2w$z7_L`)yt{fikaj#^{ues6(X-C6Y>gXUJ8PeB zz9S}9$q-XcCxW2TdByl@EJXKD4NjU)IKP*C>Y~)_ZekDVNEyzEZ3?Si7x;D0yJ%00 zSIWgS?CbvS@b|woOhW8HPqSYWDX;S3=kOOvcPsyQ%X7i^D1K~M=ZAdm?$7&3Z{`0` z$ho)v{}giHpZh`km&M;hm@B^jheEE>Gol9rB1U<|&zg67cfI+~g5HYVni;@To zBi{@299X84cLRhQL$WZ#)O4HnOk7NjzNbQn%HnJQtE_dH?<#I{PZhL0oZg!!CUk`; zbPUbFUS=*iQ$>NeW6!psI>?iTS?(1`r2&~5AoyQ!V;-~0g02;0gW|peBGSui=H@x| zT$+d-tLqYzy((y-&ZjawWwol^A?!dWFKTgj>D(qN=bCW}55^w^CA(IEuw(wS{X0<{ zuC#h&{-fv3?*pOMStu2`#8Hc-eI46z{hWCwT)SqGEU4T$2(1|VKNH0?c~sBfe zC1sR&RwWB022*!A0I&&x*iB*w`A~kJ&sWUceMsps6jzXrD=;-G;dbli%QWOhe*KYMg{_s$niBrA9~7s3617hwi|}H)?>K=z)?-YyxLH z1xX?KKf!IXAhXyA`OSugd_Clt;@K2)_HlT+Stw68WQqZRdgKRC4P?ghe+zE^mq?CZ z%;5itK4GUZW~64gNLGSB z)Cp!YUu1c^ z{Vxpv8yuR}8#c~oG=vdGOdpM+jr;riYp>Va*UkMk2ln>c=@;TS3eWHJ_W3cZ7ph*1 z=gaYR?BKuuba{U7oR$LzkIsj{#`EP#fM>vT766eK4JY4=s|$z#n1|}W0`QL00}VhN z5RUAhGHeIZXAdyFI#22*xVU6Z&mODn85jW4mG$# zyw(PIaSf^WT=?yBoxK0vBpTojHd4*i0)5rdL5&}ovzRqY0APp(CWt|zX+v(gqz&H& z1DQu{TMYX*B_^nonGB;))Fl)JFyWPD+U|LN)&zxSGp|+=`l}x_we)~|9%v5ef#;mv zxr=}D`oj5@df?I5))Q5s@2$;#t!Sg?8(M`z4@~0$zZ7sIgT9!}YR-s% zG+d$>^h>LOa=DCjw#UxcOKG{(yeEBTK8308TUOz3*Ll&4As5-|6gkCBAI}(Yq9r*> z>F&16w+Gm=T$C-TWzF*odyH0C*Tjkv;?fyfoC+LHyi=9EOY;(5h+L@zUWIrw;h z#b)ofopo1hmICA>UOF{AyhHx(gji2F z;nUr545>FN?LFCP$MP~Y5lHE7%*f5X_Pp&N|M9^haY*j1qE{^C8Lh;s@I2tjD!M&1 zU_Qd?K6CZmlX@nsQWWhl|A7v|Nn>mhK&25<9koSUkDn87#Cl(3c4xw%<<`mp8 z4&lK>QbBTiiKJIrMT@6+sdqvW>=1{AyJl7NI^<~X)LtaFRkY$3_Ex{7j8&l1Ys{lw z9*cdo!3p)1#q8o!3n02ed7*la46lhGhh$I8@y4>@b}KZkk6!a#sK+#8udZKsby(FG z(yD)?VY>NDK43_mD5^Eq9DOAn^u}Dh%FhHiT=J+#+0>;Zh=)1;GH@` zPm$u+o8U$1<*=u1brXdbw9(hC#9QAIS3wxiXc)=08krwril6HLsh+;E)7;Ow3->yw zgbW{7?n)I!v>5`;7bkE4A8s6ruKb_x;dJRPp?c5$XOGYapB zbhY8BTq?d;Yj7IrK5WTlH_rBHSM2Y_@6>PEQ~6N$;z~G;ki}puG2NBMpk6OvV~#h2 zGy2*;{NW^Xj#i~uKJ9c_X4qgo2;Sv36q2bgv}*-s4Yq#I+YybC|YdzMxq4;xJ zh_hX{-ogVM&VvXk7vx|#qm3NR6Vg_w)=G1;i1iCem2&X&w{@+R$s#I_ua4199-A{x*D0rpGD*SidgA5z zeYw2PsyHf!}%2HhKdHiYNx}L+V;8c+R-rHcO!g`Ti zJr6U8L8I$%l1xwNewK-fks@9`*ugh1JWVi?t&?I#hm?X7ZaI_WBj>KIQq2C?R+WKF@1FW$^y zQpPOQyZ#+xu9h=+FYs>0u;3kOQ{(+?=Qhmmig-j$VmJ zI?}C|bI0J6ycoWKuDFTCw{&UE5(ZhSFIFldrQ6SKd%|KS-6o)rcN5#0k&iX*UU9o% zdct5_xaQ>20@^-y=V9=LJB9WAD`KrXK=BSIH*o;0zfv2%RX!=qe2>kR#`@gibVEt} zx-3w%O`zR#2==xmm&+1&pZATX#9qZ{CpZnfca#J`Y`LnH2ZcAij@iN-nQNFQIIAa6 ze8lwGWza%YI&{mtoX$(RZjT3N*EA`oPcuZQDHhrCf~q+YE9CU2FGT`zu0>#WXt9zM zWA6asC1Teh(&I}Ccbm1o#RDXUj(IoPGNY`9^U|Sw)E?mF-4ETq=CB33ri_xSp|~A{ z=G{7pVNQ9bE9vgZfgy4gxb}3PA&5JDb{MNuv^Y>@ufB7+bgSrAj<%G$O8s4`tE>K7 zz)V=yiCy=U03)1*-|frm8gRWh7_|fnf_aJ|X+5}z@@5F$xh8M~%LWExgEjSH*GB5A zYyp7WHE(c!eFV99XP98uq~cvGBJQ{PK0W#3kWrjq$D-#|si(RLze=AJ3|W`1|7WoA z995t2;9w6ETG9Q>BiUPsJu=lY=n0BQoZ6{Q0I9oVRcjTOfT{Ls6+`OldUS?|I(gu5Re`$j!+aK_DJzYPq2JWxt zFMhrb{NHcanR+|Ebi3wMU_gZ^&()P3bOmR91oqjl1jJ(hU0%U4@O&|~y=1r0DYym1 ziXoMQit;dCgG;f~^%VnBmCX!bl{AkST}G@N$O2_XG5ZO|4B6%=CDRL3D<~#rX(|$R z9c-1UV_)=7N$6N+GzCuz{I`TlhdiR42uUTt{%;94hHicdDc_FQ%%rK1vT9zh)AYN9 z>v!E*cs@Zc@Ny8+jAEa^HkDko&j}*^M4@A_C{2B13y^hgx1`z8F3jzFKKK|Hu3JHt zRVWhmP~O*+Z*pnX6UFyhm&*jnSV7K-a4b?$pac=}$(YY8?vy1U zz#O}GmES_%r~kDp^^3bF=#8$sF33(>=$cb`D!WgcZ@_$SgMA={=oZXLqj*LL&7y}i zu}vyUoP|zO(5onx0g+;(pD0p<;^RkgVCNRD4T<0lA4{Zrz4*ZiL`{?Al{JN|oi^{o2~ zPxl|w7Ks3f1}MIuo5f*Dlf)WZPvj5-3+Hvs8vOk7-#jc7QIc0(zGgE7hILCFy1u5a zL|gJ*L@r#u{ig(BkTv~2A@iqV#Vt4 zC9(wRVGi#^9dBq_Emk=~gNcuFr0I*3$rNlPdU!OQk(aSVe5A>E>h)B6`=j^zV}vgg zlbP$2pUL#(ZpJ5VR6)LU!rlfx*{C);ON9+Mm3*Z6Ijla6fd}cJ4|?^KO1m{o$rW*vTVFN=0Ms_ zu|eUKg1}H(7iA?ZpplzI8$UbD66&SsoVxZ?5S}rd9MNOg>;Sz3U(S*b#*g*eh=IA3 z6?da(D5LK-bV&C369No~063!8p_!tx(X01Z%)n_RCkKB}qt?Ub*UZcrj2pV4LToqS zH}=c@uF78TXkb>_I_eT5*ab(&EI>o+;}y=yoG&d~PGAAfR@^>sspv*oX7CyCpxg(> zipT}Tj`SZoW?Y(#NV1TJiGj9-2McHZ89L^9>;Zj=9TZ)+Nxdg?hyvSd5$iVo#Ixk1 zoqL&4azQIYfUSgp<82`EB{V};^e`GaxpNKKAx;>ODhvEb3Snh%Mj`}dT-vk2&;Dje zkh9_VyD3gfznpBNhbJ)m+zF?GQ${F*QKQ4TZtkGKnG?xd#W@P16?ElyT5f|F18)oIZUcrgA&)FmCZFs2k8IvV6_%-U+% zg)+5Gn=(lJ5^D$;>es;I%yPu){(`&PGZyef)tkB{YeAq5yd1COGa8bYw=RfB+=o-> z{_`9SQNR`*6(=flAG85F!Mr%Re1$%KBDwxWPahF8<68AV8u*S%7~QyzqWTE1C=6qK zAgVfx0=O0Z`mCTn!M#S5E11>r28@=dlo$ZuY96)HdNQ#j7N{@OkpR@BM1S)0^_Z7B zt-t+@f7CEa!38N@L5!g9=>Tdehfmy+<0k4@)6>zpV z6U|?o`QT8?=p!K4>1*fo8)^0WiNJ)_H9_>JjLw)>35wO1hW|@L-pGYoTMl;G&Tlq0 zFx-h+xW1ok?h%Z)aFs@$q*Zkj~)gp`>#W_|2YV)WC zqPFgQuCQIR0-GvAc$}+l32%}!Fd~cZburhWmiU25<1b#2*-is|6iZLq85h|=X9 zawaOa!MW`h%M2Gduq;8t0d zxrnHt3~bM2QTIEr$Q>g~W6F}T4~(BWVJ@4(kcWl3ko{p&Qyg(ybVT)gl&p6*2lHGQ zjcdi`eTZ=y!82?eQ!u>hh=U&sn_&OyuluxZWfkObk2R*BBgyJB5|aT_#H39S8o(hc zAM0kt{(vQLeE%FVhq;VB=VA6qWGYeU(icd8BJhJDyU*>_4SDXUO>u~OOo@^Uc2wcD zC6%)s0;#$y8Uh@3Wt`_r&0kH1U`uq3ENf>ECwcFK1~}*h1RGU_K*oION%R~oGhYIz z;Hk@`Y23~V`9(>6_OQtqPPZ@?82-KI%MK%rCih}7Mj10iQfEr@@vsN>P~kgvo^)37 zmgwT(6EH-fPQ|Eg=yX%OCor`vXbyHj$TjdDVV9GEgLK@RGargmrt)93mc@+$u_xn0 zS5Zo!WHZ#^S0A>Tzw(SOotTK@ zR2@I&o7sY$l$>oH*NVqTs6m-LH2V<>OL}S|6cATL^l%p0Wd$Fpls&CTUn75O zt^dduI2=#eUxo}=RRj7UA71~_6A<3{!2r(`49~!3EHW7dhTH&lAW8upSjBsiPee{p zUbfPtxkhP5MC}fS)sTsjhFq}r)+M1~y+0L@;uFM>qJQ&j1In;!YohaqvV^D zk3G~9j!qVW0!LIh?mj`L_0m4Z166MunPrz}x~lcpsefmw+gD54C*Y5g74}Wy=gq;=G$%PR& z0h--yXUsv{Lk)rR8OnyCJwj2=yO4yNhqNh`ePC0P@Vp91QaRTw{sj8oFVwgiN(axx zhGY7F78Kk+WAq)!5!GW(e`0#NMEpl*0%?}7=UEY(=YhSK0(#;~L5zTRN?qp*mqBm2WY>9M#Odjp&z__<%B+%F? zjH}m9!^Fk76_yC9^g-dzmrMU`Yg%@*Av0KKZ>w77lc+L8Bkpr7(--~-nM4ozTwR(c zH6PvDB-I~z{eCtkgbar#Oy3>ixbm1j@l=yW5A4X?HO&iA2~nv2jZ%m~lp)l!5Yji) zE(4$xE#TEqStn`+I3bRqTP#HN?Iv_xG98rkcqXmj5OPp81g4?Eil#S7H^1vKYxBm#0v|XenEAy_e+!BV+u+OTCdWk+77ds?7VN6-=-#(RviFbcSiPj+r zq{F~m(F1(yb zk>nAjd2)V%ma8~@5L>4ygbTaakZieBHC3mToiM%UTl}v zT5eNn4`|xXh4p4OXBn$1gVj;Pz{5yBfXG}f3#T=!O%u(^3L3#<6qIAt--&pFWrB;! z$Zm6nd4#dNHrCTLRP!VJ+FQud+izfpblx$}q3Eh7umZ-CMctN+je10$<-Wi~o8b?S z_|@ur6BGjE_{6}!>YT4Kl4}#Cp6ZO^mF{C6jw{733z7cQoc2@JVuRGCac>>m>!vwsprxZC{VAcTSs55Col7I`62>qns-m3pgk&<)AiQ<4QVc-I8jw2BVq| zmNinEiP5!(-kM-k`zP*A+X~CDUS%USBiY%0^EiF2dX|+P3AfGeYlvz1&iA(vsjtrx z_k`sLOr)=Ppsdd{d`RNa3r{QSG2^>{P}RKpTo_`h`yDl=GMpinXn}8rj_{C05_;SZ z7Po-e$4L3-JJo;0E$;ilEUH6ONl4`B(}&7a^Rsz9x$2?Svzdl_0YYn-{n9DJECGJ~ zBRJWeB7&JiZcwV}=S_lhuU0A(;{KB!8CKR)^`~N^$J?Xp=qu47wE^R`oln_%O!4OD zCnE*k($*VE*<+Rh%T2 z^d@nZhgcd7T|iZAz7jG|-g{r0)sv{h{MeXsl4y#pv~Xjin@G_5+(>hqB6|HRn<1f3uLnCV z*8A9HI2m6YCET~tqZah4j>WC*uK1;`#e-lPe-C^MgJb(>k-2p9nb3H19!Y6mHRV%K zY^^`H4x(kTBPwWQ3$!6}7eM#OcnFTLUr_cOyw()v%IuqW3j-Z;0SJ}$B}#+>{k(yt zir?Q_nXK5$lQH<)AU`LPWCe{b#J-jKecLbAi$fL5g0Rkr9TPk(J$itmgmUXYtqQ&? z9C^bK0b`JlwsWzv?#V_fw_06ZgH9??8&a`3pO#70=dq%049}rMv{X|_=rV^=zIp)y zW-U$i)YakGS%@S|?zH3RdUGTROfQHYuWvSF+5ZvwCmcK}Uo_G6M?@xewX(g!UcMMc zSTt7^GTc&)rUVXp9qxB#hf0qs2ChAY#>QZg)V#-IwhQ3HZkDs{gDDVK-h)8S;okX7 zyk5>j?cVv1u5cg*qP{#rZw>zvNyQas&{9S?Z75)QfgL`KXA;ir^1wA^@r!Etv*vum zK>nRpqCc8ym#s`TDD$%jZUSw>&PO_h>KU`BH7c>7l?PYE)gxx<;-Z=$J&UpyIz+Vp zp{**6N)V)oSG7!wHEXZkjp&Sj-u8@3j z_;@|JTV&tv91II`X4hE5T(sl=@zuXc#n*NDPK~pJr`H|7xyI-FaQJ*ZZ`ITLI2s-N zRS1@N-OsMt`FXv(FWTMiy3qT6KJ4ahh530syr;6`JLrnIWIYu!jbLQEd4|h1{NcQu zt@b2t$~ao9zu8Z{Aysik#e;Yecr-mKR10J`rI;zrwFnLPK7CY-(Lx%aMZak-_`M$k;01= zqdH9rUc@Gtzy0RPxCx1=S`oOj;#x`;wGN)uvNl$s6aBR7zjnX#*W;R13NUUD1%G5d zNf~+#tk%jc^IyGx#jo#kzqv0wz7c-$DyMPVI>^|KH2GT7M2ubX72aDVo8*RR0JJqJtUQm8|Ua~WJ! zsFtXM72bsY&=pRvHNkG8hwk)ucP^L2|JXPn>%gLCAx~x1nJg@$(Zg_M1X@oK@LJgR{ z!22HH`zeL z;a@C~@+;l&Z|~Ez2VIOOUBQc-badbG3j+PZqgdLulsyEJpOLZ zjc(oV53;n=ugmY{ur$uE=X;6Q%k^dZYZsquf!B|ZZ!32swX_rZmf}+P+q1y7ziAN{ zH3%>C=J>YMEEq#L91oK5S2_1<5ZA>P6Z+L_oHh2+L!iDG@1>q_tH`Y4Z@bZcVpN;m zHkw74`u5E83qzoq2}KhP*?(LeWL&YD*0#@X`Q@Il1~)W*VY~CyYKec>bb_r^m9l0* z<^vOIB3IBEBP78jAX7zr$*>ZtG@Ncv`eozk(FNvE!h23JmCPbTlw7aPE(8wJ31V?y z+vA-YturR!$9W;h8^wMIhHvIzU~O8_ly`h$Qdnx?04!&HF<}zE8=kHMp)FxG)dbGO z6n=W*ePM0!AZHMOYQd$iSSY?@)M`*A4D6QL(nMXb^bq{LcW9pX^9?t2(|{c-0;4g~X0kSsVcTxJwS37wdtB$29|L8Gl6h&0Y-ns* z+4y5~QP#~5d<$zp;)b&YzBiRtAehJHt&R+grR^BGZGPyr49KLW~Sk77BP-f zuE>A-j{_FL7t&rZZ+>np1{Gn3r50dS0_9L1OsebR&nmbYDllZw9C$I6n^#q>mn!Op z8#q6?N*olu8|pkSdUOMh3q`wC=vbW~cTRT|Y+5cKgHSjK2C(S~iCc?MaZz|50icub z3vId{Uuzp%CGbEalDS3$4Bm_f903l`8vso_^~!Y_ah4K zWm^=LX4dL1Y-i1uRvfkfvI{Hf=Ojt|yve5MOOQkTISQVY!z9wg(CgJc=$yuf6dHtR zDQbeg4{?ZQdzgQg-}d=z=yGyA!7o8~wGB6%%mw7cE*Kg?!3lz$Is{D1$aF5TQY65Y zrA#9E8%-nVa}&>;w)GLrLbKN|)GB`!x3HRq3qKZj66(lh{g6V^;F5?mI{0-8_sdXV zj4sM&siC&wp@XQd8Kn;cT8uNa2kpoo3BpEZ8%4#&?1$0%oo>dA7SO^0#Iy+$SNa^n z?}rP+UGpG!K^1f$+D&rrAI_xZup;};?cNy7{`hs?}79z?qL-*h{~f#P@Pbd6f{OjgC49N z{s5K^aI6y1u?|&kWQp`AU`KiWK1ExN4sfI4;U0H*dBI2|!1n`TsSvk~61tF(mhcDC z#!V1=6q1@6ql-8e!1K}L=fVG8)v89G^PNKGlFpk`7ag(F%gy1wb8*enQ@Zh*T#yAA z^72f-!Q+}Aj11-4ZL_dgQ;op2BxkLQ>Ceuh1&B%KCC25~NAZPITLai{5p)CdrqMytYOiyG>)5YlqmTlYK8<1Bk}J(l%74}oqFVkl0E8NF}Z z_G7I#Dof@Kps$!B`612`V6+4Ed8n6jf(HD7%`d6zRq~@WI zhaH3v;R>q`nyVxF2@=rUwhgWaMyEVC=4-@Wg3+N{Gy@4}d*hj5E-wV152${;{&$s^ECFp% z9c6G9bg_|y)@LpQooCn*+LFvSt6`ye7GLcAD6f_4Jk`#)%<%tX?3{vohyQh5yQ{Ws z+qP}nwzbM%ZQHiHYP+kpZDaNHzt7FtXZFRu$RsnFOsnmcpv{bS_ev_o z$HkaZ7^Bm9ygvZqg8Ss4)Di`RRwUx@2oW(m=y<%!P>8aw?)kL{nfa4T{6 zs>}iW2L479kl{!&*=Aczv?`=nWZ*4ZtYfMZNijCbTw&gvobokONaaZBJQ>bGiT(Yc zA*qP>)APiIG!$mE5$)5?R5RY|Z}t^71&q+5608Lc(+%)vEUT28ZbuX=@3rjjFtnOrT0^#ILnS9U{QlVsyD#$?Y& z2@LiC2rUd$vl#p&J%KQT;dB&gFogJ_qyn57SgFY7OV9W$R5(Lx;sZIC!cl3Pfk2gk zB6MAUPI5I+9WrqEKu~4MW@)Als^-GgWBm=}p^JTAtZFwOVR}@O{*$aQNz6H#m@x({ zSeV#M6`#(!q3kzve){90tIaMhnSlB9I5&J8dy(`m1YcurQVJ*ucC%Jl_rRcaUM_^o zOBhmoI=5Ji!0-t=txE(A z{f~(#dw#mG5HK$_f2V^6ZQjA~CpvLTl%=pu8tp4clO``m!*uOFKbu97C5~t-tEj8Cb@pYlK zkbl3wnONOOm9CjaYhg)q^mm7q*!B`TuZ4>$@F?@@rGpqYfrC-$Ax zE(%?oy7S$I1Ej%ynAe5o2(INut*X{YZpmovSvZh4ixZv|P|I#~9Q2_l1uEmkH4mmt z_}*J`91!=!!@*(0#WA*^h)!E$A zw*I=UQb@}3#%;H?zDU+c0-egLrv_^u$mk|WM6`a0BAU;94E;uI!aR({L*WeO@p9ZQ zEF-a!OVwK6m4byj6k>;``DM)8bkCYgeQ48s){CuWyrSvP)W^HH)n629UiUUJRyOUj|WdjySjq2V9`rDKAqnk<_!m7Ubp-@(4e^?-KPCukH|---!rcsD=fb`GCd}Z ze0`aKG(A*!{mGHiJFE^{qtvlvxW1zbqnOrc4!k=8YxW6Es3(BkpbSjL!#ozPYO|Z1 zB7P=D<}sfrx1(a)39UsI43uLV+RJ=Ljtj$1u2udzq#nvL7u63`L9tRNmgJ_|)~MtT zP7r;iw_+OdYcY)Uhq&XJy339u9_%SHhG21bexEj0r8tg~U{q`>wp6yN)l?!{&zKaL zG`#P3E$0_k)F3K91Wi!BN#^-Ig5$T`dX4Rd{nJaV z$C_oaArsWOz$pMx*{IY)qv<&s+d>ty+;&rp8p?^XAnYvLo2qD4v#r!@SStiK9d?=y z>4`NlWpiPx1FBV+mR@|Wv*2HT|MU{y_}B5^^vU+~dCSMtc=tU_`HdS1bYg2WY!8DOo9+1Gu;>rEEF9Tmz2`o%{UBpTAT^DZg5N zH`gbz6+RixDukO?aln8{8wK|f%~v|yAOODT(|QIYS5Jt{%8fb#MAp3aaxfJizz~22 zZj41rqn9A#Nd?KxOqXNGH=^fA5#0M44!iQ@MDl)3t1M_6Aw#<=527GGleu(fnhCqi zUuX1sO9MC3mRS@%v(CP(CtpwQK~Q-Xb6bBRBd!g z!vdE5#l#_LOpo*Xg9oyw)+un2%zwzmmex;vnd?kq zOf?FT&Op%=F`Xa@bWF&~PW&O?s4f{LsjSe``c8o!{AjyEC>XiTWBpn26mNejhNYjU64+l{H25^HI=;7xl~GS#9HRXYbTI&$D^TFztVv= z<@psWZ>MlLrU#2tmN}|A7g`gxPs)y+P8(ez_51H3bID$)O{+DZ%xL6GS%sYiq0mpO z659XRDZGwhrHICA%K9|yyQdV4J^Ak+Dam=qb=0DY8=P6YO*30g)roX7nfzAyY_|I9 z7L8H;#rH9D%1IYhHBJZsl~~bfPGgynBIQtC?_`)q>{VCewo)L?wY_xC#uk5i*pB=QYVz2Y|0O(C`Ig&It(#9EaU0x>|-$;C21wx*d$3@q2xJc6|wUbNJ@u^Y;ko-@|>+*Ta3+OxhVNso5Io#;`y)ma1*3|%?A|+5{FW%WJBpg>XpVmIOjaOCaRU<)H6)_I|`_S>Dyz0 z*wKUvZOR&cGNdiKyZ%oLVEXK?H4)Zw%t`LEQio`9?ket<)PSh^KABT%g$ z1Nph5P)G)?0xo!eR4?6dT)K1`P2Aczz_z=87OXuaXP&a+lEsPqJ~`@x;0*w$bQV+a z0-xTmSARNiYVhv^gq_)#>8}WTlt@^F5eT;N|Gky%ZSA#%$YKOHe=-X^r!;Ot^Kheu zHhPW<^x`c8E#g~tu97zp@zyiY#-`R&k~k*g4Xc695i z1e!KDsQ{TvJ_X6)Si{*iI9V57ht-BL(rq+_hvkA|qR&#R5aZRKo^-^*#I)ddmT5e- z_PNI8ckSAZK7x|TVuX6|dw50n!TTF*cu8B5A+UVd4JLSEa;3h(KevJ@01$lD%~T1Vp~uzY zc(m{=YcN-}jo5@^qG$|qH-GmY#VN}_HVH5Z6t>D`jNBEpyjf~qPoLKJfj(+#Wh+WK z93)T_>9|y@F+}~-H%9bvNkxG?;z}7|zIZiAs=NF5Cco4uyzNIi=)CU|nCPQ;$EL|n zxPP3YQvG1{)Im(DYd^PlPi>v=_`lF1#?X#!#Vw^ljogAl;;6M3*=js>E#2;>4mfV639Q z3(A4|Es=zixbQC1#oOnL=B{`xrG}=RhK@;{yGiC+$tx3YFqN#cyf5$tvexFzE_ib9w&@-=)NERJ>0$Gm=BX5iMP$+fWE!>tsl zkF=QQgXbLdGCBe1YTEJpuJtMCyXFwr-l`8V{g3GtE&}Dir{jV zS+Tgw(*0`Vcn{B3Z+chmM~$9@YuxA5We_N$uLvhXuKsG_v*lPhzQ? zsIX)jwmqZTB=bob4**i)D^x!XB-|QIT~LvZ#8>r?eW9m_Gf8WUV3vFcEC+t5N0&%> zqlSkKBOf!cI*MjHG2)5G;J3@eNS#Ce9*Ph~}f!Gd)Lv<+v z@~*24EfyMj0V8}ni`v!Q?$1vs2*jZYmo3;+sCp>4a;M}k<87VWvl)D` zyvMXlLt|{!#ZRJs_?TiXwd@(@-R>J?*6;y*9-s-}UuzvTi0~K!CE_HfNXOS^O)~RK z=Qc{TU{AjsA-8Oa5|@S+SV&$ODo<5&LPW6l2m4N9$Z27*;8S5YbM`Y$#!vI@ao@_B z)tOar7Ol!2OdJ0#;d1sXEib!#1;)em+dy+vxY-mqxHf$3>$c5rzT1}4mk?XRp-x+{ zN9Aub71I+v2?4a98vfDP?d2mC$-AIUD;I?pjnA5p*&SKQse|^vT%G5tav`mv6J@it zs2g`qB$QFRI_5$L>(0btJwJ#zQncZazA~#aFI1a2#%w5%Gb&Z`PhA3TqwjHlMluobZa-PDde`wn|b1pcNg_+x_%oe9|XK-c6WL zf)obnWjRsu>2W$s(Y(S0mdfWtIq!#G>P(Qe*okAsEYnd0JmC|&9HmRO>ofv=efiNE zfVNe!SH@DjEC?adb1jzMuqAGlc z;HpW8qjl>{)@Ix>AikuPZsp~&U#{@+|8#Mlh4VJW3m!Xa$-rQgmyk(@fz$!9gzR!A z)Uh*9TwfiT92|0Pv4@Q!6l|m{W%9PEUD;GG$t(tU_#KY35KTm0S$W~L(3Gxm^Jje3 zsjNjF(yin~5ZUyWs8%JHg%$7KY)|`{0&2Yeusz!~Zl3U8MYVoF_18p%!q#zqA;vMF zcr_@<5jP5N_&6SDi%;>=1vwAnMRLdNP660QA_mpg3Lt#2+hHc?Uabt?l$glwC8`)1#>}9Ji%KzVRC)P2^~$(?-YD`8&7i#Nk)2OT zL+c}J6Z{hYNQ6pSnxY*Mx#aa)X6ad>Ic617U=Sh9CiT$~`jWJ%p^O%+wKlCH zE>tCJ_i<=TAC8z<+?*>~P{n%xjP-O=wkz^HluRauo&R#&M1^l{O$0=?k|)&7!iTdW zV}i*UHly50rpEwGhHbu@G$A2}*~PyHiy`r~%!9y>xf9EAWi{okGE0T|YVWw`iPT&2 zE3V{e_yzg)o8-69;^{Gw^pj0xyb7A-kGJUFNrOKRdUW)6+^ZTEL;DsVPP80;c>`^m ze7$Bb4|G0h4&z!j=ZykaSS=tqOYN%ZyDBflv|SQS_5uX%9&fjq<^+eM;F5<)`SEyB zwp)!)d{yx+wre3Y`bc9A33yh%@=eTszT37A7J5lEH7Q-gE@*m===@O(F5R*z^_1U-%z$O|a<*n6#9XJs3bw?gwlx2*yE+3?UOJ46)hQ^NlpHqYUU)@&&u>SO!ZaUp+Hx@2{TPve> z<8Ho{y40Fyo;2we)=jW#+)vP2xd;!SL-~bZFUAQ<5G%^j4#=WvYRBKs`!>w$PX2wX zRE5!fCcIs(cA?LaJa6>1bM@;^$&0iwOsczfs0eqW$0xt!ROjKpDlohmm1gHRQ((XR zd6m$5f_hFpQV@)##=PckMuFAlqjP&z5s2!5m0fgr-308*qV#Jdz)+vHtaEnaqALn- z_7$&9RnKU4;%F)gdnC}-Rj-R&8%{M`YVTVmxb)}LORy5MR(q*QJENOtBZ$BlTIlSr z)^!d&1xS8C%}(Xd2piN0!x(CWKVv%LrgEnTlW4w+*Cndr88JSr8vqKS!WCvQ(eaZ~ z7BX#bj%%<;e@vQhXm^NHCgDS~Q-15VVWi>XhEz2$D-yz{Jqz& zF5LagYkp2T_xu$1Krfyl1&3c6W)lD&pTnuK$jc!o!uYQ&N8ORlG%FFNKLLyNmu)lQD*re=%vI`k0V-X;3p%nOAJ-FEpNLxk0;>mM>6_L;iqZwz;Lte`+4-$wRiTh^Zmr6{~x%5K<`&z0JI)LHb6Yw zz{Ugcs~D3sgk_>ZAfB&LUD(7XrK1BymWku2{(SjwAk`X zL|Bv8ZOqvo3hxjPj8#0{QiRJft^;80R0Pcn#a*fS8nBgdC;c-Gj!ltwrFKp@&q!vk zAZ5=RS-t%88eIz538qUR%hC(T!WU8P4xF4Pd04H{(+a&8^AbCWtICtBEsDqEey$t% z?VM}#6j#s_m2%OXd&mW_Ld7k8Lyyi0cZi$V2EU-MegX>wIv)jBvAgYwu3sxYg*ROr zdXHXJ>tY^3y)UB5g;-&81D0}*dG>6lZ}u9I-4>Mg-h~q$AO!<7GpmH8K9bbi%KHpI z1&rb}PkPwC&DjOLl{5djr^ni-&ZB0XFAj;zH0H+=I6o>8gNeB^8j+c|Bj#c~3bS2= zOy;Es<{X4$v+|`pRlpL(IR{nCC^cW{uP*g`p7p8Lgqt|?LrT+6a0u4ye16;A7v;G@ zK1#uK8%FuL{cqrsDPG6_DR=&FnRr|*|6lP!FK)B-&MzP=7gqE*Trxor(a@tO>zPPw z5qHjl!zmawVyk^dBsH!ZJdDH&96QJ*LPyU5Cfw%jX_KCy1}}i zOAzm3`vNvf4ER5tJ)dfRh~Be%e+_o}KK2g61^ho({l1>6elT5LTanjU4)S%g;fsrV zf89=tuXFwR$6O89I^?lgB>(b#xxZ>d6{Pw1p5^{?Yv*MX)LN9mKqLbyahZ%>_-DQ8 z6##Y$K)fa{?tt2>M)XG4!Ovx*ELlSI^pHM}#NZ zAMSG8o=y(BJbvv$z^4~9z^Rx7ACPPX6Jv&86L!I*BH2kEPSaoagA{&| zPU1m3&?j)91+cH77ZI52z?}X@+jN{T%Cf(e$N4Nsno#8dODy6BbBADq{+_fYoHhJp zhV52-ZdT(P2`6E#J@*y=wD{;ad9#Mm)bl5bj<5utgB42Z%O=7O%9c9ck0JKfGK2rjT{DJ?oCOO9 zz%3 zn?Nu|;bwNXpDDSI5-%XNU5L7mPtopAjIBs)Ocd(~5s~R4oI!GeDHR>cUr*gI4{IhI z3V-=RB?YrXw#+sbdp$~aKjOFO(X~tB(r7;6mk$G<&1s7p2|*r0T9_ab8T(swFqQns zXHUPqFV!5BR<>G!6zppHrw5o1TrczhG9~Jbn3uf*QwX?|82E<3HIHpVJ5>I z>(Z|Tk96dDh*gJ5Lg$Ld?|kf9X?zB`@T*th8atGiuw+X4*2oLWBmYPta@WJE)-~NS zDalBHGYA}%7M_W>mqEOp%x)1YOp=XUI1w1c2+~Yg<{oKcq}*$T)}S`8r!9zM8`BDl zi8!xD471`5P>cn7|L~56`y#>aG-|U+*_#O>X+K1pH;=rrq-Blx{x3v^TdI zoNq82&7reu{iBvGS`|Lj3MEl}VXD`9X^EiQAe12N<7`Ulqw&<^)vXfK3Q%A0{6$kA zl_pmrV3bVYN}dSz#q~GoGM+X*66!`7PH3RFco6hYk!dmaj8Vo2u`hHa%ZJPq#w^xs zTSBtV^!GETWi)Jk3T*ql&g~UEYFg}bp*F`3d?l-+M7DJTs+cXJI!u@esnH?ahO1Vd z35A0?HTuL$dK(E&278lg*`BM?ZEdkAi*Om4MElVGXcGB3#Ro}4XHO;Si!ufpUNY{@ z_&DkwC!m@_oH8$tf{Y;wG8|B%FCecguZ{^XN9*IWX={^!OO_{dG;Wi#D8|Xgwcytr z`KFcRN{n3^0U5l}&B}zZJ{&ap+uA0|~d%|H=Guk_@3r*C%vLpkN z^$BJZOIWh=67|g+n9=4W2@6S@6V}$ZL9Du)j!3?Zg24XiI;gtAwk3 z7GWczq9lS))u!Wt-2R z*4{uav2dciqoW^P%WxPHyELY#<$Go?%6Y5Ro;4u9sgj2k6jVh$Yw1F(+c!->VZmR+ zMx-l1d1n30h(_7Ap=xPpbl5E}lnJj%dn`UPf*-1Rv;3Csc7TncCU0B&m z8a?g+O3hN^cT$@dAQ$DLpPA#9Sqy$HApOt|(fJ*P!N3PXzC`X0X!XGi<`+&w!&iqI z>ov4v{d$9sS@Sd5ykokbp_6SDTB5pq?nbm-yst&G{(4xgEHNCTl0wBKv!8l$!rknM zz_$UH9zN)edozu^LR=4~^18U@_<=80!AZN50Y$3I@bpCGne>uOkxC*tMTYutdH`i5 zsC>OV(a8uV`3Y3VFSQ1#i23I7Ma1ww6>^Fh>1&2hvMG&6g!)LyWos7^AX%}nPJ(|~ zyz!+xU-jS29Z0XJz>};P)Jhs-o=N|0KzSJJNM(`1XC}dsb=h3e$N{`=73<@@ zGcY;QM1uSG*NtuusauK#T@LB`+Aym6nE;bvu+ zGMcJ9!#q5LhH~x8$4tn)ym)sR1V_wXx|bRS0g&1`wp7a<98ZjV5X0)-B-X$ntS@D}(q-0?clyB!&)%04rtKJDWs@l#}_=XGX6%N*Pi zrUG9evi%M>Qr|i!rZ3m3wPdVyfCt(%x~Ob|+74_Hk*-2~^FFi~+o z!<^^t59jAq(dtL}mCM1nB(#Rf>MywoM?_=K#4oRk>jshrh6uX=%P1t^J zza41D7dVe60dTh#ve`W7nBuS2S7j{wRK{snY^$C!@p)K@8W@3~f)!F&suleyMvh5;Pr+UyCZ2m7nV$)p^Hgsqianb_+!U*#@I(a+c=-7 zmvQHs*Lo>yY7rLA*Wz}}yV_qw zJK7>o!4B(Wg-1Y88fafuk={GYdE5Q?d($;Hg^-cyMhWY$qHz8--Nvl^cehFWmuaf6*kLxqhieKdVyaWaEub z7|gKsI{3A3KaR^{;|)&)-0*(S?FVd5zOaiXK$W8)>Ei3OK_rFuyV7>3V05A@hTRh# zZ1_S8j;GI~9Ei3B*}oQ#Ey4PUq);$Brfkjh97OeCsKb4uGfoeH?e5>E4E(CdT_ZY) zRx_liENy#ITRp88AGI?p!(F(j0RtsE<)tyUCP&Mo|*s_Ya=o%;^(27p)Am>Gx9P_~LKgPDX>! z;j+nBDO+ePv{4HpxW@z8v!jz)PWTeZ4(YU(+$o$w_(n!+`?ht9W1r4f)+dhVU6y>R z*xc+0hRJ%nq*Um)f`-=90rpIsW18VrR*66cnTOV$E`wSF3I3rcqWxd|jJ|ZWI#x5j zUf6lZ=PvON+0disL!hS&ap3->bBzewV<^Wqd#}9nv(G)h-+pua%b1FO+vdG0a!lQS z<6mXm;TbK9`$BDnUD;V6*5e>^ar0WJtR+lwOL`R;;WV=&6-0}ksXn?G+fI=Kdo6q{ zy$kq#HJN3n93C`ddHg0WkQC4%rWr|Kj)k5_;G^MyWT?lYc{b5FW355mf&YoK>8EPJjoAw#j^X=K2< z-Lh)1k)~vqPL);76POSi)J#mOaZ@%|2xKwD>VCn`tT`(BNjkv`cG-lCCp)*?tT#8; zjuiIK@@p=h<;DJgq**%%g-u4nl0F-doZgogeE~#wvj&GdssFZzkGdZA{@x9a8U*+! z{W~094EX+P^?7RJ==*%Xo*w;)OBecIx1$0ABMjf4&(jJH0&{)8jku}2Z3YZ39h0a^ zW0)o{7b=}Bj<~K2Qn}$bR8p)N zN1=_|_iQ7){+~iXLxYz~+!a(S$4(r9c$+$_&^Y?BT#!wT<>a+Hl3!2CWo2Z(Lye?p zbC0sPmI>zm;v)pznjNxID<+v8ENZVgt=DCGPKio^O;sh@C#w5 z>3T5W7ec_-=ULfFUElZTW{=my?cfW8L6e1<-$lSzU9u`S?K1VBA28LO?NpY#{ysAv!@YK6ipJE_^Rr ze8&I-eOZpuDO|1yp3T@q0JVV4P3>8H`($5v9IYJm?%3tnI_QH3swx7}A?sg%kkncM z6{6KXMR>vz?uYha)r#zUf(sr-KnPmu3Iuj%hFj`2`8ROnfeLcp+GNw!$2hne3MLPG zn1RGq=^p=OhWc@7Z9|ympZ>8iU!GL8&fp5vP6iI?+`V>5hDACGzK{N~qy&(kCk^;` z`)-xL(i%y8HyE?f1pMnts$is_GI4}6!f!pQ3ag-(SKwm+5QKAI-oPeXzz)7zw4fnG z@668!OT&leShpLUyS4&ketcLcriqdJ{qaZ^tjxSrIUkxvzhR2mDpZ>7#!%+?L?0J* zb!_c~YCrEW4l8AIrFE*$*n91Xm9i(J0(5I*O)U|RGE44woCRjgSe>H|kTsWf54Eh^ zzY}vgM6MQw@H)^>V1R?TyoxwrP#v+>A;D876*o9l9aQ(>-1sFfcox{E$t+TK`e|tb zhMnQMS^W;+m?||nHdDG8ivbvugehko$5W#+NUTN_gvRx$WN(9&m^1ZTg-K8oT)l?a z{fkYB>b|+^lOh?HVbG*|lcZSTB-$g4&`_L%NA{?j$tW-&TAT-i7#OjqpB=oP&;>SP z<>Xkum8hFULokNq_F@x08Z@?N^jmZg@rAr>8BrVLC$+NTxsAZghlVC-;M4{<6O~0q zNe%yUd`D_;rXdV(-3g=_&R+g=8x;s zUQ;0CbPSJCYf_yrxv&Ij zA0P8o&>KfFO261@GZuF1`p>M*QCrt0r)ifQEgbFy-eJ?ul{q? z=B)|h=Apq$LXf3b8@zSy3cWO$nSwR$3gNXsQB?3dSY}CMmLoGFB~u&rXi9HWC(?On zg`;|VlnXP}sj*TcU(r4yG7}6D_MnnVMja*qJ{j;sUTq`_aZlYvqPtk-15m;kKYnKO z*c2a1`_+dfKC+p)5=Gpq;@z0)jh`!f!&dY5<}T12O`uCZ_>9@&Dwsr|HoF1#t!@}; zJh*s8%Y)gK{ek8AAk`}?>2MKW;-A=lp(ZwxpQA9rnpjNKp$6+v*6DBP8{9-HByxqh z>zRJ=gE~9mPTSQJ)1Y0VOP_1Bt%!tPm_#EYyz-$2Op~syurU2@!iSEHV;gb&Y_Z|Y zHI2))p;spYZ06H|ze3oHDl$w0Mh1p$z3J+%HPF7+DRoxy$`$I)CddU7(w{0GDF3>x zd~UOgnyvSwOM#UJQYB4p-W`k}IrJAP9bkqj!S`cNY~xkjCbR1>-r ztF%@F29%=>9MM+Y_b5FFY=Ran>Gdd?NE4zMwZph;H$8ypX|Awa&x9u zTyQ38xR^Z)jE7myc@r>KQKSWI zpq{Ohw?a{Q3x%4JC~G*A+hhDZP3$3v*^|j1_t^>|QVRN|w$J|Rnhq+=1wQhT_)TSr zS?6qzaH8TZF2`ukl!xrNY>$&gZ0R`NXg`w=jm5N{3EQeUFO=O%t?$ zFrY_*O_;aVRfCEZ_gO@zU%v$QHKD81HNsKacn$$*;%p#R%7;>R6HP82xF#Jz z$Q1FvMpAM(+-0Zs_=ezTRwFG(4^FJ%8>7seK%JR4gPQp#)%@hK*2w7T3fR|O$!S@b zSYeD=S@Ojnbk!o_0kK;xv~Y5mD#(O3IUtsOYxpUDsTQBsKlzChU5&B7FgFL`T0~AR zW=-A=CAv9aCXMx&cBCH&PWZy|>kH+K4u0P(SPxmLCD1_z3+}*OY)8=##NKm-As3Xg zB#u-tVU9$#MO`Ecajw+U*b~WA^GWU~9M5AG=IbCF@N=(CldCq2&Uq2RlHlGcrj41G zNvdp^rNHMwOP}Q#vCOj8(}k??>Vqx_b?u234Ch_Y#9R0EWhXY`xj(+&E0(vC%zi%AFixtJF zh-qa8lI9Jf?X)rc!okp-1z#`8%EeyTz)qwzs(Wjv@Vs_0+n}%GmDcbX;{$%w zot1wZN<$f&O3P;PiIVGOvpBXTxrN2!nG}?GpjH$Y3FR;Z&I723m@MX*z&|s%ThfE# z0qVwl{kMa8V|2JB?1V+QK~>rcQ$pO^swsnGYsK|Ddh4+rJ}MdMaYr_2-+sb`O{gYU z*D`+qP`lQ{kkuWQ!BvjSC{btC@^(s+bDN|Ln4Ro>Zv!V%vFJxs$QQ0$%}{l=w#|tq zkR}C_^9jZ*X`t#otpr~g<)3o#nTd(C5!+o`kRBcjv!g2gRzo}?ggF&aoid#wajx@XSNy)^A9jbD|U!Cqi^)tbpJx$`*`2AKMos^MM-lN#EL zarq&9;#1vAx3W6G954gc%x4P)g{F;?uI0KpmA*1EEl-g^7u9){z6z3GpS*4US}CT} zv(q~k8J|@nmg;Q1l*K~M$fp?5=4uBYLfZ9l`E`su7Bu@wxL)KFKR@0pVbyEv@4`sv zXkzjYoc=VlZXd6?n&qn2upt@dET2zw=llD!FRb$wD(PiF+wR(fOyWIFnt?(;rhG|it3@7d&-d9!|C|2V6{KV)>pQSF^o^LZ@o{fgR4wyA zIAe)`d>Qx7cIzI;3tn6@22?v)5BbxnuaRUiGNj3o&UIP1l` zQLGp)quqTzXjQ&m^}0xVtvP&kyxXqd!WZ}UUZ36$>TW(S-17c?+`McJ?ri_`cF(pR zMrZRn!}I*VPnx=3PkumoUf*m154ERIkIJiUpci)y*gtM!J!XFik;mWG8+?mGFOM=O z>lV@+M@wlpe3*zyUIXewmBJt$;Y0w07^N1T|+15V~6rwM8f1sSI`j< zG}7@%G_nEM8Gv&OG5*x!QV$coG;~_~e>uYF;?vaWc_II=Bdk+MhU9a?tuAFgxRF&N z^0F{AMG?I5A+Z@lBI0-)no3Szv@L^FY`6nb>J{37(WPRez20%G!-xa~%nwW!*VJS_*i)5xyk*^#9b4TSJl6Z+8DJdO8+z3YP zt__Yb3oR&tb!i;+6S9sTPENcr6qKuc)}%4S$~=oG&&00LwyfqqIBYICI3B0r{ai$L zHs`)JAt}+x;QdHLHsreV<@N*8Op}Qx@Lm|9N}$P-f8QbG_Z| z^?H7vHX8e1DJyO9*44W`GWP!ZEF9$tr!?oRoHg|P`s`#8M;OZB{iW6C{p9Rjm9WHA zVS0>`cr2N4NK%-VYzSGnns~_aHDki2)80N*Gxa)W+k%eBy?Auck9Lz}6QW{%66dko zS$)_BZ+88801CeyV&Oo3S};N>=zyib`IfW>8W&3VY1-+y#1S?x&!r-{n7!>cQRsvV z097<+q)if7Qh`f59%eC=(T(WR)`m;b&AYm7O)?%^rKxv&!{U+V1I{gvCv7O+n7t;9GgPC*b}vmhh{H#*;AoKOwlV{ zjC8^9CJ1Hp2uQa~l4g-@bex39y}Sk4O*2%scsd=nR!G94IM3yFoyha)pn6)v**JDF z(o1S&!!Ys*D|Wr7XNuj6%Y>&60W2qtVXSsrCxdf}8Tm}x!A<*DcE=REcHnPJ^)fed zgokxe@6Ch_J`sJb3xF&Eg$p5`Nq7TMYB?Rx&rOjf36MGTm9bo$)BTapeouHdp;|AO zr%9WIw~J8=u6qf<|0~JwwQJMWUpr76)hE=%`0z6GQ0wb0kNK)CCE&xaErY4AX+25# z`il+#wL)o7lgs3iBQNxka$+N0#XE zELdOL8lS>v|Mi|gm_+*s&pkd07OWWZ_6no5Hm)0L5!_95?JeWR7T(*E165A5s~ax> zZ&hw^=#;}AuP>sD@(JnAz`@-`q2%Vdz2(~1IXu!}&G(_&9_dbPfLU0%}N!nY$hZwr0khjP&V49E9 z@ad@y*^mOdtZ>vK4r;w_P1rheBn(q!N@Fh-=KRL&B8fTJCY(QjHq=L|Ux&@2B*&T0 z%B)gSHVb-np$Ckrsz*||RB};ImXqfdEbg&}T(BT~93}bN;2=|!rGiy_vM4H)(o_Y# zd5l<(0_BBz(7#p)Tt#jDcI}i2*G-%ww05kz&iw-npFScy5RK~z0t>?Xpm&YXddUz= zeK5w;Tv9;*rv|e1WC%Zpfpfb3>yPlNwsMyXH-otFQ%}l*rz*bKpisw_usJK!@}3-k-NS(VJ_{*fyLEq-}BLvR=^G%36IjWn794dy;Hz7!%*8?dXtmgzzr zG<whg!rXKed%k|z!h?Lu%KMDO4HSaqCvhgD~wb@08_tg(v%A*k2N+7du+Tbe? zyRFYlxFhND@wuHUbT7r$!=iFV3~?bgV(N6o5o6|L&SiDudx>P?^2Uj8yd1_*fFSy^ zL?I!lm#rm7yb;i_*OLd~CgmH+Pe6X8&G*V8?q=Ezz(JzLih6>dhf<|b(dXg&eC$+a zQM`#(etR81Q?T*Opwc4F`e8A1z$*l7uv|NvOyWdB0{hFhbtZ5@BUc3V}NL}+byNAcm*MYfqSunmcy(kKf*$>?=0D?f5 zZQ)t86A0ruO+GIzC(IFVH2M4(t9y*B*e~BU0UuEsvQ=iVE9gZ&M% z=9xEF05;XNqXBX|u)AJ)h(Qm!fi;@bYIKuFgQQ&jBV4L7iF&X1@q#^7;KTK$Q*`^y zzaBxr>#l4kX8(({_6KD6kvw8rh=gl@1ub6Bd<)xo3?nINn`A+J z*F|df!T_?K<4y|Uj7Vx5+||TKVo6-}R-@7WHA`6nq{u8>eR%)P*&b`ADM{em=mp_1 ziRY-NV#$z(0oOlAN(t%2N`m=Lz9}Trp_w^`OS6kJ<}Iy5GDczw?RmdNiK~-1H?Z6| zz2ohx%tUvrFbA^!+GCUJX;zsB&L+Cn=SHuIScv>>^WH>bh~ApzXS=v*T3m0yk`EDQ zvzDdkMEMgsR2_WL^F-$fCLm#^r^~V#H;TXVe;9kGAW?#LYqP!EHh0^$ZQHhO+qSLU zwr$(CZBL&c5p!m~i*sEORTX)YEAw4zJ!&?<_8|G*Q9RNk8!1M*-u^}{yxsl`j0vh4 zfQ5ePs1HJwU-%qDo&2O?Z$YV6sH{CITk#qO%g1~%*O#z&^*FF3Sr&6xyo~XbxFSpk zWGSo4Zf-Mq6pFwwClN@IYno1san~;Pb5Dg^U9%<)F|3z1b&j^rS)>FnJ2Q&VdN54S z00ig2(8iW=s+1p=Z2bgMOCg$-)lEoX4V#}i7iW2S8C<^CR8*OY)$)a-kne4QQ{qkR z(;w-QxU+Vg$U>gHA?B&(!G8sts6dklBnH{3FX!|Z>VZBd+0dDD^{t_fn#{A>Xm1tYNqFAZaO5pnpF0m8H@0LD(_?y z3!qRRJQ)HpmyB;>RBF3>p6Kp98*;iTVEl4OuE3C!%vvYrx&T0$&BUW0b#_sHS9+ue zMWqPA#0bV?qW8Oo4Gj#f|EA`e{S)qn9r8Wc>}ncWL>Zxj?3zilMm{!yPal0m%QINU zV#D%6|CZ>ULoKLpV##v2yJGPgA1-b^K&ZFuprZfwI~dTgW`cq$dpY8(r@gvNN>e_sNqZXM&MYmtLRFE`Ig$ zJo)m(9WDIh0Tu3w_qQlG*(XfE>%u%9POFbIJ9ic@_s`=1=a1{3obQL4|8-{jdR+*0 zo%zLJ&2oEvT=3>>h5GvZTz|ae-sTd;;ShHv9OO#VrCZxC+ap3pzN1P$r(l$~or}FZ zdb8@p6+=yG>vbtBVT@7apg$8DL!ymV@lh0or!!lbM~}=S6%R#1qoSRB2V9dAJADEf zwDLIwMx-20M#!JRoCLcx8Q^X{PkIwWtA)$?^G{bYQ_z!1WJ%WWZ%gV&6ESG(6_awE zl(4R2j=5waz0MZ&|Z5g}qL!6>?p)U8 zF3g@VJ+i}i%Lvw_hD6mpn2TiyjP|0{GbP0<1Vb$_fxL~F65dICnMhyH2|Ryypeur{ z&zc+;DjY2#-(a8}pxx&ksa*|F_~e6ov?@U+y^Pm6h>(Aym3Ta8|EF`?|FAcVft~5U zPsX%0Z4X#be`Axgj{X#(u8813gW=pAaN1TI0Nyz=3wo$&>Df%)tG+$(H;uyK5yTr3 z$h~3I5vh(J)A(@0%xPp_s)8_2vC@x7fTQmVspp=-aaJG|SG-d2)&L0dNJHkp*bVP* zb?;Z9@0L$p1jhm!8DAC^Ut-0(kjzmn(E;5Dsc=ni_n%7I-hZDKbeEQX!Qo#|M{hT> zv`Vze=h))Bl=a_u<0M1ZhTYzLh zc_4ns01-fCFn$KlxR8H0b^v~1;tj4$oqPuxsNk~Zs>AIXyo{;U9Qf`Df%>mDsGo0IdSRv*>8(0*}U zB>?c^W@aNeEj!OE&lNRI))(~nf{8e(7!~BAR+bwZ=do|xe5@PWi*P^X&2ZiXMBtnV z*L7Rb1!%`T`^`CFY7)#J9UHPYjOPqTY^~Oz znkrC*kX2=TPxV-S0KMA06X^voWb+!%lOBJG6Z*GTA(Pw{sfAFaUnF( z8%=I8hzj))x>!Jxy7Ks|S+1YCZP$^KBM{!-4GME)2YV#=m~l;W%GG;>(lpPq-r&%z zDvX;^BM`nk#0yJJGZ`>?fgyj1aR>OyJ7rW77vO_D?_Sdncc-B z{X^2+1+Qdgz`1^|1h*wa<)A|#GG`i%t64g-(!AOFiHl-(P~>8>-YnkoUU)Lqg2kP3 zL`bJ2^ zk=j5h zFer)ejpsdt| zTvBXR8t1^-UwcD!G5sjUJUm{G)z*tl;aSs+%vW|D@d!z`hn`(4>ER$-oH==lzv&Y*Hi7+2jih$eRCF z6SnaHqg^=2B|3^@)>uV&U!AJ~VqIOnNQjB2r5mJotd>Lle4@?+lW+fG@@KOx4*!A% zp>RfD77}Dm$J`cXfePlFg=5{95MLyGba8jGC-5r~y-Vw16N$uy5z~t(`*)e#uW3?# z*Q);3Rz2_7wWpYy)yO|aU zY1E^%bz^bU=$c`t{3g=qVKuyJT8K(XHMjVg0n%0;ssi%bY~aaf=+B6&(m|JQgAdJK zmpe==Ucrbd;B?#E&}Jfa8M>|P1quY^Ro2;=2y;8kDo;=v?5qfAY<;gmu>3*3O)0oa z#1~w|qG*{JK$@XjFf(#S0ipMtG0tNpUS6ga!nm~$t;z8#U@*3!r7o1oppi) zZd4=!WY^lbIT2p1lSEWQbzrZw;eta8`31E_FVpFyF!>=_SUhaffp=;Hsxx3zmKF7o zP{+gr+1?{R`Nk4Q`}k?xa?xy8HsE8;<Y8rrvJzEn}`6gvzLgc}hyh0}NO~k?1xlCaa};bD@J1*lV7I*G2>a zgj6$X;=?I|h;MFL(|SyI1Qo`?3`Wg(hndm^C=^0}$=XJFs|@ub9ty`Vxeb#?i%=p> z(W)@1!Bi5(g}33}cJ1)ixYotqmQ3p{i0LF_^Dn`abe7gq`bkGOw$VZ}i1@hf2P@sK zU<;jSh)B|OPpeE(3l+DJ%vIoGL6$LQ>qY@kL0i)V$l{}L`W??gCMuUP#!yQt4yWn5 z(C8Uj=vtA;BqYUZX7_^z9jLkjM1=d-^k_pE8dLn^$})`Q9I!^uM-5qj2{Xx^%Zj01 zN%ORVXWqRz5KgoteN}9okwm&M^M+1E<=CdCv$7w#Bk;S z>Wj+DZF4@_3Xii~@XcdM;hJ3+0lSCtQiX4FMBV?@COdW<-@| zT+#1yY<;6fTq%xip;qJ_MX{O1o0NlI6V7q(ZdVK=rGEX7Y2f5GnV03lo7k)vdM-Dk zUAL5UW+2zx4Zb=~Bg>OSr~YdQSJQ;+r3W6pC=r)hMO|JaQw(@Ijz&NCGgF^oQc90W zCsVrOyxE?^0qV?BuMii+NOA;2G4>Z(e5sc566nfctzUOBRh|(|+&tG5wqN**-x3eK z%g)>U0np`l+k4x)4*!(>fJK2DA!tRoncCN<+Sjw-SJS&rJeYn-8&B;B^GQZbi3HYqbEEL0jdq z@1Ei7_b@ZhG7{2(R*f_2FD7xk%e3%b+A!Ou8$e7rNlW;cz?)*Z!{h+U1=ywMErJmk zBOHr#V9Nf;!=$uhl@cdu0zs%q-1GgNlAn$O5g#Z^fL0^xZNm(4SQDGeu@)7;V{dNQ zEK3`$%|34A)(nik#?IF|S=);-5nr~G=|l7|g#x$D-7OdZF$t9vE_txRJAjyU<;mtk zA6pt_33f;_MWIn8tm!yVe)OT*uutJjuFy{##fri>jzTGuUB)_eVx165LPFkeEBS=X ze7HphTukdFlH(d4y6N`zBzL_Fd(9HTEpGUiNIh!dq2i(Ln(_2qNbTY*Sb?RnHG3W+ za}rXdv}F@E25mG58jdBAv7a8`&3gD1dnfWJ^e~0ELr7*xhCubqSCeK^GLmrOc~I0B zgqZFWDoObO2Fy=Xo&^PZZ%ABcr$O_LC-0;k_@8wA|FHgqft}^Q&tJ48V>es>_xz>T zBElAt4!Y69gN5BHZVEQ8q2YoVTkpz^!E>|+?zN;n^PHeK$G(6Ve}8HZH}k{Qw@JfP#?W(V$jWFd5G>&5EzHg{`Fm)H0G?CtC&H#d~k_S%Q-^T@|< z?`q@hyEYTo)fLX`ua(=Uvnbbq(JXNMUuYa$-;FN70u;Y^01vo4QUF4~FkruYfDAx0 zV7(ha2))WMIG@RHmfexd9uc7I%bx>ppk6XxU;Eg?tKrrjn-jZ-4R$6!o{$UDnesn* z1hY+@>nDV~*FG3#Z}tRKIJj=LJvReQZa2uU?A3_vakSk;dU>00fgJ z7LPOKe~O1UYX_}CN;tH7CVFB+v67p|1;o@k>P?Cju4pzxAykbz?L$@I%TNbmk^|uHWw0ye zqj**eEbMiOIj?!5Egp@`C?D78+L`M6i2+aqv(j&D^q@c0*Gl}C7u%xt(vX`uV@*i$ z7TJvehZhfuYrN8i0IKQ1$^;Quj%f#3OHe%nJvl->3pOXUlUVBF2-q+5GCT$bRVfpV z06nGhvg-i;w4AD4xts?qxz-V(fFnC?r0rC?Gpm9VRH?!SNfipBf@<(;wC4D1O^+l> zqPRWfUC0^JuN*ybOtDJzUAPcRmfXy0puIbzX{DA1bv}(PoR+{dw;1#zQR=#Dd}v9y zy$evEm^Zca;xc`7f?kzj8Da})`QeWt4%Aw zyO0I!P*~Jj$Lnl`U*Y}{BulmNjHOP@c<%}2-lP$k4ozhm2~v61SoD~%3WKZDKCWOOOcw{$&)P2iwtV6XUxl`GW|Y< zhwx@2+Lo%o_tA;pEPTBKzg)*k1rbdIdPpE91uRf+>sQM9Z6(Ba8NU&TOjfVq}j{mVv`-%_sj+j9cw_T_ogJv{IAuD@Gsm(9pl*QWKQ z9lvBEdf}DMZ2Vfs85Je2^P1cwde*)pY`#AE^?UDV0~QeqQ2t2aiZJA{alme0G))_oYx_FW zy~WkxGk`%#whXo*R5hw~oz#CJd_xbR6oPR4!pcV&50`WBX+6P0(3&dKS#pvv+K#F0 zlEr#rYz>N7*(4vu@Wd7QXP(h?#uu(s$=|rf+^483%c@#bF%LMwY>qj@8&|dk&ST1& zRfMIhAbm9>1fiVlG4rr$4u#;+R-ikwLDlMekK?fk(^oYb3c}*O)d$70n(w%T12T;s zK_^+GNj={R)>L)L)}E#aj0vLW`va2daP6Pgq1|!|Hz#nnVzNHgL5hVJnsw~gnXHsD zUhj#fYE{x3oSgcOW~&AL8rx(tZ$TcxItfigmR?z z7xQ%bu#mra%a9;WopI-pftoDH@FDzDBd5))wF0+@1Pp~qS*M5HL#_)F;fbPx46CU+ z8O~5PwEFVzJ?#rML<5l0B^;#p7383!Ye>9lxt1Y%P2 zB>$AlwEYzI-(ZLHn0WLuU|N>|iTM=-llFSonG;zNeeQGj{0W9fN|-A!jA^bz8jUc5 zk}=oX3E9!S9*|Gf5pu$bv5xHue~i{qLH=U`<-6rV=HKmLfDo--e0MK9~B` z;KqZzsho-hwu8$@v=5LH7gd0=y#gGK=)ovPo;YmX%vj`RP3q*Hg%UAo$4(O> zn?|O+={VxkjSel8pB9>K*IgYUYDf<-{c@P;NnKQq#FNmU!OqT`(eGAPxY;wey&z6F z2-s4%?Z#8o%qno?(Z~&af~niDzHBrB22@-e&DVuXeTO(z-kgIIiOe0m^Ww&2YMo0c z6ItU2QNnJo47LGYb3xxo5ecJMkUHNIJGk}phAvW{Y^Rxe|Ab*z*B&AeF`*0Je{ce? zL&-B>3)^w`REs4Fq)C}}h=udL|AK*8e~YMS5eXdp}w3A4J%(*n(AD6q@gLbMsB}4C{Tj}Nnb@Z z^d3|*gGfE#oEDp5Y6TmDl}n zJo7Lm;i%xT4}oT35LBfN;e4(ThhFf}@SUs)IrhlQ)}be5F^WZjv1S&Vm~lM7;YyWH z`jBJsus+ys|6g*Mcx)>qYOJ=VZX!8PqVaRtN>kjwGa)k;wPAA$CBbd!ow-3O%ca%q zrf{Sx+YN>6(`Ab0H_VCWXVt3hxxV)>I2Rz3}f9{f5^j+XQ!_0+IZ}8_z zx6obq>f{}ZaI6h-UvY+~zp@Q8-fwmYJU!ru#@@MU1{G`gz8f=1S0efosPpdcF}vhe zSUsmE0jzICuEhsSxAA`Zrp^6nEX)c+H6R+(-*zftwoB4O9YFaTPDoJXj1+`VT1R3~ z#og7K>ZekadlPKMLk7HOmTD&&J&LKqAQ*Nm4N)jx4O= z`h9q=yw}~AdT~z3&yiDwO)QEBpM_II-VN;E8t-BcccBB+|vY?chXqU`w{==V49z^Wnp_r_+~$caQ3SQEwR+JV>Alfdl^n++nCkg;?aL zVe7el8rK3Bu<&gG;6!i5LPfY4tj8o(L-z^>E7i^hvrAdWe5@lija2}tked4NMGtld zN+{#{wFwH#I@kz@-^Mh|*HpLuVI*`$vAsv63G|D?EHp-qTOmT*4zNPrGy^1nn_WlJ zap1NvZp@>akyq>}vnN&(zUn-_S|SyCI1E}Osj1(nOgQg%he*B^MAuVb{QKGNr|i=9 zPf91dP`mg2aAQrdb{$Dsp@_tNY0pA-(Ys|!_(pR{rUEGA_s#zYdfV^)Z!Pb*Lzy@s zBR{M%9pl$I?UNB4ZaT%UnwEo z#rd}8r<#}^ZA?W?ZCN2f)j?4XdMP0$MMlQEOfbct2Mq|m`ClX?FJv?#aDPsq7we|7 zatjts6RnCSttTVT$e#7t74(9paI2GnoOMje{Fe5A0O-VBxc`&F|DP63&@umi3J(AO z3je)sOh54Q8i1X%LuUYRIfk?$^z*}ys=LTsqNoVt4-%GHt0-dR(7#w^yhx>&B#f7u zK-l)1_e)uzybfI-UN3g|g8#yN;28(K@THxn#drP@7k;_@zJ1|!&V|*5g{D0qL;$7y$xT z%FzKvF~Zt`>{t4<3-1qW$i0@K0YchY2Akr)+ml&aUGiYytK|PoW#a-g=MwUmeyph0 z#6Eg}cfw&GVL=LIeY)-pKMC5L>ia<^44YYv?0!HT5SE2@om9g;Z*N?G=Y~#r_f-aX zt{g9e>OE9tF+$J&xS9sh`>zP!bkB+>FTr_}AVIzB3CYa6fEipv4VOD`y=pq_9Y z`dn$Q>}@;Dfpdhob?203VtG+fjy@!4gY$J;%ut~tQx^C-C5r*1GPo;$M)aQ~aBVfs#C7tzYckWUW#o`cQ7 zO%wmO+7TqND_}sZkLRs#=ptE`Rb$(@wTblZb$)gFW-I#iXve}{(h&CT zjKqy;V8iOZ6s|uk_D8anh^=gzlo%J9)eW!g@ZSoplE6^XscbRMeC^+?#yvJHb$JNV zPM$}Qv42p>E_?t)nLKa#x}d0y({;6Te&FlvBFJ_V>^IHpDHAbF8#{|9ZH5yfKwY#5 zSzIsRBN8s(>YTUT`OH9jL618t#k41+8vppFI;*~PSdC*LLg`Sr6*oLUm-@1#tWzi~ zZ#htdW1_a~EE^2ifZIOxIR_d%4azkE(J|}QVzYY;>|_PKP~HaDJ`cyx6p1o3?934k zpi?fkxH1qyQ=_zW z%Go#n93_y&QkKhBd(vCh6)-wihVe|r3&1(wgd?VpJy#bL)j_{AjzB}``;-alDZI}< z#bx^IDFO(ADaDo4Xm<>7%wVrD1oJjo#RzMoz$V20A$~DGkz$K%m)ns@av~T~?$^r| zvNVI7Q#EW$jON}a{4hVEK~5)TL?jD`Vq%U8VBneOnWkSmPDe$87&)Quj{%1DwHVU7 z>!(AINM(tdU~QaV5SihmesmOTD(j9!K~~NxnktX(-fLj!f3=z{Rrx*o+|avMAy!xo z(lJ(oVQU0#M!-YK>(|%q88)azt4A?-c%c%_>=hpENj9E}d7L{0?7 z;2EV0Ua*~Mv>0`NxAks-WFJB#Qm>R9vQloX^x+*|QEuk!uEl+_@E>E7fVv)votX;7s zjyqIL*ko<%5KOTeGi0lYAsR&Og-Zr)US19+sLtzL4?HRc@!7nli#wu4dIEH8OTQY|uIsjP`BCFfd6_rH$%VlR;ougE0! zSbkBWp2txWMixZj+9n1||Cs?i@XwO7U3MGCU&>uiX3Nc)092s z6Lh@Mh5uV0(&|twhXiqs9+p?CR66<~`pyP&l(-NDukf=(4X0_!psgK6om!ZSkW+;U zRR_aEqD^!|KaMkxdbD6HRkF@fus%+*h*um&wE5>BoNR&%H2@fW_Sv6IsH>CA^n&y+ zBegRYvhWP(q>5D|p>{>DahznF4rj4*uLO`Q<@*OrY2=y6fCv<>VqFdj^(|vDd#xh6v)ruWyo7OxzJ^LLZ zohVg3R=pkzZdz!lf#-fW{|v~+xm%x76r*P{w;`7v<7g!PpiC3?l%d`ZxoJp4Ug-({ zY91N}^(gKtZeJdeu2ooL_BG7>Uj0b#~?bxr-Hbz59jYeZ7C<|Io9|A)FT1 z@~V}N2tO5EIfk$*$%4a6D7OO|@_`butH~3e>~7f<9m+tA&{X(*dN>(*N0yzJzjjEX5%>*d zggq9#M4UCIePx_k;Ts*YikO=bNub(DEyzvsrbWL( zRk2z+#O@c2xY8(sY1B<(-^iqTCRUcdY9_0@Ha6Em^WG*h)5!bRS5vvhH0}EW0*TX$ z{--m;|1kH?K+p8w%jq;FZ8urqyKib{+xQOm6b1i+*J@ZU;3_ah`{yhSLMZ%|Ip7HW z{t)n*=r|xwto!WC&%eiGGlh^0mhDDdP-swbx>@tV`AfdLyg zXNe|_(Z{LJ7)o`v(7t~v{}^Sag71pght$lkd``fT`z_nrzubCE!o9+b5J-?JU5;56 z9RVH?`hjB|xZxd$wzz8v3lFf>;JSrBw!x^+;*3{d z4F^;tqwFWolMel+K_5;^`Wd+FbNa6#o7=H0sT=d!R>wzTGNRzEmSQpXfJw3;$_NNH zn(tc>#NHU2%OI_A)|@4I<^ECH@T}+ z1BEn-E0JwB9X|G4=2BfU-|Q1Q^{hj$gINT2!Q)KJ0f9>hHl=rH%bDejyOJY-M!l5i8 zVvT>sS#m;sc3`9giv{LsB*=my?p!%46?g*dN&B zOT-%)V$CyY>;m@DGNMZ!^Q84_7TmDurzz-B({}Azr?6`+z@kzrP zU$c}&$dc3-Tb=G%^AVqLU>4O`2Vbi<&^vI0D|BgnW#sBiQph7UM==a%*j3{AN&6by zyxAaHW!GZtx@0^8A~+#=SrH)Z8U)5htX^~1i`Uj*kx}Y=LRTsU8P88b~A$=5b-2}7Btw2f(TZK z^qWdtz)%)sy=Nzh5u00O&mG<$

SS7^4Hmi@+sQYaX~*-FW+op!r(JB8dYav^&Il5$;g7N%jfusdZsFOeP)Y-3M)%gGi_aHi zffI>zoufqUd}jt8X8$o>ZdeI2Zw;?hoK0-$QKv~vBcg)A^t-W_>4eE7>5*VuvO)sL zbBp>6E8*ELn~uZ`Y9XM+Nb~lLNRe5~wW}bwZmJj|1Kz8Vcc69kauA$^E_3lz^&QF2 z@qp&dRBS?P#(GxXVt!X^xCMvZm_nuZvaY{B2`x#nvmIxzZQRn)6Z$egR-KR{D znM|oB{zc4^@lL!a$!qckq{gWC>9nR3j70mQE_hDpnI?LuU>1S*^Wc4O5pCq-GIPnG zrTX2-1~RJJi}7*qC!B06YH~I_`_@?eaq3Lm0>BkyY&POqAV{lqWe!lfdX9LvSZB;o z6wLxUC{ZFZR7VbJL7XR1ho(ATAA8e?JOjdx5FOz>1{TxX1{m%h zEvmG8c(b8;a%Q&36!hKNFOhDxydi7JAx}<~9$S0rI;uz$slzIc1nI>#6yF}-LuG-r z=fK~LR*{cWqI>km<=s4i^c@gk&{iH!2cDMX(1+Gn?jWfw4&|09O?2~G@nSh^?fKQL zd=dZ`l>o`9u@&!V{vjm8IaZUC!b)a0m_4rtWs@7KSJxI*y;<6pxy_eT-_1^lN-XAr#{rSD6he}^nP82FJN!jRj(dV zM@7L{$fRXl@1y47nrYBy)LO97%%jk^Y_dr5#Nr|p^d}zf0zznIY#i$h?lgL|hb#}>t711$N-S9an9S&yzLk16Lh z`iJAB8yJzKosO&u8}7Z(=ohr>MSUk7xTU6WPD_qxPPAM6arS}RwN%*sY*bGyoPW#L zDFB55*AqoVn-TTK-#?Z@kZ(B^`Lx6O50o}ul}!i~UFuA^pqMN*bu#Xiv)H(^_u11N zQjg-35061|K~63%oaa%{r+-u7tdVus*3EIUzE9;(CNjQo6r*)*M}~8g4uFW%E2Av& z!DcABB?nnv?`$?{rtOdgI$@^KZ<#*RU&VkvA(6DItAxjx6qid#H?$(e%JjT&$=H_sa|Sz2>-cG; zEob})=NDsbPE(3^31$RmJwkt_#%Ps!Pu7G{Dz?GbD{t85H~sc#AP>iSR*oj-mOA7z z4zo~(VX;J=UOSJaBz}-w*#1t#-<;t>&8(&OJ2;9dVbv#S#IrsFY*`#o&w6Sec8CG* z&tMfv>M7kBNC@DC5X7f=!3N1NsqNVxD#I_@^-nSqalb1&Re*mY^}zBWTx=yq=1@0i z`B_s_RtiPKZ5g@iB}wv5$ciJ?QgOWOlLdP5j6W$Glh7LxZlrYeIo;j^miFPaCFsZJpjR*@k6O zyNCi2BeWdoamzP|xWFf0uisH)M3$JHb+<^1;{l91Kj0cRH4e&QMo+jmr>2Y+q@}XXt`I5s{srDz zHbLNRoYu)%URznKNrDc3#)2_|hNNo`twxK`DBz!1td0N+jdJAAquhLKTE!k#oX?sb~Dx}8ZINp1r%8CTwAFb|SDymt)+Mt$s~R!n09r7=%Z zKb8CTFchVG%BBZMRW-W4a|RD8jTEYD%MFdU2I96))mY21I?i3_8EZw!A{A*C%>i=K zT4T>Fb%^BBOvl>UgR)}_OQkLT1WB)@X{eU*n*2HbB%|q5vhs>03e`(M!D;KVNO&{& zOOL%}O8Q@Yf^ZXt~7Tr#JwSJ3RsLh$MqAV07{PIcu zNnKd4_sq?KoR4e=D_=1yP6znK=4RIk=D=`mL`NInYC9Pd)r8<#>pMk}HYfhF!gy%z zrof=PC2z-Q&_sX>4BFgy9=A4<#P&;k71-<^W_djerHPYlLxDN^3?T9?o?pl%v{oP| z_p-Q`4F@18Dy~T|qrPX}2koQh4lI!Pa#^0|B_2n#YkwwFxaX zvsDc%mHVK0@wD6`#fATfg%9A?j*GBbFE+%VPDDFuKs0N~ z*-7GO_d+vq&RVhBQ%%dEl4ho<&#go7=h7_avaMVH3r0UajyAIc*%1fnq>I}G?8h;1 zt`oX)LM9&Yx3l34x^MvYI=`i|zzjb`Tif1U#4t!umzX|sT_26e%sac`y|gXyI>!Klprj`iM@4#|W*FWHtZ? zn(ttkFyDUC56d&#=1kw#Kbv@e{`7obMZGuB%6-4CZ0udz+HQA!-~PE-8J-`3PM`B{E>nmVw0in3PA#cF~AA#q4HdHVL7HLli`sxi6aoa{m!;+8Bm= z{w$zJVrJYhNV~?min*;lzHOpDkAu70@@#ERGjKdO*$We^I|!?> z$%uUwTJt~>%{o&%@=kp-+0%6?b_QSYIq&9*AJTqVblesT(K-Hmvht5wWFt6QP`K3J zdmp^-tCH7;gPOq=8u|u#hW_sP@51Z<&~3xQ#QOj2U2$6OboBC0Kr|leJAp-ks-hGB z_u3Wg|6jWbIB?)fPUtAIbKf!&sEc)wggBmPyZj>5d1*1$YW}n!`02j8d>Ywd>#^l% z2~f~_krU^GkCbXil8pgf5VZc&x%Kftzu}s(!_M@zYZ_3)a7leYvaoj%(_^jPdhl-B zd^ZuI$5zuFx1smd;r{sieB<--vKRCFkBwfB&*RmXt=!L7-Y(9}d(yJmYoZU5C$1i5 zaPWbTwK~wo8R?p5daQMshm9sqF0LMW*h5an6Nljn@QQY*(=?^y?F%p)hyl|K$1GkP zfM`a>sEGwp@gQ@5CwHnU2piyT7Q+4$p2%Rv3L-C;^B{Ze;p2PMaJXgg@r5#`CmMcc zCX<*d#4`6vT7)DIdAc~psotaPJD@?#xkF5V>cDfHy`#}4)9~KSO9w=J%$-k9`vzkk z8Cm0_W3yHNCVZ7S6#}pv;yNCp7Gw3(5*`zL$6X}u@XJlTKlnyHbI0T&FSnEu?e!!+ z5enfV%H=#`wOTR^qGNDlZCa!Sv=YHs+Qeuc&93hOk)sK+XYrwzmXJlscDoRA%}#5(Mr4O)Va_)koKaq24CX09KO z%U%lwOgWTIH9S%<%Id*QG4vm`5cEXDCmO^Is}+=IB?fDP3;4;#z|gWwp{|Wz4kDs5 z5W76?7=o8l4@Esf!YjtB1H7D7NYzDVbs4+1QRR~}Sjpet(+rD=rtzt*JXrX}|2PYG zy>FltSgoQC^8~BML~dJ2uoaEy3C$%;!kryfrBS8hA6VgF3H;gc{9Ye;mqgvhO4aRH+A*`Q*=b5Y9lKx|g4$zOEh|jc+jKbO}+A94l zPrpSKhxLBcj!`A1DoRD*^thswrUE8nPo`Q_szdBlQBOe?OmOboYzRh8P|dR=^k*b2 z@C2aqu~{Ddcr-V4YgK*V^-n{C#g7TZOWG$aI?17oJH@6q7X;Xt^qyZ5jaj+8?zKBK zKL^7}<2>wK5=kZ2!EB699gr%4TtJP^-t*6wgnNr|KXnwkQUJW(ExiUL0XXwTYA;ND z_xQ&S4RnT17x3=*-)%eT)a9z_eo?ztF_k~?rXeX%)WX7n(|Vd3wSWx)drbW}5GZ1g zYhhq`DW#3t3%h@UB#_&Du-_;1LSWe<{vR1S1f~exs)kV6OQhI8#;&4s3A2+tx4e;Z zmc#`mt&74e?p>my{7-b{3q|cQ!^}^MfgUuNwM;p`ERL9If#uty^czv*99vh&t{sXl ziNs`tt0h<=;O;Y()4*RSBisnodCI}bdlN#_+@^0=y!gXzumB@&QDR+6lSpLf_B^H) zfQCj~?21j%E!FTf?cG%J!G_gT`!QrVpdE>nBASA4oI<{ON4kyu(fT#gNTUAwqvo}& ze?4M8>GcnWD(Jk&uT@1><}B7CxfqER$7R;_%61eZc2Jj8XkI}BJ+R%=o8ODH5t0}D z#{oCYtD(=ChnEAkbXpOI*-dB4D{6-u!Mx}eTgS5-HQ2BSpq$ax~bHG|5T513VGkC>Ix{ej%M##3Ll_+RkvphL&}_o! zy!=`{1yB>S_bPRo^W;t92HWF07Pl+-$`fmD9Dd0M}eqMnA7`uwu8=(P)YBO3Ap+_l?cs3A9{lx*pn8nd+ouFGX$9 zPF)-XuAHwiEFU20mTI0Ba(mQ}nx^GCbvGcU7w6ycQQycL}8cT3*LY_y9Q zbkb$m8IBT%;3E&mAEar!rO0LeV>yozln=yY^dTTu0rzWj1M4k74^s?TKyB0I4W`V^ zbbMvWigq>U$?hF;XNO$i3`DL@xRo7^ygK$r#7hHgVI(bMCdvLXJk;1dQyvcmriM8A zxX+Acd^~0gYLvf1&>v56_~@Z9 zuh2?tLO=f_`!A+IPrPECUy$(PV%R0juAqn&KoYn_aEJ1Ou7h|_&;OVD3Cdo6P-I&` zIhu7b2(&$^Nj1O_S;a>Z%6vY<$&U(E6+u*}%wStKfr=&GC|in%^i{qtiC&+4INYH+ z8w4=~-;*l4DrZ!~>vr?Q-#KM$Pp4jrJl_6)&Ma6$n5N4|;+*u=vhYb>eV=JDjoEE~ z##r5AVMvAtJfsG3LHk>A-(}yKNq7Xpm0@Ijn&cZ}kuuUP?j3>MH=w;}I{X8O9{soBo+hEIz>!qHR#2v7jTF0Z_9ea@#|FzzeadQnqnD4>M>Zl zIGdTBd*8BiM-GYjoZ^&s746#l5_AOxEOHc#tQ84TJ8c4IL{Z-tTs)pcoo&M#D^hNo zux=KeY=3%&CX58!8d@?pyPt$Yl7jKM6eTR?YsOy5-PNW?RpY_9NK9u#GI3{>^kJMC zp;(HcK}h_F{QR{`e;3IMUJdx=MnOz7g+V)oq(f`e%RpDoxx|2pQ6=}6gF^!Lx>Db@ zp(rT0#r15Ja@(fDHDONxq)>2U*AmXvq+%KHha`kBzxl#p)a6I{pwAiD;&vTqjTZ~L6@TvKap%xFK1~I zcCQ)iLOZ~uZSj`*9gVR>rIvY2%S~T?{kUm<$4mhH`$b3?s)8uO)8s=@=6r90Ej?4) zru@jxANyYSOB8#i=Ffp*<|^g+VyE7E$p9G9gEe zCvCk($LV7WfHeN|(o}J*h0NP5u%dz0ts~3HN$2F|EFIg*4mX{&`yf>XspFB;8qkWw zr;GHCJ<7E8(sZTNCmM(>!1CeUz?!Z<9xpvg@s@3gdenhVTybbm8WvVA!fLFex@~kZ zx|Vf+q{i;E@JfGA=X&!DfX0K(bN?$Np|Ui4%z6taIUK%p?7@52oUmYEysl39<17~! z^+Cy9(eYB!xq;6Yk2Z%u#U74k1!oq5>3-9D5jVmNmSHhxS`T%!jxsFc@UTS-nqY1l#H^*VGYP;XQ&S1;><>OHaI@tX}4$Zh`u28hqmcv1;?Lxzz~ z^kzg)_CFlsI-uU~0E5+$`*{sPRs{ytBqrr78GCTFr=n~sSg!{|=D}G{?A%F!!!r*2 zUK*`Y!$AIhMkY`3<3diti~Cc7N*2gC=H>l^p3JeWQA~}>-tb~NVL?s##nnP*@b7)- zu@Qb&1BPg%L0_JDvd6&8lHsV(X;-XATaubxCJbY(0da9{MCwSFVq=u7Djf_fqMm0n zn%`3n{rT$f3EE-u=>WnYVl@rMp0-jEMG-*DGPtD9p(|z7(MEQ?hLxXPQBK8%^g*Dt ziCkqTM47L*5@v@E%ZPL~uD0>@tI+lANi}-AN}F7>vO05Ftl2$)0M^s%?*%k`23Eu- z+MdneUX^aEaPfGok!d3T!`5-f)D2GalA-+9lx@IBH;d5gJ$v+xkJL`G?vu-lOOJcg z`|aII&d%U-7w`AYAKR9iue;+Ey`8Stmy37T4YfZXcQrA4BR$>T4+|Rz|5WTOCf0J3 ze08#D0kDSD8sV11aHV}v6_JZt&E8+;@7O2>%oxJ01P~={Pmj76#Kjvj#?%mPq8+LeUStyk=Se$ zL5`{?aM4X!72*P%rE?lX%H0GO#QW1%`cd@6iSAL@>nd!B3DVu%7J%ENVVR9^q8`@MMhd&appnD(QW=Jt#DA6tcosTy%|F*F(8(o*GV- z=+{M@1FG4Gh!hY6De{sm^mEEtOYdyZ!a7AMsx6fa{N(FziA}AjNjk!)t{Lw}o^Sp% zXSmTZVymspt1Or4mO6MOd8jyQHhpa&zZ(YYPR>SPc`ypaFbgfWyE7MBi5Snq1YuDX z&nLl@m_T01HHsbtOlQzGk3?EPGGZC}os)H1#7;Q+c>gro5`G@Uo;l<@*9M2AEcCIe z>06`lC@Y zM0K&@_IBKvc#rPof!j<}~NjQNJM(jQO*JjzX{;{34L zw;O(r?3%p2zX{v0u~J-Ow@c%&@G4TH0)?VyAy8T%2D*=D#gX?D)yS)9l z*s~l?t@Qn0Y<6Z2j!+R+Q;LBU8W^2iB=<%mihDY%@Sxh@Woa*&AV9ntdNDBdnBC~5*2Pw-<0*l3V{hcxr+jfTep2P#J;2t3y-aA%S9;Lq+PcTUZbpzIk$H`KM$ zWIPmi++2>@Meu8xGap>$K1clyp5nfE^GMl;L;JW7h+);6px62rW8@J=*xii!Y@9d{ zOcus`#NmH+<9LC6SR9C?M8oK7qZ#|1`<@xjzl>3;V>&!uwp0|StFHIl<%DQ;4%|GO zk|i%@mkVFGikAh<*tmYn=)qB~qw#L#B_z2q1S9UAlq4jrM~NXh<;bdf*v`>2+pVF$ zdwCbsP`*j6b-}?*$GTYnj5HHF5E>eX?2koNlS3RuHb7m5+xpknntvjA}Rv^h%|I@WW0CZNhr+$&=b*Bc^}2U}(fdQV7H_#lfplwZd58HaPfA z;{>FHs8xO8#!gh;+@)=7bkp22FYBk}WaHpblKN4w4u_63?WXoK?_AkV(_Nj6?Jk$B zvF-fk4iPcP_8l#jDE@EY3c*?LFF!)j$!BIM)`2>+lu?Egs%nWRDnY#mVkXC-6Vt!H z488IGI5VkYqwL8eu3-7>__b=F%Fc@%PeXp-FKHdOuaJjPlH0ZL()&oL;_LSE_KdPO zJO|A9`$Plz0@mmyW_WJJH;d9jIP5gu6cMT>r3Q}S#wVj&4G?r#|fB*sb8^I ziIBR457+&fIzHiBqtKn&279n93xKdNKMWd*8N~YaA>73?7KpD2ti>KmALu|qXKZ>S zyt&1|=lj%5(viwnW7#T>VT=dm461(#*S}+0qWO0zRh2`|yVc zu&9Fv!??9wQ*~6v%vloA@GZ~+&)lBLsZ9jr-IZOkN-iZ3SEBRz#H^vYY*Mn5GxxU* z$SCXY<8pv{MMs||>A}@9D!@@A-Ywd565^Vq_3=IWOLP*e1m$$ld~(YWLX@Wi!C_mm zor(6l;_pxZxOyeBk7&VViNzmx+07et?puZ2P?bdz#GRx?iJ+-n3FB}hTj~mm;|eOV z-c$2#hr&XD_HP`KKFNH?rb2-6=9hV}^goi-!V0eJ(b1iu0lG`OOkg7NFHG-HR_J=532AqT?7I{ok`^>MGJ zj+mkztSJi5^GO-kKxgoOXc&c!3t%oj5}SC&NAHg&XtQwE@~Xb?nXPZrG!8T8NKQgQ z2j?lIf%R|GMpi$+Ss=EtRm;L5qTa;SJPO?+QZq!bm->=*LdK|MVY#BT3N0sPnmV;1 zXU)PCd-PJ!{I8ex9lPD~L~`%sP1{?4!CQj>wo(wlPrkvt0X`-pT75bGPSC%~rcjfKfuV-|nYVy(-g1?WQR)#FS)Lvfz zcA>E$=TU;yDUjU7Jh^*m@E8C>#ad|;VxGqyaD>}YR^I>GHSd*(OyD?2)N<`0dr4gg zArGz(om;&uqNQXC&<_C-nl*P$>v1T}tYCl`k2f^oQGm#InD~I7sr7KgQ~p^R%m&-> zl2IrSsdBx;c-9gPfd=Rv&Wy*I);sWGis#5pzvsJ5NG@T}Dq3Q)(RNU^l~8eivrJxZ zjjNleKlbQ)xkT+Z-FIz}Ou*J0SBJzBp=#92t|;N8ftj)qu#CM+%E;>2JPLP~{C$sL zlfzzDtcB-c7Js6G!=afSqKuk(Q1TmxC(Be3_C(J&-sRN!f$j4+wao{*t0(ya)N zXV_9uPi4JJk3WRX7A-8#4&p8{l`Be@ZybR2jkp-!o!keI!KD4#*mT^*(Fjv^J&`R z>@Gshi&~ezsO@R(ouf#WMIW1fWa9j*7K;VG?*_?i`VYCqBRMsS80uTGQLJt6C+2Jf zHjr`X-J|X@kkDHWn(&Thvm_XsMTbmj;jC`kyhGBDPq>XCF1cd8|PH^nn zaKuxmI_H8EB!r5HN-?4U*p#i>DF zGDHuXWDb;cGV(4tw0`BI#ZL{b>Bfw!P`0FwMyVSA9~2weEy8= zk~5K+aeu`bzvLB^`0Gl>vwfpi$)7kjh2W}oK}}d)!UkjYB5~$e^F)m3UF8xlQOKJJ zWIYXNhpSv2Lx8V2RI!e-D_5`V#Xq!TCQb&Y*?$vLtnFuUQtf}K$Kz=6?y0^Y35gcH z9im%8>nxVG-(P^1s3Dn;W7hNzL{`($*1(9xDm6G%-wAlqKp0VyYl6tA>DMYdOIcR! z(%}wm+Gxu<2amQLLx$M1da2hoU2ja@^H_Q}{gRwvS94irRSy=6rH$Etqfm9D|E=0# zlOd*uqm0?m;2!=>YhpwrA_f9QoFLai0W@C>P%R6<4&s4cyV^cC>}^_?0qkn&u8N#d zIRd}Ljl2kPcl0j@zOsR-mMJid9c5;+_zmekHEo?P6cdazjP%aZ2S2X+S3A;wxW78$ zk4CMG>!-tPA8W3l_NVdFMLptxo?$1zua_80kDm7J59UyNG+36!u7@sD_5uaVn#sG_ zU5UCLjc2P-B%a~5-OB!2qjK9iaD1fA*%VZF#m7&36-jr7${b!-jza6T(bnkJRp}~5 zu08j<4nFVteesGdJ5PinL_Qtig`u>ZxYDq@L#v#|){kH+S|dPfF?ZB;uK2a#YAO+x z$o86#J$Z?uJSLR2UNZl=v=TtoG=#U80Hb~4uw6N?!l(eI(u5bUO< zR1%lGt_Vq)BZIl}+vo2Ec)j(&xE}HZ`ELjA#6 zHaV@|Dq)rrOvPM{ipYy4Js0>&@m-Z+_(Bf&?tpknma&}n2Z=-3ydwy+k6qm4eINj5 zv7h6s`JgjpMraeNe~;4mCiQBoxsVR-NR%khecQgJ22un~J??8ldhmU?Yx_bKLg?>e z2w`ZhIKDCejM(0tR5ZohjJP};jL7wT{9|*@`15_DcN5I+>;C>gf3x#LP!GKCO+EK~ zA1HOcj=0+TdOg?K2(N&e7R>GW{@y)qQf3rS_I^QKznFt5sbT@e$@ay~ciizH*av0w z7>HW%XE5}@rC4$6rGt|v0E2OSS;m#CLaG|ez_F60TL9(0w<8i?z26PbVH@0otwkuY}cCupIwr$%sE4FQ$Rk3gWea30*b9ZAmXKQxm8e_fR zi$~w4KJ4L64C4p|U=XC_ek;44Z+Wdl2{WNcd&{fecDm*N6i_Nq_>Pd}(dV5a&et~G=D`pD5V_Z#P0?uWy}TqAoS zbYz?Bj!FAUILH5$vQ9z0>?FkV(IV!C%@p;&7jc^1+ag4FNYFUx70$c>uytI)2V;ujFXFnc`*Y>!huXqYn>#-#zgfz#$ zczCo&6bm_~*#Hm*rW2cZiSI*fPg*uvHfC((Pw)@*v?SggX-nc)Hr?ujrbzG2h!TYM z&-MKPJX=VF=cc3&_$4C?fErpFiT}eULti{?`{86-yw$%q8-E4j(|g0$`4j~J{h`ai zN83X6`*!`OFVMHS?K4^G_PzeIvV0gum@D}Gc6k4AvApf}v$C9S;Q9G>XWz%mcYQb|78N8QkwKnhV3q@FgTBj`?g_N!MyP5j)$d+tH2B+gtI7rlgbX9wZq&-UqOtVs zlmyQRnn)IJu^m!ftWN$5j1(Qe<(F|xR^a`+r)}3$ z_CpO<>|c)}mbCs$gudLM`wnvA5Y$WZKwWIk#SqK@($E+-sSz0N?38vAEwx+nN9+2t z2g55(W>WbR?tUvF=bVg%czWM`O715KWQ~CJK~ETUR17m+?$8*zTJh_eBA57gwF<=C zwrcIYL&QGxk#3o~DP8z$1we%yH{JH>p2CU?Clcr+gMY zzl{qD4=LVnKndt1+i-}xs-1hMFt#!hMi<5Msyz`pb9M)-y?nW3M6#%Y{lmf!d2m!F zHOG-mD4p%aRnCc=FXLHnA=eNUDc7_m>7Ou}nM$QmTwE|(aiI*!-Q5kDEv;f8reV4x zIs!nr!|QHE_34cdm8ytDfQab*ber&Ww1#_ij|2jVKfB9@)w#+fu2)mC`!{k zxt$%+HgcbH=%}*ZrTo28;AzM*;gX4ef3IK;5>#Tms-#)K7?!8xLTQmvM;O}OwPAcE z%|eb3xG54dDN()_B|}OJr;i=QlC28IY@R|*0;>m8$L8g(y37?D%U9f`_#gYTXmY3S zN6vVA!v*gy9vUIT>~zBV^ONHOscMdV8uu8h z;HG-m{MEanaPA`!a{BDt&xDdd7E;`pBpY@pn^~qoKl$Ow22F9gE`<^vDy6+=G7U(H z=#3{Bm&GWJmsH~lHPlISuUsqwiYtjXUMnYEMXgYk%Pr4lV;lfv^hAoMV*D)B>N;4T zqniNY#wgOaX>ys;oGP1)$R`wNXl05UHEX%n%Zg-KzR!GjCq0E#F*EP8V0L@C7 z=Mjd+m0s+Ue*8+Ki6cH5)!pM-d4q^Ek+G5c=>`+9E(+Q#!lnwugmxp+J`~G+JeT9( zc(Eufr^lFSV+?YKE->EwS_~6uW#FBrm8gRw8fimj zVo`}gQi-K|kjc^uqxF2yH(I8SWL(URvJJX}<}Qdn#t_ z44W$G%6c09Q8|dhx=%gtuC2?j9J zZH$sWV@G(^;5?3+SiNNHIs*S7un}PLIX>D9(Q9A@&#YRHXx33IUSxxv1Ds8YEmB^co(7 z3VbHN1uTPViQ~Bgsh!%$FDncGz*x5mZ>T*NYl}dkASKF~TsAF-b6J5J_7oSK1#lCW zv9wxAaE_Ta#_hkuj8Na}J{Um|-{tcB#1z#cDrewAU$YBw(wjUP2V)Bi6iqsl10Bj` z8)h71ZMHh|C0VYR^_9fy=#(IXkoD7`@l2Jb3f}nX9`jUGB-hWiuGkz;_4H^2)Lsde0kckN?8fyk7bdZ($aS~|2L{KsQnx7DrZq7M zdoMsuM<-YbsCGPvtVz)u&{luRHR@Sa1gfyEpE5_8*{0DLTzM7_O^D?wRXN=LBdM>U z5wofO+fR?Gu9t1`2X8BrgP^k-OYFt?Id;N>Ig57akkqa;b8(KKiAj`{wOf}5UpEdX zs)vB}kc$S3gH|rE{34e=|q zy{xdC-EIrhJX)JlIZbqrFwMEcoR#*vsd7jwc#&uWe7MU;20(F!|OGS0jH*Z>(Su>ZGt`pz0zm{QG`r<;>~*b@JYY zg*qXMxWsVsDGTXg>tnCc_jW*hGaJp}mu>(s!hW(;4}_6Lo$9=ICQ?lsQy#skLzD37 z62oe+woCSt{H)eyw!+O9_H;9pNhdl!bU4j8&fl6D9!0T1q5K|L9?bXYgO;v>Qj500vc<^rg&rkFTMWlkzz-#-G~Qu)JBMP&sx0~U zz;jH;yBC>br&Y(jAAryEkF~NQbq$`^OGmpD|tu_${+XJGFo_ZI) zE9J2nZXtj#_pBh@>5_&J8G`j2c;KtPfp4@oDSIKtmh426{!HO=F$>r%l4?a zUOZtHhw5Ue5(vGeM7qo{h2A-VeJPO&5;7sqNi^*&NSC7M`(e5wf-Aw{n!&~>u`1kj zX{s*m2g6Bk-@bR>XA8)r;--4RFIH{vktLn)FGMN9Z`8h;&z;%7UGLl5U-$R#dAl!p zA0BVFeY^5*eqQ%CpJAM{w}QUuH$PTj-t5gm-fr*f`St0)RsSJTgVcd9qlDUbnzJFI z`e1jkA?tFC$Z_b>vOEf}Uk|nlZb38u#eMB|Xx~xjbOI&d{RPf#Ic4bS#P_gsCbuJ2 z&&z$!xg-mP^uv7xZV?ibax@Z)xC?YD(6I@JWMy@cp_PJ80~QvKnP(v#^Gb)E73TOa zn33Jw4laQc|9`=ZX6H$}&VVC~gCJWfN}(UQx*QpZ6h>IAD%8 zpV10Q$J5X3yw-N0*~#r0iB#U2ckubQLs&wKVGsLZ6nQ$&b{ z%BG&Y2^}b`;LpHqH0Bfzzpis>%X{?f{7#YX8YVwu2A!LAHV%)ymmO}>h26aRo6&cfO( za_92xt{3t_?KO-y{@BfvYs_Goac0LK?xiz>iLSpm&ZVsn5jBV{Irs)r=JDtKpG5Zm zc94vl>Ayo?e_Gv#t&iLP3C7P8>_`zo8F=tn5Gt`v1NrPwWD$WkZd!99e!d4j|I$pB zT+gN8MKwUGBPU2a^(Ez3GTrh6g=6w&F8tXeN8+D3y`ji!O8XI_J#(k zKE18lKi3btR|ao3ELsSTG=kt^{?XpeAafvpB!T#Wv3`X2uh!j5R)2(B9AIaV{J>y8 znQvKK$gqDBKsBIn2>FEDUCsxWw9Z+a!8aS;xF}F($S61qIx4b4bTC_LvB2OU;anl~ zRB;IOgJuXfupr>+22NjOOFF`ts!SYaw|Qc*OLg;bgT^F| zz&*kth_u?`19!3z7vWM7BT%ZcY>x3@PKp_ccQZJ_+YHJ^`u1 zCUOgG#_%MU3ufyT{%wB(p;7_-zjvS*2Z2df+a`qL*pML%8^F&=94Atu?H;AkM<&`q zQ1d}kDV}pt$H@Cz@0Y-sl-hV~DPD%ahwlyrVAI z91>D-uH7SHt83N}bEQt48Yp4$pFH_9-1}ecQ2&ZInqFB(vtNN5QGj=s&*j zI1`&8`)1E3@dLu|!TGn{#{L1Q6&1+^}Gn&k2 zfGvh8yVCe)^W8f9v|Zm#Z4L5V(%->UIoU6^RCkN!RZafbO+R|yVDALn<8mwPXmyQ? zbcuCeUYpZ;5=aH*1f85rKCQ;utR7U(Zr>)bm8d;>OkPa&w%2oG3A2J7DnfLm)drfi z0G5=6aX7^GW{@#54O8lBH^6#00sr9Glk^J|4k6aIE8pJ9h?c7uQ6$ zax5JnE*s6*DH-tN$*inQ+nM>yH@myDDrNFFb;S#BPY%fD^!_qLdQ8IH<|K%+PNmdg zjAfyX$93qvF63m4JjoqnS9;R&q>+GU#YFYF*)q%ufs3se!{iaRimiNl5hDO~NGg8& za7$!yEp{D$u$*xymLA-gjI+`eHUJVXe9x4eZ(7wwo8fbCEs|Q%NmjEiqUuSyc5SST zaK~exROBI2)LCWvn`_Dw9W@9ij;Lgbv;+58Hy@*&5)69*q0tR7Tz!x=>Z6b2^IRuf zUdXWY8xb}`BR|y+#lMw1{9#boUAo*}8+pg>LhGO|$c7Zw;T4FkEuQni%hD=4{SS$$ zvbSGD^C3$D)g#oo?Q`Km$KeJwo%&qA#+#I1HQL$8QsfgT2|IEqBGUivsjZJOcxk*@$2AP70`m= zca(OP%H^C<%8*4!N9&BJHDq zk@Mg-FzQ#s1*>r1X}YMXpKeLui%C!yh9>$n7U)-6Z{>gW&bEVMgH|}_5oKV~Nt0U5NBtDBuiF%?~$x)dnMGZ|cw=IV8t8groYe=hd zWC>hg#&Vrso|z8Th>!F-oJc`+ThxHSA>4NBu;1EXGG$n~${JzFF(A>hv?h6$U6f(G z=GJ6#X$+e|P4h6zDHkZ5@lKJ6ZORqiy>AC${MuB7kk#w*q9m|L*msw?8ps*w11L#i zxYml4__!3e1Ye*+#dMbQQOs51s}f9_;MEQnZ%EvnJanDro|g>QKHod}m_pMs|HV{& zT8~5Y!^BFY*G{U)=El7dLcy_qf<{&itvN2~c#ejqmx4Rz#o5`{JPn{Z8Q0|1Vv@2I zv^9v=@XahDVv^@8H^$~Vhx~={e1c0sOsFE{xe*5)lS#I+#eQJ|^I|CRoJMyYImb5D zrs#j_UHr!zTucPhcv6K&Z!?C=rV?5vU~Eo((9@Qk#3S|zfjp49Yu`v%030p&`4|jCdjxFHl(q*dKMSaUd0ICuRze5Gr+3%G z1z_LbZj6BZ@$ks1GUo-(N{o^(o`GK@ z$-EFeM8N)OuBu$u6ghjPvjdHaHz{az!OFU%G2}2N8swbC>wXkh1wgGmUEu2vb5fJIo z;J0PuA@@80e@7_N{3%rpJapRkGq&BQVQ49c3d&WWS-j)?!}jw zE2@>biQ4=fT%ho$$G5w?CQOC7MJzQ&`KpR?ZUdO}jSuv?Ctc79>G)9@u5GR?NGedMk{yn>2OiZFO6bAmr70J-VL z$u}93qiu#upN(@|KhiBQKUxiLFM{r~{)pA#2>kwvQOq_14|NyTb2%®h>XGC!WF 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

1WAcV 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

kjUF+pQP;I+vEvvgh#8e!zGak5KNSw*Qwbiti* z$D5wSES7~v#(nzuqsjJ@EPjtouGZl45XsO^M<%Sul)vp4u&2yM6r)zZr$OWR{wqrs z49*L_0{4&Af>VbUY z$_bUGmCH=pSe?%=$)9r2F(LSBk4h)o4h@b=4!yBDkh%9=bsVQTo`shDe zSDce`cSlwMEHe!^WPQ2%aM!OrsBS)T15U)yjv|GsSFur^a|I(zyq(JHF^cDe^T?A{@ zZLBs49$b%zt+y~l<6dcc%!!Oe#Uo!?wZBw2>ulrZ1A87__GlHK8TLvq%F8*!EIQ}Y z?X{Y@-mTm|4EKNL>}>Se_eW3D4$(IL-MTa;dY5jfz=yOY(qL}5PjG)Kb zc7H9M5@wol`1Q%jPqhCENbx)nub-3uaQLvy2{zik&Z9CiJM>YTvSjVhV70OFj^7SV zdDs1=`-&A!i`U(__%r%yfx~@|=X*AEs{Gl){pGkm2Az_><=#)ZeKoc3i|Y;#os7gm zNv_qmE(KMcFDy&yE3EEw}`+MnuHt><(`<*ZORnS$eofcb|RtQ^jw>hwhU!<*e#I@<+d0{cbOreRWQL z^K}DG;bYNYKeINDlg~UJ-{*jSh%Nzs7Q&%H+#E&V}5-M=H5v zv`oL{`fq+Fv2WgE_xtQ^*R$JX6+E>+7OwUn%P=fd5)vxu<{mI~m?Jd z($;IEt_s>n4Bkd;AMs$OXTdLvrfs~KjmG@>aYH)_H9+{6N?vd@m@)s8jlxcQw^7F0IOYU(reMqTsR4bh}H1 zPZHGzq|3Dm_DY_gi9EX|Meq97VoT?TsTwN`zt#8lNqkfIzC%Tuu*d6n_qefZ-@ql? zwHF0!O#h^N9bYpPwztb`Z*^2MjN(0e=;+ss^I#HF1sxkK6k7g=y{}2x9afefy*{}6+RiO)A#UAouL1-VT;r~2datlH_x24@QJ;ULN9*mw!8+Ya%2(zJWem$E3S_3_xr8INZB|NO2pY{%;3S6){93@9kR)H%;-WBlqU(WviE zr{4r6>^T;p>)7}4-sm{Rsr%pU#5zq1e`jg@*6%;kmo2p2{8Go~YV7Bb zKkx;84-zjjivN9ok$e47dj$7_yI6-W(4 zax7AXGDFTToT5(BAJAXnhU zSCPa(E|3ev+9H8K@Xyn%|M?U1*sFwlT+*EP+~ohy3z&SOxtA)rb20z@DNL67|2~@e z|NgDl1#+ptT3f6wRA`IvB#Q(b%{w)7}kN@uJKkwH{1>Ezt|Gr==#n%2W zUa%Dl_%GP{K6KtG=)9-evt7TVla|LvMDIFmHMGlKgJBshJG+Mj9EkH$eyZyxHX8PI ziO}J9JAN8uyMtf^Bp&OX=O=PW($(cwpV{>HayTgZAZm=>w;D-&o!m` z%vt{~&#gi@N_V5dis9|UPee^VFv#3oJ$16wd}5s6(zfd#4qUk?$xeR0-hS3DhgnmG zjj%i!nfq>6c@N(&Kl1wq4OwR!e%$w|Z+N`dDIfd3Zz@&7ujwxtmFtnTvZn8suASJn@8TiQmrsUlqYUL;OFF9g|mMSyB1Fe>9d8PjmLsSZ@8_ zqDE?fef+DBxbBmh)iTpT*ph(A>ZO z#S@8yVg^qrl87bJKa7Pe@Wx^diICt)6>?~z-`4=1Ov2&`g-T{Dw`T=3-tS`t0?0Rn z`*#@d#6lrN_qR0!0+B!@CF_dCoL1!HNfaWeyWe2kd{Q|s<2M-QQwT)-J#%;pfsDmd zDsY;=j|HCOpQpEZ^NEF0A%6`HPbBA$6r9j5t3-F{O0hHu#V+8_JCmQ~Y6nase|IW=8}z;*G_+a*>j~54l97;GZdnCl#~zA%|x`?oBS2@y7}T3OpcB z@szM)zn>NGBoZmXgUIkIu{1$YWM_W(Da50qjhe=h>=?R-3@&*I78UHlFM9(bI;XN*%Sn7sf`DTj~o z`&cZ1?J)Nt6iOs;Vpu!~KM#i8;h_0rx%s4wtO|s=`QvVc}Rj zcyW9f@StG$Fw7^Ci1=p;JOzMcJ{fBVF&QhX+>kp1CzBls{J9vlO@u7dED3@UEfVIeca^}tjLWL0F4~qvUncbg4@&~?0Ou!$D`Q#GHe^LqKtANv>P6-`S1Yo?q z08brR;^vdH@*xrd#NRWAN9-!pvx2op zuoWWKk3cXhV*MQ8Nm%(1iQ&NTbq>~5%31jk!DU4l%bcH5$;yWadYAD1KMI;RmeZWX zf5E~MhKGPBA$~FN;7zgf$>nTJ!W|$hA0nwxO!Pfe6LaSX0_3cY<*>wT{2`KoQ`z$q z3Z+CoWHJOfyghUCDTsVPLomK5&_n_vA7B^cFZlN%6d~~8!MN}P&K?iO&4*x!2Lql| z!SDu$Cnxd&y~fyh4iAYBW7)<`YX;`4A(pVAkO9WUT!VgIwm$ zIXryy$y-Ap2A49v0PrNN&j37RMp*p}pNo|bF}z6;;RCp_486!Y{o$M?Y^;kzmP+NU zzJk-h%7<9Yg{(Z(EO0)5=ST2$r9+8z`Fr8; z6pXEfK|xA^FN2&qh3CYl0|!OzK5{{}k+Atry0hSJU*>qi`Q22K#;Ia%Pu7DY2WD9s)(u22WtP5FS>5y_a zOz%Bgf*_l>XZ+S5(pQ9^A=2!9AfH3z7cMaCzd+q1*}_``^ny3|XAe68ABn#g4o||$ zxkQOH9HB!>;(ZBnJj~g1^RY3606PXIyFZzbm2+f8shvUknU!+{0TKy62Y_`^3*xVV z^dwR;5#%rqc0MJwtFRudoJ$e8u=z>s4~WcsoH}6787I%m zIWh`L=FZ{na%z#8PtG}PJQ#prco@G2%0DX(kF^z?bg(%x;BlTOGoJ!^Ggf}# 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 literal 0 HcmV?d00001 diff --git a/docsify.txt b/docsify.txt new file mode 100644 index 0000000..6e616ad --- /dev/null +++ b/docsify.txt @@ -0,0 +1,10233 @@ +(function () { + /** + * Create a cached version of a pure function. + * @param {*} fn The function call to be cached + * @void + */ + + function cached(fn) { + var cache = Object.create(null); + return function (str) { + var key = isPrimitive(str) ? str : JSON.stringify(str); + var hit = cache[key]; + return hit || (cache[key] = fn(str)); + }; + } + + /** + * Hyphenate a camelCase string. + */ + var hyphenate = cached(function (str) { + return str.replace(/([A-Z])/g, function (m) { return '-' + m.toLowerCase(); }); + }); + + var hasOwn = Object.prototype.hasOwnProperty; + + /** + * Simple Object.assign polyfill + * @param {Object} to The object to be merged with + * @returns {Object} The merged object + */ + var merge = + Object.assign || + function (to) { + var arguments$1 = arguments; + + for (var i = 1; i < arguments.length; i++) { + var from = Object(arguments$1[i]); + + for (var key in from) { + if (hasOwn.call(from, key)) { + to[key] = from[key]; + } + } + } + + return to; + }; + + /** + * Check if value is primitive + * @param {*} value Checks if a value is primitive + * @returns {Boolean} Result of the check + */ + function isPrimitive(value) { + return typeof value === 'string' || typeof value === 'number'; + } + + /** + * Performs no operation. + * @void + */ + function noop() {} + + /** + * Check if value is function + * @param {*} obj Any javascript object + * @returns {Boolean} True if the passed-in value is a function + */ + function isFn(obj) { + return typeof obj === 'function'; + } + + /** + * Check if url is external + * @param {String} string url + * @returns {Boolean} True if the passed-in url is external + */ + function isExternal(url) { + var match = url.match( + /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ + ); + + if ( + typeof match[1] === 'string' && + match[1].length > 0 && + match[1].toLowerCase() !== location.protocol + ) { + return true; + } + if ( + typeof match[2] === 'string' && + match[2].length > 0 && + match[2].replace( + new RegExp( + ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$' + ), + '' + ) !== location.host + ) { + return true; + } + if (/^\/\\/.test(url)) { + return true; + } + return false; + } + + var inBrowser = !false; + + var isMobile = document.body.clientWidth <= 600; + + /** + * @see https://github.com/MoOx/pjax/blob/master/lib/is-supported.js + */ + var supportsPushState = + + (function () { + // Borrowed wholesale from https://github.com/defunkt/jquery-pjax + return ( + window.history && + window.history.pushState && + window.history.replaceState && + // PushState isn’t reliable on iOS until 5. + !navigator.userAgent.match( + /((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/ + ) + ); + })(); + + var cacheNode = {}; + + /** + * Get Node + * @param {String|Element} el A DOM element + * @param {Boolean} noCache Flag to use or not use the cache + * @return {Element} The found node element + */ + function getNode(el, noCache) { + if ( noCache === void 0 ) noCache = false; + + if (typeof el === 'string') { + if (typeof window.Vue !== 'undefined') { + return find(el); + } + + el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el)); + } + + return el; + } + + var $ = document; + + var body = $.body; + + var head = $.head; + + /** + * Find elements + * @param {String|Element} el The root element where to perform the search from + * @param {Element} node The query + * @returns {Element} The found DOM element + * @example + * find('nav') => document.querySelector('nav') + * find(nav, 'a') => nav.querySelector('a') + */ + function find(el, node) { + return node ? el.querySelector(node) : $.querySelector(el); + } + + /** + * Find all elements + * @param {String|Element} el The root element where to perform the search from + * @param {Element} node The query + * @returns {Array} An array of DOM elements + * @example + * findAll('a') => [].slice.call(document.querySelectorAll('a')) + * findAll(nav, 'a') => [].slice.call(nav.querySelectorAll('a')) + */ + function findAll(el, node) { + return [].slice.call( + node ? el.querySelectorAll(node) : $.querySelectorAll(el) + ); + } + + function create(node, tpl) { + node = $.createElement(node); + if (tpl) { + node.innerHTML = tpl; + } + + return node; + } + + function appendTo(target, el) { + return target.appendChild(el); + } + + function before(target, el) { + return target.insertBefore(el, target.children[0]); + } + + function on(el, type, handler) { + isFn(type) + ? window.addEventListener(el, type) + : el.addEventListener(type, handler); + } + + function off(el, type, handler) { + isFn(type) + ? window.removeEventListener(el, type) + : el.removeEventListener(type, handler); + } + + /** + * Toggle class + * @param {String|Element} el The element that needs the class to be toggled + * @param {Element} type The type of action to be performed on the classList (toggle by default) + * @param {String} val Name of the class to be toggled + * @void + * @example + * toggleClass(el, 'active') => el.classList.toggle('active') + * toggleClass(el, 'add', 'active') => el.classList.add('active') + */ + function toggleClass(el, type, val) { + el && el.classList[val ? type : 'toggle'](val || type); + } + + function style(content) { + appendTo(head, create('style', content)); + } + + /** + * Fork https://github.com/bendrucker/document-ready/blob/master/index.js + * @param {Function} callback The callbacack to be called when the page is loaded + * @returns {Number|void} If the page is already laoded returns the result of the setTimeout callback, + * otherwise it only attaches the callback to the DOMContentLoaded event + */ + function documentReady(callback, doc) { + if ( doc === void 0 ) doc = document; + + var state = doc.readyState; + + if (state === 'complete' || state === 'interactive') { + return setTimeout(callback, 0); + } + + doc.addEventListener('DOMContentLoaded', callback); + } + + var dom = /*#__PURE__*/Object.freeze({ + __proto__: null, + getNode: getNode, + $: $, + body: body, + head: head, + find: find, + findAll: findAll, + create: create, + appendTo: appendTo, + before: before, + on: on, + off: off, + toggleClass: toggleClass, + style: style, + documentReady: documentReady + }); + + function startsWith(str, prefix) { + return str.indexOf(prefix) === 0; + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + var decode = decodeURIComponent; + var encode = encodeURIComponent; + + function parseQuery(query) { + var res = {}; + + query = query.trim().replace(/^(\?|#|&)/, ''); + + if (!query) { + return res; + } + + // Simple parse + query.split('&').forEach(function (param) { + var parts = param.replace(/\+/g, ' ').split('='); + + res[parts[0]] = parts[1] && decode(parts[1]); + }); + + return res; + } + + function stringifyQuery(obj, ignores) { + if ( ignores === void 0 ) ignores = []; + + var qs = []; + + for (var key in obj) { + if (ignores.indexOf(key) > -1) { + continue; + } + + qs.push( + obj[key] + ? ((encode(key)) + "=" + (encode(obj[key]))).toLowerCase() + : encode(key) + ); + } + + return qs.length ? ("?" + (qs.join('&'))) : ''; + } + + var isAbsolutePath = cached(function (path) { + return /(:|(\/{2}))/g.test(path); + }); + + var removeParams = cached(function (path) { + return path.split(/[?#]/)[0]; + }); + + var getParentPath = cached(function (path) { + if (/\/$/g.test(path)) { + return path; + } + + var matchingParts = path.match(/(\S*\/)[^/]+$/); + return matchingParts ? matchingParts[1] : ''; + }); + + var cleanPath = cached(function (path) { + return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/'); + }); + + var resolvePath = cached(function (path) { + var segments = path.replace(/^\//, '').split('/'); + var resolved = []; + for (var i = 0, len = segments.length; i < len; i++) { + var segment = segments[i]; + if (segment === '..') { + resolved.pop(); + } else if (segment !== '.') { + resolved.push(segment); + } + } + + return '/' + resolved.join('/'); + }); + + /** + * Normalises the URI path to handle the case where Docsify is + * hosted off explicit files, i.e. /index.html. This function + * eliminates any path segments that contain `#` fragments. + * + * This is used to map browser URIs to markdown file sources. + * + * For example: + * + * http://example.org/base/index.html#/blah + * + * would be mapped to: + * + * http://example.org/base/blah.md. + * + * See here for more information: + * + * https://github.com/docsifyjs/docsify/pull/1372 + * + * @param {string} path The URI path to normalise + * @return {string} { path, query } + */ + + function normaliseFragment(path) { + return path + .split('/') + .filter(function (p) { return p.indexOf('#') === -1; }) + .join('/'); + } + + function getPath() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return cleanPath(args.map(normaliseFragment).join('/')); + } + + var replaceSlug = cached(function (path) { + return path.replace('#', '?id='); + }); + + var cached$1 = {}; + + function getAlias(path, alias, last) { + var match = Object.keys(alias).filter(function (key) { + var re = cached$1[key] || (cached$1[key] = new RegExp(("^" + key + "$"))); + return re.test(path) && path !== last; + })[0]; + + return match + ? getAlias(path.replace(cached$1[match], alias[match]), alias, path) + : path; + } + + function getFileName(path, ext) { + return new RegExp(("\\.(" + (ext.replace(/^\./, '')) + "|html)$"), 'g').test(path) + ? path + : /\/$/g.test(path) + ? (path + "README" + ext) + : ("" + path + ext); + } + + var History = function History(config) { + this.config = config; + }; + + History.prototype.getBasePath = function getBasePath () { + return this.config.basePath; + }; + + History.prototype.getFile = function getFile (path, isRelative) { + if ( path === void 0 ) path = this.getCurrentPath(); + + var ref = this; + var config = ref.config; + var base = this.getBasePath(); + var ext = typeof config.ext === 'string' ? config.ext : '.md'; + + path = config.alias ? getAlias(path, config.alias) : path; + path = getFileName(path, ext); + path = path === ("/README" + ext) ? config.homepage || path : path; + path = isAbsolutePath(path) ? path : getPath(base, path); + + if (isRelative) { + path = path.replace(new RegExp(("^" + base)), ''); + } + + return path; + }; + + History.prototype.onchange = function onchange (cb) { + if ( cb === void 0 ) cb = noop; + + cb(); + }; + + History.prototype.getCurrentPath = function getCurrentPath () {}; + + History.prototype.normalize = function normalize () {}; + + History.prototype.parse = function parse () {}; + + History.prototype.toURL = function toURL (path, params, currentRoute) { + var local = currentRoute && path[0] === '#'; + var route = this.parse(replaceSlug(path)); + + route.query = merge({}, route.query, params); + path = route.path + stringifyQuery(route.query); + path = path.replace(/\.md(\?)|\.md$/, '$1'); + + if (local) { + var idIndex = currentRoute.indexOf('?'); + path = + (idIndex > 0 ? currentRoute.substring(0, idIndex) : currentRoute) + + path; + } + + if (this.config.relativePath && path.indexOf('/') !== 0) { + var currentDir = currentRoute.substring( + 0, + currentRoute.lastIndexOf('/') + 1 + ); + return cleanPath(resolvePath(currentDir + path)); + } + + return cleanPath('/' + path); + }; + + function replaceHash(path) { + var i = location.href.indexOf('#'); + location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path); + } + var HashHistory = /*@__PURE__*/(function (History) { + function HashHistory(config) { + History.call(this, config); + this.mode = 'hash'; + } + + if ( History ) HashHistory.__proto__ = History; + HashHistory.prototype = Object.create( History && History.prototype ); + HashHistory.prototype.constructor = HashHistory; + + HashHistory.prototype.getBasePath = function getBasePath () { + var path = window.location.pathname || ''; + var base = this.config.basePath; + + // This handles the case where Docsify is served off an + // explicit file path, i.e.`/base/index.html#/blah`. This + // prevents the `/index.html` part of the URI from being + // remove during routing. + // See here: https://github.com/docsifyjs/docsify/pull/1372 + var basePath = endsWith(path, '.html') + ? path + '#/' + base + : path + '/' + base; + return /^(\/|https?:)/g.test(base) ? base : cleanPath(basePath); + }; + + HashHistory.prototype.getCurrentPath = function getCurrentPath () { + // We can't use location.hash here because it's not + // consistent across browsers - Firefox will pre-decode it! + var href = location.href; + var index = href.indexOf('#'); + return index === -1 ? '' : href.slice(index + 1); + }; + + /** @param {((params: {source: TODO}) => void)} [cb] */ + HashHistory.prototype.onchange = function onchange (cb) { + if ( cb === void 0 ) cb = noop; + + // The hashchange event does not tell us if it originated from + // a clicked link or by moving back/forward in the history; + // therefore we set a `navigating` flag when a link is clicked + // to be able to tell these two scenarios apart + var navigating = false; + + on('click', function (e) { + var el = e.target.tagName === 'A' ? e.target : e.target.parentNode; + + if (el && el.tagName === 'A' && !isExternal(el.href)) { + navigating = true; + } + }); + + on('hashchange', function (e) { + var source = navigating ? 'navigate' : 'history'; + navigating = false; + cb({ event: e, source: source }); + }); + }; + + HashHistory.prototype.normalize = function normalize () { + var path = this.getCurrentPath(); + + path = replaceSlug(path); + + if (path.charAt(0) === '/') { + return replaceHash(path); + } + + replaceHash('/' + path); + }; + + /** + * Parse the url + * @param {string} [path=location.herf] URL to be parsed + * @return {object} { path, query } + */ + HashHistory.prototype.parse = function parse (path) { + if ( path === void 0 ) path = location.href; + + var query = ''; + + var hashIndex = path.indexOf('#'); + if (hashIndex >= 0) { + path = path.slice(hashIndex + 1); + } + + var queryIndex = path.indexOf('?'); + if (queryIndex >= 0) { + query = path.slice(queryIndex + 1); + path = path.slice(0, queryIndex); + } + + return { + path: path, + file: this.getFile(path, true), + query: parseQuery(query), + }; + }; + + HashHistory.prototype.toURL = function toURL (path, params, currentRoute) { + return '#' + History.prototype.toURL.call(this, path, params, currentRoute); + }; + + return HashHistory; + }(History)); + + /** @typedef {any} TODO */ + + var HTML5History = /*@__PURE__*/(function (History) { + function HTML5History(config) { + History.call(this, config); + this.mode = 'history'; + } + + if ( History ) HTML5History.__proto__ = History; + HTML5History.prototype = Object.create( History && History.prototype ); + HTML5History.prototype.constructor = HTML5History; + + HTML5History.prototype.getCurrentPath = function getCurrentPath () { + var base = this.getBasePath(); + var path = window.location.pathname; + + if (base && path.indexOf(base) === 0) { + path = path.slice(base.length); + } + + return (path || '/') + window.location.search + window.location.hash; + }; + + HTML5History.prototype.onchange = function onchange (cb) { + if ( cb === void 0 ) cb = noop; + + on('click', function (e) { + var el = e.target.tagName === 'A' ? e.target : e.target.parentNode; + + if (el && el.tagName === 'A' && !isExternal(el.href)) { + e.preventDefault(); + var url = el.href; + window.history.pushState({ key: url }, '', url); + cb({ event: e, source: 'navigate' }); + } + }); + + on('popstate', function (e) { + cb({ event: e, source: 'history' }); + }); + }; + + /** + * Parse the url + * @param {string} [path=location.href] URL to be parsed + * @return {object} { path, query } + */ + HTML5History.prototype.parse = function parse (path) { + if ( path === void 0 ) path = location.href; + + var query = ''; + + var queryIndex = path.indexOf('?'); + if (queryIndex >= 0) { + query = path.slice(queryIndex + 1); + path = path.slice(0, queryIndex); + } + + var base = getPath(location.origin); + var baseIndex = path.indexOf(base); + + if (baseIndex > -1) { + path = path.slice(baseIndex + base.length); + } + + return { + path: path, + file: this.getFile(path), + query: parseQuery(query), + }; + }; + + return HTML5History; + }(History)); + + /** + * @typedef {{ + * path?: string + * }} Route + */ + + /** @type {Route} */ + var lastRoute = {}; + + /** @typedef {import('../Docsify').Constructor} Constructor */ + + /** + * @template {!Constructor} T + * @param {T} Base - The class to extend + */ + function Router(Base) { + return /*@__PURE__*/(function (Base) { + function Router() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + Base.apply(this, args); + + this.route = {}; + } + + if ( Base ) Router.__proto__ = Base; + Router.prototype = Object.create( Base && Base.prototype ); + Router.prototype.constructor = Router; + + Router.prototype.updateRender = function updateRender () { + this.router.normalize(); + this.route = this.router.parse(); + body.setAttribute('data-page', this.route.file); + }; + + Router.prototype.initRouter = function initRouter () { + var this$1 = this; + + var config = this.config; + var mode = config.routerMode || 'hash'; + var router; + + if (mode === 'history' && supportsPushState) { + router = new HTML5History(config); + } else { + router = new HashHistory(config); + } + + this.router = router; + this.updateRender(); + lastRoute = this.route; + + // eslint-disable-next-line no-unused-vars + router.onchange(function (params) { + this$1.updateRender(); + this$1._updateRender(); + + if (lastRoute.path === this$1.route.path) { + this$1.$resetEvents(params.source); + return; + } + + this$1.$fetch(noop, this$1.$resetEvents.bind(this$1, params.source)); + lastRoute = this$1.route; + }); + }; + + return Router; + }(Base)); + } + + var RGX = /([^{]*?)\w(?=\})/g; + + var MAP = { + YYYY: 'getFullYear', + YY: 'getYear', + MM: function (d) { + return d.getMonth() + 1; + }, + DD: 'getDate', + HH: 'getHours', + mm: 'getMinutes', + ss: 'getSeconds', + fff: 'getMilliseconds' + }; + + function tinydate (str, custom) { + var parts=[], offset=0; + + str.replace(RGX, function (key, _, idx) { + // save preceding string + parts.push(str.substring(offset, idx - 1)); + offset = idx += key.length + 1; + // save function + parts.push(custom && custom[key] || function (d) { + return ('00' + (typeof MAP[key] === 'string' ? d[MAP[key]]() : MAP[key](d))).slice(-key.length); + }); + }); + + if (offset !== str.length) { + parts.push(str.substring(offset)); + } + + return function (arg) { + var out='', i=0, d=arg||new Date(); + for (; i 80 ? 80 : num; + } else { + num = Math.floor((loaded / total) * 100); + } + + barEl.style.opacity = 1; + barEl.style.width = num >= 95 ? '100%' : num + '%'; + + if (num >= 95) { + clearTimeout(timeId); + // eslint-disable-next-line no-unused-vars + timeId = setTimeout(function (_) { + barEl.style.opacity = 0; + barEl.style.width = '0%'; + }, 200); + } + } + + /* eslint-disable no-unused-vars */ + + var cache = {}; + + /** + * Ajax GET implmentation + * @param {string} url Resource URL + * @param {boolean} [hasBar=false] Has progress bar + * @param {String[]} headers Array of headers + * @return {Promise} Promise response + */ + function get(url, hasBar, headers) { + if ( hasBar === void 0 ) hasBar = false; + if ( headers === void 0 ) headers = {}; + + var xhr = new XMLHttpRequest(); + var on = function () { + xhr.addEventListener.apply(xhr, arguments); + }; + + var cached = cache[url]; + + if (cached) { + return { then: function (cb) { return cb(cached.content, cached.opt); }, abort: noop }; + } + + xhr.open('GET', url); + for (var i in headers) { + if (hasOwn.call(headers, i)) { + xhr.setRequestHeader(i, headers[i]); + } + } + + xhr.send(); + + return { + then: function (success, error) { + if ( error === void 0 ) error = noop; + + if (hasBar) { + var id = setInterval( + function (_) { return progressbar({ + step: Math.floor(Math.random() * 5 + 1), + }); }, + 500 + ); + + on('progress', progressbar); + on('loadend', function (evt) { + progressbar(evt); + clearInterval(id); + }); + } + + on('error', error); + on('load', function (ref) { + var target = ref.target; + + if (target.status >= 400) { + error(target); + } else { + var result = (cache[url] = { + content: target.response, + opt: { + updatedAt: xhr.getResponseHeader('last-modified'), + }, + }); + + success(result.content, result.opt); + } + }); + }, + abort: function (_) { return xhr.readyState !== 4 && xhr.abort(); }, + }; + } + + function replaceVar(block, color) { + block.innerHTML = block.innerHTML.replace( + /var\(\s*--theme-color.*?\)/g, + color + ); + } + + function cssVars (color) { + // Variable support + if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) { + return; + } + + var styleBlocks = findAll('style:not(.inserted),link'); + [].forEach.call(styleBlocks, function (block) { + if (block.nodeName === 'STYLE') { + replaceVar(block, color); + } else if (block.nodeName === 'LINK') { + var href = block.getAttribute('href'); + + if (!/\.css$/.test(href)) { + return; + } + + get(href).then(function (res) { + var style = create('style', res); + + head.appendChild(style); + replaceVar(style, color); + }); + } + }); + } + + /* eslint-disable no-unused-vars */ + + var title = $.title; + /** + * Toggle button + * @param {Element} el Button to be toggled + * @void + */ + function btn(el) { + var toggle = function (_) { return body.classList.toggle('close'); }; + + el = getNode(el); + if (el === null || el === undefined) { + return; + } + + on(el, 'click', function (e) { + e.stopPropagation(); + toggle(); + }); + + isMobile && + on( + body, + 'click', + function (_) { return body.classList.contains('close') && toggle(); } + ); + } + + function collapse(el) { + el = getNode(el); + if (el === null || el === undefined) { + return; + } + + on(el, 'click', function (ref) { + var target = ref.target; + + if ( + target.nodeName === 'A' && + target.nextSibling && + target.nextSibling.classList && + target.nextSibling.classList.contains('app-sub-sidebar') + ) { + toggleClass(target.parentNode, 'collapse'); + } + }); + } + + function sticky() { + var cover = getNode('section.cover'); + if (!cover) { + return; + } + + var coverHeight = cover.getBoundingClientRect().height; + + if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) { + toggleClass(body, 'add', 'sticky'); + } else { + toggleClass(body, 'remove', 'sticky'); + } + } + + /** + * Get and active link + * @param {Object} router Router + * @param {String|Element} el Target element + * @param {Boolean} isParent Active parent + * @param {Boolean} autoTitle Automatically set title + * @return {Element} Active element + */ + function getAndActive(router, el, isParent, autoTitle) { + el = getNode(el); + var links = []; + if (el !== null && el !== undefined) { + links = findAll(el, 'a'); + } + + var hash = decodeURI(router.toURL(router.getCurrentPath())); + var target; + + links + .sort(function (a, b) { return b.href.length - a.href.length; }) + .forEach(function (a) { + var href = decodeURI(a.getAttribute('href')); + var node = isParent ? a.parentNode : a; + + a.title = a.title || a.innerText; + + if (hash.indexOf(href) === 0 && !target) { + target = a; + toggleClass(node, 'add', 'active'); + } else { + toggleClass(node, 'remove', 'active'); + } + }); + + if (autoTitle) { + $.title = target + ? target.title || ((target.innerText) + " - " + title) + : title; + } + + return target; + } + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var SingleTweener = function () { + function SingleTweener() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, SingleTweener); + + this.start = opts.start; + this.end = opts.end; + this.decimal = opts.decimal; + } + + _createClass(SingleTweener, [{ + key: "getIntermediateValue", + value: function getIntermediateValue(tick) { + if (this.decimal) { + return tick; + } else { + return Math.round(tick); + } + } + }, { + key: "getFinalValue", + value: function getFinalValue() { + return this.end; + } + }]); + + return SingleTweener; + }(); + + var _createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }(); + + function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var Tweezer = function () { + function Tweezer() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck$1(this, Tweezer); + + this.duration = opts.duration || 1000; + this.ease = opts.easing || this._defaultEase; + this.tweener = opts.tweener || new SingleTweener(opts); + this.start = this.tweener.start; + this.end = this.tweener.end; + + this.frame = null; + this.next = null; + this.isRunning = false; + this.events = {}; + this.direction = this.start < this.end ? 'up' : 'down'; + } + + _createClass$1(Tweezer, [{ + key: 'begin', + value: function begin() { + if (!this.isRunning && this.next !== this.end) { + this.frame = window.requestAnimationFrame(this._tick.bind(this)); + } + return this; + } + }, { + key: 'stop', + value: function stop() { + window.cancelAnimationFrame(this.frame); + this.isRunning = false; + this.frame = null; + this.timeStart = null; + this.next = null; + return this; + } + }, { + key: 'on', + value: function on(name, handler) { + this.events[name] = this.events[name] || []; + this.events[name].push(handler); + return this; + } + }, { + key: '_emit', + value: function _emit(name, val) { + var _this = this; + + var e = this.events[name]; + e && e.forEach(function (handler) { + return handler.call(_this, val); + }); + } + }, { + key: '_tick', + value: function _tick(currentTime) { + this.isRunning = true; + + var lastTick = this.next || this.start; + + if (!this.timeStart) { this.timeStart = currentTime; } + this.timeElapsed = currentTime - this.timeStart; + this.next = this.ease(this.timeElapsed, this.start, this.end - this.start, this.duration); + + if (this._shouldTick(lastTick)) { + this._emit('tick', this.tweener.getIntermediateValue(this.next)); + this.frame = window.requestAnimationFrame(this._tick.bind(this)); + } else { + this._emit('tick', this.tweener.getFinalValue()); + this._emit('done', null); + } + } + }, { + key: '_shouldTick', + value: function _shouldTick(lastTick) { + return { + up: this.next < this.end && lastTick <= this.next, + down: this.next > this.end && lastTick >= this.next + }[this.direction]; + } + }, { + key: '_defaultEase', + value: function _defaultEase(t, b, c, d) { + if ((t /= d / 2) < 1) { return c / 2 * t * t + b; } + return -c / 2 * (--t * (t - 2) - 1) + b; + } + }]); + + return Tweezer; + }(); + + var currentScript = document.currentScript; + + /** @param {import('./Docsify').Docsify} vm */ + function config (vm) { + var config = merge( + { + auto2top: false, + autoHeader: false, + basePath: '', + catchPluginErrors: true, + cornerExternalLinkTarget: '_blank', + coverpage: '', + el: '#app', + executeScript: null, + ext: '.md', + externalLinkRel: 'noopener', + externalLinkTarget: '_blank', + formatUpdated: '', + ga: '', + homepage: 'README.md', + loadNavbar: null, + loadSidebar: null, + maxLevel: 6, + mergeNavbar: false, + name: '', + nameLink: window.location.pathname, + nativeEmoji: false, + noCompileLinks: [], + noEmoji: false, + notFoundPage: true, + relativePath: false, + repo: '', + routes: {}, + routerMode: 'hash', + subMaxLevel: 0, + themeColor: '', + topMargin: 0, + }, + typeof window.$docsify === 'function' + ? window.$docsify(vm) + : window.$docsify + ); + + var script = + currentScript || + [].slice + .call(document.getElementsByTagName('script')) + .filter(function (n) { return /docsify\./.test(n.src); })[0]; + + if (script) { + for (var prop in config) { + if (hasOwn.call(config, prop)) { + var val = script.getAttribute('data-' + hyphenate(prop)); + + if (isPrimitive(val)) { + config[prop] = val === '' ? true : val; + } + } + } + } + + if (config.loadSidebar === true) { + config.loadSidebar = '_sidebar' + config.ext; + } + + if (config.loadNavbar === true) { + config.loadNavbar = '_navbar' + config.ext; + } + + if (config.coverpage === true) { + config.coverpage = '_coverpage' + config.ext; + } + + if (config.repo === true) { + config.repo = ''; + } + + if (config.name === true) { + config.name = ''; + } + + window.$docsify = config; + + return config; + } + + var nav = {}; + var hoverOver = false; + var scroller = null; + var enableScrollEvent = true; + var coverHeight = 0; + + function scrollTo(el, offset) { + if ( offset === void 0 ) offset = 0; + + if (scroller) { + scroller.stop(); + } + + enableScrollEvent = false; + scroller = new Tweezer({ + start: window.pageYOffset, + end: + Math.round(el.getBoundingClientRect().top) + window.pageYOffset - offset, + duration: 500, + }) + .on('tick', function (v) { return window.scrollTo(0, v); }) + .on('done', function () { + enableScrollEvent = true; + scroller = null; + }) + .begin(); + } + + function highlight(path) { + if (!enableScrollEvent) { + return; + } + + var sidebar = getNode('.sidebar'); + var anchors = findAll('.anchor'); + var wrap = find(sidebar, '.sidebar-nav'); + var active = find(sidebar, 'li.active'); + var doc = document.documentElement; + var top = ((doc && doc.scrollTop) || document.body.scrollTop) - coverHeight; + var last; + + for (var i = 0, len = anchors.length; i < len; i += 1) { + var node = anchors[i]; + + if (node.offsetTop > top) { + if (!last) { + last = node; + } + + break; + } else { + last = node; + } + } + + if (!last) { + return; + } + + var li = nav[getNavKey(path, last.getAttribute('data-id'))]; + + if (!li || li === active) { + return; + } + + active && active.classList.remove('active'); + li.classList.add('active'); + active = li; + + // Scroll into view + // https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297 + if (!hoverOver && body.classList.contains('sticky')) { + var height = sidebar.clientHeight; + var curOffset = 0; + var cur = active.offsetTop + active.clientHeight + 40; + var isInView = + active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height; + var notThan = cur - curOffset < height; + + sidebar.scrollTop = isInView + ? wrap.scrollTop + : notThan + ? curOffset + : cur - height; + } + } + + function getNavKey(path, id) { + return ((decodeURIComponent(path)) + "?id=" + (decodeURIComponent(id))); + } + + function scrollActiveSidebar(router) { + var cover = find('.cover.show'); + coverHeight = cover ? cover.offsetHeight : 0; + + var sidebar = getNode('.sidebar'); + var lis = []; + if (sidebar !== null && sidebar !== undefined) { + lis = findAll(sidebar, 'li'); + } + + for (var i = 0, len = lis.length; i < len; i += 1) { + var li = lis[i]; + var a = li.querySelector('a'); + if (!a) { + continue; + } + + var href = a.getAttribute('href'); + + if (href !== '/') { + var ref = router.parse(href); + var id = ref.query.id; + var path$1 = ref.path; + if (id) { + href = getNavKey(path$1, id); + } + } + + if (href) { + nav[decodeURIComponent(href)] = li; + } + } + + if (isMobile) { + return; + } + + var path = removeParams(router.getCurrentPath()); + off('scroll', function () { return highlight(path); }); + on('scroll', function () { return highlight(path); }); + on(sidebar, 'mouseover', function () { + hoverOver = true; + }); + on(sidebar, 'mouseleave', function () { + hoverOver = false; + }); + } + + function scrollIntoView(path, id) { + if (!id) { + return; + } + var topMargin = config().topMargin; + var section = find('#' + id); + section && scrollTo(section, topMargin); + + var li = nav[getNavKey(path, id)]; + var sidebar = getNode('.sidebar'); + var active = find(sidebar, 'li.active'); + active && active.classList.remove('active'); + li && li.classList.add('active'); + } + + var scrollEl = $.scrollingElement || $.documentElement; + + function scroll2Top(offset) { + if ( offset === void 0 ) offset = 0; + + scrollEl.scrollTop = offset === true ? 0 : Number(offset); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var defaults = createCommonjsModule(function (module) { + function getDefaults() { + return { + baseUrl: null, + breaks: false, + gfm: true, + headerIds: true, + headerPrefix: '', + highlight: null, + langPrefix: 'language-', + mangle: true, + pedantic: false, + renderer: null, + sanitize: false, + sanitizer: null, + silent: false, + smartLists: false, + smartypants: false, + tokenizer: null, + walkTokens: null, + xhtml: false + }; + } + + function changeDefaults(newDefaults) { + module.exports.defaults = newDefaults; + } + + module.exports = { + defaults: getDefaults(), + getDefaults: getDefaults, + changeDefaults: changeDefaults + }; + }); + var defaults_1 = defaults.defaults; + var defaults_2 = defaults.getDefaults; + var defaults_3 = defaults.changeDefaults; + + /** + * Helpers + */ + var escapeTest = /[&<>"']/; + var escapeReplace = /[&<>"']/g; + var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; + var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; + var escapeReplacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + var getEscapeReplacement = function (ch) { return escapeReplacements[ch]; }; + function escape(html, encode) { + if (encode) { + if (escapeTest.test(html)) { + return html.replace(escapeReplace, getEscapeReplacement); + } + } else { + if (escapeTestNoEncode.test(html)) { + return html.replace(escapeReplaceNoEncode, getEscapeReplacement); + } + } + + return html; + } + + var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig; + + function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(unescapeTest, function (_, n) { + n = n.toLowerCase(); + if (n === 'colon') { return ':'; } + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); + } + + var caret = /(^|[^\[])\^/g; + function edit(regex, opt) { + regex = regex.source || regex; + opt = opt || ''; + var obj = { + replace: function (name, val) { + val = val.source || val; + val = val.replace(caret, '$1'); + regex = regex.replace(name, val); + return obj; + }, + getRegex: function () { + return new RegExp(regex, opt); + } + }; + return obj; + } + + var nonWordAndColonTest = /[^\w:]/g; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + function cleanUrl(sanitize, base, href) { + if (sanitize) { + var prot; + try { + prot = decodeURIComponent(unescape(href)) + .replace(nonWordAndColonTest, '') + .toLowerCase(); + } catch (e) { + return null; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return null; + } + } + if (base && !originIndependentUrl.test(href)) { + href = resolveUrl(base, href); + } + try { + href = encodeURI(href).replace(/%25/g, '%'); + } catch (e) { + return null; + } + return href; + } + + var baseUrls = {}; + var justDomain = /^[^:]+:\/*[^/]*$/; + var protocol = /^([^:]+:)[\s\S]*$/; + var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/; + + function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (justDomain.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = rtrim(base, '/', true); + } + } + base = baseUrls[' ' + base]; + var relativeBase = base.indexOf(':') === -1; + + if (href.substring(0, 2) === '//') { + if (relativeBase) { + return href; + } + return base.replace(protocol, '$1') + href; + } else if (href.charAt(0) === '/') { + if (relativeBase) { + return href; + } + return base.replace(domain, '$1') + href; + } else { + return base + href; + } + } + + var noopTest = { exec: function noopTest() {} }; + + function merge$1(obj) { + var arguments$1 = arguments; + + var i = 1, + target, + key; + + for (; i < arguments.length; i++) { + target = arguments$1[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; + } + + function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + var row = tableRow.replace(/\|/g, function (match, offset, str) { + var escaped = false, + curr = offset; + while (--curr >= 0 && str[curr] === '\\') { escaped = !escaped; } + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } else { + // add space before unescaped | + return ' |'; + } + }), + cells = row.split(/ \|/); + var i = 0; + + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) { cells.push(''); } + } + + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(/\\\|/g, '|'); + } + return cells; + } + + // Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + // /c*$/ is vulnerable to REDOS. + // invert: Remove suffix of non-c chars instead. Default falsey. + function rtrim(str, c, invert) { + var l = str.length; + if (l === 0) { + return ''; + } + + // Length of suffix matching the invert condition. + var suffLen = 0; + + // Step left until we fail to match the invert condition. + while (suffLen < l) { + var currChar = str.charAt(l - suffLen - 1); + if (currChar === c && !invert) { + suffLen++; + } else if (currChar !== c && invert) { + suffLen++; + } else { + break; + } + } + + return str.substr(0, l - suffLen); + } + + function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + var l = str.length; + var level = 0, + i = 0; + for (; i < l; i++) { + if (str[i] === '\\') { + i++; + } else if (str[i] === b[0]) { + level++; + } else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; + } + + function checkSanitizeDeprecation(opt) { + if (opt && opt.sanitize && !opt.silent) { + console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options'); + } + } + + // copied from https://stackoverflow.com/a/5450113/806777 + function repeatString(pattern, count) { + if (count < 1) { + return ''; + } + var result = ''; + while (count > 1) { + if (count & 1) { + result += pattern; + } + count >>= 1; + pattern += pattern; + } + return result + pattern; + } + + var helpers = { + escape: escape, + unescape: unescape, + edit: edit, + cleanUrl: cleanUrl, + resolveUrl: resolveUrl, + noopTest: noopTest, + merge: merge$1, + splitCells: splitCells, + rtrim: rtrim, + findClosingBracket: findClosingBracket, + checkSanitizeDeprecation: checkSanitizeDeprecation, + repeatString: repeatString + }; + + var defaults$1 = defaults.defaults; + + var rtrim$1 = helpers.rtrim; + var splitCells$1 = helpers.splitCells; + var escape$1 = helpers.escape; + var findClosingBracket$1 = helpers.findClosingBracket; + + function outputLink(cap, link, raw) { + var href = link.href; + var title = link.title ? escape$1(link.title) : null; + var text = cap[1].replace(/\\([\[\]])/g, '$1'); + + if (cap[0].charAt(0) !== '!') { + return { + type: 'link', + raw: raw, + href: href, + title: title, + text: text + }; + } else { + return { + type: 'image', + raw: raw, + href: href, + title: title, + text: escape$1(text) + }; + } + } + + function indentCodeCompensation(raw, text) { + var matchIndentToCode = raw.match(/^(\s+)(?:```)/); + + if (matchIndentToCode === null) { + return text; + } + + var indentToCode = matchIndentToCode[1]; + + return text + .split('\n') + .map(function (node) { + var matchIndentInNode = node.match(/^\s+/); + if (matchIndentInNode === null) { + return node; + } + + var indentInNode = matchIndentInNode[0]; + + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + + return node; + }) + .join('\n'); + } + + /** + * Tokenizer + */ + var Tokenizer = /*@__PURE__*/(function () { + function Tokenizer(options) { + this.options = options || defaults$1; + } + + Tokenizer.prototype.space = function space (src) { + var cap = this.rules.block.newline.exec(src); + if (cap) { + if (cap[0].length > 1) { + return { + type: 'space', + raw: cap[0] + }; + } + return { raw: '\n' }; + } + }; + + Tokenizer.prototype.code = function code (src, tokens) { + var cap = this.rules.block.code.exec(src); + if (cap) { + var lastToken = tokens[tokens.length - 1]; + // An indented code block cannot interrupt a paragraph. + if (lastToken && lastToken.type === 'paragraph') { + return { + raw: cap[0], + text: cap[0].trimRight() + }; + } + + var text = cap[0].replace(/^ {1,4}/gm, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic + ? rtrim$1(text, '\n') + : text + }; + } + }; + + Tokenizer.prototype.fences = function fences (src) { + var cap = this.rules.block.fences.exec(src); + if (cap) { + var raw = cap[0]; + var text = indentCodeCompensation(raw, cap[3] || ''); + + return { + type: 'code', + raw: raw, + lang: cap[2] ? cap[2].trim() : cap[2], + text: text + }; + } + }; + + Tokenizer.prototype.heading = function heading (src) { + var cap = this.rules.block.heading.exec(src); + if (cap) { + var text = cap[2].trim(); + + // remove trailing #s + if (/#$/.test(text)) { + var trimmed = rtrim$1(text, '#'); + if (this.options.pedantic) { + text = trimmed.trim(); + } else if (!trimmed || / $/.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + + return { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text: text + }; + } + }; + + Tokenizer.prototype.nptable = function nptable (src) { + var cap = this.rules.block.nptable.exec(src); + if (cap) { + var item = { + type: 'table', + header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [], + raw: cap[0] + }; + + if (item.header.length === item.align.length) { + var l = item.align.length; + var i; + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + l = item.cells.length; + for (i = 0; i < l; i++) { + item.cells[i] = splitCells$1(item.cells[i], item.header.length); + } + + return item; + } + } + }; + + Tokenizer.prototype.hr = function hr (src) { + var cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: 'hr', + raw: cap[0] + }; + } + }; + + Tokenizer.prototype.blockquote = function blockquote (src) { + var cap = this.rules.block.blockquote.exec(src); + if (cap) { + var text = cap[0].replace(/^ *> ?/gm, ''); + + return { + type: 'blockquote', + raw: cap[0], + text: text + }; + } + }; + + Tokenizer.prototype.list = function list (src) { + var cap = this.rules.block.list.exec(src); + if (cap) { + var raw = cap[0]; + var bull = cap[2]; + var isordered = bull.length > 1; + + var list = { + type: 'list', + raw: raw, + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [] + }; + + // Get each top-level item. + var itemMatch = cap[0].match(this.rules.block.item); + + var next = false, + item, + space, + bcurr, + bnext, + addBack, + loose, + istask, + ischecked; + + var l = itemMatch.length; + bcurr = this.rules.block.listItemStart.exec(itemMatch[0]); + for (var i = 0; i < l; i++) { + item = itemMatch[i]; + raw = item; + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (i !== l - 1) { + bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]); + if ( + !this.options.pedantic + ? bnext[1].length > bcurr[0].length || bnext[1].length > 3 + : bnext[1].length > bcurr[1].length + ) { + // nested list + itemMatch.splice(i, 2, itemMatch[i] + '\n' + itemMatch[i + 1]); + i--; + l--; + continue; + } else { + if ( + // different bullet style + !this.options.pedantic || this.options.smartLists + ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1] + : isordered === (bnext[2].length === 1) + ) { + addBack = itemMatch.slice(i + 1).join('\n'); + list.raw = list.raw.substring(0, list.raw.length - addBack.length); + i = l - 1; + } + } + bcurr = bnext; + } + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+[.)]) ?/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) { loose = next; } + } + + if (loose) { + list.loose = true; + } + + // Check for task list items + if (this.options.gfm) { + istask = /^\[[ xX]\] /.test(item); + ischecked = undefined; + if (istask) { + ischecked = item[1] !== ' '; + item = item.replace(/^\[[ xX]\] +/, ''); + } + } + + list.items.push({ + type: 'list_item', + raw: raw, + task: istask, + checked: ischecked, + loose: loose, + text: item + }); + } + + return list; + } + }; + + Tokenizer.prototype.html = function html (src) { + var cap = this.rules.block.html.exec(src); + if (cap) { + return { + type: this.options.sanitize + ? 'paragraph' + : 'html', + raw: cap[0], + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0] + }; + } + }; + + Tokenizer.prototype.def = function def (src) { + var cap = this.rules.block.def.exec(src); + if (cap) { + if (cap[3]) { cap[3] = cap[3].substring(1, cap[3].length - 1); } + var tag = cap[1].toLowerCase().replace(/\s+/g, ' '); + return { + tag: tag, + raw: cap[0], + href: cap[2], + title: cap[3] + }; + } + }; + + Tokenizer.prototype.table = function table (src) { + var cap = this.rules.block.table.exec(src); + if (cap) { + var item = { + type: 'table', + header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + item.raw = cap[0]; + + var l = item.align.length; + var i; + for (i = 0; i < l; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + l = item.cells.length; + for (i = 0; i < l; i++) { + item.cells[i] = splitCells$1( + item.cells[i].replace(/^ *\| *| *\| *$/g, ''), + item.header.length); + } + + return item; + } + } + }; + + Tokenizer.prototype.lheading = function lheading (src) { + var cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1] + }; + } + }; + + Tokenizer.prototype.paragraph = function paragraph (src) { + var cap = this.rules.block.paragraph.exec(src); + if (cap) { + return { + type: 'paragraph', + raw: cap[0], + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }; + } + }; + + Tokenizer.prototype.text = function text (src, tokens) { + var cap = this.rules.block.text.exec(src); + if (cap) { + var lastToken = tokens[tokens.length - 1]; + if (lastToken && lastToken.type === 'text') { + return { + raw: cap[0], + text: cap[0] + }; + } + + return { + type: 'text', + raw: cap[0], + text: cap[0] + }; + } + }; + + Tokenizer.prototype.escape = function escape$1$1 (src) { + var cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: escape$1(cap[1]) + }; + } + }; + + Tokenizer.prototype.tag = function tag (src, inLink, inRawBlock) { + var cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!inLink && /^/i.test(cap[0])) { + inLink = false; + } + if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + inRawBlock = true; + } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + inRawBlock = false; + } + + return { + type: this.options.sanitize + ? 'text' + : 'html', + raw: cap[0], + inLink: inLink, + inRawBlock: inRawBlock, + text: this.options.sanitize + ? (this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape$1(cap[0])) + : cap[0] + }; + } + }; + + Tokenizer.prototype.link = function link (src) { + var cap = this.rules.inline.link.exec(src); + if (cap) { + var trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && /^$/.test(trimmedUrl))) { + return; + } + + // ending angle bracket cannot be escaped + var rtrimSlash = rtrim$1(trimmedUrl.slice(0, -1), '\\'); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } else { + // find closing parenthesis + var lastParenIndex = findClosingBracket$1(cap[2], '()'); + if (lastParenIndex > -1) { + var start = cap[0].indexOf('!') === 0 ? 5 : 4; + var linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + var href = cap[2]; + var title = ''; + if (this.options.pedantic) { + // split pedantic href and title + var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + + if (link) { + href = link[1]; + title = link[3]; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + + href = href.trim(); + if (/^$/.test(trimmedUrl))) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline._escapes, '$1') : href, + title: title ? title.replace(this.rules.inline._escapes, '$1') : title + }, cap[0]); + } + }; + + Tokenizer.prototype.reflink = function reflink (src, links) { + var cap; + if ((cap = this.rules.inline.reflink.exec(src)) + || (cap = this.rules.inline.nolink.exec(src))) { + var link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = links[link.toLowerCase()]; + if (!link || !link.href) { + var text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text: text + }; + } + return outputLink(cap, link, cap[0]); + } + }; + + Tokenizer.prototype.strong = function strong (src, maskedSrc, prevChar) { + if ( prevChar === void 0 ) prevChar = ''; + + var match = this.rules.inline.strong.start.exec(src); + + if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) { + maskedSrc = maskedSrc.slice(-1 * src.length); + var endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd; + + endReg.lastIndex = 0; + + var cap; + while ((match = endReg.exec(maskedSrc)) != null) { + cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3)); + if (cap) { + return { + type: 'strong', + raw: src.slice(0, cap[0].length), + text: src.slice(2, cap[0].length - 2) + }; + } + } + } + }; + + Tokenizer.prototype.em = function em (src, maskedSrc, prevChar) { + if ( prevChar === void 0 ) prevChar = ''; + + var match = this.rules.inline.em.start.exec(src); + + if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) { + maskedSrc = maskedSrc.slice(-1 * src.length); + var endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd; + + endReg.lastIndex = 0; + + var cap; + while ((match = endReg.exec(maskedSrc)) != null) { + cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2)); + if (cap) { + return { + type: 'em', + raw: src.slice(0, cap[0].length), + text: src.slice(1, cap[0].length - 1) + }; + } + } + } + }; + + Tokenizer.prototype.codespan = function codespan (src) { + var cap = this.rules.inline.code.exec(src); + if (cap) { + var text = cap[2].replace(/\n/g, ' '); + var hasNonSpaceChars = /[^ ]/.test(text); + var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + text = escape$1(text, true); + return { + type: 'codespan', + raw: cap[0], + text: text + }; + } + }; + + Tokenizer.prototype.br = function br (src) { + var cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: 'br', + raw: cap[0] + }; + } + }; + + Tokenizer.prototype.del = function del (src) { + var cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2] + }; + } + }; + + Tokenizer.prototype.autolink = function autolink (src, mangle) { + var cap = this.rules.inline.autolink.exec(src); + if (cap) { + var text, href; + if (cap[2] === '@') { + text = escape$1(this.options.mangle ? mangle(cap[1]) : cap[1]); + href = 'mailto:' + text; + } else { + text = escape$1(cap[1]); + href = text; + } + + return { + type: 'link', + raw: cap[0], + text: text, + href: href, + tokens: [ + { + type: 'text', + raw: text, + text: text + } + ] + }; + } + }; + + Tokenizer.prototype.url = function url (src, mangle) { + var cap; + if (cap = this.rules.inline.url.exec(src)) { + var text, href; + if (cap[2] === '@') { + text = escape$1(this.options.mangle ? mangle(cap[0]) : cap[0]); + href = 'mailto:' + text; + } else { + // do extended autolink path validation + var prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])[0]; + } while (prevCapZero !== cap[0]); + text = escape$1(cap[0]); + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + return { + type: 'link', + raw: cap[0], + text: text, + href: href, + tokens: [ + { + type: 'text', + raw: text, + text: text + } + ] + }; + } + }; + + Tokenizer.prototype.inlineText = function inlineText (src, inRawBlock, smartypants) { + var cap = this.rules.inline.text.exec(src); + if (cap) { + var text; + if (inRawBlock) { + text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0]; + } else { + text = escape$1(this.options.smartypants ? smartypants(cap[0]) : cap[0]); + } + return { + type: 'text', + raw: cap[0], + text: text + }; + } + }; + + return Tokenizer; + }()); + + var noopTest$1 = helpers.noopTest; + var edit$1 = helpers.edit; + var merge$2 = helpers.merge; + + /** + * Block-Level Grammar + */ + var block = { + newline: /^(?: *(?:\n|$))+/, + code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, + fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/, + html: '^ {0,3}(?:' // optional indentation + + '<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:\\n{2,}|$)' // (6) + + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag + + ')', + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + nptable: noopTest$1, + table: noopTest$1, + lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/, + // regex template, placeholders will be replaced according to different paragraph + // interruption rules of commonmark and the original markdown spec: + _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/, + text: /^[^\n]+/ + }; + + block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; + block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; + block.def = edit$1(block.def) + .replace('label', block._label) + .replace('title', block._title) + .getRegex(); + + block.bullet = /(?:[*+-]|\d{1,9}[.)])/; + block.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/; + block.item = edit$1(block.item, 'gm') + .replace(/bull/g, block.bullet) + .getRegex(); + + block.listItemStart = edit$1(/^( *)(bull)/) + .replace('bull', block.bullet) + .getRegex(); + + block.list = edit$1(block.list) + .replace(/bull/g, block.bullet) + .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))') + .replace('def', '\\n+(?=' + block.def.source + ')') + .getRegex(); + + block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + + '|track|ul'; + block._comment = /|$)/; + block.html = edit$1(block.html, 'i') + .replace('comment', block._comment) + .replace('tag', block._tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); + + block.paragraph = edit$1(block._paragraph) + .replace('hr', block.hr) + .replace('heading', ' {0,3}#{1,6} ') + .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|!--)') + .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks + .getRegex(); + + block.blockquote = edit$1(block.blockquote) + .replace('paragraph', block.paragraph) + .getRegex(); + + /** + * Normal Block Grammar + */ + + block.normal = merge$2({}, block); + + /** + * GFM Block Grammar + */ + + block.gfm = merge$2({}, block.normal, { + nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header + + ' {0,3}([-:]+ *\\|[-| :]*)' // Align + + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells + table: '^ *\\|(.+)\\n' // Header + + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align + + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells + }); + + block.gfm.nptable = edit$1(block.gfm.nptable) + .replace('hr', block.hr) + .replace('heading', ' {0,3}#{1,6} ') + .replace('blockquote', ' {0,3}>') + .replace('code', ' {4}[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|!--)') + .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks + .getRegex(); + + block.gfm.table = edit$1(block.gfm.table) + .replace('hr', block.hr) + .replace('heading', ' {0,3}#{1,6} ') + .replace('blockquote', ' {0,3}>') + .replace('code', ' {4}[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|!--)') + .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks + .getRegex(); + + /** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ + + block.pedantic = merge$2({}, block.normal, { + html: edit$1( + '^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', block._comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest$1, // fences not supported + paragraph: edit$1(block.normal._paragraph) + .replace('hr', block.hr) + .replace('heading', ' *#{1,6} *[^\n]') + .replace('lheading', block.lheading) + .replace('blockquote', ' {0,3}>') + .replace('|fences', '') + .replace('|list', '') + .replace('|html', '') + .getRegex() + }); + + /** + * Inline-Level Grammar + */ + var inline = { + escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noopTest$1, + tag: '^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^', // CDATA section + link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/, + reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, + nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, + reflinkSearch: 'reflink|nolink(?!\\()', + strong: { + start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation + middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/, + endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline) + endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline) + }, + em: { + start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation + middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/, + endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline) + endUnd: /[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline) + }, + code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, + br: /^( {2,}|\\)\n(?!\s*$)/, + del: noopTest$1, + text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~'; + inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex(); + + // sequences em should skip over [title](link), `code`, + inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>'; + inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*'; + + inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex(); + + inline.em.start = edit$1(inline.em.start) + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.em.middle = edit$1(inline.em.middle) + .replace(/punctuation/g, inline._punctuation) + .replace(/overlapSkip/g, inline._overlapSkip) + .getRegex(); + + inline.em.endAst = edit$1(inline.em.endAst, 'g') + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.em.endUnd = edit$1(inline.em.endUnd, 'g') + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.strong.start = edit$1(inline.strong.start) + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.strong.middle = edit$1(inline.strong.middle) + .replace(/punctuation/g, inline._punctuation) + .replace(/overlapSkip/g, inline._overlapSkip) + .getRegex(); + + inline.strong.endAst = edit$1(inline.strong.endAst, 'g') + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g') + .replace(/punctuation/g, inline._punctuation) + .getRegex(); + + inline.blockSkip = edit$1(inline._blockSkip, 'g') + .getRegex(); + + inline.overlapSkip = edit$1(inline._overlapSkip, 'g') + .getRegex(); + + inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; + + inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; + inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; + inline.autolink = edit$1(inline.autolink) + .replace('scheme', inline._scheme) + .replace('email', inline._email) + .getRegex(); + + inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; + + inline.tag = edit$1(inline.tag) + .replace('comment', inline._comment) + .replace('attribute', inline._attribute) + .getRegex(); + + inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; + inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/; + inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; + + inline.link = edit$1(inline.link) + .replace('label', inline._label) + .replace('href', inline._href) + .replace('title', inline._title) + .getRegex(); + + inline.reflink = edit$1(inline.reflink) + .replace('label', inline._label) + .getRegex(); + + inline.reflinkSearch = edit$1(inline.reflinkSearch, 'g') + .replace('reflink', inline.reflink) + .replace('nolink', inline.nolink) + .getRegex(); + + /** + * Normal Inline Grammar + */ + + inline.normal = merge$2({}, inline); + + /** + * Pedantic Inline Grammar + */ + + inline.pedantic = merge$2({}, inline.normal, { + strong: { + start: /^__|\*\*/, + middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + endAst: /\*\*(?!\*)/g, + endUnd: /__(?!_)/g + }, + em: { + start: /^_|\*/, + middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/, + endAst: /\*(?!\*)/g, + endUnd: /_(?!_)/g + }, + link: edit$1(/^!?\[(label)\]\((.*?)\)/) + .replace('label', inline._label) + .getRegex(), + reflink: edit$1(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', inline._label) + .getRegex() + }); + + /** + * GFM Inline Grammar + */ + + inline.gfm = merge$2({}, inline.normal, { + escape: edit$1(inline.escape).replace('])', '~|])').getRegex(), + _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, + url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\ 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; + } + + /** + * Block Lexer + */ + var Lexer = /*@__PURE__*/(function () { + function Lexer(options) { + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || defaults$2; + this.options.tokenizer = this.options.tokenizer || new Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + + var rules = { + block: block$1.normal, + inline: inline$1.normal + }; + + if (this.options.pedantic) { + rules.block = block$1.pedantic; + rules.inline = inline$1.pedantic; + } else if (this.options.gfm) { + rules.block = block$1.gfm; + if (this.options.breaks) { + rules.inline = inline$1.breaks; + } else { + rules.inline = inline$1.gfm; + } + } + this.tokenizer.rules = rules; + } + + var staticAccessors = { rules: { configurable: true } }; + + /** + * Expose Rules + */ + staticAccessors.rules.get = function () { + return { + block: block$1, + inline: inline$1 + }; + }; + + /** + * Static Lex Method + */ + Lexer.lex = function lex (src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); + }; + + /** + * Static Lex Inline Method + */ + Lexer.lexInline = function lexInline (src, options) { + var lexer = new Lexer(options); + return lexer.inlineTokens(src); + }; + + /** + * Preprocessing + */ + Lexer.prototype.lex = function lex (src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' '); + + this.blockTokens(src, this.tokens, true); + + this.inline(this.tokens); + + return this.tokens; + }; + + /** + * Lexing + */ + Lexer.prototype.blockTokens = function blockTokens (src, tokens, top) { + if ( tokens === void 0 ) tokens = []; + if ( top === void 0 ) top = true; + + if (this.options.pedantic) { + src = src.replace(/^ +$/gm, ''); + } + var token, i, l, lastToken; + + while (src) { + // newline + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + if (token.type) { + tokens.push(token); + } + continue; + } + + // code + if (token = this.tokenizer.code(src, tokens)) { + src = src.substring(token.raw.length); + if (token.type) { + tokens.push(token); + } else { + lastToken = tokens[tokens.length - 1]; + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + } + continue; + } + + // fences + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // heading + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // table no leading pipe (gfm) + if (token = this.tokenizer.nptable(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // hr + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // blockquote + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + token.tokens = this.blockTokens(token.text, [], top); + tokens.push(token); + continue; + } + + // list + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + l = token.items.length; + for (i = 0; i < l; i++) { + token.items[i].tokens = this.blockTokens(token.items[i].text, [], false); + } + tokens.push(token); + continue; + } + + // html + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // def + if (top && (token = this.tokenizer.def(src))) { + src = src.substring(token.raw.length); + if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title + }; + } + continue; + } + + // table (gfm) + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // lheading + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // top-level paragraph + if (top && (token = this.tokenizer.paragraph(src))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // text + if (token = this.tokenizer.text(src, tokens)) { + src = src.substring(token.raw.length); + if (token.type) { + tokens.push(token); + } else { + lastToken = tokens[tokens.length - 1]; + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + } + continue; + } + + if (src) { + var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + + return tokens; + }; + + Lexer.prototype.inline = function inline (tokens) { + var i, + j, + k, + l2, + row, + token; + + var l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + switch (token.type) { + case 'paragraph': + case 'text': + case 'heading': { + token.tokens = []; + this.inlineTokens(token.text, token.tokens); + break; + } + case 'table': { + token.tokens = { + header: [], + cells: [] + }; + + // header + l2 = token.header.length; + for (j = 0; j < l2; j++) { + token.tokens.header[j] = []; + this.inlineTokens(token.header[j], token.tokens.header[j]); + } + + // cells + l2 = token.cells.length; + for (j = 0; j < l2; j++) { + row = token.cells[j]; + token.tokens.cells[j] = []; + for (k = 0; k < row.length; k++) { + token.tokens.cells[j][k] = []; + this.inlineTokens(row[k], token.tokens.cells[j][k]); + } + } + + break; + } + case 'blockquote': { + this.inline(token.tokens); + break; + } + case 'list': { + l2 = token.items.length; + for (j = 0; j < l2; j++) { + this.inline(token.items[j].tokens); + } + break; + } + } + } + + return tokens; + }; + + /** + * Lexing/Compiling + */ + Lexer.prototype.inlineTokens = function inlineTokens (src, tokens, inLink, inRawBlock) { + if ( tokens === void 0 ) tokens = []; + if ( inLink === void 0 ) inLink = false; + if ( inRawBlock === void 0 ) inRawBlock = false; + + var token; + + // String with links masked to avoid interference with em and strong + var maskedSrc = src; + var match; + var keepPrevChar, prevChar; + + // Mask out reflinks + if (this.tokens.links) { + var links = Object.keys(this.tokens.links); + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + // Mask out other blocks + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + keepPrevChar = false; + // escape + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // tag + if (token = this.tokenizer.tag(src, inLink, inRawBlock)) { + src = src.substring(token.raw.length); + inLink = token.inLink; + inRawBlock = token.inRawBlock; + tokens.push(token); + continue; + } + + // link + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + if (token.type === 'link') { + token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); + } + tokens.push(token); + continue; + } + + // reflink, nolink + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + if (token.type === 'link') { + token.tokens = this.inlineTokens(token.text, [], true, inRawBlock); + } + tokens.push(token); + continue; + } + + // strong + if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); + tokens.push(token); + continue; + } + + // em + if (token = this.tokenizer.em(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); + tokens.push(token); + continue; + } + + // code + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // br + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // del (gfm) + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock); + tokens.push(token); + continue; + } + + // autolink + if (token = this.tokenizer.autolink(src, mangle)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // url (gfm) + if (!inLink && (token = this.tokenizer.url(src, mangle))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + + // text + if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) { + src = src.substring(token.raw.length); + prevChar = token.raw.slice(-1); + keepPrevChar = true; + tokens.push(token); + continue; + } + + if (src) { + var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } else { + throw new Error(errMsg); + } + } + } + + return tokens; + }; + + Object.defineProperties( Lexer, staticAccessors ); + + return Lexer; + }()); + + var defaults$3 = defaults.defaults; + + var cleanUrl$1 = helpers.cleanUrl; + var escape$2 = helpers.escape; + + /** + * Renderer + */ + var Renderer = /*@__PURE__*/(function () { + function Renderer(options) { + this.options = options || defaults$3; + } + + Renderer.prototype.code = function code (code$1, infostring, escaped) { + var lang = (infostring || '').match(/\S*/)[0]; + if (this.options.highlight) { + var out = this.options.highlight(code$1, lang); + if (out != null && out !== code$1) { + escaped = true; + code$1 = out; + } + } + + code$1 = code$1.replace(/\n$/, '') + '\n'; + + if (!lang) { + return '

'
+          + (escaped ? code$1 : escape$2(code$1, true))
+          + '
\n'; + } + + return '
'
+        + (escaped ? code$1 : escape$2(code$1, true))
+        + '
\n'; + }; + + Renderer.prototype.blockquote = function blockquote (quote) { + return '
\n' + quote + '
\n'; + }; + + Renderer.prototype.html = function html (html$1) { + return html$1; + }; + + Renderer.prototype.heading = function heading (text, level, raw, slugger) { + if (this.options.headerIds) { + return '' + + text + + '\n'; + } + // ignore IDs + return '' + text + '\n'; + }; + + Renderer.prototype.hr = function hr () { + return this.options.xhtml ? '
\n' : '
\n'; + }; + + Renderer.prototype.list = function list (body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startatt + '>\n' + body + '\n'; + }; + + Renderer.prototype.listitem = function listitem (text) { + return '
  • ' + text + '
  • \n'; + }; + + Renderer.prototype.checkbox = function checkbox (checked) { + return ' '; + }; + + Renderer.prototype.paragraph = function paragraph (text) { + return '

    ' + text + '

    \n'; + }; + + Renderer.prototype.table = function table (header, body) { + if (body) { body = '' + body + ''; } + + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; + }; + + Renderer.prototype.tablerow = function tablerow (content) { + return '\n' + content + '\n'; + }; + + Renderer.prototype.tablecell = function tablecell (content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' align="' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; + }; + + // span level renderer + Renderer.prototype.strong = function strong (text) { + return '' + text + ''; + }; + + Renderer.prototype.em = function em (text) { + return '' + text + ''; + }; + + Renderer.prototype.codespan = function codespan (text) { + return '' + text + ''; + }; + + Renderer.prototype.br = function br () { + return this.options.xhtml ? '
    ' : '
    '; + }; + + Renderer.prototype.del = function del (text) { + return '' + text + ''; + }; + + Renderer.prototype.link = function link (href, title, text) { + href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href); + if (href === null) { + return text; + } + var out = '
    '; + return out; + }; + + Renderer.prototype.image = function image (href, title, text) { + href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href); + if (href === null) { + return text; + } + + var out = '' + text + '' : '>'; + return out; + }; + + Renderer.prototype.text = function text (text$1) { + return text$1; + }; + + return Renderer; + }()); + + /** + * TextRenderer + * returns only the textual part of the token + */ + var TextRenderer = /*@__PURE__*/(function () { + function TextRenderer () {} + + TextRenderer.prototype.strong = function strong (text) { + return text; + }; + + TextRenderer.prototype.em = function em (text) { + return text; + }; + + TextRenderer.prototype.codespan = function codespan (text) { + return text; + }; + + TextRenderer.prototype.del = function del (text) { + return text; + }; + + TextRenderer.prototype.html = function html (text) { + return text; + }; + + TextRenderer.prototype.text = function text (text$1) { + return text$1; + }; + + TextRenderer.prototype.link = function link (href, title, text) { + return '' + text; + }; + + TextRenderer.prototype.image = function image (href, title, text) { + return '' + text; + }; + + TextRenderer.prototype.br = function br () { + return ''; + }; + + return TextRenderer; + }()); + + /** + * Slugger generates header id + */ + var Slugger = /*@__PURE__*/(function () { + function Slugger() { + this.seen = {}; + } + + Slugger.prototype.serialize = function serialize (value) { + return value + .toLowerCase() + .trim() + // remove html tags + .replace(/<[!\/a-z].*?>/ig, '') + // remove unwanted chars + .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '') + .replace(/\s/g, '-'); + }; + + /** + * Finds the next safe (unique) slug to use + */ + Slugger.prototype.getNextSafeSlug = function getNextSafeSlug (originalSlug, isDryRun) { + var slug = originalSlug; + var occurenceAccumulator = 0; + if (this.seen.hasOwnProperty(slug)) { + occurenceAccumulator = this.seen[originalSlug]; + do { + occurenceAccumulator++; + slug = originalSlug + '-' + occurenceAccumulator; + } while (this.seen.hasOwnProperty(slug)); + } + if (!isDryRun) { + this.seen[originalSlug] = occurenceAccumulator; + this.seen[slug] = 0; + } + return slug; + }; + + /** + * Convert string to unique id + * @param {object} options + * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator. + */ + Slugger.prototype.slug = function slug (value, options) { + if ( options === void 0 ) options = {}; + + var slug = this.serialize(value); + return this.getNextSafeSlug(slug, options.dryrun); + }; + + return Slugger; + }()); + + var defaults$4 = defaults.defaults; + + var unescape$1 = helpers.unescape; + + /** + * Parsing & Compiling + */ + var Parser = /*@__PURE__*/(function () { + function Parser(options) { + this.options = options || defaults$4; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; + this.textRenderer = new TextRenderer(); + this.slugger = new Slugger(); + } + + /** + * Static Parse Method + */ + Parser.parse = function parse (tokens, options) { + var parser = new Parser(options); + return parser.parse(tokens); + }; + + /** + * Static Parse Inline Method + */ + Parser.parseInline = function parseInline (tokens, options) { + var parser = new Parser(options); + return parser.parseInline(tokens); + }; + + /** + * Parse Loop + */ + Parser.prototype.parse = function parse (tokens, top) { + if ( top === void 0 ) top = true; + + var out = '', + i, + j, + k, + l2, + l3, + row, + cell, + header, + body, + token, + ordered, + start, + loose, + itemBody, + item, + checked, + task, + checkbox; + + var l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + switch (token.type) { + case 'space': { + continue; + } + case 'hr': { + out += this.renderer.hr(); + continue; + } + case 'heading': { + out += this.renderer.heading( + this.parseInline(token.tokens), + token.depth, + unescape$1(this.parseInline(token.tokens, this.textRenderer)), + this.slugger); + continue; + } + case 'code': { + out += this.renderer.code(token.text, + token.lang, + token.escaped); + continue; + } + case 'table': { + header = ''; + + // header + cell = ''; + l2 = token.header.length; + for (j = 0; j < l2; j++) { + cell += this.renderer.tablecell( + this.parseInline(token.tokens.header[j]), + { header: true, align: token.align[j] } + ); + } + header += this.renderer.tablerow(cell); + + body = ''; + l2 = token.cells.length; + for (j = 0; j < l2; j++) { + row = token.tokens.cells[j]; + + cell = ''; + l3 = row.length; + for (k = 0; k < l3; k++) { + cell += this.renderer.tablecell( + this.parseInline(row[k]), + { header: false, align: token.align[k] } + ); + } + + body += this.renderer.tablerow(cell); + } + out += this.renderer.table(header, body); + continue; + } + case 'blockquote': { + body = this.parse(token.tokens); + out += this.renderer.blockquote(body); + continue; + } + case 'list': { + ordered = token.ordered; + start = token.start; + loose = token.loose; + l2 = token.items.length; + + body = ''; + for (j = 0; j < l2; j++) { + item = token.items[j]; + checked = item.checked; + task = item.task; + + itemBody = ''; + if (item.task) { + checkbox = this.renderer.checkbox(checked); + if (loose) { + if (item.tokens.length > 0 && item.tokens[0].type === 'text') { + item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text; + } + } else { + item.tokens.unshift({ + type: 'text', + text: checkbox + }); + } + } else { + itemBody += checkbox; + } + } + + itemBody += this.parse(item.tokens, loose); + body += this.renderer.listitem(itemBody, task, checked); + } + + out += this.renderer.list(body, ordered, start); + continue; + } + case 'html': { + // TODO parse inline content if parameter markdown=1 + out += this.renderer.html(token.text); + continue; + } + case 'paragraph': { + out += this.renderer.paragraph(this.parseInline(token.tokens)); + continue; + } + case 'text': { + body = token.tokens ? this.parseInline(token.tokens) : token.text; + while (i + 1 < l && tokens[i + 1].type === 'text') { + token = tokens[++i]; + body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text); + } + out += top ? this.renderer.paragraph(body) : body; + continue; + } + default: { + var errMsg = 'Token with "' + token.type + '" type was not found.'; + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + + return out; + }; + + /** + * Parse Inline Tokens + */ + Parser.prototype.parseInline = function parseInline (tokens, renderer) { + renderer = renderer || this.renderer; + var out = '', + i, + token; + + var l = tokens.length; + for (i = 0; i < l; i++) { + token = tokens[i]; + switch (token.type) { + case 'escape': { + out += renderer.text(token.text); + break; + } + case 'html': { + out += renderer.html(token.text); + break; + } + case 'link': { + out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer)); + break; + } + case 'image': { + out += renderer.image(token.href, token.title, token.text); + break; + } + case 'strong': { + out += renderer.strong(this.parseInline(token.tokens, renderer)); + break; + } + case 'em': { + out += renderer.em(this.parseInline(token.tokens, renderer)); + break; + } + case 'codespan': { + out += renderer.codespan(token.text); + break; + } + case 'br': { + out += renderer.br(); + break; + } + case 'del': { + out += renderer.del(this.parseInline(token.tokens, renderer)); + break; + } + case 'text': { + out += renderer.text(token.text); + break; + } + default: { + var errMsg = 'Token with "' + token.type + '" type was not found.'; + if (this.options.silent) { + console.error(errMsg); + return; + } else { + throw new Error(errMsg); + } + } + } + } + return out; + }; + + return Parser; + }()); + + var merge$3 = helpers.merge; + var checkSanitizeDeprecation$1 = helpers.checkSanitizeDeprecation; + var escape$3 = helpers.escape; + + var getDefaults = defaults.getDefaults; + var changeDefaults = defaults.changeDefaults; + var defaults$5 = defaults.defaults; + + /** + * Marked + */ + function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected'); + } + + if (typeof opt === 'function') { + callback = opt; + opt = null; + } + + opt = merge$3({}, marked.defaults, opt || {}); + checkSanitizeDeprecation$1(opt); + + if (callback) { + var highlight = opt.highlight; + var tokens; + + try { + tokens = Lexer.lex(src, opt); + } catch (e) { + return callback(e); + } + + var done = function(err) { + var out; + + if (!err) { + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!tokens.length) { return done(); } + + var pending = 0; + marked.walkTokens(tokens, function(token) { + if (token.type === 'code') { + pending++; + setTimeout(function () { + highlight(token.text, token.lang, function(err, code) { + if (err) { + return done(err); + } + if (code != null && code !== token.text) { + token.text = code; + token.escaped = true; + } + + pending--; + if (pending === 0) { + done(); + } + }); + }, 0); + } + }); + + if (pending === 0) { + done(); + } + + return; + } + + try { + var tokens$1 = Lexer.lex(src, opt); + if (opt.walkTokens) { + marked.walkTokens(tokens$1, opt.walkTokens); + } + return Parser.parse(tokens$1, opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (opt.silent) { + return '

    An error occurred:

    '
    +          + escape$3(e.message + '', true)
    +          + '
    '; + } + throw e; + } + } + + /** + * Options + */ + + marked.options = + marked.setOptions = function(opt) { + merge$3(marked.defaults, opt); + changeDefaults(marked.defaults); + return marked; + }; + + marked.getDefaults = getDefaults; + + marked.defaults = defaults$5; + + /** + * Use Extension + */ + + marked.use = function(extension) { + var opts = merge$3({}, extension); + if (extension.renderer) { + var renderer = marked.defaults.renderer || new Renderer(); + var loop = function ( prop ) { + var prevRenderer = renderer[prop]; + renderer[prop] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ret = extension.renderer[prop].apply(renderer, args); + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + return ret; + }; + }; + + for (var prop in extension.renderer) loop( prop ); + opts.renderer = renderer; + } + if (extension.tokenizer) { + var tokenizer = marked.defaults.tokenizer || new Tokenizer(); + var loop$1 = function ( prop ) { + var prevTokenizer = tokenizer[prop$1]; + tokenizer[prop$1] = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ret = extension.tokenizer[prop$1].apply(tokenizer, args); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + return ret; + }; + }; + + for (var prop$1 in extension.tokenizer) loop$1( prop ); + opts.tokenizer = tokenizer; + } + if (extension.walkTokens) { + var walkTokens = marked.defaults.walkTokens; + opts.walkTokens = function (token) { + extension.walkTokens(token); + if (walkTokens) { + walkTokens(token); + } + }; + } + marked.setOptions(opts); + }; + + /** + * Run callback for every token + */ + + marked.walkTokens = function(tokens, callback) { + for (var i$3 = 0, list$3 = tokens; i$3 < list$3.length; i$3 += 1) { + var token = list$3[i$3]; + + callback(token); + switch (token.type) { + case 'table': { + for (var i = 0, list = token.tokens.header; i < list.length; i += 1) { + var cell = list[i]; + + marked.walkTokens(cell, callback); + } + for (var i$2 = 0, list$2 = token.tokens.cells; i$2 < list$2.length; i$2 += 1) { + var row = list$2[i$2]; + + for (var i$1 = 0, list$1 = row; i$1 < list$1.length; i$1 += 1) { + var cell$1 = list$1[i$1]; + + marked.walkTokens(cell$1, callback); + } + } + break; + } + case 'list': { + marked.walkTokens(token.items, callback); + break; + } + default: { + if (token.tokens) { + marked.walkTokens(token.tokens, callback); + } + } + } + } + }; + + /** + * Parse Inline + */ + marked.parseInline = function(src, opt) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked.parseInline(): input parameter is undefined or null'); + } + if (typeof src !== 'string') { + throw new Error('marked.parseInline(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected'); + } + + opt = merge$3({}, marked.defaults, opt || {}); + checkSanitizeDeprecation$1(opt); + + try { + var tokens = Lexer.lexInline(src, opt); + if (opt.walkTokens) { + marked.walkTokens(tokens, opt.walkTokens); + } + return Parser.parseInline(tokens, opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (opt.silent) { + return '

    An error occurred:

    '
    +          + escape$3(e.message + '', true)
    +          + '
    '; + } + throw e; + } + }; + + /** + * Expose + */ + + marked.Parser = Parser; + marked.parser = Parser.parse; + + marked.Renderer = Renderer; + marked.TextRenderer = TextRenderer; + + marked.Lexer = Lexer; + marked.lexer = Lexer.lex; + + marked.Tokenizer = Tokenizer; + + marked.Slugger = Slugger; + + marked.parse = marked; + + var marked_1 = marked; + + /** + * Render github corner + * @param {Object} data URL for the View Source on Github link + * @param {String} cornerExternalLinkTarget value of the target attribute of the link + * @return {String} SVG element as string + */ + function corner(data, cornerExternalLinkTarget) { + if (!data) { + return ''; + } + + if (!/\/\//.test(data)) { + data = 'https://github.com/' + data; + } + + data = data.replace(/^git\+/, ''); + // Double check + cornerExternalLinkTarget = cornerExternalLinkTarget || '_blank'; + + return ( + "
    " + + '' + + '' + ); + } + + /** + * Renders main content + * @param {Object} config Configuration object + * @returns {String} HTML of the main content + */ + function main(config) { + var name = config.name ? config.name : ''; + + var aside = + '' + + ''; + return ( + "
    " + aside + + '
    ' + + '
    ' + + '
    ' + + '
    ' + ); + } + + /** + * Cover Page + * @returns {String} Cover page + */ + function cover() { + var SL = ', 100%, 85%'; + var bgc = + 'linear-gradient(to left bottom, ' + + "hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 0%," + + "hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 100%)"; + + return ( + "
    " + + '
    ' + + '
    ' + + '
    ' + ); + } + + /** + * Render tree + * @param {Array} toc Array of TOC section links + * @param {String} tpl TPL list + * @return {String} Rendered tree + */ + function tree(toc, tpl) { + if ( tpl === void 0 ) tpl = '
      {inner}
    '; + + if (!toc || !toc.length) { + return ''; + } + + var innerHTML = ''; + toc.forEach(function (node) { + var title = node.title.replace(/(<([^>]+)>)/g, ''); + innerHTML += "
  • " + (node.title) + "
  • "; + if (node.children) { + innerHTML += tree(node.children, tpl); + } + }); + return tpl.replace('{inner}', innerHTML); + } + + function helper(className, content) { + return ("

    " + (content.slice(5).trim()) + "

    "); + } + + function theme(color) { + return (""); + } + + /** + * Gen toc tree + * @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81 + * @param {Array} toc List of TOC elements + * @param {Number} maxLevel Deep level + * @return {Array} Headlines + */ + function genTree(toc, maxLevel) { + var headlines = []; + var last = {}; + + toc.forEach(function (headline) { + var level = headline.level || 1; + var len = level - 1; + + if (level > maxLevel) { + return; + } + + if (last[len]) { + last[len].children = (last[len].children || []).concat(headline); + } else { + headlines.push(headline); + } + + last[level] = headline; + }); + + return headlines; + } + + var cache$1 = {}; + var re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g; + + function lower(string) { + return string.toLowerCase(); + } + + function slugify(str) { + if (typeof str !== 'string') { + return ''; + } + + var slug = str + .trim() + .replace(/[A-Z]+/g, lower) + .replace(/<[^>]+>/g, '') + .replace(re, '') + .replace(/\s/g, '-') + .replace(/-+/g, '-') + .replace(/^(\d)/, '_$1'); + var count = cache$1[slug]; + + count = hasOwn.call(cache$1, slug) ? count + 1 : 0; + cache$1[slug] = count; + + if (count) { + slug = slug + '-' + count; + } + + return slug; + } + + slugify.clear = function () { + cache$1 = {}; + }; + + /* eslint-disable */ + + // ============================================================================= + // DO NOT EDIT: This file is auto-generated by an /build/emoji.js + // ============================================================================= + + var emojiData = { + "baseURL": "https://github.githubassets.com/images/icons/emoji/", + "data": { + "100": "unicode/1f4af.png?v8", + "1234": "unicode/1f522.png?v8", + "+1": "unicode/1f44d.png?v8", + "-1": "unicode/1f44e.png?v8", + "1st_place_medal": "unicode/1f947.png?v8", + "2nd_place_medal": "unicode/1f948.png?v8", + "3rd_place_medal": "unicode/1f949.png?v8", + "8ball": "unicode/1f3b1.png?v8", + "a": "unicode/1f170.png?v8", + "ab": "unicode/1f18e.png?v8", + "abacus": "unicode/1f9ee.png?v8", + "abc": "unicode/1f524.png?v8", + "abcd": "unicode/1f521.png?v8", + "accept": "unicode/1f251.png?v8", + "accessibility": "accessibility.png?v8", + "accordion": "unicode/1fa97.png?v8", + "adhesive_bandage": "unicode/1fa79.png?v8", + "adult": "unicode/1f9d1.png?v8", + "aerial_tramway": "unicode/1f6a1.png?v8", + "afghanistan": "unicode/1f1e6-1f1eb.png?v8", + "airplane": "unicode/2708.png?v8", + "aland_islands": "unicode/1f1e6-1f1fd.png?v8", + "alarm_clock": "unicode/23f0.png?v8", + "albania": "unicode/1f1e6-1f1f1.png?v8", + "alembic": "unicode/2697.png?v8", + "algeria": "unicode/1f1e9-1f1ff.png?v8", + "alien": "unicode/1f47d.png?v8", + "ambulance": "unicode/1f691.png?v8", + "american_samoa": "unicode/1f1e6-1f1f8.png?v8", + "amphora": "unicode/1f3fa.png?v8", + "anatomical_heart": "unicode/1fac0.png?v8", + "anchor": "unicode/2693.png?v8", + "andorra": "unicode/1f1e6-1f1e9.png?v8", + "angel": "unicode/1f47c.png?v8", + "anger": "unicode/1f4a2.png?v8", + "angola": "unicode/1f1e6-1f1f4.png?v8", + "angry": "unicode/1f620.png?v8", + "anguilla": "unicode/1f1e6-1f1ee.png?v8", + "anguished": "unicode/1f627.png?v8", + "ant": "unicode/1f41c.png?v8", + "antarctica": "unicode/1f1e6-1f1f6.png?v8", + "antigua_barbuda": "unicode/1f1e6-1f1ec.png?v8", + "apple": "unicode/1f34e.png?v8", + "aquarius": "unicode/2652.png?v8", + "argentina": "unicode/1f1e6-1f1f7.png?v8", + "aries": "unicode/2648.png?v8", + "armenia": "unicode/1f1e6-1f1f2.png?v8", + "arrow_backward": "unicode/25c0.png?v8", + "arrow_double_down": "unicode/23ec.png?v8", + "arrow_double_up": "unicode/23eb.png?v8", + "arrow_down": "unicode/2b07.png?v8", + "arrow_down_small": "unicode/1f53d.png?v8", + "arrow_forward": "unicode/25b6.png?v8", + "arrow_heading_down": "unicode/2935.png?v8", + "arrow_heading_up": "unicode/2934.png?v8", + "arrow_left": "unicode/2b05.png?v8", + "arrow_lower_left": "unicode/2199.png?v8", + "arrow_lower_right": "unicode/2198.png?v8", + "arrow_right": "unicode/27a1.png?v8", + "arrow_right_hook": "unicode/21aa.png?v8", + "arrow_up": "unicode/2b06.png?v8", + "arrow_up_down": "unicode/2195.png?v8", + "arrow_up_small": "unicode/1f53c.png?v8", + "arrow_upper_left": "unicode/2196.png?v8", + "arrow_upper_right": "unicode/2197.png?v8", + "arrows_clockwise": "unicode/1f503.png?v8", + "arrows_counterclockwise": "unicode/1f504.png?v8", + "art": "unicode/1f3a8.png?v8", + "articulated_lorry": "unicode/1f69b.png?v8", + "artificial_satellite": "unicode/1f6f0.png?v8", + "artist": "unicode/1f9d1-1f3a8.png?v8", + "aruba": "unicode/1f1e6-1f1fc.png?v8", + "ascension_island": "unicode/1f1e6-1f1e8.png?v8", + "asterisk": "unicode/002a-20e3.png?v8", + "astonished": "unicode/1f632.png?v8", + "astronaut": "unicode/1f9d1-1f680.png?v8", + "athletic_shoe": "unicode/1f45f.png?v8", + "atm": "unicode/1f3e7.png?v8", + "atom": "atom.png?v8", + "atom_symbol": "unicode/269b.png?v8", + "australia": "unicode/1f1e6-1f1fa.png?v8", + "austria": "unicode/1f1e6-1f1f9.png?v8", + "auto_rickshaw": "unicode/1f6fa.png?v8", + "avocado": "unicode/1f951.png?v8", + "axe": "unicode/1fa93.png?v8", + "azerbaijan": "unicode/1f1e6-1f1ff.png?v8", + "b": "unicode/1f171.png?v8", + "baby": "unicode/1f476.png?v8", + "baby_bottle": "unicode/1f37c.png?v8", + "baby_chick": "unicode/1f424.png?v8", + "baby_symbol": "unicode/1f6bc.png?v8", + "back": "unicode/1f519.png?v8", + "bacon": "unicode/1f953.png?v8", + "badger": "unicode/1f9a1.png?v8", + "badminton": "unicode/1f3f8.png?v8", + "bagel": "unicode/1f96f.png?v8", + "baggage_claim": "unicode/1f6c4.png?v8", + "baguette_bread": "unicode/1f956.png?v8", + "bahamas": "unicode/1f1e7-1f1f8.png?v8", + "bahrain": "unicode/1f1e7-1f1ed.png?v8", + "balance_scale": "unicode/2696.png?v8", + "bald_man": "unicode/1f468-1f9b2.png?v8", + "bald_woman": "unicode/1f469-1f9b2.png?v8", + "ballet_shoes": "unicode/1fa70.png?v8", + "balloon": "unicode/1f388.png?v8", + "ballot_box": "unicode/1f5f3.png?v8", + "ballot_box_with_check": "unicode/2611.png?v8", + "bamboo": "unicode/1f38d.png?v8", + "banana": "unicode/1f34c.png?v8", + "bangbang": "unicode/203c.png?v8", + "bangladesh": "unicode/1f1e7-1f1e9.png?v8", + "banjo": "unicode/1fa95.png?v8", + "bank": "unicode/1f3e6.png?v8", + "bar_chart": "unicode/1f4ca.png?v8", + "barbados": "unicode/1f1e7-1f1e7.png?v8", + "barber": "unicode/1f488.png?v8", + "baseball": "unicode/26be.png?v8", + "basecamp": "basecamp.png?v8", + "basecampy": "basecampy.png?v8", + "basket": "unicode/1f9fa.png?v8", + "basketball": "unicode/1f3c0.png?v8", + "basketball_man": "unicode/26f9-2642.png?v8", + "basketball_woman": "unicode/26f9-2640.png?v8", + "bat": "unicode/1f987.png?v8", + "bath": "unicode/1f6c0.png?v8", + "bathtub": "unicode/1f6c1.png?v8", + "battery": "unicode/1f50b.png?v8", + "beach_umbrella": "unicode/1f3d6.png?v8", + "bear": "unicode/1f43b.png?v8", + "bearded_person": "unicode/1f9d4.png?v8", + "beaver": "unicode/1f9ab.png?v8", + "bed": "unicode/1f6cf.png?v8", + "bee": "unicode/1f41d.png?v8", + "beer": "unicode/1f37a.png?v8", + "beers": "unicode/1f37b.png?v8", + "beetle": "unicode/1fab2.png?v8", + "beginner": "unicode/1f530.png?v8", + "belarus": "unicode/1f1e7-1f1fe.png?v8", + "belgium": "unicode/1f1e7-1f1ea.png?v8", + "belize": "unicode/1f1e7-1f1ff.png?v8", + "bell": "unicode/1f514.png?v8", + "bell_pepper": "unicode/1fad1.png?v8", + "bellhop_bell": "unicode/1f6ce.png?v8", + "benin": "unicode/1f1e7-1f1ef.png?v8", + "bento": "unicode/1f371.png?v8", + "bermuda": "unicode/1f1e7-1f1f2.png?v8", + "beverage_box": "unicode/1f9c3.png?v8", + "bhutan": "unicode/1f1e7-1f1f9.png?v8", + "bicyclist": "unicode/1f6b4.png?v8", + "bike": "unicode/1f6b2.png?v8", + "biking_man": "unicode/1f6b4-2642.png?v8", + "biking_woman": "unicode/1f6b4-2640.png?v8", + "bikini": "unicode/1f459.png?v8", + "billed_cap": "unicode/1f9e2.png?v8", + "biohazard": "unicode/2623.png?v8", + "bird": "unicode/1f426.png?v8", + "birthday": "unicode/1f382.png?v8", + "bison": "unicode/1f9ac.png?v8", + "black_cat": "unicode/1f408-2b1b.png?v8", + "black_circle": "unicode/26ab.png?v8", + "black_flag": "unicode/1f3f4.png?v8", + "black_heart": "unicode/1f5a4.png?v8", + "black_joker": "unicode/1f0cf.png?v8", + "black_large_square": "unicode/2b1b.png?v8", + "black_medium_small_square": "unicode/25fe.png?v8", + "black_medium_square": "unicode/25fc.png?v8", + "black_nib": "unicode/2712.png?v8", + "black_small_square": "unicode/25aa.png?v8", + "black_square_button": "unicode/1f532.png?v8", + "blond_haired_man": "unicode/1f471-2642.png?v8", + "blond_haired_person": "unicode/1f471.png?v8", + "blond_haired_woman": "unicode/1f471-2640.png?v8", + "blonde_woman": "unicode/1f471-2640.png?v8", + "blossom": "unicode/1f33c.png?v8", + "blowfish": "unicode/1f421.png?v8", + "blue_book": "unicode/1f4d8.png?v8", + "blue_car": "unicode/1f699.png?v8", + "blue_heart": "unicode/1f499.png?v8", + "blue_square": "unicode/1f7e6.png?v8", + "blueberries": "unicode/1fad0.png?v8", + "blush": "unicode/1f60a.png?v8", + "boar": "unicode/1f417.png?v8", + "boat": "unicode/26f5.png?v8", + "bolivia": "unicode/1f1e7-1f1f4.png?v8", + "bomb": "unicode/1f4a3.png?v8", + "bone": "unicode/1f9b4.png?v8", + "book": "unicode/1f4d6.png?v8", + "bookmark": "unicode/1f516.png?v8", + "bookmark_tabs": "unicode/1f4d1.png?v8", + "books": "unicode/1f4da.png?v8", + "boom": "unicode/1f4a5.png?v8", + "boomerang": "unicode/1fa83.png?v8", + "boot": "unicode/1f462.png?v8", + "bosnia_herzegovina": "unicode/1f1e7-1f1e6.png?v8", + "botswana": "unicode/1f1e7-1f1fc.png?v8", + "bouncing_ball_man": "unicode/26f9-2642.png?v8", + "bouncing_ball_person": "unicode/26f9.png?v8", + "bouncing_ball_woman": "unicode/26f9-2640.png?v8", + "bouquet": "unicode/1f490.png?v8", + "bouvet_island": "unicode/1f1e7-1f1fb.png?v8", + "bow": "unicode/1f647.png?v8", + "bow_and_arrow": "unicode/1f3f9.png?v8", + "bowing_man": "unicode/1f647-2642.png?v8", + "bowing_woman": "unicode/1f647-2640.png?v8", + "bowl_with_spoon": "unicode/1f963.png?v8", + "bowling": "unicode/1f3b3.png?v8", + "bowtie": "bowtie.png?v8", + "boxing_glove": "unicode/1f94a.png?v8", + "boy": "unicode/1f466.png?v8", + "brain": "unicode/1f9e0.png?v8", + "brazil": "unicode/1f1e7-1f1f7.png?v8", + "bread": "unicode/1f35e.png?v8", + "breast_feeding": "unicode/1f931.png?v8", + "bricks": "unicode/1f9f1.png?v8", + "bride_with_veil": "unicode/1f470-2640.png?v8", + "bridge_at_night": "unicode/1f309.png?v8", + "briefcase": "unicode/1f4bc.png?v8", + "british_indian_ocean_territory": "unicode/1f1ee-1f1f4.png?v8", + "british_virgin_islands": "unicode/1f1fb-1f1ec.png?v8", + "broccoli": "unicode/1f966.png?v8", + "broken_heart": "unicode/1f494.png?v8", + "broom": "unicode/1f9f9.png?v8", + "brown_circle": "unicode/1f7e4.png?v8", + "brown_heart": "unicode/1f90e.png?v8", + "brown_square": "unicode/1f7eb.png?v8", + "brunei": "unicode/1f1e7-1f1f3.png?v8", + "bubble_tea": "unicode/1f9cb.png?v8", + "bucket": "unicode/1faa3.png?v8", + "bug": "unicode/1f41b.png?v8", + "building_construction": "unicode/1f3d7.png?v8", + "bulb": "unicode/1f4a1.png?v8", + "bulgaria": "unicode/1f1e7-1f1ec.png?v8", + "bullettrain_front": "unicode/1f685.png?v8", + "bullettrain_side": "unicode/1f684.png?v8", + "burkina_faso": "unicode/1f1e7-1f1eb.png?v8", + "burrito": "unicode/1f32f.png?v8", + "burundi": "unicode/1f1e7-1f1ee.png?v8", + "bus": "unicode/1f68c.png?v8", + "business_suit_levitating": "unicode/1f574.png?v8", + "busstop": "unicode/1f68f.png?v8", + "bust_in_silhouette": "unicode/1f464.png?v8", + "busts_in_silhouette": "unicode/1f465.png?v8", + "butter": "unicode/1f9c8.png?v8", + "butterfly": "unicode/1f98b.png?v8", + "cactus": "unicode/1f335.png?v8", + "cake": "unicode/1f370.png?v8", + "calendar": "unicode/1f4c6.png?v8", + "call_me_hand": "unicode/1f919.png?v8", + "calling": "unicode/1f4f2.png?v8", + "cambodia": "unicode/1f1f0-1f1ed.png?v8", + "camel": "unicode/1f42b.png?v8", + "camera": "unicode/1f4f7.png?v8", + "camera_flash": "unicode/1f4f8.png?v8", + "cameroon": "unicode/1f1e8-1f1f2.png?v8", + "camping": "unicode/1f3d5.png?v8", + "canada": "unicode/1f1e8-1f1e6.png?v8", + "canary_islands": "unicode/1f1ee-1f1e8.png?v8", + "cancer": "unicode/264b.png?v8", + "candle": "unicode/1f56f.png?v8", + "candy": "unicode/1f36c.png?v8", + "canned_food": "unicode/1f96b.png?v8", + "canoe": "unicode/1f6f6.png?v8", + "cape_verde": "unicode/1f1e8-1f1fb.png?v8", + "capital_abcd": "unicode/1f520.png?v8", + "capricorn": "unicode/2651.png?v8", + "car": "unicode/1f697.png?v8", + "card_file_box": "unicode/1f5c3.png?v8", + "card_index": "unicode/1f4c7.png?v8", + "card_index_dividers": "unicode/1f5c2.png?v8", + "caribbean_netherlands": "unicode/1f1e7-1f1f6.png?v8", + "carousel_horse": "unicode/1f3a0.png?v8", + "carpentry_saw": "unicode/1fa9a.png?v8", + "carrot": "unicode/1f955.png?v8", + "cartwheeling": "unicode/1f938.png?v8", + "cat": "unicode/1f431.png?v8", + "cat2": "unicode/1f408.png?v8", + "cayman_islands": "unicode/1f1f0-1f1fe.png?v8", + "cd": "unicode/1f4bf.png?v8", + "central_african_republic": "unicode/1f1e8-1f1eb.png?v8", + "ceuta_melilla": "unicode/1f1ea-1f1e6.png?v8", + "chad": "unicode/1f1f9-1f1e9.png?v8", + "chains": "unicode/26d3.png?v8", + "chair": "unicode/1fa91.png?v8", + "champagne": "unicode/1f37e.png?v8", + "chart": "unicode/1f4b9.png?v8", + "chart_with_downwards_trend": "unicode/1f4c9.png?v8", + "chart_with_upwards_trend": "unicode/1f4c8.png?v8", + "checkered_flag": "unicode/1f3c1.png?v8", + "cheese": "unicode/1f9c0.png?v8", + "cherries": "unicode/1f352.png?v8", + "cherry_blossom": "unicode/1f338.png?v8", + "chess_pawn": "unicode/265f.png?v8", + "chestnut": "unicode/1f330.png?v8", + "chicken": "unicode/1f414.png?v8", + "child": "unicode/1f9d2.png?v8", + "children_crossing": "unicode/1f6b8.png?v8", + "chile": "unicode/1f1e8-1f1f1.png?v8", + "chipmunk": "unicode/1f43f.png?v8", + "chocolate_bar": "unicode/1f36b.png?v8", + "chopsticks": "unicode/1f962.png?v8", + "christmas_island": "unicode/1f1e8-1f1fd.png?v8", + "christmas_tree": "unicode/1f384.png?v8", + "church": "unicode/26ea.png?v8", + "cinema": "unicode/1f3a6.png?v8", + "circus_tent": "unicode/1f3aa.png?v8", + "city_sunrise": "unicode/1f307.png?v8", + "city_sunset": "unicode/1f306.png?v8", + "cityscape": "unicode/1f3d9.png?v8", + "cl": "unicode/1f191.png?v8", + "clamp": "unicode/1f5dc.png?v8", + "clap": "unicode/1f44f.png?v8", + "clapper": "unicode/1f3ac.png?v8", + "classical_building": "unicode/1f3db.png?v8", + "climbing": "unicode/1f9d7.png?v8", + "climbing_man": "unicode/1f9d7-2642.png?v8", + "climbing_woman": "unicode/1f9d7-2640.png?v8", + "clinking_glasses": "unicode/1f942.png?v8", + "clipboard": "unicode/1f4cb.png?v8", + "clipperton_island": "unicode/1f1e8-1f1f5.png?v8", + "clock1": "unicode/1f550.png?v8", + "clock10": "unicode/1f559.png?v8", + "clock1030": "unicode/1f565.png?v8", + "clock11": "unicode/1f55a.png?v8", + "clock1130": "unicode/1f566.png?v8", + "clock12": "unicode/1f55b.png?v8", + "clock1230": "unicode/1f567.png?v8", + "clock130": "unicode/1f55c.png?v8", + "clock2": "unicode/1f551.png?v8", + "clock230": "unicode/1f55d.png?v8", + "clock3": "unicode/1f552.png?v8", + "clock330": "unicode/1f55e.png?v8", + "clock4": "unicode/1f553.png?v8", + "clock430": "unicode/1f55f.png?v8", + "clock5": "unicode/1f554.png?v8", + "clock530": "unicode/1f560.png?v8", + "clock6": "unicode/1f555.png?v8", + "clock630": "unicode/1f561.png?v8", + "clock7": "unicode/1f556.png?v8", + "clock730": "unicode/1f562.png?v8", + "clock8": "unicode/1f557.png?v8", + "clock830": "unicode/1f563.png?v8", + "clock9": "unicode/1f558.png?v8", + "clock930": "unicode/1f564.png?v8", + "closed_book": "unicode/1f4d5.png?v8", + "closed_lock_with_key": "unicode/1f510.png?v8", + "closed_umbrella": "unicode/1f302.png?v8", + "cloud": "unicode/2601.png?v8", + "cloud_with_lightning": "unicode/1f329.png?v8", + "cloud_with_lightning_and_rain": "unicode/26c8.png?v8", + "cloud_with_rain": "unicode/1f327.png?v8", + "cloud_with_snow": "unicode/1f328.png?v8", + "clown_face": "unicode/1f921.png?v8", + "clubs": "unicode/2663.png?v8", + "cn": "unicode/1f1e8-1f1f3.png?v8", + "coat": "unicode/1f9e5.png?v8", + "cockroach": "unicode/1fab3.png?v8", + "cocktail": "unicode/1f378.png?v8", + "coconut": "unicode/1f965.png?v8", + "cocos_islands": "unicode/1f1e8-1f1e8.png?v8", + "coffee": "unicode/2615.png?v8", + "coffin": "unicode/26b0.png?v8", + "coin": "unicode/1fa99.png?v8", + "cold_face": "unicode/1f976.png?v8", + "cold_sweat": "unicode/1f630.png?v8", + "collision": "unicode/1f4a5.png?v8", + "colombia": "unicode/1f1e8-1f1f4.png?v8", + "comet": "unicode/2604.png?v8", + "comoros": "unicode/1f1f0-1f1f2.png?v8", + "compass": "unicode/1f9ed.png?v8", + "computer": "unicode/1f4bb.png?v8", + "computer_mouse": "unicode/1f5b1.png?v8", + "confetti_ball": "unicode/1f38a.png?v8", + "confounded": "unicode/1f616.png?v8", + "confused": "unicode/1f615.png?v8", + "congo_brazzaville": "unicode/1f1e8-1f1ec.png?v8", + "congo_kinshasa": "unicode/1f1e8-1f1e9.png?v8", + "congratulations": "unicode/3297.png?v8", + "construction": "unicode/1f6a7.png?v8", + "construction_worker": "unicode/1f477.png?v8", + "construction_worker_man": "unicode/1f477-2642.png?v8", + "construction_worker_woman": "unicode/1f477-2640.png?v8", + "control_knobs": "unicode/1f39b.png?v8", + "convenience_store": "unicode/1f3ea.png?v8", + "cook": "unicode/1f9d1-1f373.png?v8", + "cook_islands": "unicode/1f1e8-1f1f0.png?v8", + "cookie": "unicode/1f36a.png?v8", + "cool": "unicode/1f192.png?v8", + "cop": "unicode/1f46e.png?v8", + "copyright": "unicode/00a9.png?v8", + "corn": "unicode/1f33d.png?v8", + "costa_rica": "unicode/1f1e8-1f1f7.png?v8", + "cote_divoire": "unicode/1f1e8-1f1ee.png?v8", + "couch_and_lamp": "unicode/1f6cb.png?v8", + "couple": "unicode/1f46b.png?v8", + "couple_with_heart": "unicode/1f491.png?v8", + "couple_with_heart_man_man": "unicode/1f468-2764-1f468.png?v8", + "couple_with_heart_woman_man": "unicode/1f469-2764-1f468.png?v8", + "couple_with_heart_woman_woman": "unicode/1f469-2764-1f469.png?v8", + "couplekiss": "unicode/1f48f.png?v8", + "couplekiss_man_man": "unicode/1f468-2764-1f48b-1f468.png?v8", + "couplekiss_man_woman": "unicode/1f469-2764-1f48b-1f468.png?v8", + "couplekiss_woman_woman": "unicode/1f469-2764-1f48b-1f469.png?v8", + "cow": "unicode/1f42e.png?v8", + "cow2": "unicode/1f404.png?v8", + "cowboy_hat_face": "unicode/1f920.png?v8", + "crab": "unicode/1f980.png?v8", + "crayon": "unicode/1f58d.png?v8", + "credit_card": "unicode/1f4b3.png?v8", + "crescent_moon": "unicode/1f319.png?v8", + "cricket": "unicode/1f997.png?v8", + "cricket_game": "unicode/1f3cf.png?v8", + "croatia": "unicode/1f1ed-1f1f7.png?v8", + "crocodile": "unicode/1f40a.png?v8", + "croissant": "unicode/1f950.png?v8", + "crossed_fingers": "unicode/1f91e.png?v8", + "crossed_flags": "unicode/1f38c.png?v8", + "crossed_swords": "unicode/2694.png?v8", + "crown": "unicode/1f451.png?v8", + "cry": "unicode/1f622.png?v8", + "crying_cat_face": "unicode/1f63f.png?v8", + "crystal_ball": "unicode/1f52e.png?v8", + "cuba": "unicode/1f1e8-1f1fa.png?v8", + "cucumber": "unicode/1f952.png?v8", + "cup_with_straw": "unicode/1f964.png?v8", + "cupcake": "unicode/1f9c1.png?v8", + "cupid": "unicode/1f498.png?v8", + "curacao": "unicode/1f1e8-1f1fc.png?v8", + "curling_stone": "unicode/1f94c.png?v8", + "curly_haired_man": "unicode/1f468-1f9b1.png?v8", + "curly_haired_woman": "unicode/1f469-1f9b1.png?v8", + "curly_loop": "unicode/27b0.png?v8", + "currency_exchange": "unicode/1f4b1.png?v8", + "curry": "unicode/1f35b.png?v8", + "cursing_face": "unicode/1f92c.png?v8", + "custard": "unicode/1f36e.png?v8", + "customs": "unicode/1f6c3.png?v8", + "cut_of_meat": "unicode/1f969.png?v8", + "cyclone": "unicode/1f300.png?v8", + "cyprus": "unicode/1f1e8-1f1fe.png?v8", + "czech_republic": "unicode/1f1e8-1f1ff.png?v8", + "dagger": "unicode/1f5e1.png?v8", + "dancer": "unicode/1f483.png?v8", + "dancers": "unicode/1f46f.png?v8", + "dancing_men": "unicode/1f46f-2642.png?v8", + "dancing_women": "unicode/1f46f-2640.png?v8", + "dango": "unicode/1f361.png?v8", + "dark_sunglasses": "unicode/1f576.png?v8", + "dart": "unicode/1f3af.png?v8", + "dash": "unicode/1f4a8.png?v8", + "date": "unicode/1f4c5.png?v8", + "de": "unicode/1f1e9-1f1ea.png?v8", + "deaf_man": "unicode/1f9cf-2642.png?v8", + "deaf_person": "unicode/1f9cf.png?v8", + "deaf_woman": "unicode/1f9cf-2640.png?v8", + "deciduous_tree": "unicode/1f333.png?v8", + "deer": "unicode/1f98c.png?v8", + "denmark": "unicode/1f1e9-1f1f0.png?v8", + "department_store": "unicode/1f3ec.png?v8", + "dependabot": "dependabot.png?v8", + "derelict_house": "unicode/1f3da.png?v8", + "desert": "unicode/1f3dc.png?v8", + "desert_island": "unicode/1f3dd.png?v8", + "desktop_computer": "unicode/1f5a5.png?v8", + "detective": "unicode/1f575.png?v8", + "diamond_shape_with_a_dot_inside": "unicode/1f4a0.png?v8", + "diamonds": "unicode/2666.png?v8", + "diego_garcia": "unicode/1f1e9-1f1ec.png?v8", + "disappointed": "unicode/1f61e.png?v8", + "disappointed_relieved": "unicode/1f625.png?v8", + "disguised_face": "unicode/1f978.png?v8", + "diving_mask": "unicode/1f93f.png?v8", + "diya_lamp": "unicode/1fa94.png?v8", + "dizzy": "unicode/1f4ab.png?v8", + "dizzy_face": "unicode/1f635.png?v8", + "djibouti": "unicode/1f1e9-1f1ef.png?v8", + "dna": "unicode/1f9ec.png?v8", + "do_not_litter": "unicode/1f6af.png?v8", + "dodo": "unicode/1f9a4.png?v8", + "dog": "unicode/1f436.png?v8", + "dog2": "unicode/1f415.png?v8", + "dollar": "unicode/1f4b5.png?v8", + "dolls": "unicode/1f38e.png?v8", + "dolphin": "unicode/1f42c.png?v8", + "dominica": "unicode/1f1e9-1f1f2.png?v8", + "dominican_republic": "unicode/1f1e9-1f1f4.png?v8", + "door": "unicode/1f6aa.png?v8", + "doughnut": "unicode/1f369.png?v8", + "dove": "unicode/1f54a.png?v8", + "dragon": "unicode/1f409.png?v8", + "dragon_face": "unicode/1f432.png?v8", + "dress": "unicode/1f457.png?v8", + "dromedary_camel": "unicode/1f42a.png?v8", + "drooling_face": "unicode/1f924.png?v8", + "drop_of_blood": "unicode/1fa78.png?v8", + "droplet": "unicode/1f4a7.png?v8", + "drum": "unicode/1f941.png?v8", + "duck": "unicode/1f986.png?v8", + "dumpling": "unicode/1f95f.png?v8", + "dvd": "unicode/1f4c0.png?v8", + "e-mail": "unicode/1f4e7.png?v8", + "eagle": "unicode/1f985.png?v8", + "ear": "unicode/1f442.png?v8", + "ear_of_rice": "unicode/1f33e.png?v8", + "ear_with_hearing_aid": "unicode/1f9bb.png?v8", + "earth_africa": "unicode/1f30d.png?v8", + "earth_americas": "unicode/1f30e.png?v8", + "earth_asia": "unicode/1f30f.png?v8", + "ecuador": "unicode/1f1ea-1f1e8.png?v8", + "egg": "unicode/1f95a.png?v8", + "eggplant": "unicode/1f346.png?v8", + "egypt": "unicode/1f1ea-1f1ec.png?v8", + "eight": "unicode/0038-20e3.png?v8", + "eight_pointed_black_star": "unicode/2734.png?v8", + "eight_spoked_asterisk": "unicode/2733.png?v8", + "eject_button": "unicode/23cf.png?v8", + "el_salvador": "unicode/1f1f8-1f1fb.png?v8", + "electric_plug": "unicode/1f50c.png?v8", + "electron": "electron.png?v8", + "elephant": "unicode/1f418.png?v8", + "elevator": "unicode/1f6d7.png?v8", + "elf": "unicode/1f9dd.png?v8", + "elf_man": "unicode/1f9dd-2642.png?v8", + "elf_woman": "unicode/1f9dd-2640.png?v8", + "email": "unicode/1f4e7.png?v8", + "end": "unicode/1f51a.png?v8", + "england": "unicode/1f3f4-e0067-e0062-e0065-e006e-e0067-e007f.png?v8", + "envelope": "unicode/2709.png?v8", + "envelope_with_arrow": "unicode/1f4e9.png?v8", + "equatorial_guinea": "unicode/1f1ec-1f1f6.png?v8", + "eritrea": "unicode/1f1ea-1f1f7.png?v8", + "es": "unicode/1f1ea-1f1f8.png?v8", + "estonia": "unicode/1f1ea-1f1ea.png?v8", + "ethiopia": "unicode/1f1ea-1f1f9.png?v8", + "eu": "unicode/1f1ea-1f1fa.png?v8", + "euro": "unicode/1f4b6.png?v8", + "european_castle": "unicode/1f3f0.png?v8", + "european_post_office": "unicode/1f3e4.png?v8", + "european_union": "unicode/1f1ea-1f1fa.png?v8", + "evergreen_tree": "unicode/1f332.png?v8", + "exclamation": "unicode/2757.png?v8", + "exploding_head": "unicode/1f92f.png?v8", + "expressionless": "unicode/1f611.png?v8", + "eye": "unicode/1f441.png?v8", + "eye_speech_bubble": "unicode/1f441-1f5e8.png?v8", + "eyeglasses": "unicode/1f453.png?v8", + "eyes": "unicode/1f440.png?v8", + "face_exhaling": "unicode/1f62e-1f4a8.png?v8", + "face_in_clouds": "unicode/1f636-1f32b.png?v8", + "face_with_head_bandage": "unicode/1f915.png?v8", + "face_with_spiral_eyes": "unicode/1f635-1f4ab.png?v8", + "face_with_thermometer": "unicode/1f912.png?v8", + "facepalm": "unicode/1f926.png?v8", + "facepunch": "unicode/1f44a.png?v8", + "factory": "unicode/1f3ed.png?v8", + "factory_worker": "unicode/1f9d1-1f3ed.png?v8", + "fairy": "unicode/1f9da.png?v8", + "fairy_man": "unicode/1f9da-2642.png?v8", + "fairy_woman": "unicode/1f9da-2640.png?v8", + "falafel": "unicode/1f9c6.png?v8", + "falkland_islands": "unicode/1f1eb-1f1f0.png?v8", + "fallen_leaf": "unicode/1f342.png?v8", + "family": "unicode/1f46a.png?v8", + "family_man_boy": "unicode/1f468-1f466.png?v8", + "family_man_boy_boy": "unicode/1f468-1f466-1f466.png?v8", + "family_man_girl": "unicode/1f468-1f467.png?v8", + "family_man_girl_boy": "unicode/1f468-1f467-1f466.png?v8", + "family_man_girl_girl": "unicode/1f468-1f467-1f467.png?v8", + "family_man_man_boy": "unicode/1f468-1f468-1f466.png?v8", + "family_man_man_boy_boy": "unicode/1f468-1f468-1f466-1f466.png?v8", + "family_man_man_girl": "unicode/1f468-1f468-1f467.png?v8", + "family_man_man_girl_boy": "unicode/1f468-1f468-1f467-1f466.png?v8", + "family_man_man_girl_girl": "unicode/1f468-1f468-1f467-1f467.png?v8", + "family_man_woman_boy": "unicode/1f468-1f469-1f466.png?v8", + "family_man_woman_boy_boy": "unicode/1f468-1f469-1f466-1f466.png?v8", + "family_man_woman_girl": "unicode/1f468-1f469-1f467.png?v8", + "family_man_woman_girl_boy": "unicode/1f468-1f469-1f467-1f466.png?v8", + "family_man_woman_girl_girl": "unicode/1f468-1f469-1f467-1f467.png?v8", + "family_woman_boy": "unicode/1f469-1f466.png?v8", + "family_woman_boy_boy": "unicode/1f469-1f466-1f466.png?v8", + "family_woman_girl": "unicode/1f469-1f467.png?v8", + "family_woman_girl_boy": "unicode/1f469-1f467-1f466.png?v8", + "family_woman_girl_girl": "unicode/1f469-1f467-1f467.png?v8", + "family_woman_woman_boy": "unicode/1f469-1f469-1f466.png?v8", + "family_woman_woman_boy_boy": "unicode/1f469-1f469-1f466-1f466.png?v8", + "family_woman_woman_girl": "unicode/1f469-1f469-1f467.png?v8", + "family_woman_woman_girl_boy": "unicode/1f469-1f469-1f467-1f466.png?v8", + "family_woman_woman_girl_girl": "unicode/1f469-1f469-1f467-1f467.png?v8", + "farmer": "unicode/1f9d1-1f33e.png?v8", + "faroe_islands": "unicode/1f1eb-1f1f4.png?v8", + "fast_forward": "unicode/23e9.png?v8", + "fax": "unicode/1f4e0.png?v8", + "fearful": "unicode/1f628.png?v8", + "feather": "unicode/1fab6.png?v8", + "feelsgood": "feelsgood.png?v8", + "feet": "unicode/1f43e.png?v8", + "female_detective": "unicode/1f575-2640.png?v8", + "female_sign": "unicode/2640.png?v8", + "ferris_wheel": "unicode/1f3a1.png?v8", + "ferry": "unicode/26f4.png?v8", + "field_hockey": "unicode/1f3d1.png?v8", + "fiji": "unicode/1f1eb-1f1ef.png?v8", + "file_cabinet": "unicode/1f5c4.png?v8", + "file_folder": "unicode/1f4c1.png?v8", + "film_projector": "unicode/1f4fd.png?v8", + "film_strip": "unicode/1f39e.png?v8", + "finland": "unicode/1f1eb-1f1ee.png?v8", + "finnadie": "finnadie.png?v8", + "fire": "unicode/1f525.png?v8", + "fire_engine": "unicode/1f692.png?v8", + "fire_extinguisher": "unicode/1f9ef.png?v8", + "firecracker": "unicode/1f9e8.png?v8", + "firefighter": "unicode/1f9d1-1f692.png?v8", + "fireworks": "unicode/1f386.png?v8", + "first_quarter_moon": "unicode/1f313.png?v8", + "first_quarter_moon_with_face": "unicode/1f31b.png?v8", + "fish": "unicode/1f41f.png?v8", + "fish_cake": "unicode/1f365.png?v8", + "fishing_pole_and_fish": "unicode/1f3a3.png?v8", + "fishsticks": "fishsticks.png?v8", + "fist": "unicode/270a.png?v8", + "fist_left": "unicode/1f91b.png?v8", + "fist_oncoming": "unicode/1f44a.png?v8", + "fist_raised": "unicode/270a.png?v8", + "fist_right": "unicode/1f91c.png?v8", + "five": "unicode/0035-20e3.png?v8", + "flags": "unicode/1f38f.png?v8", + "flamingo": "unicode/1f9a9.png?v8", + "flashlight": "unicode/1f526.png?v8", + "flat_shoe": "unicode/1f97f.png?v8", + "flatbread": "unicode/1fad3.png?v8", + "fleur_de_lis": "unicode/269c.png?v8", + "flight_arrival": "unicode/1f6ec.png?v8", + "flight_departure": "unicode/1f6eb.png?v8", + "flipper": "unicode/1f42c.png?v8", + "floppy_disk": "unicode/1f4be.png?v8", + "flower_playing_cards": "unicode/1f3b4.png?v8", + "flushed": "unicode/1f633.png?v8", + "fly": "unicode/1fab0.png?v8", + "flying_disc": "unicode/1f94f.png?v8", + "flying_saucer": "unicode/1f6f8.png?v8", + "fog": "unicode/1f32b.png?v8", + "foggy": "unicode/1f301.png?v8", + "fondue": "unicode/1fad5.png?v8", + "foot": "unicode/1f9b6.png?v8", + "football": "unicode/1f3c8.png?v8", + "footprints": "unicode/1f463.png?v8", + "fork_and_knife": "unicode/1f374.png?v8", + "fortune_cookie": "unicode/1f960.png?v8", + "fountain": "unicode/26f2.png?v8", + "fountain_pen": "unicode/1f58b.png?v8", + "four": "unicode/0034-20e3.png?v8", + "four_leaf_clover": "unicode/1f340.png?v8", + "fox_face": "unicode/1f98a.png?v8", + "fr": "unicode/1f1eb-1f1f7.png?v8", + "framed_picture": "unicode/1f5bc.png?v8", + "free": "unicode/1f193.png?v8", + "french_guiana": "unicode/1f1ec-1f1eb.png?v8", + "french_polynesia": "unicode/1f1f5-1f1eb.png?v8", + "french_southern_territories": "unicode/1f1f9-1f1eb.png?v8", + "fried_egg": "unicode/1f373.png?v8", + "fried_shrimp": "unicode/1f364.png?v8", + "fries": "unicode/1f35f.png?v8", + "frog": "unicode/1f438.png?v8", + "frowning": "unicode/1f626.png?v8", + "frowning_face": "unicode/2639.png?v8", + "frowning_man": "unicode/1f64d-2642.png?v8", + "frowning_person": "unicode/1f64d.png?v8", + "frowning_woman": "unicode/1f64d-2640.png?v8", + "fu": "unicode/1f595.png?v8", + "fuelpump": "unicode/26fd.png?v8", + "full_moon": "unicode/1f315.png?v8", + "full_moon_with_face": "unicode/1f31d.png?v8", + "funeral_urn": "unicode/26b1.png?v8", + "gabon": "unicode/1f1ec-1f1e6.png?v8", + "gambia": "unicode/1f1ec-1f1f2.png?v8", + "game_die": "unicode/1f3b2.png?v8", + "garlic": "unicode/1f9c4.png?v8", + "gb": "unicode/1f1ec-1f1e7.png?v8", + "gear": "unicode/2699.png?v8", + "gem": "unicode/1f48e.png?v8", + "gemini": "unicode/264a.png?v8", + "genie": "unicode/1f9de.png?v8", + "genie_man": "unicode/1f9de-2642.png?v8", + "genie_woman": "unicode/1f9de-2640.png?v8", + "georgia": "unicode/1f1ec-1f1ea.png?v8", + "ghana": "unicode/1f1ec-1f1ed.png?v8", + "ghost": "unicode/1f47b.png?v8", + "gibraltar": "unicode/1f1ec-1f1ee.png?v8", + "gift": "unicode/1f381.png?v8", + "gift_heart": "unicode/1f49d.png?v8", + "giraffe": "unicode/1f992.png?v8", + "girl": "unicode/1f467.png?v8", + "globe_with_meridians": "unicode/1f310.png?v8", + "gloves": "unicode/1f9e4.png?v8", + "goal_net": "unicode/1f945.png?v8", + "goat": "unicode/1f410.png?v8", + "goberserk": "goberserk.png?v8", + "godmode": "godmode.png?v8", + "goggles": "unicode/1f97d.png?v8", + "golf": "unicode/26f3.png?v8", + "golfing": "unicode/1f3cc.png?v8", + "golfing_man": "unicode/1f3cc-2642.png?v8", + "golfing_woman": "unicode/1f3cc-2640.png?v8", + "gorilla": "unicode/1f98d.png?v8", + "grapes": "unicode/1f347.png?v8", + "greece": "unicode/1f1ec-1f1f7.png?v8", + "green_apple": "unicode/1f34f.png?v8", + "green_book": "unicode/1f4d7.png?v8", + "green_circle": "unicode/1f7e2.png?v8", + "green_heart": "unicode/1f49a.png?v8", + "green_salad": "unicode/1f957.png?v8", + "green_square": "unicode/1f7e9.png?v8", + "greenland": "unicode/1f1ec-1f1f1.png?v8", + "grenada": "unicode/1f1ec-1f1e9.png?v8", + "grey_exclamation": "unicode/2755.png?v8", + "grey_question": "unicode/2754.png?v8", + "grimacing": "unicode/1f62c.png?v8", + "grin": "unicode/1f601.png?v8", + "grinning": "unicode/1f600.png?v8", + "guadeloupe": "unicode/1f1ec-1f1f5.png?v8", + "guam": "unicode/1f1ec-1f1fa.png?v8", + "guard": "unicode/1f482.png?v8", + "guardsman": "unicode/1f482-2642.png?v8", + "guardswoman": "unicode/1f482-2640.png?v8", + "guatemala": "unicode/1f1ec-1f1f9.png?v8", + "guernsey": "unicode/1f1ec-1f1ec.png?v8", + "guide_dog": "unicode/1f9ae.png?v8", + "guinea": "unicode/1f1ec-1f1f3.png?v8", + "guinea_bissau": "unicode/1f1ec-1f1fc.png?v8", + "guitar": "unicode/1f3b8.png?v8", + "gun": "unicode/1f52b.png?v8", + "guyana": "unicode/1f1ec-1f1fe.png?v8", + "haircut": "unicode/1f487.png?v8", + "haircut_man": "unicode/1f487-2642.png?v8", + "haircut_woman": "unicode/1f487-2640.png?v8", + "haiti": "unicode/1f1ed-1f1f9.png?v8", + "hamburger": "unicode/1f354.png?v8", + "hammer": "unicode/1f528.png?v8", + "hammer_and_pick": "unicode/2692.png?v8", + "hammer_and_wrench": "unicode/1f6e0.png?v8", + "hamster": "unicode/1f439.png?v8", + "hand": "unicode/270b.png?v8", + "hand_over_mouth": "unicode/1f92d.png?v8", + "handbag": "unicode/1f45c.png?v8", + "handball_person": "unicode/1f93e.png?v8", + "handshake": "unicode/1f91d.png?v8", + "hankey": "unicode/1f4a9.png?v8", + "hash": "unicode/0023-20e3.png?v8", + "hatched_chick": "unicode/1f425.png?v8", + "hatching_chick": "unicode/1f423.png?v8", + "headphones": "unicode/1f3a7.png?v8", + "headstone": "unicode/1faa6.png?v8", + "health_worker": "unicode/1f9d1-2695.png?v8", + "hear_no_evil": "unicode/1f649.png?v8", + "heard_mcdonald_islands": "unicode/1f1ed-1f1f2.png?v8", + "heart": "unicode/2764.png?v8", + "heart_decoration": "unicode/1f49f.png?v8", + "heart_eyes": "unicode/1f60d.png?v8", + "heart_eyes_cat": "unicode/1f63b.png?v8", + "heart_on_fire": "unicode/2764-1f525.png?v8", + "heartbeat": "unicode/1f493.png?v8", + "heartpulse": "unicode/1f497.png?v8", + "hearts": "unicode/2665.png?v8", + "heavy_check_mark": "unicode/2714.png?v8", + "heavy_division_sign": "unicode/2797.png?v8", + "heavy_dollar_sign": "unicode/1f4b2.png?v8", + "heavy_exclamation_mark": "unicode/2757.png?v8", + "heavy_heart_exclamation": "unicode/2763.png?v8", + "heavy_minus_sign": "unicode/2796.png?v8", + "heavy_multiplication_x": "unicode/2716.png?v8", + "heavy_plus_sign": "unicode/2795.png?v8", + "hedgehog": "unicode/1f994.png?v8", + "helicopter": "unicode/1f681.png?v8", + "herb": "unicode/1f33f.png?v8", + "hibiscus": "unicode/1f33a.png?v8", + "high_brightness": "unicode/1f506.png?v8", + "high_heel": "unicode/1f460.png?v8", + "hiking_boot": "unicode/1f97e.png?v8", + "hindu_temple": "unicode/1f6d5.png?v8", + "hippopotamus": "unicode/1f99b.png?v8", + "hocho": "unicode/1f52a.png?v8", + "hole": "unicode/1f573.png?v8", + "honduras": "unicode/1f1ed-1f1f3.png?v8", + "honey_pot": "unicode/1f36f.png?v8", + "honeybee": "unicode/1f41d.png?v8", + "hong_kong": "unicode/1f1ed-1f1f0.png?v8", + "hook": "unicode/1fa9d.png?v8", + "horse": "unicode/1f434.png?v8", + "horse_racing": "unicode/1f3c7.png?v8", + "hospital": "unicode/1f3e5.png?v8", + "hot_face": "unicode/1f975.png?v8", + "hot_pepper": "unicode/1f336.png?v8", + "hotdog": "unicode/1f32d.png?v8", + "hotel": "unicode/1f3e8.png?v8", + "hotsprings": "unicode/2668.png?v8", + "hourglass": "unicode/231b.png?v8", + "hourglass_flowing_sand": "unicode/23f3.png?v8", + "house": "unicode/1f3e0.png?v8", + "house_with_garden": "unicode/1f3e1.png?v8", + "houses": "unicode/1f3d8.png?v8", + "hugs": "unicode/1f917.png?v8", + "hungary": "unicode/1f1ed-1f1fa.png?v8", + "hurtrealbad": "hurtrealbad.png?v8", + "hushed": "unicode/1f62f.png?v8", + "hut": "unicode/1f6d6.png?v8", + "ice_cream": "unicode/1f368.png?v8", + "ice_cube": "unicode/1f9ca.png?v8", + "ice_hockey": "unicode/1f3d2.png?v8", + "ice_skate": "unicode/26f8.png?v8", + "icecream": "unicode/1f366.png?v8", + "iceland": "unicode/1f1ee-1f1f8.png?v8", + "id": "unicode/1f194.png?v8", + "ideograph_advantage": "unicode/1f250.png?v8", + "imp": "unicode/1f47f.png?v8", + "inbox_tray": "unicode/1f4e5.png?v8", + "incoming_envelope": "unicode/1f4e8.png?v8", + "india": "unicode/1f1ee-1f1f3.png?v8", + "indonesia": "unicode/1f1ee-1f1e9.png?v8", + "infinity": "unicode/267e.png?v8", + "information_desk_person": "unicode/1f481.png?v8", + "information_source": "unicode/2139.png?v8", + "innocent": "unicode/1f607.png?v8", + "interrobang": "unicode/2049.png?v8", + "iphone": "unicode/1f4f1.png?v8", + "iran": "unicode/1f1ee-1f1f7.png?v8", + "iraq": "unicode/1f1ee-1f1f6.png?v8", + "ireland": "unicode/1f1ee-1f1ea.png?v8", + "isle_of_man": "unicode/1f1ee-1f1f2.png?v8", + "israel": "unicode/1f1ee-1f1f1.png?v8", + "it": "unicode/1f1ee-1f1f9.png?v8", + "izakaya_lantern": "unicode/1f3ee.png?v8", + "jack_o_lantern": "unicode/1f383.png?v8", + "jamaica": "unicode/1f1ef-1f1f2.png?v8", + "japan": "unicode/1f5fe.png?v8", + "japanese_castle": "unicode/1f3ef.png?v8", + "japanese_goblin": "unicode/1f47a.png?v8", + "japanese_ogre": "unicode/1f479.png?v8", + "jeans": "unicode/1f456.png?v8", + "jersey": "unicode/1f1ef-1f1ea.png?v8", + "jigsaw": "unicode/1f9e9.png?v8", + "jordan": "unicode/1f1ef-1f1f4.png?v8", + "joy": "unicode/1f602.png?v8", + "joy_cat": "unicode/1f639.png?v8", + "joystick": "unicode/1f579.png?v8", + "jp": "unicode/1f1ef-1f1f5.png?v8", + "judge": "unicode/1f9d1-2696.png?v8", + "juggling_person": "unicode/1f939.png?v8", + "kaaba": "unicode/1f54b.png?v8", + "kangaroo": "unicode/1f998.png?v8", + "kazakhstan": "unicode/1f1f0-1f1ff.png?v8", + "kenya": "unicode/1f1f0-1f1ea.png?v8", + "key": "unicode/1f511.png?v8", + "keyboard": "unicode/2328.png?v8", + "keycap_ten": "unicode/1f51f.png?v8", + "kick_scooter": "unicode/1f6f4.png?v8", + "kimono": "unicode/1f458.png?v8", + "kiribati": "unicode/1f1f0-1f1ee.png?v8", + "kiss": "unicode/1f48b.png?v8", + "kissing": "unicode/1f617.png?v8", + "kissing_cat": "unicode/1f63d.png?v8", + "kissing_closed_eyes": "unicode/1f61a.png?v8", + "kissing_heart": "unicode/1f618.png?v8", + "kissing_smiling_eyes": "unicode/1f619.png?v8", + "kite": "unicode/1fa81.png?v8", + "kiwi_fruit": "unicode/1f95d.png?v8", + "kneeling_man": "unicode/1f9ce-2642.png?v8", + "kneeling_person": "unicode/1f9ce.png?v8", + "kneeling_woman": "unicode/1f9ce-2640.png?v8", + "knife": "unicode/1f52a.png?v8", + "knot": "unicode/1faa2.png?v8", + "koala": "unicode/1f428.png?v8", + "koko": "unicode/1f201.png?v8", + "kosovo": "unicode/1f1fd-1f1f0.png?v8", + "kr": "unicode/1f1f0-1f1f7.png?v8", + "kuwait": "unicode/1f1f0-1f1fc.png?v8", + "kyrgyzstan": "unicode/1f1f0-1f1ec.png?v8", + "lab_coat": "unicode/1f97c.png?v8", + "label": "unicode/1f3f7.png?v8", + "lacrosse": "unicode/1f94d.png?v8", + "ladder": "unicode/1fa9c.png?v8", + "lady_beetle": "unicode/1f41e.png?v8", + "lantern": "unicode/1f3ee.png?v8", + "laos": "unicode/1f1f1-1f1e6.png?v8", + "large_blue_circle": "unicode/1f535.png?v8", + "large_blue_diamond": "unicode/1f537.png?v8", + "large_orange_diamond": "unicode/1f536.png?v8", + "last_quarter_moon": "unicode/1f317.png?v8", + "last_quarter_moon_with_face": "unicode/1f31c.png?v8", + "latin_cross": "unicode/271d.png?v8", + "latvia": "unicode/1f1f1-1f1fb.png?v8", + "laughing": "unicode/1f606.png?v8", + "leafy_green": "unicode/1f96c.png?v8", + "leaves": "unicode/1f343.png?v8", + "lebanon": "unicode/1f1f1-1f1e7.png?v8", + "ledger": "unicode/1f4d2.png?v8", + "left_luggage": "unicode/1f6c5.png?v8", + "left_right_arrow": "unicode/2194.png?v8", + "left_speech_bubble": "unicode/1f5e8.png?v8", + "leftwards_arrow_with_hook": "unicode/21a9.png?v8", + "leg": "unicode/1f9b5.png?v8", + "lemon": "unicode/1f34b.png?v8", + "leo": "unicode/264c.png?v8", + "leopard": "unicode/1f406.png?v8", + "lesotho": "unicode/1f1f1-1f1f8.png?v8", + "level_slider": "unicode/1f39a.png?v8", + "liberia": "unicode/1f1f1-1f1f7.png?v8", + "libra": "unicode/264e.png?v8", + "libya": "unicode/1f1f1-1f1fe.png?v8", + "liechtenstein": "unicode/1f1f1-1f1ee.png?v8", + "light_rail": "unicode/1f688.png?v8", + "link": "unicode/1f517.png?v8", + "lion": "unicode/1f981.png?v8", + "lips": "unicode/1f444.png?v8", + "lipstick": "unicode/1f484.png?v8", + "lithuania": "unicode/1f1f1-1f1f9.png?v8", + "lizard": "unicode/1f98e.png?v8", + "llama": "unicode/1f999.png?v8", + "lobster": "unicode/1f99e.png?v8", + "lock": "unicode/1f512.png?v8", + "lock_with_ink_pen": "unicode/1f50f.png?v8", + "lollipop": "unicode/1f36d.png?v8", + "long_drum": "unicode/1fa98.png?v8", + "loop": "unicode/27bf.png?v8", + "lotion_bottle": "unicode/1f9f4.png?v8", + "lotus_position": "unicode/1f9d8.png?v8", + "lotus_position_man": "unicode/1f9d8-2642.png?v8", + "lotus_position_woman": "unicode/1f9d8-2640.png?v8", + "loud_sound": "unicode/1f50a.png?v8", + "loudspeaker": "unicode/1f4e2.png?v8", + "love_hotel": "unicode/1f3e9.png?v8", + "love_letter": "unicode/1f48c.png?v8", + "love_you_gesture": "unicode/1f91f.png?v8", + "low_brightness": "unicode/1f505.png?v8", + "luggage": "unicode/1f9f3.png?v8", + "lungs": "unicode/1fac1.png?v8", + "luxembourg": "unicode/1f1f1-1f1fa.png?v8", + "lying_face": "unicode/1f925.png?v8", + "m": "unicode/24c2.png?v8", + "macau": "unicode/1f1f2-1f1f4.png?v8", + "macedonia": "unicode/1f1f2-1f1f0.png?v8", + "madagascar": "unicode/1f1f2-1f1ec.png?v8", + "mag": "unicode/1f50d.png?v8", + "mag_right": "unicode/1f50e.png?v8", + "mage": "unicode/1f9d9.png?v8", + "mage_man": "unicode/1f9d9-2642.png?v8", + "mage_woman": "unicode/1f9d9-2640.png?v8", + "magic_wand": "unicode/1fa84.png?v8", + "magnet": "unicode/1f9f2.png?v8", + "mahjong": "unicode/1f004.png?v8", + "mailbox": "unicode/1f4eb.png?v8", + "mailbox_closed": "unicode/1f4ea.png?v8", + "mailbox_with_mail": "unicode/1f4ec.png?v8", + "mailbox_with_no_mail": "unicode/1f4ed.png?v8", + "malawi": "unicode/1f1f2-1f1fc.png?v8", + "malaysia": "unicode/1f1f2-1f1fe.png?v8", + "maldives": "unicode/1f1f2-1f1fb.png?v8", + "male_detective": "unicode/1f575-2642.png?v8", + "male_sign": "unicode/2642.png?v8", + "mali": "unicode/1f1f2-1f1f1.png?v8", + "malta": "unicode/1f1f2-1f1f9.png?v8", + "mammoth": "unicode/1f9a3.png?v8", + "man": "unicode/1f468.png?v8", + "man_artist": "unicode/1f468-1f3a8.png?v8", + "man_astronaut": "unicode/1f468-1f680.png?v8", + "man_beard": "unicode/1f9d4-2642.png?v8", + "man_cartwheeling": "unicode/1f938-2642.png?v8", + "man_cook": "unicode/1f468-1f373.png?v8", + "man_dancing": "unicode/1f57a.png?v8", + "man_facepalming": "unicode/1f926-2642.png?v8", + "man_factory_worker": "unicode/1f468-1f3ed.png?v8", + "man_farmer": "unicode/1f468-1f33e.png?v8", + "man_feeding_baby": "unicode/1f468-1f37c.png?v8", + "man_firefighter": "unicode/1f468-1f692.png?v8", + "man_health_worker": "unicode/1f468-2695.png?v8", + "man_in_manual_wheelchair": "unicode/1f468-1f9bd.png?v8", + "man_in_motorized_wheelchair": "unicode/1f468-1f9bc.png?v8", + "man_in_tuxedo": "unicode/1f935-2642.png?v8", + "man_judge": "unicode/1f468-2696.png?v8", + "man_juggling": "unicode/1f939-2642.png?v8", + "man_mechanic": "unicode/1f468-1f527.png?v8", + "man_office_worker": "unicode/1f468-1f4bc.png?v8", + "man_pilot": "unicode/1f468-2708.png?v8", + "man_playing_handball": "unicode/1f93e-2642.png?v8", + "man_playing_water_polo": "unicode/1f93d-2642.png?v8", + "man_scientist": "unicode/1f468-1f52c.png?v8", + "man_shrugging": "unicode/1f937-2642.png?v8", + "man_singer": "unicode/1f468-1f3a4.png?v8", + "man_student": "unicode/1f468-1f393.png?v8", + "man_teacher": "unicode/1f468-1f3eb.png?v8", + "man_technologist": "unicode/1f468-1f4bb.png?v8", + "man_with_gua_pi_mao": "unicode/1f472.png?v8", + "man_with_probing_cane": "unicode/1f468-1f9af.png?v8", + "man_with_turban": "unicode/1f473-2642.png?v8", + "man_with_veil": "unicode/1f470-2642.png?v8", + "mandarin": "unicode/1f34a.png?v8", + "mango": "unicode/1f96d.png?v8", + "mans_shoe": "unicode/1f45e.png?v8", + "mantelpiece_clock": "unicode/1f570.png?v8", + "manual_wheelchair": "unicode/1f9bd.png?v8", + "maple_leaf": "unicode/1f341.png?v8", + "marshall_islands": "unicode/1f1f2-1f1ed.png?v8", + "martial_arts_uniform": "unicode/1f94b.png?v8", + "martinique": "unicode/1f1f2-1f1f6.png?v8", + "mask": "unicode/1f637.png?v8", + "massage": "unicode/1f486.png?v8", + "massage_man": "unicode/1f486-2642.png?v8", + "massage_woman": "unicode/1f486-2640.png?v8", + "mate": "unicode/1f9c9.png?v8", + "mauritania": "unicode/1f1f2-1f1f7.png?v8", + "mauritius": "unicode/1f1f2-1f1fa.png?v8", + "mayotte": "unicode/1f1fe-1f1f9.png?v8", + "meat_on_bone": "unicode/1f356.png?v8", + "mechanic": "unicode/1f9d1-1f527.png?v8", + "mechanical_arm": "unicode/1f9be.png?v8", + "mechanical_leg": "unicode/1f9bf.png?v8", + "medal_military": "unicode/1f396.png?v8", + "medal_sports": "unicode/1f3c5.png?v8", + "medical_symbol": "unicode/2695.png?v8", + "mega": "unicode/1f4e3.png?v8", + "melon": "unicode/1f348.png?v8", + "memo": "unicode/1f4dd.png?v8", + "men_wrestling": "unicode/1f93c-2642.png?v8", + "mending_heart": "unicode/2764-1fa79.png?v8", + "menorah": "unicode/1f54e.png?v8", + "mens": "unicode/1f6b9.png?v8", + "mermaid": "unicode/1f9dc-2640.png?v8", + "merman": "unicode/1f9dc-2642.png?v8", + "merperson": "unicode/1f9dc.png?v8", + "metal": "unicode/1f918.png?v8", + "metro": "unicode/1f687.png?v8", + "mexico": "unicode/1f1f2-1f1fd.png?v8", + "microbe": "unicode/1f9a0.png?v8", + "micronesia": "unicode/1f1eb-1f1f2.png?v8", + "microphone": "unicode/1f3a4.png?v8", + "microscope": "unicode/1f52c.png?v8", + "middle_finger": "unicode/1f595.png?v8", + "military_helmet": "unicode/1fa96.png?v8", + "milk_glass": "unicode/1f95b.png?v8", + "milky_way": "unicode/1f30c.png?v8", + "minibus": "unicode/1f690.png?v8", + "minidisc": "unicode/1f4bd.png?v8", + "mirror": "unicode/1fa9e.png?v8", + "mobile_phone_off": "unicode/1f4f4.png?v8", + "moldova": "unicode/1f1f2-1f1e9.png?v8", + "monaco": "unicode/1f1f2-1f1e8.png?v8", + "money_mouth_face": "unicode/1f911.png?v8", + "money_with_wings": "unicode/1f4b8.png?v8", + "moneybag": "unicode/1f4b0.png?v8", + "mongolia": "unicode/1f1f2-1f1f3.png?v8", + "monkey": "unicode/1f412.png?v8", + "monkey_face": "unicode/1f435.png?v8", + "monocle_face": "unicode/1f9d0.png?v8", + "monorail": "unicode/1f69d.png?v8", + "montenegro": "unicode/1f1f2-1f1ea.png?v8", + "montserrat": "unicode/1f1f2-1f1f8.png?v8", + "moon": "unicode/1f314.png?v8", + "moon_cake": "unicode/1f96e.png?v8", + "morocco": "unicode/1f1f2-1f1e6.png?v8", + "mortar_board": "unicode/1f393.png?v8", + "mosque": "unicode/1f54c.png?v8", + "mosquito": "unicode/1f99f.png?v8", + "motor_boat": "unicode/1f6e5.png?v8", + "motor_scooter": "unicode/1f6f5.png?v8", + "motorcycle": "unicode/1f3cd.png?v8", + "motorized_wheelchair": "unicode/1f9bc.png?v8", + "motorway": "unicode/1f6e3.png?v8", + "mount_fuji": "unicode/1f5fb.png?v8", + "mountain": "unicode/26f0.png?v8", + "mountain_bicyclist": "unicode/1f6b5.png?v8", + "mountain_biking_man": "unicode/1f6b5-2642.png?v8", + "mountain_biking_woman": "unicode/1f6b5-2640.png?v8", + "mountain_cableway": "unicode/1f6a0.png?v8", + "mountain_railway": "unicode/1f69e.png?v8", + "mountain_snow": "unicode/1f3d4.png?v8", + "mouse": "unicode/1f42d.png?v8", + "mouse2": "unicode/1f401.png?v8", + "mouse_trap": "unicode/1faa4.png?v8", + "movie_camera": "unicode/1f3a5.png?v8", + "moyai": "unicode/1f5ff.png?v8", + "mozambique": "unicode/1f1f2-1f1ff.png?v8", + "mrs_claus": "unicode/1f936.png?v8", + "muscle": "unicode/1f4aa.png?v8", + "mushroom": "unicode/1f344.png?v8", + "musical_keyboard": "unicode/1f3b9.png?v8", + "musical_note": "unicode/1f3b5.png?v8", + "musical_score": "unicode/1f3bc.png?v8", + "mute": "unicode/1f507.png?v8", + "mx_claus": "unicode/1f9d1-1f384.png?v8", + "myanmar": "unicode/1f1f2-1f1f2.png?v8", + "nail_care": "unicode/1f485.png?v8", + "name_badge": "unicode/1f4db.png?v8", + "namibia": "unicode/1f1f3-1f1e6.png?v8", + "national_park": "unicode/1f3de.png?v8", + "nauru": "unicode/1f1f3-1f1f7.png?v8", + "nauseated_face": "unicode/1f922.png?v8", + "nazar_amulet": "unicode/1f9ff.png?v8", + "neckbeard": "neckbeard.png?v8", + "necktie": "unicode/1f454.png?v8", + "negative_squared_cross_mark": "unicode/274e.png?v8", + "nepal": "unicode/1f1f3-1f1f5.png?v8", + "nerd_face": "unicode/1f913.png?v8", + "nesting_dolls": "unicode/1fa86.png?v8", + "netherlands": "unicode/1f1f3-1f1f1.png?v8", + "neutral_face": "unicode/1f610.png?v8", + "new": "unicode/1f195.png?v8", + "new_caledonia": "unicode/1f1f3-1f1e8.png?v8", + "new_moon": "unicode/1f311.png?v8", + "new_moon_with_face": "unicode/1f31a.png?v8", + "new_zealand": "unicode/1f1f3-1f1ff.png?v8", + "newspaper": "unicode/1f4f0.png?v8", + "newspaper_roll": "unicode/1f5de.png?v8", + "next_track_button": "unicode/23ed.png?v8", + "ng": "unicode/1f196.png?v8", + "ng_man": "unicode/1f645-2642.png?v8", + "ng_woman": "unicode/1f645-2640.png?v8", + "nicaragua": "unicode/1f1f3-1f1ee.png?v8", + "niger": "unicode/1f1f3-1f1ea.png?v8", + "nigeria": "unicode/1f1f3-1f1ec.png?v8", + "night_with_stars": "unicode/1f303.png?v8", + "nine": "unicode/0039-20e3.png?v8", + "ninja": "unicode/1f977.png?v8", + "niue": "unicode/1f1f3-1f1fa.png?v8", + "no_bell": "unicode/1f515.png?v8", + "no_bicycles": "unicode/1f6b3.png?v8", + "no_entry": "unicode/26d4.png?v8", + "no_entry_sign": "unicode/1f6ab.png?v8", + "no_good": "unicode/1f645.png?v8", + "no_good_man": "unicode/1f645-2642.png?v8", + "no_good_woman": "unicode/1f645-2640.png?v8", + "no_mobile_phones": "unicode/1f4f5.png?v8", + "no_mouth": "unicode/1f636.png?v8", + "no_pedestrians": "unicode/1f6b7.png?v8", + "no_smoking": "unicode/1f6ad.png?v8", + "non-potable_water": "unicode/1f6b1.png?v8", + "norfolk_island": "unicode/1f1f3-1f1eb.png?v8", + "north_korea": "unicode/1f1f0-1f1f5.png?v8", + "northern_mariana_islands": "unicode/1f1f2-1f1f5.png?v8", + "norway": "unicode/1f1f3-1f1f4.png?v8", + "nose": "unicode/1f443.png?v8", + "notebook": "unicode/1f4d3.png?v8", + "notebook_with_decorative_cover": "unicode/1f4d4.png?v8", + "notes": "unicode/1f3b6.png?v8", + "nut_and_bolt": "unicode/1f529.png?v8", + "o": "unicode/2b55.png?v8", + "o2": "unicode/1f17e.png?v8", + "ocean": "unicode/1f30a.png?v8", + "octocat": "octocat.png?v8", + "octopus": "unicode/1f419.png?v8", + "oden": "unicode/1f362.png?v8", + "office": "unicode/1f3e2.png?v8", + "office_worker": "unicode/1f9d1-1f4bc.png?v8", + "oil_drum": "unicode/1f6e2.png?v8", + "ok": "unicode/1f197.png?v8", + "ok_hand": "unicode/1f44c.png?v8", + "ok_man": "unicode/1f646-2642.png?v8", + "ok_person": "unicode/1f646.png?v8", + "ok_woman": "unicode/1f646-2640.png?v8", + "old_key": "unicode/1f5dd.png?v8", + "older_adult": "unicode/1f9d3.png?v8", + "older_man": "unicode/1f474.png?v8", + "older_woman": "unicode/1f475.png?v8", + "olive": "unicode/1fad2.png?v8", + "om": "unicode/1f549.png?v8", + "oman": "unicode/1f1f4-1f1f2.png?v8", + "on": "unicode/1f51b.png?v8", + "oncoming_automobile": "unicode/1f698.png?v8", + "oncoming_bus": "unicode/1f68d.png?v8", + "oncoming_police_car": "unicode/1f694.png?v8", + "oncoming_taxi": "unicode/1f696.png?v8", + "one": "unicode/0031-20e3.png?v8", + "one_piece_swimsuit": "unicode/1fa71.png?v8", + "onion": "unicode/1f9c5.png?v8", + "open_book": "unicode/1f4d6.png?v8", + "open_file_folder": "unicode/1f4c2.png?v8", + "open_hands": "unicode/1f450.png?v8", + "open_mouth": "unicode/1f62e.png?v8", + "open_umbrella": "unicode/2602.png?v8", + "ophiuchus": "unicode/26ce.png?v8", + "orange": "unicode/1f34a.png?v8", + "orange_book": "unicode/1f4d9.png?v8", + "orange_circle": "unicode/1f7e0.png?v8", + "orange_heart": "unicode/1f9e1.png?v8", + "orange_square": "unicode/1f7e7.png?v8", + "orangutan": "unicode/1f9a7.png?v8", + "orthodox_cross": "unicode/2626.png?v8", + "otter": "unicode/1f9a6.png?v8", + "outbox_tray": "unicode/1f4e4.png?v8", + "owl": "unicode/1f989.png?v8", + "ox": "unicode/1f402.png?v8", + "oyster": "unicode/1f9aa.png?v8", + "package": "unicode/1f4e6.png?v8", + "page_facing_up": "unicode/1f4c4.png?v8", + "page_with_curl": "unicode/1f4c3.png?v8", + "pager": "unicode/1f4df.png?v8", + "paintbrush": "unicode/1f58c.png?v8", + "pakistan": "unicode/1f1f5-1f1f0.png?v8", + "palau": "unicode/1f1f5-1f1fc.png?v8", + "palestinian_territories": "unicode/1f1f5-1f1f8.png?v8", + "palm_tree": "unicode/1f334.png?v8", + "palms_up_together": "unicode/1f932.png?v8", + "panama": "unicode/1f1f5-1f1e6.png?v8", + "pancakes": "unicode/1f95e.png?v8", + "panda_face": "unicode/1f43c.png?v8", + "paperclip": "unicode/1f4ce.png?v8", + "paperclips": "unicode/1f587.png?v8", + "papua_new_guinea": "unicode/1f1f5-1f1ec.png?v8", + "parachute": "unicode/1fa82.png?v8", + "paraguay": "unicode/1f1f5-1f1fe.png?v8", + "parasol_on_ground": "unicode/26f1.png?v8", + "parking": "unicode/1f17f.png?v8", + "parrot": "unicode/1f99c.png?v8", + "part_alternation_mark": "unicode/303d.png?v8", + "partly_sunny": "unicode/26c5.png?v8", + "partying_face": "unicode/1f973.png?v8", + "passenger_ship": "unicode/1f6f3.png?v8", + "passport_control": "unicode/1f6c2.png?v8", + "pause_button": "unicode/23f8.png?v8", + "paw_prints": "unicode/1f43e.png?v8", + "peace_symbol": "unicode/262e.png?v8", + "peach": "unicode/1f351.png?v8", + "peacock": "unicode/1f99a.png?v8", + "peanuts": "unicode/1f95c.png?v8", + "pear": "unicode/1f350.png?v8", + "pen": "unicode/1f58a.png?v8", + "pencil": "unicode/1f4dd.png?v8", + "pencil2": "unicode/270f.png?v8", + "penguin": "unicode/1f427.png?v8", + "pensive": "unicode/1f614.png?v8", + "people_holding_hands": "unicode/1f9d1-1f91d-1f9d1.png?v8", + "people_hugging": "unicode/1fac2.png?v8", + "performing_arts": "unicode/1f3ad.png?v8", + "persevere": "unicode/1f623.png?v8", + "person_bald": "unicode/1f9d1-1f9b2.png?v8", + "person_curly_hair": "unicode/1f9d1-1f9b1.png?v8", + "person_feeding_baby": "unicode/1f9d1-1f37c.png?v8", + "person_fencing": "unicode/1f93a.png?v8", + "person_in_manual_wheelchair": "unicode/1f9d1-1f9bd.png?v8", + "person_in_motorized_wheelchair": "unicode/1f9d1-1f9bc.png?v8", + "person_in_tuxedo": "unicode/1f935.png?v8", + "person_red_hair": "unicode/1f9d1-1f9b0.png?v8", + "person_white_hair": "unicode/1f9d1-1f9b3.png?v8", + "person_with_probing_cane": "unicode/1f9d1-1f9af.png?v8", + "person_with_turban": "unicode/1f473.png?v8", + "person_with_veil": "unicode/1f470.png?v8", + "peru": "unicode/1f1f5-1f1ea.png?v8", + "petri_dish": "unicode/1f9eb.png?v8", + "philippines": "unicode/1f1f5-1f1ed.png?v8", + "phone": "unicode/260e.png?v8", + "pick": "unicode/26cf.png?v8", + "pickup_truck": "unicode/1f6fb.png?v8", + "pie": "unicode/1f967.png?v8", + "pig": "unicode/1f437.png?v8", + "pig2": "unicode/1f416.png?v8", + "pig_nose": "unicode/1f43d.png?v8", + "pill": "unicode/1f48a.png?v8", + "pilot": "unicode/1f9d1-2708.png?v8", + "pinata": "unicode/1fa85.png?v8", + "pinched_fingers": "unicode/1f90c.png?v8", + "pinching_hand": "unicode/1f90f.png?v8", + "pineapple": "unicode/1f34d.png?v8", + "ping_pong": "unicode/1f3d3.png?v8", + "pirate_flag": "unicode/1f3f4-2620.png?v8", + "pisces": "unicode/2653.png?v8", + "pitcairn_islands": "unicode/1f1f5-1f1f3.png?v8", + "pizza": "unicode/1f355.png?v8", + "placard": "unicode/1faa7.png?v8", + "place_of_worship": "unicode/1f6d0.png?v8", + "plate_with_cutlery": "unicode/1f37d.png?v8", + "play_or_pause_button": "unicode/23ef.png?v8", + "pleading_face": "unicode/1f97a.png?v8", + "plunger": "unicode/1faa0.png?v8", + "point_down": "unicode/1f447.png?v8", + "point_left": "unicode/1f448.png?v8", + "point_right": "unicode/1f449.png?v8", + "point_up": "unicode/261d.png?v8", + "point_up_2": "unicode/1f446.png?v8", + "poland": "unicode/1f1f5-1f1f1.png?v8", + "polar_bear": "unicode/1f43b-2744.png?v8", + "police_car": "unicode/1f693.png?v8", + "police_officer": "unicode/1f46e.png?v8", + "policeman": "unicode/1f46e-2642.png?v8", + "policewoman": "unicode/1f46e-2640.png?v8", + "poodle": "unicode/1f429.png?v8", + "poop": "unicode/1f4a9.png?v8", + "popcorn": "unicode/1f37f.png?v8", + "portugal": "unicode/1f1f5-1f1f9.png?v8", + "post_office": "unicode/1f3e3.png?v8", + "postal_horn": "unicode/1f4ef.png?v8", + "postbox": "unicode/1f4ee.png?v8", + "potable_water": "unicode/1f6b0.png?v8", + "potato": "unicode/1f954.png?v8", + "potted_plant": "unicode/1fab4.png?v8", + "pouch": "unicode/1f45d.png?v8", + "poultry_leg": "unicode/1f357.png?v8", + "pound": "unicode/1f4b7.png?v8", + "pout": "unicode/1f621.png?v8", + "pouting_cat": "unicode/1f63e.png?v8", + "pouting_face": "unicode/1f64e.png?v8", + "pouting_man": "unicode/1f64e-2642.png?v8", + "pouting_woman": "unicode/1f64e-2640.png?v8", + "pray": "unicode/1f64f.png?v8", + "prayer_beads": "unicode/1f4ff.png?v8", + "pregnant_woman": "unicode/1f930.png?v8", + "pretzel": "unicode/1f968.png?v8", + "previous_track_button": "unicode/23ee.png?v8", + "prince": "unicode/1f934.png?v8", + "princess": "unicode/1f478.png?v8", + "printer": "unicode/1f5a8.png?v8", + "probing_cane": "unicode/1f9af.png?v8", + "puerto_rico": "unicode/1f1f5-1f1f7.png?v8", + "punch": "unicode/1f44a.png?v8", + "purple_circle": "unicode/1f7e3.png?v8", + "purple_heart": "unicode/1f49c.png?v8", + "purple_square": "unicode/1f7ea.png?v8", + "purse": "unicode/1f45b.png?v8", + "pushpin": "unicode/1f4cc.png?v8", + "put_litter_in_its_place": "unicode/1f6ae.png?v8", + "qatar": "unicode/1f1f6-1f1e6.png?v8", + "question": "unicode/2753.png?v8", + "rabbit": "unicode/1f430.png?v8", + "rabbit2": "unicode/1f407.png?v8", + "raccoon": "unicode/1f99d.png?v8", + "racehorse": "unicode/1f40e.png?v8", + "racing_car": "unicode/1f3ce.png?v8", + "radio": "unicode/1f4fb.png?v8", + "radio_button": "unicode/1f518.png?v8", + "radioactive": "unicode/2622.png?v8", + "rage": "unicode/1f621.png?v8", + "rage1": "rage1.png?v8", + "rage2": "rage2.png?v8", + "rage3": "rage3.png?v8", + "rage4": "rage4.png?v8", + "railway_car": "unicode/1f683.png?v8", + "railway_track": "unicode/1f6e4.png?v8", + "rainbow": "unicode/1f308.png?v8", + "rainbow_flag": "unicode/1f3f3-1f308.png?v8", + "raised_back_of_hand": "unicode/1f91a.png?v8", + "raised_eyebrow": "unicode/1f928.png?v8", + "raised_hand": "unicode/270b.png?v8", + "raised_hand_with_fingers_splayed": "unicode/1f590.png?v8", + "raised_hands": "unicode/1f64c.png?v8", + "raising_hand": "unicode/1f64b.png?v8", + "raising_hand_man": "unicode/1f64b-2642.png?v8", + "raising_hand_woman": "unicode/1f64b-2640.png?v8", + "ram": "unicode/1f40f.png?v8", + "ramen": "unicode/1f35c.png?v8", + "rat": "unicode/1f400.png?v8", + "razor": "unicode/1fa92.png?v8", + "receipt": "unicode/1f9fe.png?v8", + "record_button": "unicode/23fa.png?v8", + "recycle": "unicode/267b.png?v8", + "red_car": "unicode/1f697.png?v8", + "red_circle": "unicode/1f534.png?v8", + "red_envelope": "unicode/1f9e7.png?v8", + "red_haired_man": "unicode/1f468-1f9b0.png?v8", + "red_haired_woman": "unicode/1f469-1f9b0.png?v8", + "red_square": "unicode/1f7e5.png?v8", + "registered": "unicode/00ae.png?v8", + "relaxed": "unicode/263a.png?v8", + "relieved": "unicode/1f60c.png?v8", + "reminder_ribbon": "unicode/1f397.png?v8", + "repeat": "unicode/1f501.png?v8", + "repeat_one": "unicode/1f502.png?v8", + "rescue_worker_helmet": "unicode/26d1.png?v8", + "restroom": "unicode/1f6bb.png?v8", + "reunion": "unicode/1f1f7-1f1ea.png?v8", + "revolving_hearts": "unicode/1f49e.png?v8", + "rewind": "unicode/23ea.png?v8", + "rhinoceros": "unicode/1f98f.png?v8", + "ribbon": "unicode/1f380.png?v8", + "rice": "unicode/1f35a.png?v8", + "rice_ball": "unicode/1f359.png?v8", + "rice_cracker": "unicode/1f358.png?v8", + "rice_scene": "unicode/1f391.png?v8", + "right_anger_bubble": "unicode/1f5ef.png?v8", + "ring": "unicode/1f48d.png?v8", + "ringed_planet": "unicode/1fa90.png?v8", + "robot": "unicode/1f916.png?v8", + "rock": "unicode/1faa8.png?v8", + "rocket": "unicode/1f680.png?v8", + "rofl": "unicode/1f923.png?v8", + "roll_eyes": "unicode/1f644.png?v8", + "roll_of_paper": "unicode/1f9fb.png?v8", + "roller_coaster": "unicode/1f3a2.png?v8", + "roller_skate": "unicode/1f6fc.png?v8", + "romania": "unicode/1f1f7-1f1f4.png?v8", + "rooster": "unicode/1f413.png?v8", + "rose": "unicode/1f339.png?v8", + "rosette": "unicode/1f3f5.png?v8", + "rotating_light": "unicode/1f6a8.png?v8", + "round_pushpin": "unicode/1f4cd.png?v8", + "rowboat": "unicode/1f6a3.png?v8", + "rowing_man": "unicode/1f6a3-2642.png?v8", + "rowing_woman": "unicode/1f6a3-2640.png?v8", + "ru": "unicode/1f1f7-1f1fa.png?v8", + "rugby_football": "unicode/1f3c9.png?v8", + "runner": "unicode/1f3c3.png?v8", + "running": "unicode/1f3c3.png?v8", + "running_man": "unicode/1f3c3-2642.png?v8", + "running_shirt_with_sash": "unicode/1f3bd.png?v8", + "running_woman": "unicode/1f3c3-2640.png?v8", + "rwanda": "unicode/1f1f7-1f1fc.png?v8", + "sa": "unicode/1f202.png?v8", + "safety_pin": "unicode/1f9f7.png?v8", + "safety_vest": "unicode/1f9ba.png?v8", + "sagittarius": "unicode/2650.png?v8", + "sailboat": "unicode/26f5.png?v8", + "sake": "unicode/1f376.png?v8", + "salt": "unicode/1f9c2.png?v8", + "samoa": "unicode/1f1fc-1f1f8.png?v8", + "san_marino": "unicode/1f1f8-1f1f2.png?v8", + "sandal": "unicode/1f461.png?v8", + "sandwich": "unicode/1f96a.png?v8", + "santa": "unicode/1f385.png?v8", + "sao_tome_principe": "unicode/1f1f8-1f1f9.png?v8", + "sari": "unicode/1f97b.png?v8", + "sassy_man": "unicode/1f481-2642.png?v8", + "sassy_woman": "unicode/1f481-2640.png?v8", + "satellite": "unicode/1f4e1.png?v8", + "satisfied": "unicode/1f606.png?v8", + "saudi_arabia": "unicode/1f1f8-1f1e6.png?v8", + "sauna_man": "unicode/1f9d6-2642.png?v8", + "sauna_person": "unicode/1f9d6.png?v8", + "sauna_woman": "unicode/1f9d6-2640.png?v8", + "sauropod": "unicode/1f995.png?v8", + "saxophone": "unicode/1f3b7.png?v8", + "scarf": "unicode/1f9e3.png?v8", + "school": "unicode/1f3eb.png?v8", + "school_satchel": "unicode/1f392.png?v8", + "scientist": "unicode/1f9d1-1f52c.png?v8", + "scissors": "unicode/2702.png?v8", + "scorpion": "unicode/1f982.png?v8", + "scorpius": "unicode/264f.png?v8", + "scotland": "unicode/1f3f4-e0067-e0062-e0073-e0063-e0074-e007f.png?v8", + "scream": "unicode/1f631.png?v8", + "scream_cat": "unicode/1f640.png?v8", + "screwdriver": "unicode/1fa9b.png?v8", + "scroll": "unicode/1f4dc.png?v8", + "seal": "unicode/1f9ad.png?v8", + "seat": "unicode/1f4ba.png?v8", + "secret": "unicode/3299.png?v8", + "see_no_evil": "unicode/1f648.png?v8", + "seedling": "unicode/1f331.png?v8", + "selfie": "unicode/1f933.png?v8", + "senegal": "unicode/1f1f8-1f1f3.png?v8", + "serbia": "unicode/1f1f7-1f1f8.png?v8", + "service_dog": "unicode/1f415-1f9ba.png?v8", + "seven": "unicode/0037-20e3.png?v8", + "sewing_needle": "unicode/1faa1.png?v8", + "seychelles": "unicode/1f1f8-1f1e8.png?v8", + "shallow_pan_of_food": "unicode/1f958.png?v8", + "shamrock": "unicode/2618.png?v8", + "shark": "unicode/1f988.png?v8", + "shaved_ice": "unicode/1f367.png?v8", + "sheep": "unicode/1f411.png?v8", + "shell": "unicode/1f41a.png?v8", + "shield": "unicode/1f6e1.png?v8", + "shinto_shrine": "unicode/26e9.png?v8", + "ship": "unicode/1f6a2.png?v8", + "shipit": "shipit.png?v8", + "shirt": "unicode/1f455.png?v8", + "shit": "unicode/1f4a9.png?v8", + "shoe": "unicode/1f45e.png?v8", + "shopping": "unicode/1f6cd.png?v8", + "shopping_cart": "unicode/1f6d2.png?v8", + "shorts": "unicode/1fa73.png?v8", + "shower": "unicode/1f6bf.png?v8", + "shrimp": "unicode/1f990.png?v8", + "shrug": "unicode/1f937.png?v8", + "shushing_face": "unicode/1f92b.png?v8", + "sierra_leone": "unicode/1f1f8-1f1f1.png?v8", + "signal_strength": "unicode/1f4f6.png?v8", + "singapore": "unicode/1f1f8-1f1ec.png?v8", + "singer": "unicode/1f9d1-1f3a4.png?v8", + "sint_maarten": "unicode/1f1f8-1f1fd.png?v8", + "six": "unicode/0036-20e3.png?v8", + "six_pointed_star": "unicode/1f52f.png?v8", + "skateboard": "unicode/1f6f9.png?v8", + "ski": "unicode/1f3bf.png?v8", + "skier": "unicode/26f7.png?v8", + "skull": "unicode/1f480.png?v8", + "skull_and_crossbones": "unicode/2620.png?v8", + "skunk": "unicode/1f9a8.png?v8", + "sled": "unicode/1f6f7.png?v8", + "sleeping": "unicode/1f634.png?v8", + "sleeping_bed": "unicode/1f6cc.png?v8", + "sleepy": "unicode/1f62a.png?v8", + "slightly_frowning_face": "unicode/1f641.png?v8", + "slightly_smiling_face": "unicode/1f642.png?v8", + "slot_machine": "unicode/1f3b0.png?v8", + "sloth": "unicode/1f9a5.png?v8", + "slovakia": "unicode/1f1f8-1f1f0.png?v8", + "slovenia": "unicode/1f1f8-1f1ee.png?v8", + "small_airplane": "unicode/1f6e9.png?v8", + "small_blue_diamond": "unicode/1f539.png?v8", + "small_orange_diamond": "unicode/1f538.png?v8", + "small_red_triangle": "unicode/1f53a.png?v8", + "small_red_triangle_down": "unicode/1f53b.png?v8", + "smile": "unicode/1f604.png?v8", + "smile_cat": "unicode/1f638.png?v8", + "smiley": "unicode/1f603.png?v8", + "smiley_cat": "unicode/1f63a.png?v8", + "smiling_face_with_tear": "unicode/1f972.png?v8", + "smiling_face_with_three_hearts": "unicode/1f970.png?v8", + "smiling_imp": "unicode/1f608.png?v8", + "smirk": "unicode/1f60f.png?v8", + "smirk_cat": "unicode/1f63c.png?v8", + "smoking": "unicode/1f6ac.png?v8", + "snail": "unicode/1f40c.png?v8", + "snake": "unicode/1f40d.png?v8", + "sneezing_face": "unicode/1f927.png?v8", + "snowboarder": "unicode/1f3c2.png?v8", + "snowflake": "unicode/2744.png?v8", + "snowman": "unicode/26c4.png?v8", + "snowman_with_snow": "unicode/2603.png?v8", + "soap": "unicode/1f9fc.png?v8", + "sob": "unicode/1f62d.png?v8", + "soccer": "unicode/26bd.png?v8", + "socks": "unicode/1f9e6.png?v8", + "softball": "unicode/1f94e.png?v8", + "solomon_islands": "unicode/1f1f8-1f1e7.png?v8", + "somalia": "unicode/1f1f8-1f1f4.png?v8", + "soon": "unicode/1f51c.png?v8", + "sos": "unicode/1f198.png?v8", + "sound": "unicode/1f509.png?v8", + "south_africa": "unicode/1f1ff-1f1e6.png?v8", + "south_georgia_south_sandwich_islands": "unicode/1f1ec-1f1f8.png?v8", + "south_sudan": "unicode/1f1f8-1f1f8.png?v8", + "space_invader": "unicode/1f47e.png?v8", + "spades": "unicode/2660.png?v8", + "spaghetti": "unicode/1f35d.png?v8", + "sparkle": "unicode/2747.png?v8", + "sparkler": "unicode/1f387.png?v8", + "sparkles": "unicode/2728.png?v8", + "sparkling_heart": "unicode/1f496.png?v8", + "speak_no_evil": "unicode/1f64a.png?v8", + "speaker": "unicode/1f508.png?v8", + "speaking_head": "unicode/1f5e3.png?v8", + "speech_balloon": "unicode/1f4ac.png?v8", + "speedboat": "unicode/1f6a4.png?v8", + "spider": "unicode/1f577.png?v8", + "spider_web": "unicode/1f578.png?v8", + "spiral_calendar": "unicode/1f5d3.png?v8", + "spiral_notepad": "unicode/1f5d2.png?v8", + "sponge": "unicode/1f9fd.png?v8", + "spoon": "unicode/1f944.png?v8", + "squid": "unicode/1f991.png?v8", + "sri_lanka": "unicode/1f1f1-1f1f0.png?v8", + "st_barthelemy": "unicode/1f1e7-1f1f1.png?v8", + "st_helena": "unicode/1f1f8-1f1ed.png?v8", + "st_kitts_nevis": "unicode/1f1f0-1f1f3.png?v8", + "st_lucia": "unicode/1f1f1-1f1e8.png?v8", + "st_martin": "unicode/1f1f2-1f1eb.png?v8", + "st_pierre_miquelon": "unicode/1f1f5-1f1f2.png?v8", + "st_vincent_grenadines": "unicode/1f1fb-1f1e8.png?v8", + "stadium": "unicode/1f3df.png?v8", + "standing_man": "unicode/1f9cd-2642.png?v8", + "standing_person": "unicode/1f9cd.png?v8", + "standing_woman": "unicode/1f9cd-2640.png?v8", + "star": "unicode/2b50.png?v8", + "star2": "unicode/1f31f.png?v8", + "star_and_crescent": "unicode/262a.png?v8", + "star_of_david": "unicode/2721.png?v8", + "star_struck": "unicode/1f929.png?v8", + "stars": "unicode/1f320.png?v8", + "station": "unicode/1f689.png?v8", + "statue_of_liberty": "unicode/1f5fd.png?v8", + "steam_locomotive": "unicode/1f682.png?v8", + "stethoscope": "unicode/1fa7a.png?v8", + "stew": "unicode/1f372.png?v8", + "stop_button": "unicode/23f9.png?v8", + "stop_sign": "unicode/1f6d1.png?v8", + "stopwatch": "unicode/23f1.png?v8", + "straight_ruler": "unicode/1f4cf.png?v8", + "strawberry": "unicode/1f353.png?v8", + "stuck_out_tongue": "unicode/1f61b.png?v8", + "stuck_out_tongue_closed_eyes": "unicode/1f61d.png?v8", + "stuck_out_tongue_winking_eye": "unicode/1f61c.png?v8", + "student": "unicode/1f9d1-1f393.png?v8", + "studio_microphone": "unicode/1f399.png?v8", + "stuffed_flatbread": "unicode/1f959.png?v8", + "sudan": "unicode/1f1f8-1f1e9.png?v8", + "sun_behind_large_cloud": "unicode/1f325.png?v8", + "sun_behind_rain_cloud": "unicode/1f326.png?v8", + "sun_behind_small_cloud": "unicode/1f324.png?v8", + "sun_with_face": "unicode/1f31e.png?v8", + "sunflower": "unicode/1f33b.png?v8", + "sunglasses": "unicode/1f60e.png?v8", + "sunny": "unicode/2600.png?v8", + "sunrise": "unicode/1f305.png?v8", + "sunrise_over_mountains": "unicode/1f304.png?v8", + "superhero": "unicode/1f9b8.png?v8", + "superhero_man": "unicode/1f9b8-2642.png?v8", + "superhero_woman": "unicode/1f9b8-2640.png?v8", + "supervillain": "unicode/1f9b9.png?v8", + "supervillain_man": "unicode/1f9b9-2642.png?v8", + "supervillain_woman": "unicode/1f9b9-2640.png?v8", + "surfer": "unicode/1f3c4.png?v8", + "surfing_man": "unicode/1f3c4-2642.png?v8", + "surfing_woman": "unicode/1f3c4-2640.png?v8", + "suriname": "unicode/1f1f8-1f1f7.png?v8", + "sushi": "unicode/1f363.png?v8", + "suspect": "suspect.png?v8", + "suspension_railway": "unicode/1f69f.png?v8", + "svalbard_jan_mayen": "unicode/1f1f8-1f1ef.png?v8", + "swan": "unicode/1f9a2.png?v8", + "swaziland": "unicode/1f1f8-1f1ff.png?v8", + "sweat": "unicode/1f613.png?v8", + "sweat_drops": "unicode/1f4a6.png?v8", + "sweat_smile": "unicode/1f605.png?v8", + "sweden": "unicode/1f1f8-1f1ea.png?v8", + "sweet_potato": "unicode/1f360.png?v8", + "swim_brief": "unicode/1fa72.png?v8", + "swimmer": "unicode/1f3ca.png?v8", + "swimming_man": "unicode/1f3ca-2642.png?v8", + "swimming_woman": "unicode/1f3ca-2640.png?v8", + "switzerland": "unicode/1f1e8-1f1ed.png?v8", + "symbols": "unicode/1f523.png?v8", + "synagogue": "unicode/1f54d.png?v8", + "syria": "unicode/1f1f8-1f1fe.png?v8", + "syringe": "unicode/1f489.png?v8", + "t-rex": "unicode/1f996.png?v8", + "taco": "unicode/1f32e.png?v8", + "tada": "unicode/1f389.png?v8", + "taiwan": "unicode/1f1f9-1f1fc.png?v8", + "tajikistan": "unicode/1f1f9-1f1ef.png?v8", + "takeout_box": "unicode/1f961.png?v8", + "tamale": "unicode/1fad4.png?v8", + "tanabata_tree": "unicode/1f38b.png?v8", + "tangerine": "unicode/1f34a.png?v8", + "tanzania": "unicode/1f1f9-1f1ff.png?v8", + "taurus": "unicode/2649.png?v8", + "taxi": "unicode/1f695.png?v8", + "tea": "unicode/1f375.png?v8", + "teacher": "unicode/1f9d1-1f3eb.png?v8", + "teapot": "unicode/1fad6.png?v8", + "technologist": "unicode/1f9d1-1f4bb.png?v8", + "teddy_bear": "unicode/1f9f8.png?v8", + "telephone": "unicode/260e.png?v8", + "telephone_receiver": "unicode/1f4de.png?v8", + "telescope": "unicode/1f52d.png?v8", + "tennis": "unicode/1f3be.png?v8", + "tent": "unicode/26fa.png?v8", + "test_tube": "unicode/1f9ea.png?v8", + "thailand": "unicode/1f1f9-1f1ed.png?v8", + "thermometer": "unicode/1f321.png?v8", + "thinking": "unicode/1f914.png?v8", + "thong_sandal": "unicode/1fa74.png?v8", + "thought_balloon": "unicode/1f4ad.png?v8", + "thread": "unicode/1f9f5.png?v8", + "three": "unicode/0033-20e3.png?v8", + "thumbsdown": "unicode/1f44e.png?v8", + "thumbsup": "unicode/1f44d.png?v8", + "ticket": "unicode/1f3ab.png?v8", + "tickets": "unicode/1f39f.png?v8", + "tiger": "unicode/1f42f.png?v8", + "tiger2": "unicode/1f405.png?v8", + "timer_clock": "unicode/23f2.png?v8", + "timor_leste": "unicode/1f1f9-1f1f1.png?v8", + "tipping_hand_man": "unicode/1f481-2642.png?v8", + "tipping_hand_person": "unicode/1f481.png?v8", + "tipping_hand_woman": "unicode/1f481-2640.png?v8", + "tired_face": "unicode/1f62b.png?v8", + "tm": "unicode/2122.png?v8", + "togo": "unicode/1f1f9-1f1ec.png?v8", + "toilet": "unicode/1f6bd.png?v8", + "tokelau": "unicode/1f1f9-1f1f0.png?v8", + "tokyo_tower": "unicode/1f5fc.png?v8", + "tomato": "unicode/1f345.png?v8", + "tonga": "unicode/1f1f9-1f1f4.png?v8", + "tongue": "unicode/1f445.png?v8", + "toolbox": "unicode/1f9f0.png?v8", + "tooth": "unicode/1f9b7.png?v8", + "toothbrush": "unicode/1faa5.png?v8", + "top": "unicode/1f51d.png?v8", + "tophat": "unicode/1f3a9.png?v8", + "tornado": "unicode/1f32a.png?v8", + "tr": "unicode/1f1f9-1f1f7.png?v8", + "trackball": "unicode/1f5b2.png?v8", + "tractor": "unicode/1f69c.png?v8", + "traffic_light": "unicode/1f6a5.png?v8", + "train": "unicode/1f68b.png?v8", + "train2": "unicode/1f686.png?v8", + "tram": "unicode/1f68a.png?v8", + "transgender_flag": "unicode/1f3f3-26a7.png?v8", + "transgender_symbol": "unicode/26a7.png?v8", + "triangular_flag_on_post": "unicode/1f6a9.png?v8", + "triangular_ruler": "unicode/1f4d0.png?v8", + "trident": "unicode/1f531.png?v8", + "trinidad_tobago": "unicode/1f1f9-1f1f9.png?v8", + "tristan_da_cunha": "unicode/1f1f9-1f1e6.png?v8", + "triumph": "unicode/1f624.png?v8", + "trolleybus": "unicode/1f68e.png?v8", + "trollface": "trollface.png?v8", + "trophy": "unicode/1f3c6.png?v8", + "tropical_drink": "unicode/1f379.png?v8", + "tropical_fish": "unicode/1f420.png?v8", + "truck": "unicode/1f69a.png?v8", + "trumpet": "unicode/1f3ba.png?v8", + "tshirt": "unicode/1f455.png?v8", + "tulip": "unicode/1f337.png?v8", + "tumbler_glass": "unicode/1f943.png?v8", + "tunisia": "unicode/1f1f9-1f1f3.png?v8", + "turkey": "unicode/1f983.png?v8", + "turkmenistan": "unicode/1f1f9-1f1f2.png?v8", + "turks_caicos_islands": "unicode/1f1f9-1f1e8.png?v8", + "turtle": "unicode/1f422.png?v8", + "tuvalu": "unicode/1f1f9-1f1fb.png?v8", + "tv": "unicode/1f4fa.png?v8", + "twisted_rightwards_arrows": "unicode/1f500.png?v8", + "two": "unicode/0032-20e3.png?v8", + "two_hearts": "unicode/1f495.png?v8", + "two_men_holding_hands": "unicode/1f46c.png?v8", + "two_women_holding_hands": "unicode/1f46d.png?v8", + "u5272": "unicode/1f239.png?v8", + "u5408": "unicode/1f234.png?v8", + "u55b6": "unicode/1f23a.png?v8", + "u6307": "unicode/1f22f.png?v8", + "u6708": "unicode/1f237.png?v8", + "u6709": "unicode/1f236.png?v8", + "u6e80": "unicode/1f235.png?v8", + "u7121": "unicode/1f21a.png?v8", + "u7533": "unicode/1f238.png?v8", + "u7981": "unicode/1f232.png?v8", + "u7a7a": "unicode/1f233.png?v8", + "uganda": "unicode/1f1fa-1f1ec.png?v8", + "uk": "unicode/1f1ec-1f1e7.png?v8", + "ukraine": "unicode/1f1fa-1f1e6.png?v8", + "umbrella": "unicode/2614.png?v8", + "unamused": "unicode/1f612.png?v8", + "underage": "unicode/1f51e.png?v8", + "unicorn": "unicode/1f984.png?v8", + "united_arab_emirates": "unicode/1f1e6-1f1ea.png?v8", + "united_nations": "unicode/1f1fa-1f1f3.png?v8", + "unlock": "unicode/1f513.png?v8", + "up": "unicode/1f199.png?v8", + "upside_down_face": "unicode/1f643.png?v8", + "uruguay": "unicode/1f1fa-1f1fe.png?v8", + "us": "unicode/1f1fa-1f1f8.png?v8", + "us_outlying_islands": "unicode/1f1fa-1f1f2.png?v8", + "us_virgin_islands": "unicode/1f1fb-1f1ee.png?v8", + "uzbekistan": "unicode/1f1fa-1f1ff.png?v8", + "v": "unicode/270c.png?v8", + "vampire": "unicode/1f9db.png?v8", + "vampire_man": "unicode/1f9db-2642.png?v8", + "vampire_woman": "unicode/1f9db-2640.png?v8", + "vanuatu": "unicode/1f1fb-1f1fa.png?v8", + "vatican_city": "unicode/1f1fb-1f1e6.png?v8", + "venezuela": "unicode/1f1fb-1f1ea.png?v8", + "vertical_traffic_light": "unicode/1f6a6.png?v8", + "vhs": "unicode/1f4fc.png?v8", + "vibration_mode": "unicode/1f4f3.png?v8", + "video_camera": "unicode/1f4f9.png?v8", + "video_game": "unicode/1f3ae.png?v8", + "vietnam": "unicode/1f1fb-1f1f3.png?v8", + "violin": "unicode/1f3bb.png?v8", + "virgo": "unicode/264d.png?v8", + "volcano": "unicode/1f30b.png?v8", + "volleyball": "unicode/1f3d0.png?v8", + "vomiting_face": "unicode/1f92e.png?v8", + "vs": "unicode/1f19a.png?v8", + "vulcan_salute": "unicode/1f596.png?v8", + "waffle": "unicode/1f9c7.png?v8", + "wales": "unicode/1f3f4-e0067-e0062-e0077-e006c-e0073-e007f.png?v8", + "walking": "unicode/1f6b6.png?v8", + "walking_man": "unicode/1f6b6-2642.png?v8", + "walking_woman": "unicode/1f6b6-2640.png?v8", + "wallis_futuna": "unicode/1f1fc-1f1eb.png?v8", + "waning_crescent_moon": "unicode/1f318.png?v8", + "waning_gibbous_moon": "unicode/1f316.png?v8", + "warning": "unicode/26a0.png?v8", + "wastebasket": "unicode/1f5d1.png?v8", + "watch": "unicode/231a.png?v8", + "water_buffalo": "unicode/1f403.png?v8", + "water_polo": "unicode/1f93d.png?v8", + "watermelon": "unicode/1f349.png?v8", + "wave": "unicode/1f44b.png?v8", + "wavy_dash": "unicode/3030.png?v8", + "waxing_crescent_moon": "unicode/1f312.png?v8", + "waxing_gibbous_moon": "unicode/1f314.png?v8", + "wc": "unicode/1f6be.png?v8", + "weary": "unicode/1f629.png?v8", + "wedding": "unicode/1f492.png?v8", + "weight_lifting": "unicode/1f3cb.png?v8", + "weight_lifting_man": "unicode/1f3cb-2642.png?v8", + "weight_lifting_woman": "unicode/1f3cb-2640.png?v8", + "western_sahara": "unicode/1f1ea-1f1ed.png?v8", + "whale": "unicode/1f433.png?v8", + "whale2": "unicode/1f40b.png?v8", + "wheel_of_dharma": "unicode/2638.png?v8", + "wheelchair": "unicode/267f.png?v8", + "white_check_mark": "unicode/2705.png?v8", + "white_circle": "unicode/26aa.png?v8", + "white_flag": "unicode/1f3f3.png?v8", + "white_flower": "unicode/1f4ae.png?v8", + "white_haired_man": "unicode/1f468-1f9b3.png?v8", + "white_haired_woman": "unicode/1f469-1f9b3.png?v8", + "white_heart": "unicode/1f90d.png?v8", + "white_large_square": "unicode/2b1c.png?v8", + "white_medium_small_square": "unicode/25fd.png?v8", + "white_medium_square": "unicode/25fb.png?v8", + "white_small_square": "unicode/25ab.png?v8", + "white_square_button": "unicode/1f533.png?v8", + "wilted_flower": "unicode/1f940.png?v8", + "wind_chime": "unicode/1f390.png?v8", + "wind_face": "unicode/1f32c.png?v8", + "window": "unicode/1fa9f.png?v8", + "wine_glass": "unicode/1f377.png?v8", + "wink": "unicode/1f609.png?v8", + "wolf": "unicode/1f43a.png?v8", + "woman": "unicode/1f469.png?v8", + "woman_artist": "unicode/1f469-1f3a8.png?v8", + "woman_astronaut": "unicode/1f469-1f680.png?v8", + "woman_beard": "unicode/1f9d4-2640.png?v8", + "woman_cartwheeling": "unicode/1f938-2640.png?v8", + "woman_cook": "unicode/1f469-1f373.png?v8", + "woman_dancing": "unicode/1f483.png?v8", + "woman_facepalming": "unicode/1f926-2640.png?v8", + "woman_factory_worker": "unicode/1f469-1f3ed.png?v8", + "woman_farmer": "unicode/1f469-1f33e.png?v8", + "woman_feeding_baby": "unicode/1f469-1f37c.png?v8", + "woman_firefighter": "unicode/1f469-1f692.png?v8", + "woman_health_worker": "unicode/1f469-2695.png?v8", + "woman_in_manual_wheelchair": "unicode/1f469-1f9bd.png?v8", + "woman_in_motorized_wheelchair": "unicode/1f469-1f9bc.png?v8", + "woman_in_tuxedo": "unicode/1f935-2640.png?v8", + "woman_judge": "unicode/1f469-2696.png?v8", + "woman_juggling": "unicode/1f939-2640.png?v8", + "woman_mechanic": "unicode/1f469-1f527.png?v8", + "woman_office_worker": "unicode/1f469-1f4bc.png?v8", + "woman_pilot": "unicode/1f469-2708.png?v8", + "woman_playing_handball": "unicode/1f93e-2640.png?v8", + "woman_playing_water_polo": "unicode/1f93d-2640.png?v8", + "woman_scientist": "unicode/1f469-1f52c.png?v8", + "woman_shrugging": "unicode/1f937-2640.png?v8", + "woman_singer": "unicode/1f469-1f3a4.png?v8", + "woman_student": "unicode/1f469-1f393.png?v8", + "woman_teacher": "unicode/1f469-1f3eb.png?v8", + "woman_technologist": "unicode/1f469-1f4bb.png?v8", + "woman_with_headscarf": "unicode/1f9d5.png?v8", + "woman_with_probing_cane": "unicode/1f469-1f9af.png?v8", + "woman_with_turban": "unicode/1f473-2640.png?v8", + "woman_with_veil": "unicode/1f470-2640.png?v8", + "womans_clothes": "unicode/1f45a.png?v8", + "womans_hat": "unicode/1f452.png?v8", + "women_wrestling": "unicode/1f93c-2640.png?v8", + "womens": "unicode/1f6ba.png?v8", + "wood": "unicode/1fab5.png?v8", + "woozy_face": "unicode/1f974.png?v8", + "world_map": "unicode/1f5fa.png?v8", + "worm": "unicode/1fab1.png?v8", + "worried": "unicode/1f61f.png?v8", + "wrench": "unicode/1f527.png?v8", + "wrestling": "unicode/1f93c.png?v8", + "writing_hand": "unicode/270d.png?v8", + "x": "unicode/274c.png?v8", + "yarn": "unicode/1f9f6.png?v8", + "yawning_face": "unicode/1f971.png?v8", + "yellow_circle": "unicode/1f7e1.png?v8", + "yellow_heart": "unicode/1f49b.png?v8", + "yellow_square": "unicode/1f7e8.png?v8", + "yemen": "unicode/1f1fe-1f1ea.png?v8", + "yen": "unicode/1f4b4.png?v8", + "yin_yang": "unicode/262f.png?v8", + "yo_yo": "unicode/1fa80.png?v8", + "yum": "unicode/1f60b.png?v8", + "zambia": "unicode/1f1ff-1f1f2.png?v8", + "zany_face": "unicode/1f92a.png?v8", + "zap": "unicode/26a1.png?v8", + "zebra": "unicode/1f993.png?v8", + "zero": "unicode/0030-20e3.png?v8", + "zimbabwe": "unicode/1f1ff-1f1fc.png?v8", + "zipper_mouth_face": "unicode/1f910.png?v8", + "zombie": "unicode/1f9df.png?v8", + "zombie_man": "unicode/1f9df-2642.png?v8", + "zombie_woman": "unicode/1f9df-2640.png?v8", + "zzz": "unicode/1f4a4.png?v8" + } + }; + + function replaceEmojiShorthand(m, $1, useNativeEmoji) { + var emojiMatch = emojiData.data[$1]; + + var result = m; + + if (emojiMatch) { + if (useNativeEmoji && /unicode/.test(emojiMatch)) { + var emojiUnicode = emojiMatch + .replace('unicode/', '') + .replace(/\.png.*/, '') + .split('-') + .map(function (u) { return ("&#x" + u + ";"); }) + // Separate multi-character emoji with zero width joiner sequence (ZWJ) + // Hat tip: https://about.gitlab.com/blog/2018/05/30/journey-in-native-unicode-emoji/#emoji-made-up-of-multiple-characters + .join('‍') + .concat('︎'); + result = "" + emojiUnicode + ""; + } else { + result = "\"""; + } + } + + return result; + } + + function emojify(text, useNativeEmoji) { + return ( + text + // Mark colons in tags + .replace( + /<(code|pre|script|template)[^>]*?>[\s\S]+?<\/(code|pre|script|template)>/g, + function (m) { return m.replace(/:/g, '__colon__'); } + ) + // Mark colons in comments + .replace(//g, function (m) { return m.replace(/:/g, '__colon__'); }) + // Mark colons in URIs + .replace(/([a-z]{2,}:)?\/\/[^\s'">)]+/gi, function (m) { return m.replace(/:/g, '__colon__'); } + ) + // Replace emoji shorthand codes + .replace(/:([a-z0-9_\-+]+?):/g, function (m, $1) { return replaceEmojiShorthand(m, $1, useNativeEmoji); } + ) + // Restore colons in tags and comments + .replace(/__colon__/g, ':') + ); + } + + /** + * Converts a colon formatted string to a object with properties. + * + * This is process a provided string and look for any tokens in the format + * of `:name[=value]` and then convert it to a object and return. + * An example of this is ':include :type=code :fragment=demo' is taken and + * then converted to: + * + * ``` + * { + * include: '', + * type: 'code', + * fragment: 'demo' + * } + * ``` + * + * @param {string} str The string to parse. + * + * @return {object} The original string and parsed object, { str, config }. + */ + function getAndRemoveConfig(str) { + if ( str === void 0 ) str = ''; + + var config = {}; + + if (str) { + str = str + .replace(/^('|")/, '') + .replace(/('|")$/, '') + .replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g, function (m, key, value) { + if (key.indexOf(':') === -1) { + config[key] = (value && value.replace(/"/g, '')) || true; + return ''; + } + + return m; + }) + .trim(); + } + + return { str: str, config: config }; + } + + /** + * Remove the tag from sidebar when the header with link, details see issue 1069 + * @param {string} str The string to deal with. + * + * @return {string} str The string after delete the element. + */ + function removeAtag(str) { + if ( str === void 0 ) str = ''; + + return str.replace(/(<\/?a.*?>)/gi, ''); + } + + var imageCompiler = function (ref) { + var renderer = ref.renderer; + var contentBase = ref.contentBase; + var router = ref.router; + + return (renderer.image = function (href, title, text) { + var url = href; + var attrs = []; + + var ref = getAndRemoveConfig(title); + var str = ref.str; + var config = ref.config; + title = str; + + if (config['no-zoom']) { + attrs.push('data-no-zoom'); + } + + if (title) { + attrs.push(("title=\"" + title + "\"")); + } + + if (config.size) { + var ref$1 = config.size.split('x'); + var width = ref$1[0]; + var height = ref$1[1]; + if (height) { + attrs.push(("width=\"" + width + "\" height=\"" + height + "\"")); + } else { + attrs.push(("width=\"" + width + "\"")); + } + } + + if (config.class) { + attrs.push(("class=\"" + (config.class) + "\"")); + } + + if (config.id) { + attrs.push(("id=\"" + (config.id) + "\"")); + } + + if (!isAbsolutePath(href)) { + url = getPath(contentBase, getParentPath(router.getCurrentPath()), href); + } + + if (attrs.length > 0) { + return ("\"""); + } + + return ("\"""); + }); + }; + + var prism = createCommonjsModule(function (module) { + /* ********************************************** + Begin prism-core.js + ********************************************** */ + + /// + + var _self = (typeof window !== 'undefined') + ? window // if in browser + : ( + (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) + ? self // if in worker + : {} // if in node js + ); + + /** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */ + var Prism = (function (_self) { + + // Private helper vars + var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i; + var uniqueId = 0; + + // The grammar object for plaintext + var plainTextGrammar = {}; + + + var _ = { + /** + * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the + * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load + * additional languages or plugins yourself. + * + * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. + * + * You obviously have to change this value before the automatic highlighting started. To do this, you can add an + * empty Prism object into the global scope before loading the Prism script like this: + * + * ```js + * window.Prism = window.Prism || {}; + * Prism.manual = true; + * // add a new + + + + \ No newline at end of file diff --git a/maybe_tampered/```JavaScript.txt b/maybe_tampered/```JavaScript.txt new file mode 100644 index 0000000..32c11b1 --- /dev/null +++ b/maybe_tampered/```JavaScript.txt @@ -0,0 +1,16 @@ +```JavaScript + +const settings = { +console: console, +that: this +} + +class InitLogs { + constructor() { + const inject = this.settings; + Object.assign(this, inject, Window); +this.inject = settings; +} + +} +``` \ No newline at end of file diff --git a/maybe_tampered/eventemitter3/README.md b/maybe_tampered/eventemitter3/README.md new file mode 100644 index 0000000..aba7e18 --- /dev/null +++ b/maybe_tampered/eventemitter3/README.md @@ -0,0 +1,94 @@ +# EventEmitter3 + +[![Version npm](https://img.shields.io/npm/v/eventemitter3.svg?style=flat-square)](https://www.npmjs.com/package/eventemitter3)[![Build Status](https://img.shields.io/travis/primus/eventemitter3/master.svg?style=flat-square)](https://travis-ci.org/primus/eventemitter3)[![Dependencies](https://img.shields.io/david/primus/eventemitter3.svg?style=flat-square)](https://david-dm.org/primus/eventemitter3)[![Coverage Status](https://img.shields.io/coveralls/primus/eventemitter3/master.svg?style=flat-square)](https://coveralls.io/r/primus/eventemitter3?branch=master)[![IRC channel](https://img.shields.io/badge/IRC-irc.freenode.net%23primus-00a8ff.svg?style=flat-square)](https://webchat.freenode.net/?channels=primus) + +[![Sauce Test Status](https://saucelabs.com/browser-matrix/eventemitter3.svg)](https://saucelabs.com/u/eventemitter3) + +EventEmitter3 is a high performance EventEmitter. It has been micro-optimized +for various of code paths making this, one of, if not the fastest EventEmitter +available for Node.js and browsers. The module is API compatible with the +EventEmitter that ships by default with Node.js but there are some slight +differences: + +- Domain support has been removed. +- We do not `throw` an error when you emit an `error` event and nobody is + listening. +- The `newListener` and `removeListener` events have been removed as they + are useful only in some uncommon use-cases. +- The `setMaxListeners`, `getMaxListeners`, `prependListener` and + `prependOnceListener` methods are not available. +- Support for custom context for events so there is no need to use `fn.bind`. +- The `removeListener` method removes all matching listeners, not only the + first. + +It's a drop in replacement for existing EventEmitters, but just faster. Free +performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3 +so it will work in the oldest browsers and node versions that you need to +support. + +## Installation + +```bash +$ npm install --save eventemitter3 +``` + +## CDN + +Recommended CDN: + +```text +https://unpkg.com/eventemitter3@latest/umd/eventemitter3.min.js +``` + +## Usage + +After installation the only thing you need to do is require the module: + +```js +var EventEmitter = require('eventemitter3'); +``` + +And you're ready to create your own EventEmitter instances. For the API +documentation, please follow the official Node.js documentation: + +http://nodejs.org/api/events.html + +### Contextual emits + +We've upgraded the API of the `EventEmitter.on`, `EventEmitter.once` and +`EventEmitter.removeListener` to accept an extra argument which is the `context` +or `this` value that should be set for the emitted events. This means you no +longer have the overhead of an event that required `fn.bind` in order to get a +custom `this` value. + +```js +var EE = new EventEmitter() + , context = { foo: 'bar' }; + +function emitted() { + console.log(this === context); // true +} + +EE.once('event-name', emitted, context); +EE.on('another-event', emitted, context); +EE.removeListener('another-event', emitted, context); +``` + +### Tests and benchmarks + +This module is well tested. You can run: + +- `npm test` to run the tests under Node.js. +- `npm run test-browser` to run the tests in real browsers via Sauce Labs. + +We also have a set of benchmarks to compare EventEmitter3 with some available +alternatives. To run the benchmarks run `npm run benchmark`. + +Tests and benchmarks are not included in the npm package. If you want to play +with them you have to clone the GitHub repository. +Note that you will have to run an additional `npm i` in the benchmarks folder +before `npm run benchmark`. + +## License + +[MIT](LICENSE) diff --git a/maybe_tampered/eventemitter3/index.js b/maybe_tampered/eventemitter3/index.js new file mode 100644 index 0000000..6ea485c --- /dev/null +++ b/maybe_tampered/eventemitter3/index.js @@ -0,0 +1,336 @@ +'use strict'; + +var has = Object.prototype.hasOwnProperty + , prefix = '~'; + +/** + * Constructor to create a storage for our `EE` objects. + * An `Events` instance is a plain object whose properties are event names. + * + * @constructor + * @private + */ +function Events() {} + +// +// We try to not inherit from `Object.prototype`. In some engines creating an +// instance in this way is faster than calling `Object.create(null)` directly. +// If `Object.create(null)` is not supported we prefix the event names with a +// character to make sure that the built-in object properties are not +// overridden or used as an attack vector. +// +if (Object.create) { + Events.prototype = Object.create(null); + + // + // This hack is needed because the `__proto__` property is still inherited in + // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. + // + if (!new Events().__proto__) prefix = false; +} + +/** + * Representation of a single event listener. + * + * @param {Function} fn The listener function. + * @param {*} context The context to invoke the listener with. + * @param {Boolean} [once=false] Specify if the listener is a one-time listener. + * @constructor + * @private + */ +function EE(fn, context, once) { + this.fn = fn; + this.context = context; + this.once = once || false; +} + +/** + * Add a listener for a given event. + * + * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} context The context to invoke the listener with. + * @param {Boolean} once Specify if the listener is a one-time listener. + * @returns {EventEmitter} + * @private + */ +function addListener(emitter, event, fn, context, once) { + if (typeof fn !== 'function') { + throw new TypeError('The listener must be a function'); + } + + var listener = new EE(fn, context || emitter, once) + , evt = prefix ? prefix + event : event; + + if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; + else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); + else emitter._events[evt] = [emitter._events[evt], listener]; + + return emitter; +} + +/** + * Clear event by name. + * + * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. + * @param {(String|Symbol)} evt The Event name. + * @private + */ +function clearEvent(emitter, evt) { + if (--emitter._eventsCount === 0) emitter._events = new Events(); + else delete emitter._events[evt]; +} + +/** + * Minimal `EventEmitter` interface that is molded against the Node.js + * `EventEmitter` interface. + * + * @constructor + * @public + */ +function EventEmitter() { + this._events = new Events(); + this._eventsCount = 0; +} + +/** + * Return an array listing the events for which the emitter has registered + * listeners. + * + * @returns {Array} + * @public + */ +EventEmitter.prototype.eventNames = function eventNames() { + var names = [] + , events + , name; + + if (this._eventsCount === 0) return names; + + for (name in (events = this._events)) { + if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); + } + + if (Object.getOwnPropertySymbols) { + return names.concat(Object.getOwnPropertySymbols(events)); + } + + return names; +}; + +/** + * Return the listeners registered for a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Array} The registered listeners. + * @public + */ +EventEmitter.prototype.listeners = function listeners(event) { + var evt = prefix ? prefix + event : event + , handlers = this._events[evt]; + + if (!handlers) return []; + if (handlers.fn) return [handlers.fn]; + + for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { + ee[i] = handlers[i].fn; + } + + return ee; +}; + +/** + * Return the number of listeners listening to a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Number} The number of listeners. + * @public + */ +EventEmitter.prototype.listenerCount = function listenerCount(event) { + var evt = prefix ? prefix + event : event + , listeners = this._events[evt]; + + if (!listeners) return 0; + if (listeners.fn) return 1; + return listeners.length; +}; + +/** + * Calls each of the listeners registered for a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Boolean} `true` if the event had listeners, else `false`. + * @public + */ +EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { + var evt = prefix ? prefix + event : event; + + if (!this._events[evt]) return false; + + var listeners = this._events[evt] + , len = arguments.length + , args + , i; + + if (listeners.fn) { + if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); + + switch (len) { + case 1: return listeners.fn.call(listeners.context), true; + case 2: return listeners.fn.call(listeners.context, a1), true; + case 3: return listeners.fn.call(listeners.context, a1, a2), true; + case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; + case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; + case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; + } + + for (i = 1, args = new Array(len -1); i < len; i++) { + args[i - 1] = arguments[i]; + } + + listeners.fn.apply(listeners.context, args); + } else { + var length = listeners.length + , j; + + for (i = 0; i < length; i++) { + if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); + + switch (len) { + case 1: listeners[i].fn.call(listeners[i].context); break; + case 2: listeners[i].fn.call(listeners[i].context, a1); break; + case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; + case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; + default: + if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { + args[j - 1] = arguments[j]; + } + + listeners[i].fn.apply(listeners[i].context, args); + } + } + } + + return true; +}; + +/** + * Add a listener for a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} [context=this] The context to invoke the listener with. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.on = function on(event, fn, context) { + return addListener(this, event, fn, context, false); +}; + +/** + * Add a one-time listener for a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} [context=this] The context to invoke the listener with. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.once = function once(event, fn, context) { + return addListener(this, event, fn, context, true); +}; + +/** + * Remove the listeners of a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn Only remove the listeners that match this function. + * @param {*} context Only remove the listeners that have this context. + * @param {Boolean} once Only remove one-time listeners. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { + var evt = prefix ? prefix + event : event; + + if (!this._events[evt]) return this; + if (!fn) { + clearEvent(this, evt); + return this; + } + + var listeners = this._events[evt]; + + if (listeners.fn) { + if ( + listeners.fn === fn && + (!once || listeners.once) && + (!context || listeners.context === context) + ) { + clearEvent(this, evt); + } + } else { + for (var i = 0, events = [], length = listeners.length; i < length; i++) { + if ( + listeners[i].fn !== fn || + (once && !listeners[i].once) || + (context && listeners[i].context !== context) + ) { + events.push(listeners[i]); + } + } + + // + // Reset the array, or remove it completely if we have no more listeners. + // + if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; + else clearEvent(this, evt); + } + + return this; +}; + +/** + * Remove all listeners, or those of the specified event. + * + * @param {(String|Symbol)} [event] The event name. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { + var evt; + + if (event) { + evt = prefix ? prefix + event : event; + if (this._events[evt]) clearEvent(this, evt); + } else { + this._events = new Events(); + this._eventsCount = 0; + } + + return this; +}; + +// +// Alias methods names because people roll like that. +// +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +// +// Expose the prefix. +// +EventEmitter.prefixed = prefix; + +// +// Allow `EventEmitter` to be imported as module namespace. +// +EventEmitter.EventEmitter = EventEmitter; + +// +// Expose the module. +// +if ('undefined' !== typeof module) { + module.exports = EventEmitter; +} diff --git a/maybe_tampered/eventemitter3/index.txt b/maybe_tampered/eventemitter3/index.txt new file mode 100644 index 0000000..118f68b --- /dev/null +++ b/maybe_tampered/eventemitter3/index.txt @@ -0,0 +1,134 @@ +/** + * Minimal `EventEmitter` interface that is molded against the Node.js + * `EventEmitter` interface. + */ +declare class EventEmitter< + EventTypes extends EventEmitter.ValidEventTypes = string | symbol, + Context extends any = any +> { + static prefixed: string | boolean; + + /** + * Return an array listing the events for which the emitter has registered + * listeners. + */ + eventNames(): Array>; + + /** + * Return the listeners registered for a given event. + */ + listeners>( + event: T + ): Array>; + + /** + * Return the number of listeners listening to a given event. + */ + listenerCount(event: EventEmitter.EventNames): number; + + /** + * Calls each of the listeners registered for a given event. + */ + emit>( + event: T, + ...args: EventEmitter.EventArgs + ): boolean; + + /** + * Add a listener for a given event. + */ + on>( + event: T, + fn: EventEmitter.EventListener, + context?: Context + ): this; + addListener>( + event: T, + fn: EventEmitter.EventListener, + context?: Context + ): this; + + /** + * Add a one-time listener for a given event. + */ + once>( + event: T, + fn: EventEmitter.EventListener, + context?: Context + ): this; + + /** + * Remove the listeners of a given event. + */ + removeListener>( + event: T, + fn?: EventEmitter.EventListener, + context?: Context, + once?: boolean + ): this; + off>( + event: T, + fn?: EventEmitter.EventListener, + context?: Context, + once?: boolean + ): this; + + /** + * Remove all listeners, or those of the specified event. + */ + removeAllListeners(event?: EventEmitter.EventNames): this; +} + +declare namespace EventEmitter { + export interface ListenerFn { + (...args: Args): void; + } + + export interface EventEmitterStatic { + new < + EventTypes extends ValidEventTypes = string | symbol, + Context = any + >(): EventEmitter; + } + + /** + * `object` should be in either of the following forms: + * ``` + * interface EventTypes { + * 'event-with-parameters': any[] + * 'event-with-example-handler': (...args: any[]) => void + * } + * ``` + */ + export type ValidEventTypes = string | symbol | object; + + export type EventNames = T extends string | symbol + ? T + : keyof T; + + export type ArgumentMap = { + [K in keyof T]: T[K] extends (...args: any[]) => void + ? Parameters + : T[K] extends any[] + ? T[K] + : any[]; + }; + + export type EventListener< + T extends ValidEventTypes, + K extends EventNames + > = T extends string | symbol + ? (...args: any[]) => void + : ( + ...args: ArgumentMap>[Extract] + ) => void; + + export type EventArgs< + T extends ValidEventTypes, + K extends EventNames + > = Parameters>; + + export const EventEmitter: EventEmitterStatic; +} + +export = EventEmitter; diff --git a/maybe_tampered/eventemitter3/package.json b/maybe_tampered/eventemitter3/package.json new file mode 100644 index 0000000..3c575b4 --- /dev/null +++ b/maybe_tampered/eventemitter3/package.json @@ -0,0 +1,56 @@ +{ + "name": "eventemitter3", + "version": "4.0.7", + "description": "EventEmitter3 focuses on performance while maintaining a Node.js AND browser compatible interface.", + "main": "index.js", + "typings": "index.d.ts", + "scripts": { + "browserify": "rm -rf umd && mkdir umd && browserify index.js -s EventEmitter3 -o umd/eventemitter3.js", + "minify": "uglifyjs umd/eventemitter3.js --source-map -cm -o umd/eventemitter3.min.js", + "benchmark": "find benchmarks/run -name '*.js' -exec benchmarks/start.sh {} \\;", + "test": "nyc --reporter=html --reporter=text mocha test/test.js", + "prepublishOnly": "npm run browserify && npm run minify", + "test-browser": "node test/browser.js" + }, + "files": [ + "index.js", + "index.d.ts", + "umd" + ], + "repository": { + "type": "git", + "url": "git://github.com/primus/eventemitter3.git" + }, + "keywords": [ + "EventEmitter", + "EventEmitter2", + "EventEmitter3", + "Events", + "addEventListener", + "addListener", + "emit", + "emits", + "emitter", + "event", + "once", + "pub/sub", + "publish", + "reactor", + "subscribe" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/primus/eventemitter3/issues" + }, + "devDependencies": { + "assume": "^2.2.0", + "browserify": "^16.5.0", + "mocha": "^8.0.1", + "nyc": "^15.1.0", + "pre-commit": "^1.2.0", + "sauce-browsers": "^2.0.0", + "sauce-test": "^1.3.3", + "uglify-js": "^3.9.0" + } +} diff --git a/maybe_tampered/eventemitter3/umd/eventemitter.js b/maybe_tampered/eventemitter3/umd/eventemitter.js new file mode 100644 index 0000000..2c5bed1 --- /dev/null +++ b/maybe_tampered/eventemitter3/umd/eventemitter.js @@ -0,0 +1,1268 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { + Certificate, + ECNamedCurves, + ECPublicKey, + RSAPublicKey, +} from "./vendor/pkijs.js"; +import { hexToIpv6Repr, b64ToPEM } from "./components/utils.mjs"; + +const getTimeZone = () => { + let timeZone = new Date().toString().match(/\(([A-Za-z\s].*)\)/); + if (timeZone === null) { + // America/Chicago + timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + } else if (timeZone.length > 1) { + timeZone = timeZone[1]; // Central Daylight Time + } else { + timeZone = "Local Time"; // not sure if this is right, but let's go with it for now + } + return timeZone; +}; + +const getPublicKeyInfo = x509 => { + let publicKey = x509.subjectPublicKeyInfo.parsedKey; + if (publicKey instanceof RSAPublicKey) { + let modulusJSON = publicKey.modulus.toJSON(); + let modulusHex = modulusJSON.valueBlock.valueHex; + return { + e: publicKey.publicExponent.toJSON().valueBlock.valueDec, + kty: "RSA", + n: hashify(modulusHex), + keysize: modulusHex.length * 4, // key size in bits + }; + } + if (publicKey instanceof ECPublicKey) { + let x = hashify(publicKey.x); + let y = hashify(publicKey.y); + let curve = ECNamedCurves.find(publicKey.namedCurve); + let keysize = curve ? curve.size * 8 : undefined; + return { + kty: "Elliptic Curve", + keysize, + x, // x coordinate + y, // y coordinate + xy: `04:${x}:${y}`, // 04 (uncompressed) public key + }; + } + return { kty: "Unknown" }; +}; + +const getX509Ext = (extensions, v) => { + for (var extension in extensions) { + if (extensions[extension].extnID === v) { + return extensions[extension].toJSON().parsedValue; + } + } + return undefined; +}; + +const getKeyUsages = (x509, criticalExtensions) => { + let keyUsages = { + critical: criticalExtensions.includes("2.5.29.15"), + purposes: [], + }; + + let keyUsagesExt = getX509Ext(x509.extensions, "2.5.29.15"); + if (keyUsagesExt !== undefined) { + // zero pad or truncate the hex value to 4 digits + let keyUsagesHex = keyUsagesExt.valueBlock.valueHex + .slice(0, 4) + .padEnd(4, "0"); + + let keyUsagesInt = parseInt(keyUsagesHex, 16); + + // Clear any unused bits (accounting for padding or truncation above). + let unusedBits = keyUsagesExt.valueBlock.unusedBits; + if (keyUsagesExt.valueBlock.valueHex.length == 2) { + unusedBits += 8; + } else if (keyUsagesExt.valueBlock.valueHex.length > 4) { + unusedBits = 0; + } + keyUsagesInt &= ~((1 << unusedBits) - 1); + + // iterate through the bit string + strings.keyUsages.forEach(usage => { + if (keyUsagesInt & 0x8000) { + keyUsages.purposes.push(usage); + } + + keyUsagesInt = keyUsagesInt << 1; + }); + } + + return keyUsages; +}; + +const parseSubsidiary = distinguishedNames => { + const subsidiary = { + cn: "", + dn: [], + entries: [], + }; + + distinguishedNames.forEach(dn => { + const distinguishedName = strings.names[dn.type]; + const value = dn.value.valueBlock.value; + + if (distinguishedName === undefined) { + subsidiary.dn.push(`OID.${dn.type}=${value}`); + subsidiary.entries.push([`OID.${dn.type}`, value]); + } else if (distinguishedName.short === undefined) { + subsidiary.dn.push(`OID.${dn.type}=${value}`); + subsidiary.entries.push([distinguishedName.long, value]); + } else { + subsidiary.dn.push(`${distinguishedName.short}=${value}`); + subsidiary.entries.push([distinguishedName.long, value]); + + // add the common name for tab display + if (distinguishedName.short === "cn") { + subsidiary.cn = value; + } + } + }); + + // turn path into a string + subsidiary.dn = subsidiary.dn.join(", "); + + return subsidiary; +}; + +const getSubjectAltNames = (x509, criticalExtensions) => { + let san = getX509Ext(x509.extensions, "2.5.29.17"); + if (san && san.hasOwnProperty("altNames")) { + san = Object.keys(san.altNames).map(index => { + const type = san.altNames[index].type; + + switch (type) { + case 4: // directory + return [ + strings.san[type], + parseSubsidiary(san.altNames[index].value.typesAndValues).dn, + ]; + case 7: { + // ip address + let address = san.altNames[index].value.valueBlock.valueHex; + + if (address.length === 8) { + // ipv4 + return [ + strings.san[type], + address + .match(/.{1,2}/g) + .map(x => parseInt(x, 16)) + .join("."), + ]; + } else if (address.length === 32) { + // ipv6 + return [strings.san[type], hexToIpv6Repr(address)]; + } + return [strings.san[type], "Unknown IP address"]; + } + default: + return [strings.san[type], san.altNames[index].value]; + } + }); + } else { + san = []; + } + san = { + altNames: san, + critical: criticalExtensions.includes("2.5.29.17"), + }; + return san; +}; + +const getBasicConstraints = (x509, criticalExtensions) => { + let basicConstraints; + const basicConstraintsExt = getX509Ext(x509.extensions, "2.5.29.19"); + if (basicConstraintsExt) { + basicConstraints = { + cA: basicConstraintsExt.cA !== undefined && basicConstraintsExt.cA, + critical: criticalExtensions.includes("2.5.29.19"), + }; + } + return basicConstraints; +}; + +const getEKeyUsages = (x509, criticalExtensions) => { + let eKeyUsages = getX509Ext(x509.extensions, "2.5.29.37"); + if (eKeyUsages) { + eKeyUsages = { + critical: criticalExtensions.includes("2.5.29.37"), + purposes: eKeyUsages.keyPurposes.map(x => strings.eKU[x] || x), + }; + } + return eKeyUsages; +}; + +const getSubjectKeyID = (x509, criticalExtensions) => { + let sKID = getX509Ext(x509.extensions, "2.5.29.14"); + if (sKID) { + sKID = { + critical: criticalExtensions.includes("2.5.29.14"), + id: hashify(sKID.valueBlock.valueHex), + }; + } + return sKID; +}; + +const getAuthorityKeyID = (x509, criticalExtensions) => { + let aKID = getX509Ext(x509.extensions, "2.5.29.35"); + if (!aKID || !aKID.keyIdentifier) { + return null; + } + aKID = { + critical: criticalExtensions.includes("2.5.29.35"), + id: hashify(aKID.keyIdentifier.valueBlock.valueHex), + }; + return aKID; +}; + +const getCRLPoints = (x509, criticalExtensions) => { + let crlPoints = getX509Ext(x509.extensions, "2.5.29.31"); + if (crlPoints) { + crlPoints = { + critical: criticalExtensions.includes("2.5.29.31"), + points: crlPoints.distributionPoints.map( + x => x.distributionPoint[0].value + ), + }; + } + return crlPoints; +}; + +const getOcspStaple = (x509, criticalExtensions) => { + let ocspStaple = getX509Ext(x509.extensions, "1.3.6.1.5.5.7.1.24"); + if (ocspStaple && ocspStaple.valueBeforeDecode === "3003020105") { + ocspStaple = { + critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.24"), + required: true, + }; + } else { + ocspStaple = { + critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.24"), + required: false, + }; + } + return ocspStaple; +}; + +const getAuthorityInfoAccess = (x509, criticalExtensions) => { + let aia = getX509Ext(x509.extensions, "1.3.6.1.5.5.7.1.1"); + if (aia) { + aia = aia.accessDescriptions.map(x => { + return { + location: x.accessLocation.value, + method: strings.aia[x.accessMethod], + }; + }); + } + + aia = { + descriptions: aia, + critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.1"), + }; + return aia; +}; + +const getSCTs = (x509, criticalExtensions) => { + let scts = getX509Ext(x509.extensions, "1.3.6.1.4.1.11129.2.4.2"); + if (scts) { + scts = Object.keys(scts.timestamps).map(x => { + let logId = scts.timestamps[x].logID.toLowerCase(); + let sctsTimestamp = scts.timestamps[x].timestamp; + return { + logId: hashify(logId), + name: ctLogNames.hasOwnProperty(logId) ? ctLogNames[logId] : undefined, + signatureAlgorithm: `${scts.timestamps[x].hashAlgorithm.replace( + "sha", + "SHA-" + )} ${scts.timestamps[x].signatureAlgorithm.toUpperCase()}`, + timestamp: `${sctsTimestamp.toLocaleString()} (${getTimeZone()})`, + timestampUTC: sctsTimestamp.toUTCString(), + version: scts.timestamps[x].version + 1, + }; + }); + } else { + scts = []; + } + + scts = { + critical: criticalExtensions.includes("1.3.6.1.4.1.11129.2.4.2"), + timestamps: scts, + }; + return scts; +}; + +const getCertificatePolicies = (x509, criticalExtensions) => { + let cp = getX509Ext(x509.extensions, "2.5.29.32"); + if (cp && cp.hasOwnProperty("certificatePolicies")) { + cp = cp.certificatePolicies.map(x => { + let id = x.policyIdentifier; + let certName = strings.cps.hasOwnProperty(id) + ? strings.cps[id].name + : undefined; + let qualifiers = undefined; + let value = strings.cps.hasOwnProperty(id) + ? strings.cps[id].value + : undefined; + + // ansi organization identifiers + if (id.startsWith("2.16.840.")) { + value = id; + id = "2.16.840"; + certName = strings.cps["2.16.840"].name; + } + + // statement identifiers + if (id.startsWith("1.3.6.1.4.1")) { + value = id; + id = "1.3.6.1.4.1"; + certName = strings.cps["1.3.6.1.4.1"].name; + } + + if (x.hasOwnProperty("policyQualifiers")) { + qualifiers = x.policyQualifiers.map(qualifier => { + let qualifierId = qualifier.policyQualifierId; + let qualifierName = strings.cps.hasOwnProperty(qualifierId) + ? strings.cps[qualifierId].name + : undefined; + let qualifierValue = qualifier.qualifier.valueBlock.value; + + // sometimes they are multiple qualifier subblocks, and for now we'll + // only return the first one because it's getting really messy at this point + if (Array.isArray(qualifierValue) && qualifierValue.length === 1) { + qualifierValue = qualifierValue[0].valueBlock.value; + } else if ( + Array.isArray(qualifierValue) && + qualifierValue.length > 1 + ) { + qualifierValue = "(currently unsupported)"; + } + + return { + qualifierId, + qualifierName, + qualifierValue, + }; + }); + } + + return { + id, + name: certName, + qualifiers, + value, + }; + }); + } + + cp = { + critical: criticalExtensions.includes("2.5.29.32"), + policies: cp, + }; + return cp; +}; + +const getMicrosoftCryptographicExtensions = (x509, criticalExtensions) => { + // now let's parse the Microsoft cryptographic extensions + let msCrypto = { + caVersion: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.1"), + certificatePolicies: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.10"), + certificateTemplate: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.7"), + certificateType: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.20.2"), + previousHash: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.2"), + }; + + if ( + msCrypto.caVersion && + Number.isInteger(msCrypto.caVersion.keyIndex) && + Number.isInteger(msCrypto.caVersion.certificateIndex) + ) { + msCrypto.caVersion = { + critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.1"), + caRenewals: msCrypto.caVersion.certificateIndex, + keyReuses: + msCrypto.caVersion.certificateIndex - msCrypto.caVersion.keyIndex, + }; + } + + if (msCrypto.certificatePolicies) { + msCrypto.certificatePolicies = { + critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.10"), + purposes: msCrypto.certificatePolicies.certificatePolicies.map( + x => strings.eKU[x.policyIdentifier] || x.policyIdentifier + ), + }; + } + + if (msCrypto.certificateTemplate) { + msCrypto.certificateTemplate = { + critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.7"), + id: msCrypto.certificateTemplate.extnID, + major: msCrypto.certificateTemplate.templateMajorVersion, + minor: msCrypto.certificateTemplate.templateMinorVersion, + }; + } + + if (msCrypto.certificateType) { + msCrypto.certificateType = { + critical: criticalExtensions.includes("1.3.6.1.4.1.311.20.2"), + type: + strings.microsoftCertificateTypes[ + msCrypto.certificateType.valueBlock.value + ] || "Unknown", + }; + } + + if (msCrypto.previousHash) { + msCrypto.previousHash = { + critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.2"), + previousHash: hashify(msCrypto.previousHash.valueBlock.valueHex), + }; + } + + msCrypto.exists = !!( + msCrypto.caVersion || + msCrypto.certificatePolicies || + msCrypto.certificateTemplate || + msCrypto.certificateType || + msCrypto.previousHash + ); + + return msCrypto; +}; + +export const parse = async certificate => { + // certificate could be an array of BER or an array of buffers + const supportedExtensions = [ + "1.3.6.1.4.1.311.20.2", // microsoft certificate type + "1.3.6.1.4.1.311.21.2", // microsoft certificate previous hash + "1.3.6.1.4.1.311.21.7", // microsoft certificate template + "1.3.6.1.4.1.311.21.1", // microsoft certification authority renewal + "1.3.6.1.4.1.311.21.10", // microsoft certificate policies + "1.3.6.1.4.1.11129.2.4.2", // embedded scts + "1.3.6.1.5.5.7.1.1", // authority info access + "1.3.6.1.5.5.7.1.24", // ocsp stapling + "1.3.101.77", // ct redaction - deprecated and not displayed + "2.5.29.14", // subject key identifier + "2.5.29.15", // key usages + "2.5.29.17", // subject alt names + "2.5.29.19", // basic constraints + "2.5.29.31", // crl points + "2.5.29.32", // certificate policies + "2.5.29.35", // authority key identifier + "2.5.29.37", // extended key usage + ]; + + let timeZone = getTimeZone(); + + // parse the certificate + let x509 = Certificate.fromBER(certificate); + + // convert the cert to PEM + const certPEM = b64ToPEM( + btoa(String.fromCharCode.apply(null, new Uint8Array(certificate))) + ); + + // get which extensions are critical + const criticalExtensions = []; + if (x509.extensions) { + x509.extensions.forEach(ext => { + if (ext.hasOwnProperty("critical") && ext.critical === true) { + criticalExtensions.push(ext.extnID); + } + }); + } + const spki = getPublicKeyInfo(x509); + const keyUsages = getKeyUsages(x509, criticalExtensions); + const san = getSubjectAltNames(x509, criticalExtensions); + const basicConstraints = getBasicConstraints(x509, criticalExtensions); + const eKeyUsages = getEKeyUsages(x509, criticalExtensions); + const sKID = getSubjectKeyID(x509, criticalExtensions); + const aKID = getAuthorityKeyID(x509, criticalExtensions); + const crlPoints = getCRLPoints(x509, criticalExtensions); + const ocspStaple = getOcspStaple(x509, criticalExtensions); + const aia = getAuthorityInfoAccess(x509, criticalExtensions); + const scts = getSCTs(x509, criticalExtensions); + const cp = getCertificatePolicies(x509, criticalExtensions); + const msCrypto = getMicrosoftCryptographicExtensions( + x509, + criticalExtensions + ); + + // determine which extensions weren't supported + let unsupportedExtensions = []; + if (x509.extensions) { + x509.extensions.forEach(ext => { + if (!supportedExtensions.includes(ext.extnID)) { + unsupportedExtensions.push(ext.extnID); + } + }); + } + + // the output shell + return { + ext: { + aia, + aKID, + basicConstraints, + crlPoints, + cp, + eKeyUsages, + keyUsages, + msCrypto, + ocspStaple, + scts, + sKID, + san, + }, + files: { + der: undefined, // TODO: implement! + pem: encodeURI(certPEM), + }, + fingerprint: { + sha1: await hash("SHA-1", certificate), + sha256: await hash("SHA-256", certificate), + }, + issuer: parseSubsidiary(x509.issuer.typesAndValues), + notBefore: `${x509.notBefore.value.toLocaleString()} (${timeZone})`, + notBeforeUTC: x509.notBefore.value.toUTCString(), + notAfter: `${x509.notAfter.value.toLocaleString()} (${timeZone})`, + notAfterUTC: x509.notAfter.value.toUTCString(), + subject: parseSubsidiary(x509.subject.typesAndValues), + serialNumber: hashify(getObjPath(x509, "serialNumber.valueBlock.valueHex")), + signature: { + name: strings.signature[getObjPath(x509, "signature.algorithmId")], + type: getObjPath(x509, "signature.algorithmId"), + }, + subjectPublicKeyInfo: spki, + unsupportedExtensions, + version: (x509.version + 1).toString(), + }; +}; + +const ctLogNames = { + "9606c02c690033aa1d145f59c6e2648d0549f0df96aab8db915a70d8ecf390a5": + "Akamai CT", + "39376f545f7b4607f59742d768cd5d2437bf3473b6534a4834bcf72e681c83c9": + "Alpha CT", + a577ac9ced7548dd8f025b67a241089df86e0f476ec203c2ecbedb185f282638: "CNNIC CT", + cdb5179b7fc1c046feea31136a3f8f002e6182faf8896fecc8b2f5b5ab604900: "Certly.IO", + "1fbc36e002ede97f40199e86b3573b8a4217d80187746ad0da03a06054d20df4": + "Cloudflare “Nimbus2017â€", + db74afeecb29ecb1feca3e716d2ce5b9aabb36f7847183c75d9d4f37b61fbf64: + "Cloudflare “Nimbus2018â€", + "747eda8331ad331091219cce254f4270c2bffd5e422008c6373579e6107bcc56": + "Cloudflare “Nimbus2019â€", + "5ea773f9df56c0e7b536487dd049e0327a919a0c84a112128418759681714558": + "Cloudflare “Nimbus2020â€", + "4494652eb0eeceafc44007d8a8fe28c0dae682bed8cb31b53fd33396b5b681a8": + "Cloudflare “Nimbus2021â€", + "41c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f6": + "Cloudflare “Nimbus2022â€", + "7a328c54d8b72db620ea38e0521ee98416703213854d3bd22bc13a57a352eb52": + "Cloudflare “Nimbus2023â€", + "6ff141b5647e4222f7ef052cefae7c21fd608e27d2af5a6e9f4b8a37d6633ee5": + "DigiCert Nessie2018", + fe446108b1d01ab78a62ccfeab6ab2b2babff3abdad80a4d8b30df2d0008830c: + "DigiCert Nessie2019", + c652a0ec48ceb3fcab170992c43a87413309e80065a26252401ba3362a17c565: + "DigiCert Nessie2020", + eec095ee8d72640f92e3c3b91bc712a3696a097b4b6a1a1438e647b2cbedc5f9: + "DigiCert Nessie2021", + "51a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e5": + "DigiCert Nessie2022", + b3737707e18450f86386d605a9dc11094a792db1670c0b87dcf0030e7936a59a: + "DigiCert Nessie2023", + "5614069a2fd7c2ecd3f5e1bd44b23ec74676b9bc99115cc0ef949855d689d0dd": + "DigiCert Server", + "8775bfe7597cf88c43995fbdf36eff568d475636ff4ab560c1b4eaff5ea0830f": + "DigiCert Server 2", + c1164ae0a772d2d4392dc80ac10770d4f0c49bde991a4840c1fa075164f63360: + "DigiCert Yeti2018", + e2694bae26e8e94009e8861bb63b83d43ee7fe7488fba48f2893019dddf1dbfe: + "DigiCert Yeti2019", + f095a459f200d18240102d2f93888ead4bfe1d47e399e1d034a6b0a8aa8eb273: + "DigiCert Yeti2020", + "5cdc4392fee6ab4544b15e9ad456e61037fbd5fa47dca17394b25ee6f6c70eca": + "DigiCert Yeti2021", + "2245450759552456963fa12ff1f76d86e0232663adc04b7f5dc6835c6ee20f02": + "DigiCert Yeti2022", + "35cf191bbfb16c57bf0fad4c6d42cbbbb627202651ea3fe12aefa803c33bd64c": + "DigiCert Yeti2023", + "717ea7420975be84a2723553f1777c26dd51af4e102144094d9019b462fb6668": "GDCA 1", + "14308d90ccd030135005c01ca526d81e84e87624e39b6248e08f724aea3bb42a": "GDCA 2", + c9cf890a21109c666cc17a3ed065c930d0e0135a9feba85af14210b8072421aa: + "GDCA CT #1", + "924a30f909336ff435d6993a10ac75a2c641728e7fc2d659ae6188ffad40ce01": + "GDCA CT #2", + fad4c97cc49ee2f8ac85c5ea5cea09d0220dbbf4e49c6b50662ff868f86b8c28: + "Google “Argon2017â€", + a4501269055a15545e6211ab37bc103f62ae5576a45e4b1714453e1b22106a25: + "Google “Argon2018â€", + "63f2dbcde83bcc2ccf0b728427576b33a48d61778fbd75a638b1c768544bd88d": + "Google “Argon2019â€", + b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e: + "Google “Argon2020â€", + f65c942fd1773022145418083094568ee34d131933bfdf0c2f200bcc4ef164e3: + "Google “Argon2021â€", + "2979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc784": + "Google “Argon2022â€", + "68f698f81f6482be3a8ceeb9281d4cfc71515d6793d444d10a67acbb4f4ffbc4": + "Google “Aviatorâ€", + c3bf03a7e1ca8841c607bae3ff4270fca5ec45b186ebbe4e2cf3fc778630f5f6: + "Google “Crucibleâ€", + "1d024b8eb1498b344dfd87ea3efc0996f7506f235d1d497061a4773c439c25fb": + "Google “Daedalusâ€", + "293c519654c83965baaa50fc5807d4b76fbf587a2972dca4c30cf4e54547f478": + "Google “Icarusâ€", + a4b90990b418581487bb13a2cc67700a3c359804f91bdfb8e377cd0ec80ddc10: + "Google “Pilotâ€", + ee4bbdb775ce60bae142691fabe19e66a30f7e5fb072d88300c47b897aa8fdcb: + "Google “Rocketeerâ€", + bbd9dfbc1f8a71b593942397aa927b473857950aab52e81a909664368e1ed185: + "Google “Skydiverâ€", + "52eb4b225ec896974850675f23e43bc1d021e3214ce52ecd5fa87c203cdfca03": + "Google “Solera2018â€", + "0b760e9a8b9a682f88985b15e947501a56446bba8830785c3842994386450c00": + "Google “Solera2019â€", + "1fc72ce5a1b799f400c359bff96ca3913548e8644220610952e9ba1774f7bac7": + "Google “Solera2020â€", + a3c99845e80ab7ce00157b3742df0207dd272b2b602ecf98ee2c12db9c5ae7e7: + "Google “Solera2021â€", + "697aafca1a6b536fae21205046debad7e0eaea13d2432e6e9d8fb379f2b9aaf3": + "Google “Solera2022â€", + a899d8780c9290aaf462f31880ccfbd52451e970d0fbf591ef75b0d99b645681: + "Google “Submarinerâ€", + b0cc83e5a5f97d6baf7c09cc284904872ac7e88b132c6350b7c6fd26e16c6c77: + "Google “Testtubeâ€", + b10cd559a6d67846811f7df9a51532739ac48d703bea0323da5d38755bc0ad4e: + "Google “Xenon2018â€", + "084114980071532c16190460bcfc47fdc2653afa292c72b37ff863ae29ccc9f0": + "Google “Xenon2019â€", + "07b75c1be57d68fff1b0c61d2315c7bae6577c5794b76aeebc613a1a69d3a21c": + "Google “Xenon2020â€", + "7d3ef2f88fff88556824c2c0ca9e5289792bc50e78097f2e6a9768997e22f0d7": + "Google “Xenon2021â€", + "46a555eb75fa912030b5a28969f4f37d112c4174befd49b885abf2fc70fe6d47": + "Google “Xenon2022â€", + "7461b4a09cfb3d41d75159575b2e7649a445a8d27709b0cc564a6482b7eb41a3": "Izenpe", + "8941449c70742e06b9fc9ce7b116ba0024aa36d59af44f0204404f00f7ea8566": + "Izenpe “Argiâ€", + "296afa2d568bca0d2ea844956ae9721fc35fa355ecda99693aafd458a71aefdd": + "Let“s Encrypt â€Clickyâ€", + "537b69a3564335a9c04904e39593b2c298eb8d7a6e83023635c627248cd6b440": + "Nordu “flimsyâ€", + aae70b7f3cb8d566c86c2f16979c9f445f69ab0eb4535589b2f77a030104f3cd: + "Nordu “plausibleâ€", + e0127629e90496564e3d0147984498aa48f8adb16600eb7902a1ef9909906273: + "PuChuangSiDa CT", + cf55e28923497c340d5206d05353aeb25834b52f1f8dc9526809f212efdd7ca6: + "SHECA CT 1", + "32dc59c2d4c41968d56e14bc61ac8f0e45db39faf3c155aa4252f5001fa0c623": + "SHECA CT 2", + db76fdadac65e7d09508886e2159bd8b90352f5fead3e3dc5e22eb350acc7b98: + "Sectigo (Comodo) “Dodo†CT", + "6f5376ac31f03119d89900a45115ff77151c11d902c10029068db2089a37d913": + "Sectigo (Comodo) “Mammoth†CT", + "5581d4c2169036014aea0b9b573c53f0c0e43878702508172fa3aa1d0713d30c": + "Sectigo (Comodo) “Sabre†CT", + "34bb6ad6c3df9c03eea8a499ff7891486c9d5e5cac92d01f7bfd1bce19db48ef": + "StartCom", + ddeb1d2b7a0d4fa6208b81ad8168707e2e8e9d01d55c888d3d11c4cdb6ecbecc: "Symantec", + a7ce4a4e6207e0addee5fdaa4b1f86768767b5d002a55d47310e7e670a95eab2: + "Symantec Deneb", + "15970488d7b997a05beb52512adee8d2e8b4a3165264121a9fabfbd5f85ad93f": + "Symantec “Siriusâ€", + bc78e1dfc5f63c684649334da10fa15f0979692009c081b4f3f6917f3ed9b8a5: + "Symantec “Vegaâ€", + b0b784bc81c0ddc47544e883f05985bb9077d134d8ab88b2b2e533980b8e508b: + "Up In The Air “Behind the Sofaâ€", + ac3b9aed7fa9674757159e6d7d575672f9d98100941e9bdeffeca1313b75782d: "Venafi", + "03019df3fd85a69a8ebd1facc6da9ba73e469774fe77f579fc5a08b8328c1d6b": + "Venafi Gen2 CT", + "41b2dc2e89e63ce4af1ba7bb29bf68c6dee6f9f1cc047e30dffae3b3ba259263": "WoSign", + "63d0006026dde10bb0601f452446965ee2b6ea2cd4fbc95ac866a550af9075b7": + "WoSign 2", + "9e4ff73dc3ce220b69217c899e468076abf8d78636d5ccfc85a31a75628ba88b": + "WoSign CT #1", + "659b3350f43b12cc5ea5ab4ec765d3fde6c88243777778e72003f9eb2b8c3129": + "Let's Encrypt Oak 2019", + e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e: + "Let's Encrypt Oak 2020", + "9420bc1e8ed58d6c88731f828b222c0dd1da4d5e6c4f943d61db4e2f584da2c2": + "Let's Encrypt Oak 2021", + dfa55eab68824f1f6cadeeb85f4e3e5aeacda212a46a5e8e3b12c020445c2a73: + "Let's Encrypt Oak 2022", + b73efb24df9c4dba75f239c5ba58f46c5dfc42cf7a9f35c49e1d098125edb499: + "Let's Encrypt Oak 2023", + "849f5f7f58d2bf7b54ecbd74611cea45c49c98f1d6481bc6f69e8c174f24f3cf": + "Let's Encrypt Testflume 2019", + c63f2218c37d56a6aa06b596da8e53d4d7156d1e9bac8e44d2202de64d69d9dc: + "Let's Encrypt Testflume 2020", + "03edf1da9776b6f38c341e39ed9d707a7570369cf9844f327fe9e14138361b60": + "Let's Encrypt Testflume 2021", + "2327efda352510dbc019ef491ae3ff1cc5a479bce37878360ee318cffb64f8c8": + "Let's Encrypt Testflume 2022", + "5534b7ab5a6ac3a7cbeba65487b2a2d71b48f650fa17c5197c97a0cb2076f3c6": + "Let's Encrypt Testflume 2023", +}; + +const strings = { + ux: { + upload: "Upload Certificate", + }, + + names: { + // Directory Pilot Attributes + "0.9.2342.19200300.100.1.1": { + short: "uid", + long: "User ID", + }, + "0.9.2342.19200300.100.1.25": { + short: "dc", + long: "Domain Component", + }, + + // PKCS-9 + "1.2.840.113549.1.9.1": { + short: "e", + long: "Email Address", + }, + + // Incorporated Locations + "1.3.6.1.4.1.311.60.2.1.1": { + short: undefined, + long: "Inc. Locality", + }, + "1.3.6.1.4.1.311.60.2.1.2": { + short: undefined, + long: "Inc. State / Province", + }, + "1.3.6.1.4.1.311.60.2.1.3": { + short: undefined, + long: "Inc. Country", + }, + + // microsoft cryptographic extensions + "1.3.6.1.4.1.311.21.7": { + name: { + short: "Certificate Template", + long: "Microsoft Certificate Template", + }, + }, + "1.3.6.1.4.1.311.21.10": { + name: { + short: "Certificate Policies", + long: "Microsoft Certificate Policies", + }, + }, + + // certificate extensions + "1.3.6.1.4.1.11129.2.4.2": { + name: { + short: "Embedded SCTs", + long: "Embedded Signed Certificate Timestamps", + }, + }, + "1.3.6.1.5.5.7.1.1": { + name: { + short: undefined, + long: "Authority Information Access", + }, + }, + "1.3.6.1.5.5.7.1.24": { + name: { + short: "OCSP Stapling", + long: "Online Certificate Status Protocol Stapling", + }, + }, + + // X.500 attribute types + "2.5.4.1": { + short: undefined, + long: "Aliased Entry", + }, + "2.5.4.2": { + short: undefined, + long: "Knowledge Information", + }, + "2.5.4.3": { + short: "cn", + long: "Common Name", + }, + "2.5.4.4": { + short: "sn", + long: "Surname", + }, + "2.5.4.5": { + short: "serialNumber", + long: "Serial Number", + }, + "2.5.4.6": { + short: "c", + long: "Country", + }, + "2.5.4.7": { + short: "l", + long: "Locality", + }, + "2.5.4.8": { + short: "s", + long: "State / Province", + }, + "2.5.4.9": { + short: "street", + long: "Stress Address", + }, + "2.5.4.10": { + short: "o", + long: "Organization", + }, + "2.5.4.11": { + short: "ou", + long: "Organizational Unit", + }, + "2.5.4.12": { + short: "t", + long: "Title", + }, + "2.5.4.13": { + short: "description", + long: "Description", + }, + "2.5.4.14": { + short: undefined, + long: "Search Guide", + }, + "2.5.4.15": { + short: undefined, + long: "Business Category", + }, + "2.5.4.16": { + short: undefined, + long: "Postal Address", + }, + "2.5.4.17": { + short: "postalCode", + long: "Postal Code", + }, + "2.5.4.18": { + short: "POBox", + long: "PO Box", + }, + "2.5.4.19": { + short: undefined, + long: "Physical Delivery Office Name", + }, + "2.5.4.20": { + short: "phone", + long: "Phone Number", + }, + "2.5.4.21": { + short: undefined, + long: "Telex Number", + }, + "2.5.4.22": { + short: undefined, + long: "Teletex Terminal Identifier", + }, + "2.5.4.23": { + short: undefined, + long: "Fax Number", + }, + "2.5.4.24": { + short: undefined, + long: "X.121 Address", + }, + "2.5.4.25": { + short: undefined, + long: "International ISDN Number", + }, + "2.5.4.26": { + short: undefined, + long: "Registered Address", + }, + "2.5.4.27": { + short: undefined, + long: "Destination Indicator", + }, + "2.5.4.28": { + short: undefined, + long: "Preferred Delivery Method", + }, + "2.5.4.29": { + short: undefined, + long: "Presentation Address", + }, + "2.5.4.30": { + short: undefined, + long: "Supported Application Context", + }, + "2.5.4.31": { + short: undefined, + long: "Member", + }, + "2.5.4.32": { + short: undefined, + long: "Owner", + }, + "2.5.4.33": { + short: undefined, + long: "Role Occupant", + }, + "2.5.4.34": { + short: undefined, + long: "See Also", + }, + "2.5.4.35": { + short: undefined, + long: "User Password", + }, + "2.5.4.36": { + short: undefined, + long: "User Certificate", + }, + "2.5.4.37": { + short: undefined, + long: "CA Certificate", + }, + "2.5.4.38": { + short: undefined, + long: "Authority Revocation List", + }, + "2.5.4.39": { + short: undefined, + long: "Certificate Revocation List", + }, + "2.5.4.40": { + short: undefined, + long: "Cross-certificate Pair", + }, + "2.5.4.41": { + short: undefined, + long: "Name", + }, + "2.5.4.42": { + short: "g", + long: "Given Name", + }, + "2.5.4.43": { + short: "i", + long: "Initials", + }, + "2.5.4.44": { + short: undefined, + long: "Generation Qualifier", + }, + "2.5.4.45": { + short: undefined, + long: "Unique Identifier", + }, + "2.5.4.46": { + short: undefined, + long: "DN Qualifier", + }, + "2.5.4.47": { + short: undefined, + long: "Enhanced Search Guide", + }, + "2.5.4.48": { + short: undefined, + long: "Protocol Information", + }, + "2.5.4.49": { + short: "dn", + long: "Distinguished Name", + }, + "2.5.4.50": { + short: undefined, + long: "Unique Member", + }, + "2.5.4.51": { + short: undefined, + long: "House Identifier", + }, + "2.5.4.52": { + short: undefined, + long: "Supported Algorithms", + }, + "2.5.4.53": { + short: undefined, + long: "Delta Revocation List", + }, + "2.5.4.58": { + short: undefined, + long: "Attribute Certificate Attribute", // huh + }, + "2.5.4.65": { + short: undefined, + long: "Pseudonym", + }, + + // extensions + "2.5.29.14": { + name: { + short: "Subject Key ID", + long: "Subject Key Identifier", + }, + }, + "2.5.29.15": { + name: { + short: undefined, + long: "Key Usages", + }, + }, + "2.5.29.17": { + name: { + short: "Subject Alt Names", + long: "Subject Alternative Names", + }, + }, + "2.5.29.19": { + name: { + short: undefined, + long: "Basic Constraints", + }, + }, + "2.5.29.31": { + name: { + short: "CRL Endpoints", + long: "Certificate Revocation List Endpoints", + }, + }, + "2.5.29.32": { + name: { + short: undefined, + long: "Certificate Policies", + }, + }, + "2.5.29.35": { + name: { + short: "Authority Key ID", + long: "Authority Key Identifier", + }, + }, + "2.5.29.37": { + name: { + short: undefined, + long: "Extended Key Usages", + }, + }, + }, + + keyUsages: [ + "Digital Signature", + "Non-Repudiation", + "Key Encipherment", + "Data Encipherment", + "Key Agreement", + "Certificate Signing", + "CRL Signing", + "Encipher Only", + "Decipher Only", + ], + + san: [ + "Other Name", + "RFC 822 Name", + "DNS Name", + "X.400 Address", + "Directory Name", + "EDI Party Name", + "URI", + "IP Address", + "Registered ID", + ], + + eKU: { + "1.3.6.1.4.1.311.10.3.1": "Certificate Trust List (CTL) Signing", + "1.3.6.1.4.1.311.10.3.2": "Timestamp Signing", + "1.3.6.1.4.1.311.10.3.4": "EFS Encryption", + "1.3.6.1.4.1.311.10.3.4.1": "EFS Recovery", + "1.3.6.1.4.1.311.10.3.5": + "Windows Hardware Quality Labs (WHQL) Cryptography", + "1.3.6.1.4.1.311.10.3.7": "Windows NT 5 Cryptography", + "1.3.6.1.4.1.311.10.3.8": "Windows NT Embedded Cryptography", + "1.3.6.1.4.1.311.10.3.10": "Qualified Subordination", + "1.3.6.1.4.1.311.10.3.11": "Escrowed Key Recovery", + "1.3.6.1.4.1.311.10.3.12": "Document Signing", + "1.3.6.1.4.1.311.10.5.1": "Digital Rights Management", + "1.3.6.1.4.1.311.10.6.1": "Key Pack Licenses", + "1.3.6.1.4.1.311.10.6.2": "License Server", + "1.3.6.1.4.1.311.20.2.1": "Enrollment Agent", + "1.3.6.1.4.1.311.20.2.2": "Smartcard Login", + "1.3.6.1.4.1.311.21.5": "Certificate Authority Private Key Archival", + "1.3.6.1.4.1.311.21.6": "Key Recovery Agent", + "1.3.6.1.4.1.311.21.19": "Directory Service Email Replication", + "1.3.6.1.5.5.7.3.1": "Server Authentication", + "1.3.6.1.5.5.7.3.2": "Client Authentication", + "1.3.6.1.5.5.7.3.3": "Code Signing", + "1.3.6.1.5.5.7.3.4": "E-mail Protection", + "1.3.6.1.5.5.7.3.5": "IPsec End System", + "1.3.6.1.5.5.7.3.6": "IPsec Tunnel", + "1.3.6.1.5.5.7.3.7": "IPSec User", + "1.3.6.1.5.5.7.3.8": "Timestamping", + "1.3.6.1.5.5.7.3.9": "OCSP Signing", + "1.3.6.1.5.5.8.2.2": "Internet Key Exchange (IKE)", + }, + + signature: { + "1.2.840.113549.1.1.4": "MD5 with RSA Encryption", + "1.2.840.113549.1.1.5": "SHA-1 with RSA Encryption", + "1.2.840.113549.1.1.11": "SHA-256 with RSA Encryption", + "1.2.840.113549.1.1.12": "SHA-384 with RSA Encryption", + "1.2.840.113549.1.1.13": "SHA-512 with RSA Encryption", + "1.2.840.10040.4.3": "DSA with SHA-1", + "2.16.840.1.101.3.4.3.2": "DSA with SHA-256", + "1.2.840.10045.4.1": "ECDSA with SHA-1", + "1.2.840.10045.4.3.2": "ECDSA with SHA-256", + "1.2.840.10045.4.3.3": "ECDSA with SHA-384", + "1.2.840.10045.4.3.4": "ECDSA with SHA-512", + }, + + aia: { + "1.3.6.1.5.5.7.48.1": "Online Certificate Status Protocol (OCSP)", + "1.3.6.1.5.5.7.48.2": "CA Issuers", + }, + + // this includes qualifiers as well + cps: { + "1.3.6.1.4.1": { + name: "Statement Identifier", + value: undefined, + }, + "1.3.6.1.5.5.7.2.1": { + name: "Practices Statement", + value: undefined, + }, + "1.3.6.1.5.5.7.2.2": { + name: "User Notice", + value: undefined, + }, + "2.16.840": { + name: "ANSI Organizational Identifier", + value: undefined, + }, + "2.23.140.1.1": { + name: "Certificate Type", + value: "Extended Validation", + }, + "2.23.140.1.2.1": { + name: "Certificate Type", + value: "Domain Validation", + }, + "2.23.140.1.2.2": { + name: "Certificate Type", + value: "Organization Validation", + }, + "2.23.140.1.2.3": { + name: "Certificate Type", + value: "Individual Validation", + }, + "2.23.140.1.3": { + name: "Certificate Type", + value: "Extended Validation (Code Signing)", + }, + "2.23.140.1.31": { + name: "Certificate Type", + value: ".onion Extended Validation", + }, + "2.23.140.2.1": { + name: "Certificate Type", + value: "Test Certificate", + }, + }, + + microsoftCertificateTypes: { + Administrator: "Administrator", + CA: "Root Certification Authority", + CAExchange: "CA Exchange", + CEPEncryption: "CEP Encryption", + CertificateRequestAgent: "Certificate Request Agent", + ClientAuth: "Authenticated Session", + CodeSigning: "Code Signing", + CrossCA: "Cross Certification Authority", + CTLSigning: "Trust List Signing", + DirectoryEmailReplication: "Directory Email Replication", + DomainController: "Domain Controller", + DomainControllerAuthentication: "Domain Controller Authentication", + EFS: "Basic EFS", + EFSRecovery: "EFS Recovery Agent", + EnrollmentAgent: "Enrollment Agent", + EnrollmentAgentOffline: "Exchange Enrollment Agent (Offline request)", + ExchangeUser: "Exchange User", + ExchangeUserSignature: "Exchange Signature Only", + IPSECIntermediateOffline: "IPSec (Offline request)", + IPSECIntermediateOnline: "IPSEC", + KerberosAuthentication: "Kerberos Authentication", + KeyRecoveryAgent: "Key Recovery Agent", + Machine: "Computer", + MachineEnrollmentAgent: "Enrollment Agent (Computer)", + OCSPResponseSigning: "OCSP Response Signing", + OfflineRouter: "Router (Offline request)", + RASAndIASServer: "RAS and IAS Server", + SmartcardLogon: "Smartcard Logon", + SmartcardUser: "Smartcard User", + SubCA: "Subordinate Certification Authority", + User: "User", + UserSignature: "User Signature Only", + WebServer: "Web Server", + Workstation: "Workstation Authentication", + }, +}; + +function stringToArrayBuffer(string) { + let result = new Uint8Array(string.length); + for (let i = 0; i < string.length; i++) { + result[i] = string.charCodeAt(i); + } + return result; +} + +// this particular prototype override makes it easy to chain down complex objects +const getObjPath = (obj, path) => { + path = path.split("."); + for (let i = 0, len = path.length; i < len; i++) { + if (Array.isArray(obj[path[i]])) { + obj = obj[path[i]][path[i + 1]]; + i++; + } else { + obj = obj[path[i]]; + } + } + return obj; +}; + +const arrayBufferToHex = arrayBuffer => { + const array = Array.from(new Uint8Array(arrayBuffer)); + + return array + .map(b => ("00" + b.toString(16)).slice(-2)) + .join(":") + .toUpperCase(); +}; + +const hash = async (algo, buffer) => { + const hashBuffer = await crypto.subtle.digest(algo, buffer); + return arrayBufferToHex(hashBuffer); +}; + +const hashify = rawHash => { + if (typeof rawHash === "string") { + return rawHash.match(/.{2}/g).join(":").toUpperCase(); + } + if (rawHash instanceof ArrayBuffer) { + return arrayBufferToHex(rawHash); + } + return rawHash.join(":").toUpperCase(); +}; + +export const pemToDER = pem => { + return stringToArrayBuffer(atob(pem)); +}; diff --git a/maybe_tampered/eventemitter3/umd/eventemitter3.js b/maybe_tampered/eventemitter3/umd/eventemitter3.js new file mode 100644 index 0000000..888fcb8 --- /dev/null +++ b/maybe_tampered/eventemitter3/umd/eventemitter3.js @@ -0,0 +1,340 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.EventEmitter3 = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { + // This property needs to remain unminified. + if (value['_$cssResult$'] === true) { + return value.cssText; + } + else if (typeof value === 'number') { + return value; + } + else { + throw new Error(`Value passed to 'css' function must be a 'css' function result: ` + + `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` + + `to ensure page security.`); + } +}; +/** + * Wrap a value for interpolation in a {@linkcode css} tagged template literal. + * + * This is unsafe because untrusted CSS text can be used to phone home + * or exfiltrate data to an attacker controlled site. Take care to only use + * this with trusted input. + */ +const unsafeCSS = (value) => new CSSResult(typeof value === 'string' ? value : String(value), undefined, constructionToken); +/** + * A template literal tag which can be used with LitElement's + * {@linkcode LitElement.styles} property to set element styles. + * + * For security reasons, only literal string values and number may be used in + * embedded expressions. To incorporate non-literal values {@linkcode unsafeCSS} + * may be used inside an expression. + */ +const css = (strings, ...values) => { + const cssText = strings.length === 1 + ? strings[0] + : values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]); + return new CSSResult(cssText, strings, constructionToken); +}; +/** + * Applies the given styles to a `shadowRoot`. When Shadow DOM is + * available but `adoptedStyleSheets` is not, styles are appended to the + * `shadowRoot` to [mimic spec behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets). + * Note, when shimming is used, any styles that are subsequently placed into + * the shadowRoot should be placed *before* any shimmed adopted styles. This + * will match spec behavior that gives adopted sheets precedence over styles in + * shadowRoot. + */ +const adoptStyles = (renderRoot, styles) => { + if (supportsAdoptingStyleSheets) { + renderRoot.adoptedStyleSheets = styles.map((s) => s instanceof CSSStyleSheet ? s : s.styleSheet); + } + else { + styles.forEach((s) => { + const style = document.createElement('style'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const nonce = global$2['litNonce']; + if (nonce !== undefined) { + style.setAttribute('nonce', nonce); + } + style.textContent = s.cssText; + renderRoot.appendChild(style); + }); + } +}; +const cssResultFromStyleSheet = (sheet) => { + let cssText = ''; + for (const rule of sheet.cssRules) { + cssText += rule.cssText; + } + return unsafeCSS(cssText); +}; +const getCompatibleStyle = supportsAdoptingStyleSheets || + (NODE_MODE$1 ) + ? (s) => s + : (s) => s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d$1; +var _e; +const global$1 = window; +const trustedTypes$1 = global$1 + .trustedTypes; +// Temporary workaround for https://crbug.com/993268 +// Currently, any attribute starting with "on" is considered to be a +// TrustedScript source. Such boolean attributes must be set to the equivalent +// trusted emptyScript value. +const emptyStringForBooleanAttribute$1 = trustedTypes$1 + ? trustedTypes$1.emptyScript + : ''; +const polyfillSupport$2 = global$1.reactiveElementPolyfillSupport; +/* + * When using Closure Compiler, JSCompiler_renameProperty(property, object) is + * replaced at compile time by the munged name for object[property]. We cannot + * alias this function, so we have to use a small shim that has the same + * behavior when not compiling. + */ +/*@__INLINE__*/ +const JSCompiler_renameProperty = (prop, _obj) => prop; +const defaultConverter = { + toAttribute(value, type) { + switch (type) { + case Boolean: + value = value ? emptyStringForBooleanAttribute$1 : null; + break; + case Object: + case Array: + // if the value is `null` or `undefined` pass this through + // to allow removing/no change behavior. + value = value == null ? value : JSON.stringify(value); + break; + } + return value; + }, + fromAttribute(value, type) { + let fromValue = value; + switch (type) { + case Boolean: + fromValue = value !== null; + break; + case Number: + fromValue = value === null ? null : Number(value); + break; + case Object: + case Array: + // Do *not* generate exception when invalid JSON is set as elements + // don't normally complain on being mis-configured. + // TODO(sorvell): Do generate exception in *dev mode*. + try { + // Assert to adhere to Bazel's "must type assert JSON parse" rule. + fromValue = JSON.parse(value); + } + catch (e) { + fromValue = null; + } + break; + } + return fromValue; + }, +}; +/** + * Change function that returns true if `value` is different from `oldValue`. + * This method is used as the default for a property's `hasChanged` function. + */ +const notEqual = (value, old) => { + // This ensures (old==NaN, value==NaN) always returns false + return old !== value && (old === old || value === value); +}; +const defaultPropertyDeclaration = { + attribute: true, + type: String, + converter: defaultConverter, + reflect: false, + hasChanged: notEqual, +}; +/** + * The Closure JS Compiler doesn't currently have good support for static + * property semantics where "this" is dynamic (e.g. + * https://github.com/google/closure-compiler/issues/3177 and others) so we use + * this hack to bypass any rewriting by the compiler. + */ +const finalized = 'finalized'; +/** + * Base element class which manages element properties and attributes. When + * properties change, the `update` method is asynchronously called. This method + * should be supplied by subclassers to render updates as desired. + * @noInheritDoc + */ +class ReactiveElement extends HTMLElement { + constructor() { + super(); + this.__instanceProperties = new Map(); + /** + * True if there is a pending update as a result of calling `requestUpdate()`. + * Should only be read. + * @category updates + */ + this.isUpdatePending = false; + /** + * Is set to `true` after the first update. The element code cannot assume + * that `renderRoot` exists before the element `hasUpdated`. + * @category updates + */ + this.hasUpdated = false; + /** + * Name of currently reflecting property + */ + this.__reflectingProperty = null; + this._initialize(); + } + /** + * Adds an initializer function to the class that is called during instance + * construction. + * + * This is useful for code that runs against a `ReactiveElement` + * subclass, such as a decorator, that needs to do work for each + * instance, such as setting up a `ReactiveController`. + * + * ```ts + * const myDecorator = (target: typeof ReactiveElement, key: string) => { + * target.addInitializer((instance: ReactiveElement) => { + * // This is run during construction of the element + * new MyController(instance); + * }); + * } + * ``` + * + * Decorating a field will then cause each instance to run an initializer + * that adds a controller: + * + * ```ts + * class MyElement extends LitElement { + * @myDecorator foo; + * } + * ``` + * + * Initializers are stored per-constructor. Adding an initializer to a + * subclass does not add it to a superclass. Since initializers are run in + * constructors, initializers will run in order of the class hierarchy, + * starting with superclasses and progressing to the instance's class. + * + * @nocollapse + */ + static addInitializer(initializer) { + var _a; + this.finalize(); + ((_a = this._initializers) !== null && _a !== void 0 ? _a : (this._initializers = [])).push(initializer); + } + /** + * Returns a list of attributes corresponding to the registered properties. + * @nocollapse + * @category attributes + */ + static get observedAttributes() { + // note: piggy backing on this to ensure we're finalized. + this.finalize(); + const attributes = []; + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.elementProperties.forEach((v, p) => { + const attr = this.__attributeNameForProperty(p, v); + if (attr !== undefined) { + this.__attributeToPropertyMap.set(attr, p); + attributes.push(attr); + } + }); + return attributes; + } + /** + * Creates a property accessor on the element prototype if one does not exist + * and stores a {@linkcode PropertyDeclaration} for the property with the + * given options. The property setter calls the property's `hasChanged` + * property option or uses a strict identity check to determine whether or not + * to request an update. + * + * This method may be overridden to customize properties; however, + * when doing so, it's important to call `super.createProperty` to ensure + * the property is setup correctly. This method calls + * `getPropertyDescriptor` internally to get a descriptor to install. + * To customize what properties do when they are get or set, override + * `getPropertyDescriptor`. To customize the options for a property, + * implement `createProperty` like this: + * + * ```ts + * static createProperty(name, options) { + * options = Object.assign(options, {myOption: true}); + * super.createProperty(name, options); + * } + * ``` + * + * @nocollapse + * @category properties + */ + static createProperty(name, options = defaultPropertyDeclaration) { + // if this is a state property, force the attribute to false. + if (options.state) { + // Cast as any since this is readonly. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options.attribute = false; + } + // Note, since this can be called by the `@property` decorator which + // is called before `finalize`, we ensure finalization has been kicked off. + this.finalize(); + this.elementProperties.set(name, options); + // Do not generate an accessor if the prototype already has one, since + // it would be lost otherwise and that would never be the user's intention; + // Instead, we expect users to call `requestUpdate` themselves from + // user-defined accessors. Note that if the super has an accessor we will + // still overwrite it + if (!options.noAccessor && !this.prototype.hasOwnProperty(name)) { + const key = typeof name === 'symbol' ? Symbol() : `__${name}`; + const descriptor = this.getPropertyDescriptor(name, key, options); + if (descriptor !== undefined) { + Object.defineProperty(this.prototype, name, descriptor); + } + } + } + /** + * Returns a property descriptor to be defined on the given named property. + * If no descriptor is returned, the property will not become an accessor. + * For example, + * + * ```ts + * class MyElement extends LitElement { + * static getPropertyDescriptor(name, key, options) { + * const defaultDescriptor = + * super.getPropertyDescriptor(name, key, options); + * const setter = defaultDescriptor.set; + * return { + * get: defaultDescriptor.get, + * set(value) { + * setter.call(this, value); + * // custom action. + * }, + * configurable: true, + * enumerable: true + * } + * } + * } + * ``` + * + * @nocollapse + * @category properties + */ + static getPropertyDescriptor(name, key, options) { + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get() { + return this[key]; + }, + set(value) { + const oldValue = this[name]; + this[key] = value; + this.requestUpdate(name, oldValue, options); + }, + configurable: true, + enumerable: true, + }; + } + /** + * Returns the property options associated with the given property. + * These options are defined with a `PropertyDeclaration` via the `properties` + * object or the `@property` decorator and are registered in + * `createProperty(...)`. + * + * Note, this method should be considered "final" and not overridden. To + * customize the options for a given property, override + * {@linkcode createProperty}. + * + * @nocollapse + * @final + * @category properties + */ + static getPropertyOptions(name) { + return this.elementProperties.get(name) || defaultPropertyDeclaration; + } + /** + * Creates property accessors for registered properties, sets up element + * styling, and ensures any superclasses are also finalized. Returns true if + * the element was finalized. + * @nocollapse + */ + static finalize() { + if (this.hasOwnProperty(finalized)) { + return false; + } + this[finalized] = true; + // finalize any superclasses + const superCtor = Object.getPrototypeOf(this); + superCtor.finalize(); + // Create own set of initializers for this class if any exist on the + // superclass and copy them down. Note, for a small perf boost, avoid + // creating initializers unless needed. + if (superCtor._initializers !== undefined) { + this._initializers = [...superCtor._initializers]; + } + this.elementProperties = new Map(superCtor.elementProperties); + // initialize Map populated in observedAttributes + this.__attributeToPropertyMap = new Map(); + // make any properties + // Note, only process "own" properties since this element will inherit + // any properties defined on the superClass, and finalization ensures + // the entire prototype chain is finalized. + if (this.hasOwnProperty(JSCompiler_renameProperty('properties'))) { + const props = this.properties; + // support symbols in properties (IE11 does not support this) + const propKeys = [ + ...Object.getOwnPropertyNames(props), + ...Object.getOwnPropertySymbols(props), + ]; + // This for/of is ok because propKeys is an array + for (const p of propKeys) { + // note, use of `any` is due to TypeScript lack of support for symbol in + // index types + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.createProperty(p, props[p]); + } + } + this.elementStyles = this.finalizeStyles(this.styles); + return true; + } + /** + * Takes the styles the user supplied via the `static styles` property and + * returns the array of styles to apply to the element. + * Override this method to integrate into a style management system. + * + * Styles are deduplicated preserving the _last_ instance in the list. This + * is a performance optimization to avoid duplicated styles that can occur + * especially when composing via subclassing. The last item is kept to try + * to preserve the cascade order with the assumption that it's most important + * that last added styles override previous styles. + * + * @nocollapse + * @category styles + */ + static finalizeStyles(styles) { + const elementStyles = []; + if (Array.isArray(styles)) { + // Dedupe the flattened array in reverse order to preserve the last items. + // Casting to Array works around TS error that + // appears to come from trying to flatten a type CSSResultArray. + const set = new Set(styles.flat(Infinity).reverse()); + // Then preserve original order by adding the set items in reverse order. + for (const s of set) { + elementStyles.unshift(getCompatibleStyle(s)); + } + } + else if (styles !== undefined) { + elementStyles.push(getCompatibleStyle(styles)); + } + return elementStyles; + } + /** + * Returns the property name for the given attribute `name`. + * @nocollapse + */ + static __attributeNameForProperty(name, options) { + const attribute = options.attribute; + return attribute === false + ? undefined + : typeof attribute === 'string' + ? attribute + : typeof name === 'string' + ? name.toLowerCase() + : undefined; + } + /** + * Internal only override point for customizing work done when elements + * are constructed. + * + * @internal + */ + _initialize() { + var _a; + this.__updatePromise = new Promise((res) => (this.enableUpdating = res)); + this._$changedProperties = new Map(); + this.__saveInstanceProperties(); + // ensures first update will be caught by an early access of + // `updateComplete` + this.requestUpdate(); + (_a = this.constructor._initializers) === null || _a === void 0 ? void 0 : _a.forEach((i) => i(this)); + } + /** + * Registers a `ReactiveController` to participate in the element's reactive + * update cycle. The element automatically calls into any registered + * controllers during its lifecycle callbacks. + * + * If the element is connected when `addController()` is called, the + * controller's `hostConnected()` callback will be immediately called. + * @category controllers + */ + addController(controller) { + var _a, _b; + ((_a = this.__controllers) !== null && _a !== void 0 ? _a : (this.__controllers = [])).push(controller); + // If a controller is added after the element has been connected, + // call hostConnected. Note, re-using existence of `renderRoot` here + // (which is set in connectedCallback) to avoid the need to track a + // first connected state. + if (this.renderRoot !== undefined && this.isConnected) { + (_b = controller.hostConnected) === null || _b === void 0 ? void 0 : _b.call(controller); + } + } + /** + * Removes a `ReactiveController` from the element. + * @category controllers + */ + removeController(controller) { + var _a; + // Note, if the indexOf is -1, the >>> will flip the sign which makes the + // splice do nothing. + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.splice(this.__controllers.indexOf(controller) >>> 0, 1); + } + /** + * Fixes any properties set on the instance before upgrade time. + * Otherwise these would shadow the accessor and break these properties. + * The properties are stored in a Map which is played back after the + * constructor runs. Note, on very old versions of Safari (<=9) or Chrome + * (<=41), properties created for native platform properties like (`id` or + * `name`) may not have default values set in the element constructor. On + * these browsers native properties appear on instances and therefore their + * default value will overwrite any element default (e.g. if the element sets + * this.id = 'id' in the constructor, the 'id' will become '' since this is + * the native platform default). + */ + __saveInstanceProperties() { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.constructor.elementProperties.forEach((_v, p) => { + if (this.hasOwnProperty(p)) { + this.__instanceProperties.set(p, this[p]); + delete this[p]; + } + }); + } + /** + * Returns the node into which the element should render and by default + * creates and returns an open shadowRoot. Implement to customize where the + * element's DOM is rendered. For example, to render into the element's + * childNodes, return `this`. + * + * @return Returns a node into which to render. + * @category rendering + */ + createRenderRoot() { + var _a; + const renderRoot = (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this.attachShadow(this.constructor.shadowRootOptions); + adoptStyles(renderRoot, this.constructor.elementStyles); + return renderRoot; + } + /** + * On first connection, creates the element's renderRoot, sets up + * element styling, and enables updating. + * @category lifecycle + */ + connectedCallback() { + var _a; + // create renderRoot before first update. + if (this.renderRoot === undefined) { + this.renderRoot = this.createRenderRoot(); + } + this.enableUpdating(true); + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostConnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Note, this method should be considered final and not overridden. It is + * overridden on the element instance with a function that triggers the first + * update. + * @category updates + */ + enableUpdating(_requestedUpdate) { } + /** + * Allows for `super.disconnectedCallback()` in extensions while + * reserving the possibility of making non-breaking feature additions + * when disconnecting at some point in the future. + * @category lifecycle + */ + disconnectedCallback() { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostDisconnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Synchronizes property values when attributes change. + * + * Specifically, when an attribute is set, the corresponding property is set. + * You should rarely need to implement this callback. If this method is + * overridden, `super.attributeChangedCallback(name, _old, value)` must be + * called. + * + * See [using the lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks) + * on MDN for more information about the `attributeChangedCallback`. + * @category attributes + */ + attributeChangedCallback(name, _old, value) { + this._$attributeToProperty(name, value); + } + __propertyToAttribute(name, value, options = defaultPropertyDeclaration) { + var _a; + const attr = this.constructor.__attributeNameForProperty(name, options); + if (attr !== undefined && options.reflect === true) { + const converter = ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.toAttribute) !== + undefined + ? options.converter + : defaultConverter; + const attrValue = converter.toAttribute(value, options.type); + // Track if the property is being reflected to avoid + // setting the property again via `attributeChangedCallback`. Note: + // 1. this takes advantage of the fact that the callback is synchronous. + // 2. will behave incorrectly if multiple attributes are in the reaction + // stack at time of calling. However, since we process attributes + // in `update` this should not be possible (or an extreme corner case + // that we'd like to discover). + // mark state reflecting + this.__reflectingProperty = name; + if (attrValue == null) { + this.removeAttribute(attr); + } + else { + this.setAttribute(attr, attrValue); + } + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** @internal */ + _$attributeToProperty(name, value) { + var _a; + const ctor = this.constructor; + // Note, hint this as an `AttributeMap` so closure clearly understands + // the type; it has issues with tracking types through statics + const propName = ctor.__attributeToPropertyMap.get(name); + // Use tracking info to avoid reflecting a property value to an attribute + // if it was just set because the attribute changed. + if (propName !== undefined && this.__reflectingProperty !== propName) { + const options = ctor.getPropertyOptions(propName); + const converter = typeof options.converter === 'function' + ? { fromAttribute: options.converter } + : ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.fromAttribute) !== undefined + ? options.converter + : defaultConverter; + // mark state reflecting + this.__reflectingProperty = propName; + this[propName] = converter.fromAttribute(value, options.type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ); + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** + * Requests an update which is processed asynchronously. This should be called + * when an element should update based on some state not triggered by setting + * a reactive property. In this case, pass no arguments. It should also be + * called when manually implementing a property setter. In this case, pass the + * property `name` and `oldValue` to ensure that any configured property + * options are honored. + * + * @param name name of requesting property + * @param oldValue old value of requesting property + * @param options property options to use instead of the previously + * configured options + * @category updates + */ + requestUpdate(name, oldValue, options) { + let shouldRequestUpdate = true; + // If we have a property key, perform property update steps. + if (name !== undefined) { + options = + options || + this.constructor.getPropertyOptions(name); + const hasChanged = options.hasChanged || notEqual; + if (hasChanged(this[name], oldValue)) { + if (!this._$changedProperties.has(name)) { + this._$changedProperties.set(name, oldValue); + } + // Add to reflecting properties set. + // Note, it's important that every change has a chance to add the + // property to `_reflectingProperties`. This ensures setting + // attribute + property reflects correctly. + if (options.reflect === true && this.__reflectingProperty !== name) { + if (this.__reflectingProperties === undefined) { + this.__reflectingProperties = new Map(); + } + this.__reflectingProperties.set(name, options); + } + } + else { + // Abort the request if the property should not be considered changed. + shouldRequestUpdate = false; + } + } + if (!this.isUpdatePending && shouldRequestUpdate) { + this.__updatePromise = this.__enqueueUpdate(); + } + // Note, since this no longer returns a promise, in dev mode we return a + // thenable which warns if it's called. + return undefined; + } + /** + * Sets up the element to asynchronously update. + */ + async __enqueueUpdate() { + this.isUpdatePending = true; + try { + // Ensure any previous update has resolved before updating. + // This `await` also ensures that property changes are batched. + await this.__updatePromise; + } + catch (e) { + // Refire any previous errors async so they do not disrupt the update + // cycle. Errors are refired so developers have a chance to observe + // them, and this can be done by implementing + // `window.onunhandledrejection`. + Promise.reject(e); + } + const result = this.scheduleUpdate(); + // If `scheduleUpdate` returns a Promise, we await it. This is done to + // enable coordinating updates with a scheduler. Note, the result is + // checked to avoid delaying an additional microtask unless we need to. + if (result != null) { + await result; + } + return !this.isUpdatePending; + } + /** + * Schedules an element update. You can override this method to change the + * timing of updates by returning a Promise. The update will await the + * returned Promise, and you should resolve the Promise to allow the update + * to proceed. If this method is overridden, `super.scheduleUpdate()` + * must be called. + * + * For instance, to schedule updates to occur just before the next frame: + * + * ```ts + * override protected async scheduleUpdate(): Promise { + * await new Promise((resolve) => requestAnimationFrame(() => resolve())); + * super.scheduleUpdate(); + * } + * ``` + * @category updates + */ + scheduleUpdate() { + return this.performUpdate(); + } + /** + * Performs an element update. Note, if an exception is thrown during the + * update, `firstUpdated` and `updated` will not be called. + * + * Call `performUpdate()` to immediately process a pending update. This should + * generally not be needed, but it can be done in rare cases when you need to + * update synchronously. + * + * Note: To ensure `performUpdate()` synchronously completes a pending update, + * it should not be overridden. In LitElement 2.x it was suggested to override + * `performUpdate()` to also customizing update scheduling. Instead, you should now + * override `scheduleUpdate()`. For backwards compatibility with LitElement 2.x, + * scheduling updates via `performUpdate()` continues to work, but will make + * also calling `performUpdate()` to synchronously process updates difficult. + * + * @category updates + */ + performUpdate() { + var _b; + // Abort any update if one is not pending when this is called. + // This can happen if `performUpdate` is called early to "flush" + // the update. + if (!this.isUpdatePending) { + return; + } + // create renderRoot before first update. + if (!this.hasUpdated) ; + // Mixin instance properties once, if they exist. + if (this.__instanceProperties) { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.__instanceProperties.forEach((v, p) => (this[p] = v)); + this.__instanceProperties = undefined; + } + let shouldUpdate = false; + const changedProperties = this._$changedProperties; + try { + shouldUpdate = this.shouldUpdate(changedProperties); + if (shouldUpdate) { + this.willUpdate(changedProperties); + (_b = this.__controllers) === null || _b === void 0 ? void 0 : _b.forEach((c) => { var _a; return (_a = c.hostUpdate) === null || _a === void 0 ? void 0 : _a.call(c); }); + this.update(changedProperties); + } + else { + this.__markUpdated(); + } + } + catch (e) { + // Prevent `firstUpdated` and `updated` from running when there's an + // update exception. + shouldUpdate = false; + // Ensure element can accept additional updates after an exception. + this.__markUpdated(); + throw e; + } + // The update is no longer considered pending and further updates are now allowed. + if (shouldUpdate) { + this._$didUpdate(changedProperties); + } + } + /** + * Invoked before `update()` to compute values needed during the update. + * + * Implement `willUpdate` to compute property values that depend on other + * properties and are used in the rest of the update process. + * + * ```ts + * willUpdate(changedProperties) { + * // only need to check changed properties for an expensive computation. + * if (changedProperties.has('firstName') || changedProperties.has('lastName')) { + * this.sha = computeSHA(`${this.firstName} ${this.lastName}`); + * } + * } + * + * render() { + * return html`SHA: ${this.sha}`; + * } + * ``` + * + * @category updates + */ + willUpdate(_changedProperties) { } + // Note, this is an override point for polyfill-support. + // @internal + _$didUpdate(changedProperties) { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostUpdated) === null || _a === void 0 ? void 0 : _a.call(c); }); + if (!this.hasUpdated) { + this.hasUpdated = true; + this.firstUpdated(changedProperties); + } + this.updated(changedProperties); + } + __markUpdated() { + this._$changedProperties = new Map(); + this.isUpdatePending = false; + } + /** + * Returns a Promise that resolves when the element has completed updating. + * The Promise value is a boolean that is `true` if the element completed the + * update without triggering another update. The Promise result is `false` if + * a property was set inside `updated()`. If the Promise is rejected, an + * exception was thrown during the update. + * + * To await additional asynchronous work, override the `getUpdateComplete` + * method. For example, it is sometimes useful to await a rendered element + * before fulfilling this Promise. To do this, first await + * `super.getUpdateComplete()`, then any subsequent state. + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + get updateComplete() { + return this.getUpdateComplete(); + } + /** + * Override point for the `updateComplete` promise. + * + * It is not safe to override the `updateComplete` getter directly due to a + * limitation in TypeScript which means it is not possible to call a + * superclass getter (e.g. `super.updateComplete.then(...)`) when the target + * language is ES5 (https://github.com/microsoft/TypeScript/issues/338). + * This method should be overridden instead. For example: + * + * ```ts + * class MyElement extends LitElement { + * override async getUpdateComplete() { + * const result = await super.getUpdateComplete(); + * await this._myChild.updateComplete; + * return result; + * } + * } + * ``` + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + getUpdateComplete() { + return this.__updatePromise; + } + /** + * Controls whether or not `update()` should be called when the element requests + * an update. By default, this method always returns `true`, but this can be + * customized to control when to update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + shouldUpdate(_changedProperties) { + return true; + } + /** + * Updates the element. This method reflects property values to attributes. + * It can be overridden to render and keep updated element DOM. + * Setting properties inside this method will *not* trigger + * another update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + update(_changedProperties) { + if (this.__reflectingProperties !== undefined) { + // Use forEach so this works even if for/of loops are compiled to for + // loops expecting arrays + this.__reflectingProperties.forEach((v, k) => this.__propertyToAttribute(k, this[k], v)); + this.__reflectingProperties = undefined; + } + this.__markUpdated(); + } + /** + * Invoked whenever the element is updated. Implement to perform + * post-updating tasks via DOM APIs, for example, focusing an element. + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + updated(_changedProperties) { } + /** + * Invoked when the element is first updated. Implement to perform one time + * work on the element after update. + * + * ```ts + * firstUpdated() { + * this.renderRoot.getElementById('my-text-area').focus(); + * } + * ``` + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + firstUpdated(_changedProperties) { } +} +_e = finalized; +/** + * Marks class as having finished creating properties. + */ +ReactiveElement[_e] = true; +/** + * Memoized list of all element properties, including any superclass properties. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category properties + */ +ReactiveElement.elementProperties = new Map(); +/** + * Memoized list of all element styles. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category styles + */ +ReactiveElement.elementStyles = []; +/** + * Options used when calling `attachShadow`. Set this property to customize + * the options for the shadowRoot; for example, to create a closed + * shadowRoot: `{mode: 'closed'}`. + * + * Note, these options are used in `createRenderRoot`. If this method + * is customized, options should be respected if possible. + * @nocollapse + * @category rendering + */ +ReactiveElement.shadowRootOptions = { mode: 'open' }; +// Apply polyfills if available +polyfillSupport$2 === null || polyfillSupport$2 === void 0 ? void 0 : polyfillSupport$2({ ReactiveElement }); +// IMPORTANT: do not change the property name or the assignment expression. +// This line will be used in regexes to search for ReactiveElement usage. +((_d$1 = global$1.reactiveElementVersions) !== null && _d$1 !== void 0 ? _d$1 : (global$1.reactiveElementVersions = [])).push('1.5.0'); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d; +// Use window for browser builds because IE11 doesn't have globalThis. +const global = window; +const __moz_domParser = new DOMParser(); +const wrap$1 = (node) => node; +const trustedTypes = global.trustedTypes; +/** + * Our TrustedTypePolicy for HTML which is declared using the html template + * tag function. + * + * That HTML is a developer-authored constant, and is parsed with innerHTML + * before any untrusted expressions have been mixed in. Therefor it is + * considered safe by construction. + */ +const policy = trustedTypes + ? trustedTypes.createPolicy('lit-html', { + createHTML: (s) => s, + }) + : undefined; +// Added to an attribute name to mark the attribute as bound so we can find +// it easily. +const boundAttributeSuffix = '$lit$'; +// This marker is used in many syntactic positions in HTML, so it must be +// a valid element name and attribute name. We don't support dynamic names (yet) +// but this at least ensures that the parse tree is closer to the template +// intention. +const marker = `lit$${String(Math.random()).slice(9)}$`; +// String used to tell if a comment is a marker comment +const markerMatch = '?' + marker; +// Text used to insert a comment marker node. We use processing instruction +// syntax because it's slightly smaller, but parses as a comment node. +const nodeMarker = `<${markerMatch}>`; +const d = document; +// Creates a dynamic marker. We never have to search for these in the DOM. +const createMarker$1 = (v = '') => d.createComment(v); +const isPrimitive$1 = (value) => value === null || (typeof value != 'object' && typeof value != 'function'); +const isArray = Array.isArray; +const isIterable = (value) => isArray(value) || + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof (value === null || value === void 0 ? void 0 : value[Symbol.iterator]) === 'function'; +const SPACE_CHAR = `[ \t\n\f\r]`; +const ATTR_VALUE_CHAR = `[^ \t\n\f\r"'\`<>=]`; +const NAME_CHAR = `[^\\s"'>=/]`; +// These regexes represent the five parsing states that we care about in the +// Template's HTML scanner. They match the *end* of the state they're named +// after. +// Depending on the match, we transition to a new state. If there's no match, +// we stay in the same state. +// Note that the regexes are stateful. We utilize lastIndex and sync it +// across the multiple regexes used. In addition to the five regexes below +// we also dynamically create a regex to find the matching end tags for raw +// text elements. +/** + * End of text is: `<` followed by: + * (comment start) or (tag) or (dynamic tag binding) + */ +const textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g; +const COMMENT_START = 1; +const TAG_NAME = 2; +const DYNAMIC_TAG_NAME = 3; +const commentEndRegex = /-->/g; +/** + * Comments not started with /g; +/** + * Comments not started with |$))/,Rt=dt("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",St).replace("tag",Ct).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Et=dt(kt).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Ct).getRegex(),At={blockquote:dt(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Et).getRegex(),code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,def:xt,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:yt,html:Rt,lheading:vt,list:_t,newline:/^(?: *(?:\n|$))+/,paragraph:Et,table:ft,text:/^[^\n]+/},Lt=dt("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Ct).getRegex(),Tt={...At,table:Lt,paragraph:dt(kt).replace("hr",yt).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",Lt).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Ct).getRegex()},Pt={...At,html:dt("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",St).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:ft,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:dt(kt).replace("hr",yt).replace("heading"," *#{1,6} *[^\n]").replace("lheading",vt).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},It=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,Dt=/^( {2,}|\\)\n(?!\s*$)/,Nt="\\p{P}\\p{S}",jt=dt(/^((?![*_])[\spunctuation])/,"u").replace(/punctuation/g,Nt).getRegex(),Ot=dt(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,Nt).getRegex(),zt=dt("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,Nt).getRegex(),Mt=dt("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,Nt).getRegex(),qt=dt(/\\([punct])/,"gu").replace(/punct/g,Nt).getRegex(),Wt=dt(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Ut=dt(St).replace("(?:--\x3e|$)","--\x3e").getRegex(),Ft=dt("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",Ut).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Bt=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Ht=dt(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",Bt).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Vt=dt(/^!?\[(label)\]\[(ref)\]/).replace("label",Bt).replace("ref",$t).getRegex(),Gt=dt(/^!?\[(ref)\](?:\[\])?/).replace("ref",$t).getRegex(),Yt={_backpedal:ft,anyPunctuation:qt,autolink:Wt,blockSkip:/\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g,br:Dt,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:ft,emStrongLDelim:Ot,emStrongRDelimAst:zt,emStrongRDelimUnd:Mt,escape:It,link:Ht,nolink:Gt,punctuation:jt,reflink:Vt,reflinkSearch:dt("reflink|nolink(?!\\()","g").replace("reflink",Vt).replace("nolink",Gt).getRegex(),tag:Ft,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\t+" ".repeat(n.length)));e;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some((r=>!!(n=r.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.space(e))e=e.substring(n.raw.length),1===n.raw.length&&t.length>0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),r=t[t.length-1],!r||"paragraph"!==r.type&&"text"!==r.type?t.push(n):(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=r.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),r=t[t.length-1],!r||"paragraph"!==r.type&&"text"!==r.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(r.raw+="\n"+n.raw,r.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=r.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else{if(s=e,this.options.extensions&&this.options.extensions.startBlock){let t=1/0;const n=e.slice(1);let r;this.options.extensions.startBlock.forEach((e=>{r=e.call({lexer:this},n),"number"==typeof r&&r>=0&&(t=Math.min(t,r))})),t<1/0&&t>=0&&(s=e.substring(0,t+1))}if(this.state.top&&(n=this.tokenizer.paragraph(s)))r=t[t.length-1],o&&"paragraph"===r.type?(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=r.text):t.push(n),o=s.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===r.type?(r.raw+="\n"+n.raw,r.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=r.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n,r,s,o,i,a,c=e;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(o=this.tokenizer.rules.inline.reflinkSearch.exec(c));)e.includes(o[0].slice(o[0].lastIndexOf("[")+1,-1))&&(c=c.slice(0,o.index)+"["+"a".repeat(o[0].length-2)+"]"+c.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(o=this.tokenizer.rules.inline.blockSkip.exec(c));)c=c.slice(0,o.index)+"["+"a".repeat(o[0].length-2)+"]"+c.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(o=this.tokenizer.rules.inline.anyPunctuation.exec(c));)c=c.slice(0,o.index)+"++"+c.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;e;)if(i||(a=""),i=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((r=>!!(n=r.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===n.type&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),r=t[t.length-1],r&&"text"===n.type&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,c,a))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e))){if(s=e,this.options.extensions&&this.options.extensions.startInline){let t=1/0;const n=e.slice(1);let r;this.options.extensions.startInline.forEach((e=>{r=e.call({lexer:this},n),"number"==typeof r&&r>=0&&(t=Math.min(t,r))})),t<1/0&&t>=0&&(s=e.substring(0,t+1))}if(n=this.tokenizer.inlineText(s))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(a=n.raw.slice(-1)),i=!0,r=t[t.length-1],r&&"text"===r.type?(r.raw+=n.raw,r.text+=n.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}else e=e.substring(n.raw.length),t.push(n);return t}}class tn{options;constructor(e){this.options=e||Xe}code(e,t,n){const r=(t||"").match(/^\S*/)?.[0];return e=e.replace(/\n$/,"")+"\n",r?'
    '+(n?e:at(e,!0))+"
    \n":"
    "+(n?e:at(e,!0))+"
    \n"}blockquote(e){return`
    \n${e}
    \n`}html(e,t){return e}heading(e,t,n){return`${e}\n`}hr(){return"
    \n"}list(e,t,n){const r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"}listitem(e,t,n){return`
  • ${e}
  • \n`}checkbox(e){return"'}paragraph(e){return`

    ${e}

    \n`}table(e,t){return t&&(t=`${t}`),"\n\n"+e+"\n"+t+"
    \n"}tablerow(e){return`\n${e}\n`}tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`\n`}strong(e){return`${e}`}em(e){return`${e}`}codespan(e){return`${e}`}br(){return"
    "}del(e){return`${e}`}link(e,t,n){const r=pt(e);if(null===r)return n;let s='
    ",s}image(e,t,n){const r=pt(e);if(null===r)return n;let s=`${n}0&&"paragraph"===n.tokens[0].type?(n.tokens[0].text=e+" "+n.tokens[0].text,n.tokens[0].tokens&&n.tokens[0].tokens.length>0&&"text"===n.tokens[0].tokens[0].type&&(n.tokens[0].tokens[0].text=e+" "+n.tokens[0].tokens[0].text)):n.tokens.unshift({type:"text",text:e+" "}):a+=e+" "}a+=this.parse(n.tokens,o),i+=this.renderer.listitem(a,s,!!r)}n+=this.renderer.list(i,t,r);continue}case"html":{const e=s;n+=this.renderer.html(e.text,e.block);continue}case"paragraph":{const e=s;n+=this.renderer.paragraph(this.parseInline(e.tokens));continue}case"text":{let o=s,i=o.tokens?this.parseInline(o.tokens):o.text;for(;r+1{const s=e[r].flat(1/0);n=n.concat(this.walkTokens(s,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let r=e.renderer.apply(this,t);return!1===r&&(r=n.apply(this,t)),r}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new tn(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if("options"===n)continue;const r=n,s=e.renderer[r],o=t[r];t[r]=(...e)=>{let n=s.apply(t,e);return!1===n&&(n=o.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new bt(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const r=n,s=e.tokenizer[r],o=t[r];t[r]=(...e)=>{let n=s.apply(t,e);return!1===n&&(n=o.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new sn;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if("options"===n)continue;const r=n,s=e.hooks[r],o=t[r];sn.passThroughHooks.has(n)?t[r]=e=>{if(this.defaults.async)return Promise.resolve(s.call(t,e)).then((e=>o.call(t,e)));const n=s.call(t,e);return o.call(t,n)}:t[r]=(...e)=>{let n=s.apply(t,e);return!1===n&&(n=o.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,r=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(r.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return en.lex(e,t??this.defaults)}parser(e,t){return rn.parse(e,t??this.defaults)}#e(e,t){return(n,r)=>{const s={...r},o={...this.defaults,...s};!0===this.defaults.async&&!1===s.async&&(o.silent||console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."),o.async=!0);const i=this.#t(!!o.silent,!!o.async);if(null==n)return i(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return i(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(o.hooks&&(o.hooks.options=o),o.async)return Promise.resolve(o.hooks?o.hooks.preprocess(n):n).then((t=>e(t,o))).then((e=>o.hooks?o.hooks.processAllTokens(e):e)).then((e=>o.walkTokens?Promise.all(this.walkTokens(e,o.walkTokens)).then((()=>e)):e)).then((e=>t(e,o))).then((e=>o.hooks?o.hooks.postprocess(e):e)).catch(i);try{o.hooks&&(n=o.hooks.preprocess(n));let r=e(n,o);o.hooks&&(r=o.hooks.processAllTokens(r)),o.walkTokens&&this.walkTokens(r,o.walkTokens);let s=t(r,o);return o.hooks&&(s=o.hooks.postprocess(s)),s}catch(e){return i(e)}}}#t(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+at(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}};function an(e,t){return on.parse(e,t)}function cn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}an.options=an.setOptions=function(e){return on.setOptions(e),an.defaults=on.defaults,et(an.defaults),an},an.getDefaults=Qe,an.defaults=Xe,an.use=function(...e){return on.use(...e),an.defaults=on.defaults,et(an.defaults),an},an.walkTokens=function(e,t){return on.walkTokens(e,t)},an.parseInline=on.parseInline,an.Parser=rn,an.parser=rn.parse,an.Renderer=tn,an.TextRenderer=nn,an.Lexer=en,an.lexer=en.lex,an.Tokenizer=bt,an.Hooks=sn,an.parse=an,an.options,an.setOptions,an.use,an.walkTokens,an.parseInline,rn.parse,en.lex;var ln,un={exports:{}};var dn,pn=(ln||(ln=1,dn=un,function(e,t){dn.exports=t()}(0,(function(){var e=[],t=[],n={},r={},s={};function o(e){return"string"==typeof e?new RegExp("^"+e+"$","i"):e}function i(e,t){return e===t?t:e===e.toLowerCase()?t.toLowerCase():e===e.toUpperCase()?t.toUpperCase():e[0]===e[0].toUpperCase()?t.charAt(0).toUpperCase()+t.substr(1).toLowerCase():t.toLowerCase()}function a(e,t){return e.replace(t[0],(function(n,r){var s,o,a=(s=t[1],o=arguments,s.replace(/\$(\d{1,2})/g,(function(e,t){return o[t]||""})));return i(""===n?e[r-1]:n,a)}))}function c(e,t,r){if(!e.length||n.hasOwnProperty(e))return t;for(var s=r.length;s--;){var o=r[s];if(o[0].test(t))return a(t,o)}return t}function l(e,t,n){return function(r){var s=r.toLowerCase();return t.hasOwnProperty(s)?i(r,s):e.hasOwnProperty(s)?i(r,e[s]):c(s,r,n)}}function u(e,t,n,r){return function(r){var s=r.toLowerCase();return!!t.hasOwnProperty(s)||!e.hasOwnProperty(s)&&c(s,s,n)===s}}function d(e,t,n){return(n?t+" ":"")+(1===t?d.singular(e):d.plural(e))}return d.plural=l(s,r,e),d.isPlural=u(s,r,e),d.singular=l(r,s,t),d.isSingular=u(r,s,t),d.addPluralRule=function(t,n){e.push([o(t),n])},d.addSingularRule=function(e,n){t.push([o(e),n])},d.addUncountableRule=function(e){"string"!=typeof e?(d.addPluralRule(e,"$0"),d.addSingularRule(e,"$0")):n[e.toLowerCase()]=!0},d.addIrregularRule=function(e,t){t=t.toLowerCase(),e=e.toLowerCase(),s[e]=t,r[t]=e},[["I","we"],["me","us"],["he","they"],["she","they"],["them","them"],["myself","ourselves"],["yourself","yourselves"],["itself","themselves"],["herself","themselves"],["himself","themselves"],["themself","themselves"],["is","are"],["was","were"],["has","have"],["this","these"],["that","those"],["echo","echoes"],["dingo","dingoes"],["volcano","volcanoes"],["tornado","tornadoes"],["torpedo","torpedoes"],["genus","genera"],["viscus","viscera"],["stigma","stigmata"],["stoma","stomata"],["dogma","dogmata"],["lemma","lemmata"],["schema","schemata"],["anathema","anathemata"],["ox","oxen"],["axe","axes"],["die","dice"],["yes","yeses"],["foot","feet"],["eave","eaves"],["goose","geese"],["tooth","teeth"],["quiz","quizzes"],["human","humans"],["proof","proofs"],["carve","carves"],["valve","valves"],["looey","looies"],["thief","thieves"],["groove","grooves"],["pickaxe","pickaxes"],["passerby","passersby"]].forEach((function(e){return d.addIrregularRule(e[0],e[1])})),[[/s?$/i,"s"],[/[^\u0000-\u007F]$/i,"$0"],[/([^aeiou]ese)$/i,"$1"],[/(ax|test)is$/i,"$1es"],[/(alias|[^aou]us|t[lm]as|gas|ris)$/i,"$1es"],[/(e[mn]u)s?$/i,"$1s"],[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i,"$1"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1i"],[/(alumn|alg|vertebr)(?:a|ae)$/i,"$1ae"],[/(seraph|cherub)(?:im)?$/i,"$1im"],[/(her|at|gr)o$/i,"$1oes"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,"$1a"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,"$1a"],[/sis$/i,"ses"],[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i,"$1$2ves"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/([^ch][ieo][ln])ey$/i,"$1ies"],[/(x|ch|ss|sh|zz)$/i,"$1es"],[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i,"$1ices"],[/\b((?:tit)?m|l)(?:ice|ouse)$/i,"$1ice"],[/(pe)(?:rson|ople)$/i,"$1ople"],[/(child)(?:ren)?$/i,"$1ren"],[/eaux$/i,"$0"],[/m[ae]n$/i,"men"],["thou","you"]].forEach((function(e){return d.addPluralRule(e[0],e[1])})),[[/s$/i,""],[/(ss)$/i,"$1"],[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,"$1fe"],[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i,"$1f"],[/ies$/i,"y"],[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,"$1ie"],[/\b(mon|smil)ies$/i,"$1ey"],[/\b((?:tit)?m|l)ice$/i,"$1ouse"],[/(seraph|cherub)im$/i,"$1"],[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,"$1"],[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,"$1sis"],[/(movie|twelve|abuse|e[mn]u)s$/i,"$1"],[/(test)(?:is|es)$/i,"$1is"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1us"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,"$1um"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,"$1on"],[/(alumn|alg|vertebr)ae$/i,"$1a"],[/(cod|mur|sil|vert|ind)ices$/i,"$1ex"],[/(matr|append)ices$/i,"$1ix"],[/(pe)(rson|ople)$/i,"$1rson"],[/(child)ren$/i,"$1"],[/(eau)x?$/i,"$1"],[/men$/i,"man"]].forEach((function(e){return d.addSingularRule(e[0],e[1])})),["adulthood","advice","agenda","aid","aircraft","alcohol","ammo","analytics","anime","athletics","audio","bison","blood","bream","buffalo","butter","carp","cash","chassis","chess","clothing","cod","commerce","cooperation","corps","debris","diabetes","digestion","elk","energy","equipment","excretion","expertise","firmware","flounder","fun","gallows","garbage","graffiti","hardware","headquarters","health","herpes","highjinks","homework","housework","information","jeans","justice","kudos","labour","literature","machinery","mackerel","mail","media","mews","moose","music","mud","manga","news","only","personnel","pike","plankton","pliers","police","pollution","premises","rain","research","rice","salmon","scissors","series","sewage","shambles","shrimp","software","species","staff","swine","tennis","traffic","transportation","trout","tuna","wealth","welfare","whiting","wildebeest","wildlife","you",/pok[eé]mon$/i,/[^aeiou]ese$/i,/deer$/i,/fish$/i,/measles$/i,/o[iu]s$/i,/pox$/i,/sheep$/i].forEach(d.addUncountableRule),d}))),un.exports),fn=cn(pn),hn=function(e){var t={};try{t.WeakMap=WeakMap}catch(u){t.WeakMap=function(e,t){var n=t.defineProperty,r=t.hasOwnProperty,s=o.prototype;return s.delete=function(e){return this.has(e)&&delete e[this._]},s.get=function(e){return this.has(e)?e[this._]:void 0},s.has=function(e){return r.call(e,this._)},s.set=function(e,t){return n(e,this._,{configurable:!0,value:t}),this},o;function o(t){n(this,"_",{value:"_@ungap/weakmap"+e++}),t&&t.forEach(i,this)}function i(e){this.set(e[0],e[1])}}(Math.random(),Object)}var n=t.WeakMap,r={};try{r.WeakSet=WeakSet}catch(u){!function(e,t){var n=s.prototype;function s(){t(this,"_",{value:"_@ungap/weakmap"+e++})}n.add=function(e){return this.has(e)||t(e,this._,{value:!0,configurable:!0}),this},n.has=function(e){return this.hasOwnProperty.call(e,this._)},n.delete=function(e){return this.has(e)&&delete e[this._]},r.WeakSet=s}(Math.random(),Object.defineProperty)}function s(e,t,n,r,s,o){for(var i=("selectedIndex"in t),a=i;r>>0;ni;)--c;l=a+r-c;var y=Array(l),w=u[c];for(--n;w;){for(var v=w.newi,k=w.oldi;v"+e+"",r.querySelectorAll(t)):(r.innerHTML=e,r.childNodes)),n},function(e,t){return("svg"===t?function(e){var t=z(S),n=z("div");return n.innerHTML=''+e+"",O(t,n.firstChild.childNodes),t}:E)(e)});function O(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function z(e){return e===S?C.createDocumentFragment():C.createElementNS("http://www.w3.org/1999/xhtml",e)}var M,q,W,U,F,B,H,V,G,Y=(q="appendChild",W="cloneNode",U="createTextNode",B=(F="importNode")in(M=e),(H=M.createDocumentFragment())[q](M[U]("g")),H[q](M[U]("")),(B?M[F](H,!0):H[W](!0)).childNodes.length<2?function e(t,n){for(var r=t[W](),s=t.childNodes||[],o=s.length,i=0;n&&i

    ',V.content.childNodes[0].getAttribute(G)==Z)||(Z="_dt: "+Z.slice(1,-1)+";",J=!0)}catch(u){}var Q="\x3c!--"+Z+"--\x3e",X=8,ee=1,te=3,ne=/^(?:style|textarea)$/i,re=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,se=" \\f\\n\\r\\t",oe="[^"+se+"\\/>\"'=]+",ie="["+se+"]+"+oe,ae="<([A-Za-z]+[A-Za-z0-9:._-]*)((?:",ce="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|"+oe.replace("\\/","")+"))?)",le=new RegExp(ae+ie+ce+"+)(["+se+"]*/?>)","g"),ue=new RegExp(ae+ie+ce+"*)(["+se+"]*/>)","g"),de=new RegExp("("+ie+"\\s*=\\s*)(['\"]?)"+Q+"\\2","gi");function pe(e,t,n,r){return"<"+t+n.replace(de,fe)+r}function fe(e,t,n){return t+(n||'"')+Z+(n||'"')}function he(e,t,n){return re.test(t)?e:"<"+t+n+">"}var me=J?function(e,t){var n=t.join(" ");return t.slice.call(e,0).sort((function(e,t){return n.indexOf(e.name)<=n.indexOf(t.name)?-1:1}))}:function(e,t){return t.slice.call(e,0)};function ge(t,n,r,s){for(var o=t.childNodes,i=o.length,a=0;a{e.remove()}))}function Dn(e,t="long"){const n=new Intl.ListFormat(o,{style:t,type:e});return(e,t)=>{let r=0;return n.formatToParts(e).map((({type:n,value:s})=>"element"===n&&t?t(s,r++,e):s))}}const Nn=Dn("conjunction"),jn=Dn("disjunction");function On(e,t){return Nn(e,t).join("")}function zn(e,t){return jn(e,t).join("")}function Mn(e){return e.replace(/&/g,"&").replace(/>/g,">").replace(/"/g,""").replace(/new Date)return o}catch(e){console.error("Failed to use Cache API.",e)}const i=await fetch(n);if(!i.ok&&o)return console.warn(`Returning a stale cached response for ${r}`),o;if(s&&i.ok){const e=i.clone(),r=new Headers(i.headers),o=new Date(Date.now()+t);r.set("Expires",o.toISOString());const a=new Response(await e.blob(),{headers:r});await s.put(n,a).catch(console.error)}return i}function Vn(e,t=(e=>e)){const n=e.map(t),r=n.slice(0,-1).map((e=>kn`${e}, `));return kn`${r}${n[n.length-1]}`}function Gn(e,t){return[].concat(Nn(e,t)).map((e=>"string"==typeof e?kn`${e}`:e))}function Yn(e,t=""){const n=function(e){let t=0;for(const n of e)t=Math.imul(31,t)+n.charCodeAt(0)|0;return String(t)}(qn(e.textContent));return Kn(e,t,n)}function Kn(e,t="",n="",r=!1){if(e.id)return e.id;n||(n=(e.title?e.title:e.textContent).trim());let s=r?n:n.toLowerCase();if(s=s.trim().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/\W+/gim,"-").replace(/^-+/,"").replace(/-+$/,""),s?!/\.$/.test(s)&&/^[a-z]/i.test(t||s)||(s=`x${s}`):s="generatedID",t&&(s=`${t}-${s}`),e.ownerDocument.getElementById(s)){let t=0,n=`${s}-${t}`;for(;e.ownerDocument.getElementById(n);)t+=1,n=`${s}-${t}`;s=n}return e.id=s,s}function Zn(e){const t=new Set,n="ltNodefault"in e.dataset?"":qn(e.textContent),r=e.children[0];if(e.dataset.lt?e.dataset.lt.split("|").map((e=>qn(e))).forEach((e=>t.add(e))):1===e.childNodes.length&&1===e.getElementsByTagName("abbr").length&&r.title?t.add(r.title):'""'===e.textContent&&t.add("the-empty-string"),t.add(n),t.delete(""),e.dataset.localLt){e.dataset.localLt.split("|").forEach((e=>t.add(qn(e))))}return[...t]}function Jn(e,t,n={copyAttributes:!0}){if(e.localName===t)return e;const r=e.ownerDocument.createElement(t);if(n.copyAttributes)for(const{name:t,value:n}of e.attributes)r.setAttribute(t,n);return r.append(...e.childNodes),e.replaceWith(r),r}function Qn(e,t){const n=t.closest(Tn);let r=!1;if(n&&(r=!t.closest(".normative")||!n.querySelector(".normative")),e.startsWith("!")){if(r)return{type:"informative",illegal:!0};r=!1}else e.startsWith("?")&&(r=!0);return{type:r?"informative":"normative",illegal:!1}}function Xn(e,t){return t.append(...e.childNodes),e.appendChild(t),e}function er(e){const t=[];for(const n of function*(e){let t=e;for(;t.previousElementSibling;)t=t.previousElementSibling,yield t}(e))"section"===n.localName&&t.push(n);return t}function tr(e,t){const n=[];let r=e.parentElement;for(;r;){const e=r.closest(t);if(!e)break;n.push(e),r=e.parentElement}return n}function nr(e){const{previousSibling:t}=e;if(!t||t.nodeType!==Node.TEXT_NODE)return"";const n=t.textContent.lastIndexOf("\n");if(-1===n)return"";const r=t.textContent.slice(n+1);return/\S/.test(r)?"":r}class rr extends Set{constructor(e=[]){super();for(const t of e)this.add(t)}add(e){return this.has(e)||this.getCanonicalKey(e)?this:super.add(e)}has(e){return super.has(e)||[...this.keys()].some((t=>t.toLowerCase()===e.toLowerCase()))}delete(e){return super.has(e)?super.delete(e):super.delete(this.getCanonicalKey(e))}getCanonicalKey(e){return super.has(e)?e:[...this.keys()].find((t=>t.toLowerCase()===e.toLowerCase()))}}function sr(e){const t=e.cloneNode(!0);return t.querySelectorAll("[id]").forEach((e=>e.removeAttribute("id"))),t.querySelectorAll("dfn").forEach((e=>{Jn(e,"span",{copyAttributes:!1})})),t.hasAttribute("id")&&t.removeAttribute("id"),or(t),t}function or(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(const e of[...ir(t)])e.remove()}function*ir(e){for(;e.nextNode();)yield e.currentNode}class ar extends Map{constructor(e=[]){return super(),e.forEach((([e,t])=>{this.set(e,t)})),this}set(e,t){return super.set(e.toLowerCase(),t),this}get(e){return super.get(e.toLowerCase())}has(e){return super.has(e.toLowerCase())}delete(e){return super.delete(e.toLowerCase())}}class cr extends Error{constructor(e,t,n){super(e,{...n.cause&&{cause:n.cause}});const r=n.isWarning?"ReSpecWarning":"ReSpecError";Object.assign(this,{message:e,plugin:t,name:r,...n}),n.elements&&n.elements.forEach((t=>function(e,t,n){e.classList.add("respec-offending-element"),e.hasAttribute("title")||e.setAttribute("title",n||t),e.id||Kn(e,"respec-offender")}(t,e,n.title)))}toJSON(){const{message:e,name:t,stack:n}=this,{plugin:r,hint:s,elements:o,title:i,details:a}=this;return{message:e,name:t,plugin:r,hint:s,elements:o,title:i,details:a,stack:n,...this.cause instanceof Error&&{cause:{name:this.cause.name,message:this.cause.message,stack:this.cause.stack}}}}}function lr(e,t,n={}){const r={...n,isWarning:!1};wr("error",new cr(e,t,r))}function ur(e,t,n={}){const r={...n,isWarning:!0};wr("warn",new cr(e,t,r))}function dr(e){return{showError:(t,n)=>lr(t,e,n),showWarning:(t,n)=>ur(t,e,n)}}function pr(e){return e?`\`${e}\``:""}function fr(e,{quotes:t}={quotes:!1}){return zn(e,t?e=>pr(mr(e)):pr)}function hr(e,{quotes:t}={quotes:!1}){return On(e,t?e=>pr(mr(e)):pr)}function mr(e){return String(e)?`"${e}"`:""}function gr(e,...t){return br(e.map(((e,n)=>{const r=t[n];if(!r)return e;if(!r.startsWith("[")&&!r.endsWith("]"))return e+r;const[s,o]=r.slice(1,-1).split("|");if(o){return`${e}[${s}](${new URL(o,"https://respec.org/docs/")})`}return`${e}[\`${s}\`](https://respec.org/docs/#${s})`})).join(""))}function br(e){if(!e)return e;const t=e.trimEnd().split("\n");for(;t.length&&!t[0].trim();)t.shift();const n=t.filter((e=>e.trim())).map((e=>e.search(/[^\s]/))),r=Math.min(...n);return t.map((e=>e.slice(r))).join("\n")}const yr=new EventTarget;function wr(e,t){if(yr.dispatchEvent(new CustomEvent(e,{detail:t})),window.parent===window.self)return;const n=String(JSON.stringify(t?.stack||t));window.parent.postMessage({topic:e,args:n},window.parent.location.origin)}function vr(e,t,n={once:!1}){yr.addEventListener(e,(async n=>{try{await t(n.detail)}catch(t){lr(`Error in handler for topic "${e}": ${t.message}`,`sub:${e}`,{cause:t})}}),n)}n("core/pubsubhub",{sub:vr});const kr=["githubToken","githubUser"];const $r=new Map([["text/html","html"],["application/xml","xml"]]);function xr(e,t=document){const n=$r.get(e);if(!n){const t=[...$r.values()].join(", ");throw new TypeError(`Invalid format: ${e}. Expected one of: ${t}.`)}const r=_r(n,t);return`data:${e};charset=utf-8,${encodeURIComponent(r)}`}function _r(e,t){const n=t.cloneNode(!0);!function(e){const{head:t,body:n,documentElement:r}=e;or(e),e.querySelectorAll(".removeOnSave, #toc-nav").forEach((e=>e.remove())),n.classList.remove("toc-sidebar"),In(r);const s=e.createDocumentFragment(),o=e.querySelector("meta[name='viewport']");o&&t.firstChild!==o&&s.appendChild(o);let i=e.querySelector("meta[charset], meta[content*='charset=']");i||(i=kn``);s.appendChild(i);const a=`ReSpec ${window.respecVersion||"Developer Channel"}`,c=kn` + + `;s.appendChild(c),t.prepend(s),wr("beforesave",r)}(n);let r="";if("xml"===e)r=(new XMLSerializer).serializeToString(n);else!function(e){e.querySelectorAll("style").forEach((e=>{e.innerHTML=`\n${e.innerHTML}\n`})),e.querySelectorAll("head > *").forEach((e=>{e.outerHTML=`\n${e.outerHTML}`}))}(n),n.doctype&&(r+=(new XMLSerializer).serializeToString(n.doctype)),r+=n.documentElement.outerHTML;return r}n("core/exporter",{rsDocToDataURL:xr});class Cr{constructor(){this._respecDonePromise=new Promise((e=>{vr("end-all",(()=>e()),{once:!0})})),this.errors=[],this.warnings=[],vr("error",(e=>{console.error(e,e.toJSON()),this.errors.push(e)})),vr("warn",(e=>{console.warn(e,e.toJSON()),this.warnings.push(e)}))}get version(){return window.respecVersion}get ready(){return this._respecDonePromise}async toHTML(){return _r("html",document)}}const Sr="core/post-process";const Rr="core/pre-process";const Er="core/base-runner";async function Ar(e){!function(){const e=new Cr;Object.defineProperty(document,"respec",{value:e})}(),wr("start-all",respecConfig),function(e){const t={},n=e=>Object.assign(t,e);n(e),vr("amend-user-config",n),vr("end-all",(()=>{const e=document.createElement("script");e.id="initialUserConfig",e.type="application/json";for(const e of kr)e in t&&delete t[e];e.innerHTML=JSON.stringify(t,null,2),document.head.appendChild(e)}))}(respecConfig),function(e){const t=new URLSearchParams(document.location.search),n=Array.from(t).filter((([e,t])=>!!e&&!!t)).map((([e,t])=>{const n=decodeURIComponent(e),r=decodeURIComponent(t.replace(/%3D/g,"="));let s;try{s=JSON.parse(r)}catch{s=r}return[n,s]})),r=Object.fromEntries(n);Object.assign(e,r),wr("amend-user-config",r)}(respecConfig),performance.mark(`${Er}-start`),await async function(e){if(Array.isArray(e.preProcess)){const t=e.preProcess.filter((e=>{const t="function"==typeof e;return t||lr("Every item in `preProcess` must be a JS function.",Rr),t}));for(const[n,r]of t.entries()){const t=`${Rr}/${r.name||`[${n}]`}`,s=dr(t);try{await r(e,document,s)}catch(e){lr(`Function ${t} threw an error during \`preProcess\`.`,Rr,{hint:"See developer console.",cause:e})}}}}(respecConfig);const t=e.filter((e=>{return(t=e)&&(t.run||t.Plugin);var t}));t.forEach((e=>!e.name&&console.warn("Plugin lacks name:",e))),await async function(e,t){for(const n of e.filter((e=>e.prepare)))try{await n.prepare(t)}catch(e){console.error(e)}}(t,respecConfig),await async function(e,t){for(const n of e){const e=n.name||"";try{await new Promise((async(r,s)=>{const o=setTimeout((()=>{const t=`Plugin ${e} took too long.`;console.error(t,n),s(new Error(t))}),15e3);performance.mark(`${e}-start`);try{n.Plugin?(await new n.Plugin(t).run(),r()):n.run&&(await n.run(t),r())}catch(e){s(e)}finally{clearTimeout(o),performance.mark(`${e}-end`),performance.measure(e,`${e}-start`,`${e}-end`)}}))}catch(e){console.error(e)}}}(t,respecConfig),wr("plugins-done",respecConfig),await async function(e){if(Array.isArray(e.postProcess)){const t=e.postProcess.filter((e=>{const t="function"==typeof e;return t||lr("Every item in `postProcess` must be a JS function.",Sr),t}));for(const[n,r]of t.entries()){const t=`${Sr}/${r.name||`[${n}]`}`,s=dr(t);try{await r(e,document,s)}catch(e){lr(`Function ${t} threw an error during \`postProcess\`.`,Sr,{hint:"See developer console.",cause:e})}}}"function"==typeof e.afterEnd&&await e.afterEnd(e,document)}(respecConfig),wr("end-all"),In(document),performance.mark(`${Er}-end`),performance.measure(Er,`${Er}-start`,`${Er}-end`)}var Lr=String.raw`.respec-modal .close-button{position:absolute;z-index:inherit;padding:.2em;font-weight:700;cursor:pointer;margin-left:5px;border:none;background:0 0} +#respec-ui{position:fixed;display:flex;flex-direction:row-reverse;top:20px;right:20px;width:202px;text-align:right;z-index:9000} +#respec-pill,.respec-info-button{height:2.4em;background:#fff;background:var(--bg,#fff);color:#787878;color:var(--tocnav-normal-text,#787878);border:1px solid #ccc;box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);box-shadow:1px 1px 8px 0 var(--tocsidebar-shadow,rgba(100,100,100,.5));padding:.2em 0} +.respec-info-button{border:none;opacity:.75;border-radius:2em;margin-right:1em;min-width:3.5em;will-change:opacity} +.respec-info-button:focus,.respec-info-button:hover{opacity:1;transition:opacity .2s} +#respec-pill{width:4.8em} +#respec-pill:not(:disabled){animation:respec-fadein .6s ease-in-out} +@keyframes respec-fadein{ +from{margin-top:-1.2em;border-radius:50%;border:.2em solid rgba(100,100,100,.5);box-shadow:none;height:4.8em} +to{margin-top:0;border:1px solid #ccc;border-radius:0;box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);height:2.4em} +} +#respec-pill:disabled{margin-top:-1.2em;position:relative;border:none;box-shadow:none;border-radius:50%;width:4.8em;height:4.8em;padding:0} +#respec-pill:disabled::after{position:absolute;content:'';inset:-.2em;border-radius:50%;border:.2em solid rgba(100,100,100,.5);border-left:.2em solid transparent;animation:respec-spin .5s infinite linear} +@media (prefers-reduced-motion){ +#respec-pill:not(:disabled){animation:none} +#respec-pill:disabled::after{animation:none;border-left:.2em solid rgba(100,100,100,.5)} +} +@keyframes respec-spin{ +0%{transform:rotate(0)} +100%{transform:rotate(360deg)} +} +.respec-hidden{visibility:hidden;opacity:0;transition:visibility 0s .2s,opacity .2s linear} +.respec-visible{visibility:visible;opacity:1;transition:opacity .2s linear} +#respec-pill:focus,#respec-pill:hover{color:#000;background-color:#f5f5f5;transition:color .2s} +#respec-menu{position:absolute;margin:0;padding:0;font-family:sans-serif;background:var(--bg,#fff);color:var(--text,#000);box-shadow:1px 1px 8px 0 rgba(100,100,100,.5);width:200px;display:none;text-align:left;margin-top:32px;font-size:.8em} +#respec-menu:not([hidden]){display:block} +#respec-menu li{list-style-type:none;margin:0;padding:0} +.respec-save-buttons{display:grid;grid-template-columns:repeat(auto-fill,minmax(47%,2fr));grid-gap:.5cm;padding:.5cm} +.respec-save-button:link{padding-top:16px;color:var(--def-text,#fff);background:var(--def-bg,#2a5aa8);justify-self:stretch;height:1cm;text-decoration:none;text-align:center;font-size:inherit;border:none;border-radius:.2cm} +.respec-save-button:link:hover{color:var(--def-text,#fff);background:var(--defrow-border,#2a5aa8);padding:0;margin:0;border:0;padding-top:16px} +.respec-save-button:link:focus{background:var(--tocnav-active-bg,#193766);color:var(--tocnav-active-text,#000)} +#respec-pill:focus,#respec-ui button:focus,.respec-option:focus{outline:0;outline-style:none} +#respec-pill-error{background-color:red;color:#fff} +#respec-pill-warning{background-color:orange;color:#fff} +.respec-error-list,.respec-warning-list{margin:0;padding:0;font-family:sans-serif;font-size:.85em} +.respec-warning-list{background-color:#fffbe6} +:is(.respec-warning-list,.respec-error-list)>li{list-style-type:none;margin:0;padding:.5em 0;padding-left:2em;padding-right:.5em} +:is(.respec-warning-list,.respec-error-list)>li+li{margin-top:.5rem} +:is(.respec-warning-list,.respec-error-list)>li:before{position:absolute;left:.4em} +:is(.respec-warning-list,.respec-error-list) p{padding:0;margin:0} +.respec-warning-list>li{color:#5c3b00;border-bottom:thin solid #fff5c2} +.respec-error-list,.respec-error-list li{background-color:#fff0f0} +.respec-warning-list>li::before{content:"âš ï¸"} +.respec-error-list>li::before{content:"💥"} +.respec-error-list>li{color:#5c3b00;border-bottom:thin solid #ffd7d7} +:is(.respec-warning-list,.respec-error-list)>li li{list-style:disc} +#respec-overlay{display:block;position:fixed;z-index:10000;top:0;left:0;height:100%;width:100%;background:#000} +.respec-show-overlay{transition:opacity .2s linear;opacity:.5} +.respec-hide-overlay{transition:opacity .2s linear;opacity:0} +.respec-modal{display:block;position:fixed;z-index:11000;top:10%;background:var(--bg,#fff);color:var(--text,#000);border:5px solid #666;border-color:var(--tocsidebar-shadow,#666);min-width:20%;padding:0;max-height:80%;overflow-y:auto;margin:0 -.5cm;left:20%;max-width:75%;min-width:60%} +.respec-modal h3{margin:0;padding:.2em;left:0!important;text-align:center;background:var(--tocsidebar-shadow,#ddd);color:var(--text,#000);font-size:1em} +#respec-menu button.respec-option{background:var(--bg,#fff);color:var(--text,#000);border:none;width:100%;text-align:left;font-size:inherit;padding:1.2em 1.2em} +#respec-menu button.respec-option:hover{background-color:var(--tocnav-hover-bg,#eee);color:var(--tocnav-hover-text,#000)} +.respec-cmd-icon{padding-right:.5em} +#respec-ui button.respec-option:first-child{margin-top:0} +#respec-ui button.respec-option:last-child{border:none;border-radius:inherit;margin-bottom:0} +.respec-button-copy-paste{position:absolute;height:28px;width:40px;cursor:pointer;background-image:linear-gradient(#fcfcfc,#eee);border:1px solid #90b8de;border-left:0;border-radius:0 0 3px 0;-webkit-user-select:none;user-select:none;-webkit-appearance:none;top:0;left:127px} +@media print{ +#respec-ui{display:none} +} +.respec-iframe{width:100%;min-height:550px;height:100%;overflow:hidden;padding:0;margin:0;border:0} +.respec-iframe:not(.ready){background:url(https://respec.org/xref/loader.gif) no-repeat center} +.respec-iframe+a[href]{font-size:.9rem;float:right;margin:0 .5em .5em;border-bottom-width:1px} +p:is(.respec-hint,.respec-occurrences){display:block;margin-top:.5em} +.respec-plugin{text-align:right;color:rgb(120,120,120,.5);font-size:.6em}`;const Tr=/>/gm,Pr=/&/gm;class Ir extends xn.Renderer{code(e,t,n){const{language:r,...s}=Ir.parseInfoString(t);if(/(^webidl$)/i.test(r))return`
    ${e}
    `;const o=super.code(e,r,n).replace('class="language-','class="'),{example:i,illegalExample:a}=s;if(!i&&!a)return o;const c=i||a,l=`${r} ${i?"example":"illegal-example"}`;return o.replace("
    ",`
    `)}image(e,t,n){if(!t)return super.image(e,t,n);return String.raw`
    +      
    + ${n} +
    ${t}
    +
    + `}static parseInfoString(e){const t=e.search(/\s/);if(-1===t)return{language:e};const n=e.slice(0,t),r=e.slice(t+1);let s;if(r)try{s=JSON.parse(`{ ${r} }`)}catch(e){console.error(e)}return{language:n,...s}}heading(e,t,n){const r=/(.+)\s+{#([\w-]+)}$/;if(r.test(e)){const[,n,s]=e.match(r);return`${n}`}return super.heading(e,t,n)}}const Dr={gfm:!0,renderer:new Ir};function Nr(e,t={inline:!1}){const n=br(e).replace(Tr,">").replace(Pr,"&");return t.inline?xn.parseInline(n,Dr):xn.parse(n,Dr)}function jr(e){for(const t of e.getElementsByTagName("pre"))t.prepend("\n");e.innerHTML=Nr(e.innerHTML)}const Or=(zr="[data-format='markdown']:not(body)",e=>{const t=e.querySelectorAll(zr);return t.forEach(jr),Array.from(t)});var zr;var Mr=Object.freeze({__proto__:null,markdownToHtml:Nr,name:"core/markdown",run:function(e){const t=!!document.querySelector("[data-format=markdown]:not(body)"),n="markdown"===e.format;if(!n&&!t)return;if(!n)return void Or(document.body);const r=document.getElementById("respec-ui");r.remove();const s=document.body.cloneNode(!0);!function(e,t){const n=e.querySelectorAll(t);for(const e of n){const{innerHTML:t}=e;if(/^<\w/.test(t.trimStart()))continue;const n=t.split("\n"),r=n.slice(0,2).join("\n"),s=n.slice(-2).join("\n");if(r.trim()&&e.prepend("\n\n"),s.trim()){const t=nr(e);e.append(`\n\n${t}`)}}}(s,"[data-format=markdown], section, div, address, article, aside, figure, header, main"),jr(s),function(e){Array.from(e).forEach((e=>{e.replaceWith(e.textContent)}))}(s.querySelectorAll(".nolinks a[href]")),s.append(r),document.body.replaceWith(s)}});function qr(e,t){e&&Array.from(t).forEach((([t,n])=>{e.setAttribute(`aria-${t}`,n)}))}!function(){const e=document.createElement("style");e.id="respec-ui-styles",e.textContent=Lr,e.classList.add("removeOnSave"),document.head.appendChild(e)}();const Wr=kn``,Ur=kn``,Fr=kn``;let Br,Hr;window.addEventListener("load",(()=>Jr(Ur)));const Vr=[],Gr=[],Yr={};vr("start-all",(()=>document.body.prepend(Wr)),{once:!0}),vr("end-all",(()=>document.body.prepend(Wr)),{once:!0});const Kr=kn``;function Zr(){Ur.classList.toggle("respec-hidden"),Ur.classList.toggle("respec-visible"),Ur.hidden=!Ur.hidden}function Jr(e){const t=e.querySelectorAll("a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled])"),n=t[0],r=t[t.length-1];n&&n.focus(),e.addEventListener("keydown",(e=>{"Tab"===e.key&&(e.shiftKey?document.activeElement===n&&(r.focus(),e.preventDefault()):document.activeElement===r&&(n.focus(),e.preventDefault()))}))}Wr.appendChild(Kr),Kr.addEventListener("click",(e=>{e.stopPropagation(),Kr.setAttribute("aria-expanded",String(Ur.hidden)),Zr(),Ur.querySelector("li:first-child button").focus()})),document.documentElement.addEventListener("click",(()=>{Ur.hidden||Zr()})),Wr.appendChild(Ur),Ur.addEventListener("keydown",(e=>{"Escape"!==e.key||Ur.hidden||(Kr.setAttribute("aria-expanded",String(Ur.hidden)),Zr(),Kr.focus())}));const Qr=new Map([["controls","respec-menu"],["expanded","false"],["haspopup","true"],["label","ReSpec Menu"]]);function Xr(e,t,n,r){t.push(e),Yr.hasOwnProperty(n)||(Yr[n]=function(e,t,n){const r=`respec-pill-${e}`,s=kn``;s.addEventListener("click",(()=>{s.setAttribute("aria-expanded","true");const r=kn`
      `;for(const e of t){const t=document.createRange().createContextualFragment(ts(e)),n=document.createElement("li");t.firstElementChild===t.lastElementChild?n.append(...t.firstElementChild.childNodes):n.appendChild(t),r.appendChild(n)}es.freshModal(n,r,s)}));const o=new Map([["expanded","false"],["haspopup","true"],["controls",`respec-pill-${e}-modal`]]);return qr(s,o),s}(n,t,r),Wr.appendChild(Yr[n]));const s=Yr[n];s.textContent=t.length;const o=1===t.length?Cn.singular(r):r;qr(s,new Map([["label",`${t.length} ${o}`]]))}qr(Kr,Qr);const es={show(){try{Wr.hidden=!1}catch(e){console.error(e)}},hide(){Wr.hidden=!0},enable(){Kr.removeAttribute("disabled")},addCommand(e,t,n,r){r=r||"";const s=`respec-button-${e.toLowerCase().replace(/\s+/,"-")}`,o=kn``,i=kn`
    1. ${o}
    2. `;return i.addEventListener("click",t),Ur.appendChild(i),o},error(e){Xr(e,Vr,"error","ReSpec Errors")},warning(e){Xr(e,Gr,"warning","ReSpec Warnings")},closeModal(e){Hr&&(Hr.classList.remove("respec-show-overlay"),Hr.classList.add("respec-hide-overlay"),Hr.addEventListener("transitionend",(()=>{Hr.remove(),Hr=null}))),e&&e.setAttribute("aria-expanded","false"),Br&&(Br.remove(),Br=null,Kr.focus())},freshModal(e,t,n){Br&&Br.remove(),Hr&&Hr.remove(),Hr=kn`
      `;const r=`${n.id}-modal`,s=`${r}-heading`;Br=kn``;const o=new Map([["labelledby",s]]);qr(Br,o),document.body.append(Hr,Br),Hr.addEventListener("click",(()=>this.closeModal(n))),Hr.classList.toggle("respec-show-overlay"),Br.hidden=!1,Jr(Br)}};function ts(e){if("string"==typeof e)return e;const t=e.plugin?`

      (plugin: "${e.plugin}")

      `:"",n=e.hint?`\n${Nr(`

      How to fix: ${br(e.hint)}`,{inline:!e.hint.includes("\n")})}\n`:"",r=Array.isArray(e.elements)?`

      Occurred ${e.elements.length} times at:

      \n ${Nr(e.elements.map(ns).join("\n"))}`:"",s=e.details?`\n\n
      \n${e.details}\n
      \n`:"";return`${Nr(`**${Mn(e.message)}**`,{inline:!0})}${n}${r}${s}${t}`}function ns(e){return`* [\`<${e.localName}>\`](#${e.id}) element`}async function rs(e){try{es.show(),await async function(){"loading"===document.readyState&&await new Promise((e=>document.addEventListener("DOMContentLoaded",e)))}(),await Ar(e)}finally{es.enable()}}document.addEventListener("keydown",(e=>{"Escape"===e.key&&es.closeModal()})),window.respecUI=es,vr("error",(e=>es.error(e))),vr("warn",(e=>es.warning(e))),window.addEventListener("error",(e=>{console.error(e.error,e.message,e)}));const ss=[Promise.resolve().then((function(){return os})),Promise.resolve().then((function(){return i})),Promise.resolve().then((function(){return ls})),Promise.resolve().then((function(){return no})),Promise.resolve().then((function(){return oo})),Promise.resolve().then((function(){return uo})),Promise.resolve().then((function(){return bo})),Promise.resolve().then((function(){return Co})),Promise.resolve().then((function(){return Mr})),Promise.resolve().then((function(){return So})),Promise.resolve().then((function(){return Ao})),Promise.resolve().then((function(){return Po})),Promise.resolve().then((function(){return Zs})),Promise.resolve().then((function(){return No})),Promise.resolve().then((function(){return jo})),Promise.resolve().then((function(){return Mo})),Promise.resolve().then((function(){return Yi})),Promise.resolve().then((function(){return Ji})),Promise.resolve().then((function(){return aa})),Promise.resolve().then((function(){return ca})),Promise.resolve().then((function(){return pa})),Promise.resolve().then((function(){return ba})),Promise.resolve().then((function(){return $a})),Promise.resolve().then((function(){return Ca})),Promise.resolve().then((function(){return Ra})),Promise.resolve().then((function(){return Ka})),Promise.resolve().then((function(){return mi})),Promise.resolve().then((function(){return mc})),Promise.resolve().then((function(){return Lc})),Promise.resolve().then((function(){return oc})),Promise.resolve().then((function(){return Si})),Promise.resolve().then((function(){return Fc})),Promise.resolve().then((function(){return Hc})),Promise.resolve().then((function(){return ko})),Promise.resolve().then((function(){return Vc})),Promise.resolve().then((function(){return Gc})),Promise.resolve().then((function(){return tl})),Promise.resolve().then((function(){return rl})),Promise.resolve().then((function(){return ol})),Promise.resolve().then((function(){return dl})),Promise.resolve().then((function(){return vl})),Promise.resolve().then((function(){return _l})),Promise.resolve().then((function(){return El})),Promise.resolve().then((function(){return Pl})),Promise.resolve().then((function(){return zl})),Promise.resolve().then((function(){return Ml})),Promise.resolve().then((function(){return Hl})),Promise.resolve().then((function(){return Ql})),Promise.resolve().then((function(){return ja})),Promise.resolve().then((function(){return ou})),Promise.resolve().then((function(){return uu})),Promise.resolve().then((function(){return pu})),Promise.resolve().then((function(){return hu})),Promise.resolve().then((function(){return gu})),Promise.resolve().then((function(){return _u})),Promise.resolve().then((function(){return Ru})),Promise.resolve().then((function(){return Pu})),Promise.resolve().then((function(){return Iu})),Promise.resolve().then((function(){return Du})),Promise.resolve().then((function(){return ju})),Promise.resolve().then((function(){return Mu})),Promise.resolve().then((function(){return Bu})),Promise.resolve().then((function(){return Gu})),Promise.resolve().then((function(){return Ju})),Promise.resolve().then((function(){return ed})),Promise.resolve().then((function(){return od})),Promise.resolve().then((function(){return cd})),Promise.resolve().then((function(){return dd})),Promise.resolve().then((function(){return bd})),Promise.resolve().then((function(){return vd})),Promise.resolve().then((function(){return xd})),Promise.resolve().then((function(){return Rd})),Promise.resolve().then((function(){return Td}))];Promise.all(ss).then((e=>rs(e))).catch((e=>console.error(e)));var os=Object.freeze({__proto__:null,name:"core/location-hash",run:function(){window.location.hash&&document.respec.ready.then((()=>{let e=decodeURIComponent(window.location.hash).slice(1);const t=document.getElementById(e),n=/\W/.test(e);if(!t&&n){const t=e.replace(/[\W]+/gim,"-").replace(/^-+/,"").replace(/-+$/,"");document.getElementById(t)&&(e=t)}window.location.hash=`#${e}`}))}});const is="w3c/group",as="https://respec.org/w3c/groups/";async function cs(e){let t="",n=e;e.includes("/")&&([t,n]=e.split("/",2));const r=new URL(`${n}/${t}`,as),s=await Hn(r.href);if(s.ok){const e=await s.json(),{id:t,name:n,patentURI:r,patentPolicy:o,type:i,wgURI:a}=e;return{wg:n,wgId:t,wgURI:a,wgPatentURI:r,wgPatentPolicy:o,groupType:i}}const o=await s.text();let i,a=`Failed to fetch group details (HTTP: ${s.status}).`;409===s.status?[a,i]=o.split("\n",2):404===s.status&&(i=gr`See the list of [supported group names](https://respec.org/w3c/groups/) to use with the ${"[group]"} configuration option.`),lr(a,is,{hint:i})}var ls=Object.freeze({__proto__:null,name:is,run:async function(e){if(!e.group)return;const{group:t}=e,n=Array.isArray(t)?await async function(e){const t=await Promise.all(e.map(cs)),n={wg:[],wgId:[],wgURI:[],wgPatentURI:[],wgPatentPolicy:[],groupType:[]};for(const e of t.filter(Boolean))for(const t of Object.keys(n))n[t].push(e[t]);return n}(t):await cs(t);Object.assign(e,n)}});function us(e){if(!e.key){const t="Found a link without `key` attribute in the configuration. See dev console.";return ur(t,"core/templates/show-link"),void console.warn(t,e)}return kn` +
      ${e.key}
      + ${e.data?e.data.map(ds):ds(e)} + `}function ds(e){return kn`
      + ${e.href?kn`${e.value||e.href}`:e.value} +
      `}const ps="core/templates/show-logo";function fs(e,t){const n=kn``;if(!e.alt){const r=gr`Add the missing "\`alt\`" property describing the logo. See ${"[logos]"} for more information.`;lr(`Logo at index ${t}${e.src?`, with \`src\` ${e.src}, `:""} is missing required "\`alt\`" property.`,ps,{hint:r,elements:[n]})}if(!e.src){const e=gr`The \`src\` property is required on every logo. See ${"[logos]"} for more information.`;lr(`Logo at index ${t} is missing "\`src\`" property.`,ps,{hint:e,elements:[n]})}return n}const hs="core/templates/show-people",ms=Wn({en:{until:e=>kn` Until ${e} `},es:{until:e=>kn` Hasta ${e} `},ko:{until:e=>kn` ${e} ì´ì „ `},ja:{until:e=>kn` ${e} ä»¥å‰ `},de:{until:e=>kn` bis ${e} `},zh:{until:e=>kn` 直到 ${e} `}}),gs=()=>kn` + + + + `;function bs(e,t){const n=e[t];if(!Array.isArray(n)||!n.length)return;const r=(s=t,function(e,t){const n="https://respec.org/docs/",r=`See [person](${n}#person) configuration for available options.`,o=`Error processing the [person object](${n}#person) at index ${t} of the "[\`${s}\`](${n}#${s})" configuration option.`;if(!e.name)return lr(`${o} Missing required property \`"name"\`.`,hs,{hint:r}),!1;if(e.orcid){const{orcid:n}=e,r=new URL(n,"https://orcid.org/");if("https://orcid.org"!==r.origin){const n=`${o} ORCID "${e.orcid}" at index ${t} is invalid.`,s=`The origin should be "https://orcid.org", not "${r.origin}".`;return lr(n,hs,{hint:s}),!1}const s=r.pathname.slice(1).replace(/\/$/,"");if(!/^\d{4}-\d{4}-\d{4}-\d{3}(\d|X)$/.test(s))return lr(`${o} ORCID "${s}" has wrong format.`,hs,{hint:'ORCIDs have the format "1234-1234-1234-1234."'}),!1;if(!function(e){const t=e[e.length-1],n=e.split("").slice(0,-1).filter((e=>/\d/.test(e))).map(Number).reduce(((e,t)=>2*(e+t)),0),r=(12-n%11)%11,s=10===r?"X":String(r);return t===s}(n))return lr(`${o} ORCID "${n}" failed checksum check.`,hs,{hint:"Please check that the ORCID is valid."}),!1;e.orcid=r.href}return e.retiredDate&&(i=e.retiredDate,"Invalid Date"===(/\d{4}-\d{2}-\d{2}/.test(i)?new Date(i):"Invalid Date").toString())?(lr(`${o} The property "\`retiredDate\`" is not a valid date.`,hs,{hint:`The expected format is YYYY-MM-DD. ${r}`}),!1):!(e.hasOwnProperty("extras")&&!function(e,t,n){return Array.isArray(e)?e.every(((e,r)=>{switch(!0){case"object"!=typeof e:return lr(`${n}. Member "extra" at index ${r} is not an object.`,hs,{hint:t}),!1;case!e.hasOwnProperty("name"):return lr(`${n} \`PersonExtra\` object at index ${r} is missing required "name" member.`,hs,{hint:t}),!1;case"string"==typeof e.name&&""===e.name.trim():return lr(`${n} \`PersonExtra\` object at index ${r} "name" can't be empty.`,hs,{hint:t}),!1}return!0})):(lr(`${n}. A person's "extras" member must be an array.`,hs,{hint:t}),!1)}(e.extras,r,o))&&(e.url&&e.mailto&&ur(`${o} Has both "url" and "mailto" property.`,hs,{hint:`Please choose either "url" or "mailto" ("url" is preferred). ${r}`}),e.companyURL&&!e.company&&ur(`${o} Has a "\`companyURL\`" property but no "\`company\`" property.`,hs,{hint:`Please add a "\`company\`" property. ${r}.`}),!0);var i});var s;return n.filter(r).map(ys)}function ys(e){const t=[e.name],n=[e.company],r=e.w3cid||null,s=[];if(e.mailto&&(e.url=`mailto:${e.mailto}`),e.url){const n="mailto:"===new URL(e.url,document.location.href).protocol?"ed_mailto u-email email p-name":"u-url url p-name fn";s.push(kn`${t}`)}else s.push(kn`${t}`);if(e.orcid&&s.push(kn`${gs()}`),e.company){const t="p-org org h-org",r=e.companyURL?kn`${n}`:kn`${n}`;s.push(kn` (${r})`)}e.note&&s.push(document.createTextNode(` (${e.note})`)),e.extras&&s.push(...e.extras.map((e=>kn`, ${function(e){const t=e.class||null,{name:n,href:r}=e;return r?kn`${n}`:kn`${n}`}(e)}`)));const{retiredDate:o}=e;if(e.retiredDate){const e=kn``;s.push(kn` - ${ms.until(e)} `)}return kn`
      + ${s} +
      `}const ws=Wn({en:{archives:"archives",author:"Author:",authors:"Authors:",commit_history:"Commit history",edited_in_place:"edited in place",editor:"Editor:",editors:"Editors:",feedback:"Feedback:",former_editor:"Former editor:",former_editors:"Former editors:",history:"History:",implementation_report:"Implementation report:",latest_editors_draft:"Latest editor's draft:",latest_published_version:"Latest published version:",latest_recommendation:"Latest Recommendation:",message_topic:"… message topic …",more_details_about_this_doc:"More details about this document",multiple_alternates:e=>`This document is also available in ${e?"these non-normative formats":"this non-normative format"}:`,prev_editor_draft:"Previous editor's draft:",prev_recommendation:"Previous Recommendation:",prev_version:"Previous version:",publication_history:"Publication history",test_suite:"Test suite:",this_version:"This version:",with_subject_line:"with subject line",your_topic_here:"YOUR TOPIC HERE"},ko:{author:"ì €ìž:",authors:"ì €ìž:",editor:"편집ìž:",editors:"편집ìž:",former_editor:"ì´ì „ 편집ìž:",former_editors:"ì´ì „ 편집ìž:",latest_editors_draft:"최신 편집 초안:",latest_published_version:"최신 버전:",this_version:"현재 버전:"},zh:{author:"作者:",authors:"作者:",commit_history:"Gitæäº¤åކå²",editor:"编辑:",editors:"编辑:",feedback:"å馈:",former_editor:"原编辑:",former_editors:"原编辑:",history:"历å²ï¼š",implementation_report:"实现报告:",latest_editors_draft:"最新编辑è‰ç¨¿ï¼š",latest_published_version:"最新å‘布版本:",latest_recommendation:"最新å‘å¸ƒçš„æ­£å¼æŽ¨èæ ‡å‡†ï¼š",message_topic:"… 邮件主题 …",prev_editor_draft:"上一版编辑è‰ç¨¿ï¼š",prev_recommendation:"ä¸Šä¸€ç‰ˆæ­£å¼æŽ¨èæ ‡å‡†ï¼š",prev_version:"上一版:",test_suite:"测试套件:",this_version:"本版本:"},ja:{archives:"アーカイブ",author:"著者:",authors:"著者:",commit_history:"更新履歴",edited_in_place:"改版ãªãæ›´æ–°",editor:"編者:",editors:"編者:",feedback:"フィードãƒãƒƒã‚¯:",former_editor:"以å‰ã®ç‰ˆã®ç·¨è€…:",former_editors:"以å‰ã®ç‰ˆã®ç·¨è€…:",history:"履歴:",implementation_report:"実装レãƒãƒ¼ãƒˆï¼š",latest_editors_draft:"最新ã®ç·¨é›†ç”¨è‰æ¡ˆï¼š",latest_published_version:"最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š",latest_recommendation:"最新ã®å‹§å‘Šç‰ˆ:",message_topic:"… メール件å …",more_details_about_this_doc:"ã“ã®æ–‡æ›¸ã«ã¤ã„ã¦ã®ã‚ˆã‚Šè©³ç´°",prev_editor_draft:"å‰å›žã®ç·¨é›†ç”¨è‰æ¡ˆ:",prev_recommendation:"å‰å›žã®å‹§å‘Šç‰ˆ:",prev_version:"å‰å›žã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³:",publication_history:"公表履歴",test_suite:"テストスイート:",this_version:"ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š",with_subject_line:"次ã®ä»¶åã§"},nl:{author:"Auteur:",authors:"Auteurs:",editor:"Redacteur:",editors:"Redacteurs:",latest_editors_draft:"Laatste werkversie:",latest_published_version:"Laatst gepubliceerde versie:",this_version:"Deze versie:"},es:{archives:"archivos",author:"Autor:",authors:"Autores:",commit_history:"Historial de cambios",edited_in_place:"editado en lugar",editor:"Editor:",editors:"Editores:",feedback:"Comentarios:",former_editor:"Antiguo editor:",former_editors:"Antiguos editores:",history:"Historia:",implementation_report:"Informe de implementación:",latest_editors_draft:"Última versión del editor:",latest_published_version:"Última versión publicada:",latest_recommendation:"Recomendación más reciente:",message_topic:"… detalles de mensaje …",more_details_about_this_doc:"Más detalles sobre este documento:",publication_history:"Historial de publicación",prev_editor_draft:"Última versión del editor:",prev_recommendation:"Última Recomendación:",prev_version:"Última versión:",test_suite:"Suite de pruebas:",this_version:"Esta versión:",with_subject_line:"con línea de asunto",your_topic_here:"TU SUJETO AQUÃ"},de:{archives:"Archiv",author:"Autor/in:",authors:"Autor/innen:",commit_history:"Commit-Historie",edited_in_place:"zuletzt geändert am",editor:"Redaktion:",editors:"Redaktion:",feedback:"Feedback:",former_editor:"Frühere Mitwirkende:",former_editors:"Frühere Mitwirkende:",history:"Verlauf:",implementation_report:"Umsetzungsbericht:",latest_editors_draft:"Letzter Entwurf:",latest_published_version:"Letzte publizierte Fassung:",latest_recommendation:"Aktuellste Empfehlung:",more_details_about_this_doc:"Mehr Informationen über dieses Dokument",multiple_alternates:e=>`Dieses Dokument ist ebenfalls in ${e?"diesen nicht-normativen Formaten verfügbar":"diesem nicht-normativen Format verfügbar"}:`,prev_editor_draft:"Vorheriger Entwurf:",prev_recommendation:"Vorherige Empfehlung:",prev_version:"Vorherige Version:",publication_history:"Veröffentlichungsverlauf",test_suite:"Testumgebung:",this_version:"Diese Fassung:"},cs:{archives:"archivy",author:"Autor:",authors:"AutoÅ™i:",commit_history:"Historie zmÄ›n",edited_in_place:"upraveno přímo",editor:"Editor:",editors:"EditoÅ™i:",feedback:"ZpÄ›tná vazba:",former_editor:"Bývalý editor:",former_editors:"Bývalí editoÅ™i:",history:"Historie:",implementation_report:"ImplementaÄní zpráva:",latest_editors_draft:"NejnovÄ›jší pracovní verze:",latest_published_version:"NejnovÄ›jší publikovaná verze:",latest_recommendation:"NejnovÄ›jší doporuÄení:",message_topic:"… pÅ™edmÄ›t zprávy …",more_details_about_this_doc:"Více informací o tomto dokumentu",multiple_alternates:e=>`Tento dokument je také dostupný v ${e?"tÄ›chto ne-normativních formátech":"tomto ne-normativním formátu"}:`,prev_editor_draft:"PÅ™edchozí pracovní verze:",prev_recommendation:"PÅ™edchozí doporuÄení:",prev_version:"PÅ™edchozí verze:",publication_history:"Historie publikací",test_suite:"Testovací sada:",this_version:"Tato verze:",with_subject_line:"s pÅ™edmÄ›tem",your_topic_here:"VÃÅ  PŘEDMÄšT ZDE"}});function vs(e){let t=document.querySelector("h2#subtitle");return t&&t.parentElement?(t.remove(),e.subtitle=t.textContent.trim()):e.subtitle&&(t=document.createElement("h2"),t.textContent=e.subtitle,t.id="subtitle"),t&&t.classList.add("subtitle"),t}var ks=(e,t)=>(vr("beforesave",(e=>{const t=e.querySelector(".head details");t&&(t.open=!0)})),kn`
      + ${e.logos.length?kn`

      ${e.logos.map(fs)}

      `:""} + ${document.querySelector("h1#title")} ${vs(e)} +

      ${function(e){const t=e.isCR||e.isCRY?e.longStatus:e.textStatus,n=e.prependW3C?kn`W3C ${t}`:kn`${t}`;return kn`${n}${" "} + ${e.modificationDate?kn`, ${ws.edited_in_place}${" "} + `:""}`}(e)}

      +
      + ${ws.more_details_about_this_doc} +
      + ${e.thisVersion?kn`
      ${ws.this_version}
      +
      + ${e.thisVersion} +
      `:""} + ${"latestVersion"in e?kn`
      ${ws.latest_published_version}
      +
      + ${e.latestVersion?kn`${e.latestVersion}`:"none"} +
      `:""} + ${e.edDraftURI?kn` +
      ${ws.latest_editors_draft}
      +
      ${e.edDraftURI}
      + `:""} + ${e.historyURI||e.github?kn`
      ${ws.history}
      + ${e.historyURI?kn`
      + ${e.historyURI} +
      `:""} + ${e.github?kn`
      + ${ws.commit_history} +
      `:""}`:""} + ${e.testSuiteURI?kn` +
      ${ws.test_suite}
      +
      ${e.testSuiteURI}
      + `:""} + ${e.implementationReportURI?kn` +
      ${ws.implementation_report}
      +
      + ${e.implementationReportURI} +
      + `:""} + ${e.prevED?kn` +
      ${ws.prev_editor_draft}
      +
      ${e.prevED}
      + `:""} + ${e.showPreviousVersion?kn` +
      ${ws.prev_version}
      +
      ${e.prevVersion}
      + `:""} + ${e.prevRecURI?e.isRec?kn` +
      ${ws.prev_recommendation}
      +
      ${e.prevRecURI}
      + `:kn` +
      ${ws.latest_recommendation}
      +
      ${e.prevRecURI}
      + `:""} + ${e.editors.length?kn` +
      ${e.editors.length>1?ws.editors:ws.editor}
      + ${bs(e,"editors")} + `:""} + ${e.formerEditors.length?kn` +
      + ${e.formerEditors.length>1?ws.former_editors:ws.former_editor} +
      + ${bs(e,"formerEditors")} + `:""} + ${e.authors.length?kn` +
      ${e.authors.length>1?ws.authors:ws.author}
      + ${bs(e,"authors")} + `:""} + ${e.github||e.wgPublicList?kn`
      ${ws.feedback}
      + ${$s(e)}`:""} + ${e.errata?kn`
      Errata:
      +
      Errata exists.
      `:""} + ${e.otherLinks?e.otherLinks.map(us):""} +
      +
      + ${e.isRec?kn`

      + See also + + translations. +

      `:""} + ${e.alternateFormats?kn`

      + ${ws.multiple_alternates(t.multipleAlternates)} + ${t.alternatesHTML} +

      `:""} + ${function(e){const t=document.querySelector(".copyright");if(t)return t.remove(),t;if(e.isUnofficial&&e.licenseInfo)return kn``;return function(e){return kn``}(e)}(e)} +
      +
      `);function $s(e){const t=[];if(e.github){const{repoURL:n,issuesURL:r,newIssuesURL:s,pullsURL:o,fullName:i}=e.github;t.push(kn`
      + GitHub ${i} + (pull requests, + new issue, + open issues) +
      `)}if(e.wgPublicList){const n=new URL(`mailto:${e.wgPublicList}@w3.org`),r=e.subjectPrefix??`[${e.shortName}] ${ws.your_topic_here}`,s=kn`${n.pathname}`,o=e.subjectPrefix||kn`[${e.shortName}] ${ws.message_topic}`,i=kn`${ws.with_subject_line}${" "} + ${o}`,a=new URL(e.wgPublicList,"https://lists.w3.org/Archives/Public/"),c=kn`(${ws.archives})`;t.push(kn`
      ${s} ${i} ${c}
      `)}return t}var xs=(e,t)=>{const n=document.querySelector(".copyright");n&&n.remove();const r=document.querySelector("h1#title"),s=r.cloneNode(!0);return kn`
      + ${e.logos.length?kn`

      ${e.logos.map(fs)}

      `:""} + ${r} ${vs(e)} +

      + ${e.longStatus} + +

      +
      + ${e.thisVersion?kn`
      ${ws.this_version}
      +
      + ${e.thisVersion} +
      `:""} + ${"latestVersion"in e?kn`
      ${ws.latest_published_version}
      +
      + ${e.latestVersion?kn`${e.latestVersion}`:"none"} +
      `:""} + ${e.edDraftURI?kn` +
      ${ws.latest_editors_draft}
      +
      ${e.edDraftURI}
      + `:""} + ${e.testSuiteURI?kn` +
      Test suite:
      +
      ${e.testSuiteURI}
      + `:""} + ${e.implementationReportURI?kn` +
      Implementation report:
      +
      + ${e.implementationReportURI} +
      + `:""} + ${e.prevVersion?kn` +
      Previous version:
      +
      ${e.prevVersion}
      + `:""} + ${e.isCGFinal?"":kn` + ${e.prevED?kn` +
      Previous editor's draft:
      +
      ${e.prevED}
      + `:""} + `} + ${e.editors.length?kn` +
      ${e.editors.length>1?ws.editors:ws.editor}
      + ${bs(e,"editors")} + `:""} + ${e.formerEditors.length?kn` +
      + ${e.formerEditors.length>1?ws.former_editors:ws.former_editor} +
      + ${bs(e,"formerEditors")} + `:""} + ${e.authors.length?kn` +
      ${e.authors.length>1?ws.authors:ws.author}
      + ${bs(e,"authors")} + `:""} + ${e.github||e.wgPublicList?kn`
      ${ws.feedback}
      + ${$s(e)}`:""} + ${e.otherLinks?e.otherLinks.map(us):""} +
      + ${e.alternateFormats?kn`

      + ${t.multipleAlternates?"This document is also available in these non-normative formats:":"This document is also available in this non-normative format:"} + ${t.alternatesHTML} +

      `:""} + ${n||kn``} +
      +
      `};const _s=Wn({en:{sotd:"Status of This Document",status_at_publication:kn`This section describes the status of this + document at the time of its publication. A list of current W3C + publications and the latest revision of this technical report can be found + in the + W3C standards and drafts index.`},ko:{sotd:"현재 ë¬¸ì„œì˜ ìƒíƒœ",status_at_publication:kn`ì´ ë¶€ë¶„ì€ í˜„ìž¬ ë¬¸ì„œì˜ ë°œí–‰ 당시 ìƒíƒœì— 대해 + 기술합니다. W3C 발행 ë¬¸ì„œì˜ ìµœì‹  ëª©ë¡ ë° í…Œí¬ë‹ˆì»¬ 리í¬íЏ 최신íŒì˜ + W3C standards and drafts index ì—서 + 열람할 수 있습니다.`},zh:{sotd:"关于本文档",status_at_publication:kn`本章节æè¿°äº†æœ¬æ–‡æ¡£çš„å‘布状æ€ã€‚W3C的文档列表和最新版本å¯é€šè¿‡W3C技术报告索引访问。`},ja:{sotd:"ã“ã®æ–‡æ›¸ã®ä½ç½®ä»˜ã‘",status_at_publication:kn`ã“ã®ç¯€ã«ã¯ã€å…¬é–‹æ™‚点ã§ã®ã“ã®æ–‡æ›¸ã®ä½ç½®ã¥ã‘ãŒè¨˜ã•れã¦ã„ã‚‹ã€‚ç¾æ™‚点ã§ã®W3Cã®ç™ºè¡Œæ–‡æ›¸ã¨ã“ã®ãƒ†ã‚¯ãƒ‹ã‚«ãƒ«ãƒ¬ãƒãƒ¼ãƒˆã®æœ€æ–°ç‰ˆã¯ã€ä¸‹è¨˜ã‹ã‚‰å‚ç…§ã§ãる。 + W3C standards and drafts index`},nl:{sotd:"Status van dit document"},es:{sotd:"Estado de este Document",status_at_publication:kn`Esta sección describe el estado del presente + documento al momento de su publicación. Una lista de las publicaciones + actuales del W3C y la última revisión del presente informe técnico puede + hallarse en + el índice de normas y borradores del + W3C.`},de:{sotd:"Status dieses Dokuments",status_at_publication:kn`Dieser Abschnitt beschreibt den Status des + Dokuments zum Zeitpunkt der Publikation. Eine Liste der aktuellen + Publikatinen des W3C und die aktuellste Fassung dieser Spezifikation kann + im W3C standards and drafts index.`},cs:{sotd:"Stav tohoto dokumentu",status_at_publication:kn`Tato sekce popisuje stav tohoto dokumentu v dobÄ› + jeho zveÅ™ejnÄ›ní. Seznam aktuálních publikací W3C a nejnovÄ›jší verzi této + technické zprávy najdete v + indexu standardů a návrhů W3C + na https://www.w3.org/TR/.`}}),Cs="https://www.w3.org/policies/process/20250818/";function Ss(e){return/^[aeiou]/i.test(e)?`an ${e}`:`a ${e}`}var Rs=(e,t)=>kn` +

      ${_s.sotd}

      + ${e.isPreview?Es(e):""} + ${e.isUnofficial?function(e){const{additionalContent:t}=e;return kn` +

      + This document is a draft of a potential specification. It has no official + standing of any kind and does not represent the support or consensus of + any standards organization. +

      + ${t} + `}(t):e.isTagFinding?t.additionalContent:e.isNoTrack?function(e,t){const{isMO:n}=e,{additionalContent:r}=t;return kn` +

      + This document is merely a W3C-internal + ${n?"member-confidential":""} document. It has no official standing + of any kind and does not represent consensus of the W3C Membership. +

      + ${r} + `}(e,t):kn` +

      ${_s.status_at_publication}

      + ${e.isMemberSubmission?function(e,t){return kn` + ${t.additionalContent} + ${e.isMemberSubmission?function(e){const t=`https://www.w3.org/Submission/${e.publishDate.getUTCFullYear()}/${e.submissionCommentNumber}/Comment/`,n="PP2017"===e.wgPatentPolicy?"https://www.w3.org/Consortium/Patent-Policy-20170801/":"https://www.w3.org/policies/patent-policy/";return kn`

      + By publishing this document, W3C acknowledges that the + Submitting Members have made a formal + Submission request to W3C for discussion. Publication of this document by + W3C indicates no endorsement of its content by W3C, nor that W3C has, is, or + will be allocating any resources to the issues addressed by it. This + document is not the product of a chartered W3C group, but is published as + potential input to the + W3C Process. A + W3C Team Comment has been published in + conjunction with this Member Submission. Publication of acknowledged Member + Submissions at the W3C site is one of the benefits of + + W3C Membership. Please consult the requirements associated with Member Submissions of + section 3.3 of the W3C Patent Policy. Please consult the complete + list of acknowledged W3C Member Submissions. +

      `}(e):""} + `}(e,t):kn` + ${e.sotdAfterWGinfo?"":t.additionalContent} + ${e.overrideStatus?"":kn` ${function(e){if(!e.wg)return;let t=null;const n=document.querySelector(".proposed-addition"),r=document.querySelector(".proposed-correction"),s=document.querySelector(".addition"),o=document.querySelector(".correction"),i=n||r||s||o;e.isRec&&i&&(n&&r||s&&o?t=kn`It includes + ${n?kn` + proposed amendments`:kn` + candidate amendments`}, + introducing substantive changes and new features since the previous + Recommendation.`:n||s?t=kn`It includes + ${n?kn` + proposed additions`:kn` + candidate additions`}, + introducing new features since the previous Recommendation.`:(r||o)&&(t=kn`It includes + ${r?kn` + proposed corrections`:kn` + candidate corrections`}.`));const a=js[e.specStatus]?kn` using the + ${js[e.specStatus]} track`:"";return kn`

      + This document was published by ${As(e)} as + ${Ss(e.longStatus)}${a}. ${t} +

      `}(e)} `} + ${e.sotdAfterWGinfo?t.additionalContent:""} + ${e.isRec?function(e){const{revisedRecEnd:t}=e,n=document.querySelector("#sotd.updateable-rec");let r="";document.querySelector(".proposed-addition")?r="additions":document.querySelector(".proposed-correction")&&(r="corrections");return kn` +

      + W3C recommends the wide deployment of this specification as a standard for + the Web. +

      + +

      + A W3C Recommendation is a specification that, after extensive + consensus-building, is endorsed by + W3C and its Members, and + has commitments from Working Group members to + royalty-free licensing + for implementations. + ${n?kn`Future updates to this Recommendation may incorporate + new features.`:""} +

      + ${document.querySelector(".addition")?kn`

      + Candidate additions are marked in the document. +

      `:""} + ${document.querySelector(".correction")?kn`

      + Candidate corrections are marked in the document. +

      `:""} + ${document.querySelector(".proposed-addition")?kn`

      + Proposed additions are marked in the document. +

      `:""} + ${document.querySelector(".proposed-correction")?kn`

      + Proposed corrections are marked in the document. +

      `:""} + ${r?kn`

      + The W3C Membership and other interested parties are invited to review + the proposed ${r} and send comments through + ${Ln.format(t)}. Advisory Committee Representatives + should consult their + WBS questionnaires. +

      `:""} + `}(e):function(e){const t=document.querySelector("#sotd.updateable-rec");let n=null,r=null,s=kn`Publication as ${Ss(e.textStatus)} does not + imply endorsement by W3C and its Members.`,o=kn`

      + This is a draft document and may be updated, replaced, or obsoleted by other + documents at any time. It is inappropriate to cite this document as other + than a work in progress. + ${t?kn`Future updates to this upcoming Recommendation may incorporate + new features.`:""} +

      `;"DISC"===e.specStatus&&(o=kn`

      + Publication as a Discontinued Draft implies that this document is no + longer intended to advance or to be maintained. It is inappropriate to + cite this document as other than abandoned work. +

      `);const i=kn`

      + This document is maintained and updated at any time. Some parts of this + document are work in progress. +

      `;switch(e.specStatus){case"STMT":s=kn`

      + A W3C Statement is a specification that, after extensive + consensus-building, is endorsed by + W3C and its Members. +

      `;break;case"RY":s=kn`

      W3C recommends the wide usage of this registry.

      +

      + A W3C Registry is a specification that, after extensive + consensus-building, is endorsed by + W3C and its Members. +

      `;break;case"CRD":n=kn`A Candidate Recommendation Draft integrates + changes from the previous Candidate Recommendation that the Working Group + intends to include in a subsequent Candidate Recommendation Snapshot.`,"LS"===e.pubMode&&(o=i);break;case"CRYD":n=kn`A Candidate Registry Draft integrates changes + from the previous Candidate Registry Snapshot that the Working Group + intends to include in a subsequent Candidate Registry Snapshot.`,"LS"===e.pubMode&&(o=i);break;case"CRY":n=kn`A Candidate Registry Snapshot has received + wide review.`,r=kn`

      + The W3C Membership and other interested parties are invited to review + the document and send comments through ${e.humanPREnd}. Advisory + Committee Representatives should consult their + WBS questionnaires. Note that substantive technical comments were expected during the + Candidate Recommendation review period that ended ${e.humanCREnd}. +

      `;break;case"CR":n=kn`A Candidate Recommendation Snapshot has received + wide review, is intended to + gather + implementation experience, + and has commitments from Working Group members to + royalty-free licensing + for implementations.`,o=kn`${t?kn`Future updates to this upcoming Recommendation may incorporate + new features.`:""}`,r="LS"===e.pubMode?kn`

      + Comments are welcome at any time but most especially before + ${Ln.format(e.crEnd)}. +

      `:kn`

      + This Candidate Recommendation is not expected to advance to Proposed + Recommendation any earlier than ${Ln.format(e.crEnd)}. +

      `;break;case"PR":r=kn`

      + The W3C Membership and other interested parties are invited to review + the document and send comments through ${Ln.format(e.prEnd)}. + Advisory Committee Representatives should consult their + WBS questionnaires. Note that substantive technical comments were expected during the + Candidate Recommendation review period that ended + ${Ln.format(e.crEnd)}. +

      `;break;case"DNOTE":s=kn`${e.textStatus}s are not endorsed by + W3C nor its Members.`;break;case"NOTE":s=kn`This ${e.textStatus} is endorsed by + ${As(e)}, but is not endorsed by + W3C itself nor its + Members.`,o=""}return kn`

      ${s} ${n}

      + ${o} ${r}`}(e)} + ${function(e){const{isNote:t,isRegistry:n,wgId:r,multipleWGs:s,wgPatentHTML:o,wgPatentURI:i,wgPatentPolicy:a}=e,c="PP2017"===a?"https://www.w3.org/Consortium/Patent-Policy-20170801/":"https://www.w3.org/policies/patent-policy/",l=t||n?kn` + The + ${"PP2017"===a?"1 August 2017 ":""}W3C Patent + Policy + does not carry any licensing requirements or commitments on this + document. + `:kn` + This document was produced by ${s?"groups":"a group"} + operating under the + ${"PP2017"===a?"1 August 2017 ":""}W3C Patent + Policy. + `;return kn`

      + ${l} + ${t||n?"":kn` + ${s?kn` W3C maintains ${o} `:kn` + W3C maintains a + public list of any patent disclosures + `} + made in connection with the deliverables of + ${s?"each group; these pages also include":"the group; that page also includes"} + instructions for disclosing a patent. An individual who has actual + knowledge of a patent that the individual believes contains + Essential Claim(s) + must disclose the information in accordance with + section 6 of the W3C Patent Policy. + `} +

      `}(e)} +

      + This document is governed by the + 18 August 2025 W3C Process Document. +

      + `} + `} + ${t.additionalSections} + `;function Es(e){const{prUrl:t,prNumber:n,edDraftURI:r}=e;return kn`
      + + This is a + preview${t&&n?kn` + of pull request + #${n} + `:""} + +

      + Do not attempt to implement this version of the specification. Do not + reference this version as authoritative in any way. + ${r?kn` + Instead, see + ${r} for the Editor's draft. + `:""} +

      +
      `}function As(e){return Array.isArray(e.wg)?Gn(e.wg,((t,n)=>kn`the ${t}`)):e.wg?kn`the ${e.wg}`:void 0}var Ls=(e,t)=>kn` +

      ${_s.sotd}

      + ${e.isPreview?Es(e):""} +

      + This specification was published by the + ${e.wg}. It is not a W3C Standard nor is it + on the W3C Standards Track. + ${e.isCGFinal?kn` + Please note that under the + W3C Community Final Specification Agreement (FSA) + other conditions apply. + `:kn` + Please note that under the + W3C Community Contributor License Agreement (CLA) + there is a limited opt-out and other conditions apply. + `} + Learn more about + W3C Community and Business Groups. +

      + ${e.sotdAfterWGinfo?"":t.additionalContent} + ${!e.github&&e.wgPublicList?function(e,t){const{mailToWGPublicListWithSubject:n,mailToWGPublicListSubscription:r}=t,{wgPublicList:s,subjectPrefix:o}=e;return kn`

      + If you wish to make comments regarding this document, please send them to + ${s}@w3.org + (subscribe, + archives)${o?kn` with ${o} at the start of your email's + subject`:""}. +

      `}(e,t):""} + ${e.github?function(e,t){if(e.github||e.wgPublicList)return kn`

      + ${e.github?kn` + GitHub Issues are preferred for + discussion of this specification. + `:""} + ${e.wgPublicList?kn` + ${e.github&&e.wgPublicList?"Alternatively, you can send comments to our mailing list.":"Comments regarding this document are welcome."} + Please send them to + ${e.wgPublicList}@w3.org + (subscribe, + archives)${e.subjectPrefix?kn` with ${e.subjectPrefix} at the start of your + email's subject`:""}. + `:""} +

      `}(e,t):""} + ${e.sotdAfterWGinfo?t.additionalContent:""} + ${t.additionalSections} + `;const Ts="w3c/headers";function Ps(e){return new URL(e,"https://www.w3.org/").href}const Is={LS:"WD",LD:"WD",FPWD:"WD","Member-SUBM":"SUBM"},Ds={DNOTE:"Group Note Draft",NOTE:"Group Note",STMT:"Statement","Member-SUBM":"Member Submission",MO:"Member-Only Document",ED:"Editor's Draft",LS:"Living Standard",LD:"Living Document",FPWD:"First Public Working Draft",WD:"Working Draft",CR:"Candidate Recommendation",CRD:"Candidate Recommendation",PR:"Proposed Recommendation",REC:"Recommendation",DISC:"Discontinued Draft",RSCND:"Rescinded Recommendation",DRY:"Registry Draft",CRYD:"Candidate Registry",CRY:"Candidate Registry",RY:"Registry",unofficial:"Unofficial Draft",UD:"Unofficial Draft",base:"",finding:"TAG Finding","draft-finding":"Draft TAG Finding","editor-draft-finding":"Draft TAG Finding","CG-DRAFT":"Draft Community Group Report","CG-FINAL":"Final Community Group Report","BG-DRAFT":"Draft Business Group Report","BG-FINAL":"Final Business Group Report"},Ns={...Ds,CR:"Candidate Recommendation Snapshot",CRD:"Candidate Recommendation Draft",CRY:"Candidate Registry Snapshot",CRYD:"Candidate Registry Draft"},js={DNOTE:"Note",NOTE:"Note",STMT:"Note","WG-NOTE":"Note","IG-NOTE":"Note",FPWD:"Recommendation",WD:"Recommendation",CR:"Recommendation",CRD:"Recommendation",PR:"Recommendation",REC:"Recommendation",DISC:"Recommendation",RSCND:"Recommendation",DRY:"Registry",CRYD:"Registry",CRY:"Registry",RY:"Registry"},Os=["DNOTE","NOTE","STMT"],zs=["CR","CRD","DISC","FPWD","PR","REC","RSCND","WD"],Ms=["DRY","CRY","CRYD","RY"],qs=["draft-finding","finding","editor-draft-finding"],Ws=["CG-DRAFT","CG-FINAL"],Us=["BG-DRAFT","BG-FINAL"],Fs=[...Ws,...Us],Bs=[...Os,...zs,...Ms],Hs=["base",...Ws,...Us,"editor-draft-finding","draft-finding","finding","MO","unofficial"],Vs=new Map([["cc0",{name:"Creative Commons 0 Public Domain Dedication",short:"CC0",url:"https://creativecommons.org/publicdomain/zero/1.0/"}],["w3c-software",{name:"W3C Software Notice and License",short:"W3C Software",url:"https://www.w3.org/copyright/software-license-2002/"}],["w3c-software-doc",{name:"W3C Software and Document Notice and License",short:"permissive document license",url:"https://www.w3.org/copyright/software-license-2023/"}],["cc-by",{name:"Creative Commons Attribution 4.0 International Public License",short:"CC-BY",url:"https://creativecommons.org/licenses/by/4.0/legalcode"}],["document",{name:"W3C Document License",short:"document use",url:"https://www.w3.org/copyright/document-license/"}],["dual",{name:"W3C Dual License",short:"dual license",url:"https://www.w3.org/Consortium/Legal/2013/copyright-documents-dual.html"}],[void 0,{name:"unlicensed",url:null,short:"UNLICENSED"}]]),Gs=["PP2017","PP2020"];function Ys(e,t,n=new Date){const r=e[t]?new Date(e[t]):new Date(n);if(Number.isFinite(r.valueOf())){const e=En.format(r);return new Date(e)}return lr(gr`${t} is not a valid date: "${e[t]}". Expected format 'YYYY-MM-DD'.`,Ts),new Date(En.format(new Date))}function Ks(e,{isTagFinding:t=!1}){const n=e.cloneNode(!0),r=document.createDocumentFragment();for(;n.hasChildNodes()&&(n.nodeType!==Node.ELEMENT_NODE||"section"!==n.firstChild.localName);)r.appendChild(n.firstChild);if(t&&!r.hasChildNodes()){ur(gr`ReSpec does not support automated SotD generation for TAG findings.`,Ts,{hint:"Please add the prerequisite content in the 'sotd' section."})}return{additionalContent:r,additionalSections:n.childNodes}}var Zs=Object.freeze({__proto__:null,W3CNotes:Os,bgStatus:Us,cgStatus:Ws,cgbgStatus:Fs,licenses:Vs,name:Ts,noTrackStatus:Hs,recTrackStatus:zs,registryTrackStatus:Ms,run:async function(e){if(e.isBasic="base"===e.specStatus,e.isCGBG=Fs.includes(e.specStatus),e.isCGFinal=e.isCGBG&&e.specStatus.endsWith("G-FINAL"),e.isCR="CR"===e.specStatus||"CRD"===e.specStatus,e.isCRDraft="CRD"===e.specStatus,e.isCRY="CRY"===e.specStatus||"CRYD"===e.specStatus,e.isEd="ED"===e.specStatus,e.isMemberSubmission="Member-SUBM"===e.specStatus,e.isMO="MO"===e.specStatus,e.isNote=Os.includes(e.specStatus),e.isNoTrack=Hs.includes(e.specStatus),e.isPR="PR"===e.specStatus,e.isRecTrack=zs.includes(e.specStatus),e.isRec=e.isRecTrack&&"REC"===e.specStatus,e.isRegistry=Ms.includes(e.specStatus),e.isRegular=!e.isCGBG&&!e.isBasic,e.isTagEditorFinding="editor-draft-finding"===e.specStatus,e.isTagFinding=qs.includes(e.specStatus),e.isUnofficial="unofficial"===e.specStatus,e.licenseInfo=function(e){let t;if("string"==typeof e.license){const n=e.license.toLowerCase();if(Vs.has(n))t=n;else{const t=`The license "\`${e.license}\`" is not supported.`,n=gr`Please set + ${"[license]"} to one of: ${fr([...Vs.keys()].filter((e=>e)),{quotes:!0})}. If in doubt, remove \`license\` and let ReSpec pick one for you.`;lr(t,Ts,{hint:n})}}if(e.isUnofficial&&!t&&(t="cc-by"),!e.isUnofficial&&["cc-by","cc0"].includes(t)){const t=gr`Please set ${"[license]"} to \`"w3c-software-doc"\` instead.`;lr(gr`License "\`${e.license}\`" is not allowed for W3C Specifications.`,Ts,{hint:t})}return Vs.get(t)}(e),e.prependW3C=!e.isBasic&&!e.isUnofficial,e.longStatus=Ns[e.specStatus],e.textStatus=Ds[e.specStatus],e.showPreviousVersion=!1,e.isRegular&&!e.shortName){const e=gr`Please set ${"[shortName]"} to a short name for the specification.`;lr(gr`The ${"[shortName]"} configuration option is required for this kind of document.`,Ts,{hint:e})}if(e.publishDate=Ys(e,"publishDate",document.lastModified),e.publishYear=e.publishDate.getUTCFullYear(),e.modificationDate&&(e.modificationDate=Ys(e,"modificationDate",document.lastModified)),e.isRecTrack&&!e.github&&!e.wgPublicList){const e=gr`Use the ${"[github]"} configuration option to add a link to a repository. Alternatively use ${"[wgPublicList]"} to link to a mailing list.`;lr("W3C Process requires a either a link to a public repository or mailing list.",Ts,{hint:e})}if(e.isEd&&!e.edDraftURI){const e=gr`Please set ${"[edDraftURI]"} to the URL of the Editor's Draft. Alternatively, use the set ${"[github]"} option, which automatically sets it for you.`;ur(gr`Editor's Drafts should set ${"[edDraftURI]"} configuration option.`,Ts,{hint:e})}const t=function(e){const{specStatus:t,group:n}=e;if(Bs.includes(t)||"wg"===e.groupType)return"/TR";switch(t){case"CG-FINAL":case"BG-FINAL":return`/community/reports/${n}`;case"finding":case"draft-finding":return"/2001/tag/doc";case"Member-SUBM":return"/Submission"}if(("tag"===e.group||"ab"===e.group)&&"TR"===e.canonicalURI)return"/TR";return""}(e);if(t&&!e.thisVersion){const n=Is[e.specStatus]||e.specStatus,{shortName:r,publishDate:s}=e,o=`${n}-${r}-${Fn(s)}`,i=[...Bs,"Member-SUBM"].includes(e.specStatus)?`${s.getUTCFullYear()}/`:"";e.thisVersion=Ps(`${t}/${i}${o}/`)}e.isEd&&(e.thisVersion=e.edDraftURI),e.isCGBG&&function(e){const t=Ds[e.specStatus],n=e.latestVersion?new URL(Ps(e.latestVersion)):null;if(!e.wg){return void lr(gr`The ${"[group]"} configuration option is required for this kind of document (${t}).`,Ts)}if(e.isCGFinal){if(!1===("https://www.w3.org"===n?.origin||"https://w3.org/"===n?.origin)){lr(gr`For ${t}, the ${"[latestVersion]"} URL must point to somewhere at https://www.w3.org/.`,Ts,{hint:"Ask a W3C Team Member for a W3C URL where the report can be published."})}}}(e),null!==e.latestVersion&&(e.latestVersion=e.latestVersion?Ps(e.latestVersion):Ps(`${t}/${e.shortName}/`)),e.latestVersion&&function(e){const t=new URL(e.latestVersion);if(("https://www.w3.org"===t.origin||"https://w3.org/"===t.origin)&&t.pathname.startsWith("/TR/")&&!1===["ED",...Bs].includes(e.specStatus)){const t=gr`Ask a W3C Team Member for a W3C URL where the report can be published and change ${"[latestVersion]"} to something else.`;lr(gr`Documents with a status of \`"${e.specStatus}"\` can't be published on the W3C's /TR/ (Technical Report) space.`,Ts,{hint:t})}}(e);const n=`${t}/${e.shortName}`;if(e.previousPublishDate){if(!e.previousMaturity&&!e.isTagFinding){lr(gr`${"[`previousPublishDate`]"} is set, but missing ${"[`previousMaturity`]"}.`,Ts)}e.previousPublishDate=Ys(e,"previousPublishDate");const r=Is[e.previousMaturity]??e.previousMaturity;if(e.isTagFinding&&e.latestVersion){const t=En.format(e.publishDate);e.thisVersion=Ps(`${n}-${t}`);const r=En.format(e.previousPublishDate);e.prevVersion=Ps(`${n}-${r}}`)}else if(e.isCGBG||e.isBasic)e.prevVersion=e.prevVersion||"";else{const n=e.previousPublishDate.getUTCFullYear(),{shortName:s}=e,o=Fn(e.previousPublishDate);e.prevVersion=Ps(`${t}/${n}/${r}-${s}-${o}/`)}}e.prevRecShortname&&!e.prevRecURI&&(e.prevRecURI=Ps(`${t}/${e.prevRecShortname}`));for(let t=0;t{if(e.w3cid)return;const n=gr`See ${"[w3cid]"} for instructions for how to retrieve it and add it.`;lr(gr`Editor ${e.name?`"${e.name}"`:`number ${t+1}`} is missing their ${"[w3cid]"}.`,Ts,{hint:n})}));if(e.alternateFormats?.some((({uri:e,label:t})=>!e||!t))){lr(gr`Every ${"[`alternateFormats`]"} entry must have a \`uri\` and a \`label\`.`,Ts)}e.copyrightStart==e.publishYear&&(e.copyrightStart=""),e.dashDate=En.format(e.publishDate),e.publishISODate=e.publishDate.toISOString(),e.shortISODate=En.format(e.publishDate),function(e){if(!e.wgPatentPolicy)return;const t=new Set([].concat(e.wgPatentPolicy));if(t.size&&![...t].every((e=>Gs.includes(e)))){const e=gr`Invalid ${"[wgPatentPolicy]"} value(s): ${hr([...t].filter((e=>!Gs.includes(e))))}.`,n=`Please use one of: ${fr(Gs)}.`;lr(e,Ts,{hint:n})}if(1!==t.size){const e="When collaborating across multiple groups, they must use the same patent policy.",n=gr`For ${"[wgPatentPolicy]"}, please check the patent policies of each group. The patent policies were: ${[...t].join(", ")}.`;lr(e,Ts,{hint:n})}e.wgPatentPolicy=[...t][0]}(e),await async function(e){if(!e.shortName||null===e.historyURI||!e.latestVersion)return;const t=e.isEd||Bs.includes(e.specStatus);if(e.historyURI&&!t){const t=gr`Please remove ${"[historyURI]"}.`;return lr(gr`The ${"[historyURI]"} can't be used with non /TR/ documents.`,Ts,{hint:t}),void(e.historyURI=null)}const n=new URL(e.historyURI??`${e.shortName}/`,"https://www.w3.org/standards/history/");if(e.historyURI&&t||["FPWD","DNOTE","NOTE","DRY"].includes(e.specStatus))return void(e.historyURI=n.href);try{const t=await fetch(n,{method:"HEAD"});t.ok&&(e.historyURI=t.url)}catch{}}(e),e.isTagEditorFinding&&(delete e.thisVersion,delete e.latestVersion),e.isTagFinding&&(e.showPreviousVersion=!!e.previousPublishDate);const r={get multipleAlternates(){return e.alternateFormats&&e.alternateFormats.length>1},get alternatesHTML(){return e.alternateFormats&&Gn(e.alternateFormats.map((({label:e})=>e)),((t,n)=>{const r=e.alternateFormats[n];return kn`${r.label}`}))}},s=(e.isCGBG?xs:ks)(e,r);document.body.prepend(s),document.body.classList.add("h-entry");const o=document.getElementById("sotd")||document.createElement("section");if((e.isCGBG||!e.isNoTrack||e.isTagFinding)&&!o.id){lr("A Status of This Document must include at least on custom paragraph.",Ts,{elements:[o],hint:"Add a `

      ` in the 'sotd' section that reflects the status of this specification."})}o.id=o.id||"sotd",o.classList.add("introductory");const i=[e.wg,e.wgURI,e.wgPatentURI];if(i.some((e=>Array.isArray(e)))&&!i.every((e=>Array.isArray(e)))){const e=gr`Use the ${"[group]"} option with an array instead.`;lr(gr`If one of ${"[wg]"}, ${"[wgURI]"}, or ${"[wgPatentURI]"} is an array, they all have to be.`,Ts,{hint:e})}if(Array.isArray(e.wg)?(e.multipleWGs=e.wg.length>1,e.wgPatentHTML=Gn(e.wg,((t,n)=>kn`a + public list of any patent disclosures (${t})`))):e.multipleWGs=!1,e.isPR&&!e.crEnd){lr(gr`${"[specStatus]"} is "PR" but no ${"[crEnd]"} is specified in the ${"[respecConfig]"} (needed to indicate end of previous CR).`,Ts)}if(e.isCR&&!e.crEnd){lr(gr`${"[specStatus]"} is "CR", but no ${"[crEnd]"} is specified in the ${"[respecConfig]"}.`,Ts)}if(e.crEnd=Ys(e,"crEnd"),e.isPr&&!e.prEnd){lr(gr`${"[specStatus]"} is "PR" but no ${"[prEnd]"} is specified in the ${"[respecConfig]"}.`,Ts)}e.prEnd=Ys(e,"prEnd");const a=o.classList.contains("updateable-rec"),c=null!==document.querySelector(".correction"),l=null!==document.querySelector(".proposed-correction"),u=null!==document.querySelector(".addition"),d=null!==document.querySelector(".proposed-addition"),p=c||u||d||l;if(e.isRec&&!e.errata&&!p){const e=gr`Add an ${"[errata]"} URL to your ${"[respecConfig]"}.`;lr("Recommendations must have an errata link.",Ts,{hint:e})}if(!a&&(u||c)){lr(gr`${"[specStatus]"} is "REC" with proposed additions but the Recommendation is not marked as allowing new features.`,Ts)}if(e.isRec&&a&&(d||l)&&!e.revisedRecEnd){lr(gr`${"[specStatus]"} is "REC" with proposed corrections or additions but no ${"[revisedRecEnd]"} is specified in the ${"[respecConfig]"}.`,Ts)}if(e.revisedRecEnd=Ys(e,"revisedRecEnd"),e.noRecTrack&&zs.includes(e.specStatus)){const t=gr`Document configured as ${"[noRecTrack]"}, but its status ("${e.specStatus}") puts it on the W3C Rec Track.`,n=fr(zs,{quotes:!0});lr(t,Ts,{hint:`Status **can't** be any of: ${n}.`})}if(o.classList.contains("override")||kn.bind(o)`${function(e,t){const n={...Ks(t,e),get mailToWGPublicList(){return`mailto:${e.wgPublicList}@w3.org`},get mailToWGPublicListWithSubject(){const t=e.subjectPrefix?`?subject=${encodeURIComponent(e.subjectPrefix)}`:"";return this.mailToWGPublicList+t},get mailToWGPublicListSubscription(){return`mailto:${e.wgPublicList}-request@w3.org?subject=subscribe`}},r=e.isCGBG?Ls:Rs;return r(e,n)}(e,o)}`,!e.implementationReportURI&&e.isCR){const e=gr`CR documents must have an ${"[implementationReportURI]"} that describes the [implementation experience](https://www.w3.org/policies/process/#implementation-experience).`;lr(gr`Missing ${"[implementationReportURI]"} configuration option in ${"[respecConfig]"}.`,Ts,{hint:e})}if(!e.implementationReportURI&&e.isPR){ur(gr`PR documents should include an ${"[implementationReportURI]"}, which needs to link to a document that describes the [implementation experience](https://www.w3.org/policies/process-20190301/#implementation-experience).`,Ts)}wr("amend-user-config",{publishISODate:e.publishISODate,generatedSubtitle:qn(document.getElementById("w3c-state")?.textContent??"")})},status2text:Ds,status2track:js,tagStatus:qs,trStatus:Bs});const Js={lint:{"no-headingless-sections":!0,"no-http-props":!0,"no-unused-vars":!1,"check-punctuation":!1,"local-refs-exist":!0,"check-internal-slots":!1,"check-charset":!1,"privsec-section":!1},pluralize:!0,specStatus:"base",highlightVars:!0,addSectionLinks:!0},Qs="w3c/defaults",Xs={src:"https://www.w3.org/StyleSheets/TR/2021/logos/W3C",alt:"W3C",height:48,width:72,url:"https://www.w3.org/"},eo={alt:"W3C Member Submission",href:"https://www.w3.org/Submission/",src:"https://www.w3.org/Icons/member_subm-v.svg",width:"211",height:"48"},to={lint:{"privsec-section":!1,"required-sections":!0,"wpt-tests-exist":!1,"informative-dfn":"warn","no-unused-dfns":"warn",a11y:!1},doJsonLd:!1,logos:[],xref:!0,wgId:"",otherLinks:[],excludeGithubLinks:!0,subtitle:"",prevVersion:"",formerEditors:[],editors:[],authors:[]};var no=Object.freeze({__proto__:null,name:Qs,run:function(e){const t=!1!==e.lint&&{...Js.lint,...to.lint,...e.lint};Object.assign(e,{...Js,...to,...e,lint:t}),"unofficial"===e.specStatus||e.hasOwnProperty("license")||(e.license="w3c-software-doc"),function(e){const{specStatus:t,groupType:n,group:r}=e;if(!t){const t=gr`Select an appropriate status from ${"[specStatus]"} based on your W3C group. If in doubt, use \`"unofficial"\`.`;return lr(gr`The ${"[specStatus]"} configuration option is required.`,Qs,{hint:t}),void(e.specStatus="base")}if(void 0===Ds[t]){const n=gr`The ${"[specStatus]"} "\`${t}\`" is not supported at for this type of document.`,r=gr`set ${"[specStatus]"} to one of: ${fr(Object.keys(Ds),{quotes:!0})}.`;return lr(n,Qs,{hint:r}),void(e.specStatus="base")}switch(n){case"cg":if(![...Ws,"unofficial","UD"].includes(t)){const n=gr`W3C Community Group documents can't use \`"${t}"\` for the ${"[specStatus]"} configuration option.`,r=fr(Ws,{quotes:!0});lr(n,Qs,{hint:`Please use one of: ${r}. Automatically falling back to \`"CG-DRAFT"\`.`}),e.specStatus="CG-DRAFT"}break;case"bg":if(![...Us,"unofficial","UD"].includes(t)){const n=gr`W3C Business Group documents can't use \`"${t}"\` for the ${"[specStatus]"} configuration option.`,r=fr(Us,{quotes:!0});lr(n,Qs,{hint:`Please use one of: ${r}. Automatically falling back to \`"BG-DRAFT"\`.`}),e.specStatus="BG-DRAFT"}break;case"wg":if(![...Bs,"unofficial","UD","ED"].includes(t)){const e=gr`Pleas see ${"[specStatus]"} for appropriate status for W3C Working Group documents.`;lr(gr`W3C Working Group documents can't use \`"${t}"\` for the ${"[specStatus]"} configuration option.`,Qs,{hint:e})}break;case"other":if("tag"===r&&!["ED",...Bs,...qs].includes(t)){const n=gr`The W3C Technical Architecture Group's documents can't use \`"${t}"\` for the ${"[specStatus]"} configuration option.`,r=fr(["ED",...Bs,...qs],{quotes:!0});lr(n,Qs,{hint:`Please use one of: ${r}. Automatically falling back to \`"unofficial"\`.`}),e.specStatus="unofficial"}break;default:if(!e.wgId&&!["unofficial","base","UD","Member-SUBM"].includes(e.specStatus)){const t="Document is not associated with a [W3C group](https://respec.org/w3c/groups/). Defaulting to 'base' status.",n=gr`Use the ${"[group]"} configuration option to associated this document with a W3C group.`;e.specStatus="base",lr(t,Qs,{hint:n})}}}(e),function(e){const{specStatus:t,wg:n}=e,r=[...zs,...Ms,...Os,...qs,"ED"].includes(t),s=n&&n.length&&r,o=["Member-SUBM"].includes(t);(s||o)&&(e.logos.unshift(Xs),"Member-SUBM"===t&&e.logos.push(eo))}(e)}});var ro=String.raw`@keyframes pop{ +0%{transform:scale(1,1)} +25%{transform:scale(1.25,1.25);opacity:.75} +100%{transform:scale(1,1)} +} +a.internalDFN{color:inherit;border-bottom:1px solid #99c;text-decoration:none} +a.externalDFN{color:inherit;border-bottom:1px dotted #ccc;text-decoration:none} +a.bibref{text-decoration:none} +.respec-offending-element:target{animation:pop .25s ease-in-out 0s 1} +.respec-offending-element,a[href].respec-offending-element{text-decoration:red wavy underline} +@supports not (text-decoration:red wavy underline){ +.respec-offending-element:not(pre){display:inline-block} +.respec-offending-element{background:url(data:image/gif;base64,R0lGODdhBAADAPEAANv///8AAP///wAAACwAAAAABAADAEACBZQjmIAFADs=) bottom repeat-x} +} +#references :target{background:#eaf3ff;animation:pop .4s ease-in-out 0s 1} +cite .bibref{font-style:italic} +a[href].orcid{padding-left:4px;padding-right:4px} +a[href].orcid>svg{margin-bottom:-2px} +ol.tof,ul.tof{list-style:none outside none} +.caption{margin-top:.5em;font-style:italic} +#issue-summary>ul{column-count:2} +#issue-summary li{list-style:none;display:inline-block} +details.respec-tests-details{margin-left:1em;display:inline-block;vertical-align:top} +details.respec-tests-details>*{padding-right:2em} +details.respec-tests-details[open]{z-index:999999;position:absolute;border:thin solid #cad3e2;border-radius:.3em;background-color:#fff;padding-bottom:.5em} +details.respec-tests-details[open]>summary{border-bottom:thin solid #cad3e2;padding-left:1em;margin-bottom:1em;line-height:2em} +details.respec-tests-details>ul{width:100%;margin-top:-.3em} +details.respec-tests-details>li{padding-left:1em} +.self-link:hover{opacity:1;text-decoration:none;background-color:transparent} +aside.example .marker>a.self-link{color:inherit} +.header-wrapper{display:flex;align-items:baseline} +:is(h2,h3,h4,h5,h6):not(#toc>h2,#abstract>h2,#sotd>h2,.head>h2){position:relative;left:-.5em} +:is(h2,h3,h4,h5,h6):not(#toch2)+a.self-link{color:inherit;order:-1;position:relative;left:-1.1em;font-size:1rem;opacity:.5} +:is(h2,h3,h4,h5,h6)+a.self-link::before{content:"§";text-decoration:none;color:var(--heading-text)} +:is(h2,h3)+a.self-link{top:-.2em} +:is(h4,h5,h6)+a.self-link::before{color:#000} +@media (max-width:767px){ +dd{margin-left:0} +} +@media print{ +.removeOnSave{display:none} +}`;const so=function(){const e=document.createElement("style");return e.id="respec-mainstyle",e.textContent=ro,document.head.appendChild(e),e}();var oo=Object.freeze({__proto__:null,name:"core/style",run:function(e){e.noReSpecCSS&&so.remove()}});function io(){const e=document.createElement("script");e.src="https://www.w3.org/scripts/TR/2021/fixup.js",location.hash&&e.addEventListener("load",(()=>{window.location.href=location.hash}),{once:!0}),document.body.appendChild(e)}const ao=function(){const e=[{hint:"preconnect",href:"https://www.w3.org"},{hint:"preload",href:"https://www.w3.org/scripts/TR/2021/fixup.js",as:"script"},{hint:"preload",href:lo("base.css").href,as:"style"},{hint:"preload",href:lo("dark.css").href,as:"style"},{hint:"preload",href:"https://www.w3.org/StyleSheets/TR/2021/logos/W3C",as:"image",corsMode:"anonymous"}],t=document.createDocumentFragment();for(const n of e.map(Pn))t.appendChild(n);return t}();function co(e){return t=>{const n=t.querySelector(`head link[href="${e}"]`);t.querySelector("head").append(n)}}function lo(e="base.css"){return new URL(`/StyleSheets/TR/2021/${e}`,"https://www.w3.org/")}ao.appendChild(kn``),document.head.querySelector("meta[name=viewport]")||ao.prepend(kn``),document.head.prepend(ao);var uo=Object.freeze({__proto__:null,name:"w3c/style",run:function(e){e.noToc||vr("end-all",io,{once:!0});const t=lo(function(e){const t=e.specStatus?.toUpperCase()??"";let n="";const r=[...zs,...Ms,...Os,"ED","MEMBER-SUBM"].includes(t)&&e.wgId;switch(t){case"WD":case"FPWD":n=r?"W3C-WD":"base.css";break;case"CG-DRAFT":case"CG-FINAL":case"BG-DRAFT":case"BG-FINAL":n=t.toLowerCase();break;case"UD":case"UNOFFICIAL":n="W3C-UD";break;case"FINDING":case"DRAFT-FINDING":case"EDITOR-DRAFT-FINDING":case"BASE":n="base.css";break;case"MEMBER-SUBM":n="W3C-Member-SUBM";break;default:n=r?`W3C-${e.specStatus}`:"base.css"}return n}(e));document.head.appendChild(kn``),vr("beforesave",co(t));let n=document.querySelector("head meta[name=color-scheme]");if(n||(n=kn``,document.head.appendChild(n)),n.content.includes("dark")){const e=lo("dark.css");document.head.appendChild(kn``),vr("beforesave",co(e))}}});const po="core/github";let fo,ho;const mo=new Promise(((e,t)=>{fo=e,ho=e=>{lr(e,po),t(new Error(e))}})),go=Wn({en:{file_a_bug:"File an issue",participate:"Participate:",commit_history:"Commit history"},ko:{participate:"참여"},zh:{file_a_bug:"å馈错误",participate:"å‚与:"},ja:{commit_history:"変更履歴",file_a_bug:"å•題報告",participate:"å‚加方法:"},nl:{commit_history:"Revisiehistorie",file_a_bug:"Dien een melding in",participate:"Doe mee:"},es:{commit_history:"Historia de cambios",file_a_bug:"Nota un bug",participate:"Participe:"},de:{commit_history:"Revisionen",file_a_bug:"Fehler melden",participate:"Mitmachen:"}});var bo=Object.freeze({__proto__:null,github:mo,name:po,run:async function(e){if(!e.hasOwnProperty("github")||!e.github)return void fo(null);if("object"==typeof e.github&&!e.github.hasOwnProperty("repoURL")){const e=gr`Config option ${"[github]"} is missing property \`repoURL\`.`;return void ho(e)}let t,n=e.github.repoURL||e.github;n.endsWith("/")||(n+="/");try{t=new URL(n,"https://github.com")}catch{const e=gr`${"[github]"} configuration option is not a valid URL? (${n}).`;return void ho(e)}if("https://github.com"!==t.origin){const e=gr`${"[github]"} configuration option must be HTTPS and pointing to GitHub. (${t.href}).`;return void ho(e)}const[r,s]=t.pathname.split("/").filter((e=>e));if(!r||!s){const e=gr`${"[github]"} URL needs a path. For example, "w3c/my-spec".`;return void ho(e)}const o=e.github.branch||"gh-pages",i=new URL("./issues/",t).href,a=new URL(`./commits/${e.github.branch??""}`,t.href),c={edDraftURI:`https://${r.toLowerCase()}.github.io/${s}/`,githubToken:void 0,githubUser:void 0,issueBase:i,atRiskBase:i,otherLinks:[],pullBase:new URL("./pulls/",t).href,shortName:s};let l="https://respec.org/github";if(e.githubAPI)if(new URL(e.githubAPI).hostname===window.parent.location.hostname)l=e.githubAPI;else{ur("The `githubAPI` configuration option is private and should not be added manually.",po)}if(!e.excludeGithubLinks){const n={key:go.participate,data:[{value:`GitHub ${r}/${s}`,href:t},{value:go.file_a_bug,href:c.issueBase},{value:go.commit_history,href:a.href},{value:"Pull requests",href:c.pullBase}]};e.otherLinks||(e.otherLinks=[]),e.otherLinks.unshift(n)}const u={branch:o,repoURL:t.href,apiBase:l,fullName:`${r}/${s}`,issuesURL:i,pullsURL:c.pullBase,newIssuesURL:new URL("./new/choose",i).href,commitHistoryURL:a.href};fo(u);const d={...c,...e,github:u,githubAPI:l};Object.assign(e,d)}});class yo{constructor(e){this.doc=e,this.root=e.createDocumentFragment(),this.stack=[this.root],this.current=this.root}static sectionClasses=new Set(["appendix","informative","notoc"]);findPosition(e){return parseInt(e.tagName.charAt(1),10)}findParent(e){let t;for(;e>0;)if(e--,t=this.stack[e],t)return t}findHeader({firstChild:e}){for(;e;){if(/H[1-6]/.test(e.tagName))return e;e=e.nextSibling}return null}addHeader(e){const t=this.doc.createElement("section"),n=this.findPosition(e);t.appendChild(e),this.findParent(n).appendChild(t),this.stack[n]=t,this.stack.length=n+1,this.current=t,this.processHeader(e,t)}processHeader(e,t){yo.sectionClasses.intersection(new Set(e.classList)).forEach((e=>{t.classList.add(e)}))}addSection(e){const t=this.findHeader(e),n=t?this.findPosition(t):1,r=this.findParent(n);t&&e.removeChild(t),e.appendChild(wo(e)),t&&e.prepend(t),r.appendChild(e),this.current=r}addElement(e){this.current.appendChild(e)}}function wo(e){const t=new yo(e.ownerDocument);for(;e.firstChild;){const n=e.firstChild;switch(n.localName){case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":t.addHeader(n);break;case"section":t.addSection(n);break;default:t.addElement(n)}}return t.root}function vo(e){const t=wo(e);if("section"===t.firstElementChild.localName&&"section"===e.localName){const n=t.firstElementChild;n.remove(),e.append(...n.childNodes)}else e.textContent="";e.appendChild(t)}var ko=Object.freeze({__proto__:null,name:"core/sections",restructure:vo,run:function(){vo(document.body)}});const $o="core/data-include";function xo(e,t,n){const r=document.querySelector(`[data-include-id=${t}]`),s=Bn(e,r.dataset.oninclude,n),o="string"==typeof r.dataset.includeReplace;!function(e,t,{replace:n}){const{includeFormat:r}=e.dataset;let s=t;"markdown"===r&&(s=Nr(s)),"text"===r?e.textContent=s:e.innerHTML=s,"markdown"===r&&vo(e),n&&e.replaceWith(...e.childNodes)}(r,s,{replace:o}),o||function(e){["data-include","data-include-format","data-include-replace","data-include-id","oninclude"].forEach((t=>e.removeAttribute(t)))}(r)}async function _o(e,t){const n=e.querySelectorAll("[data-include]"),r=Array.from(n).map((async e=>{const n=e.dataset.include;if(!n)return;const r=`include-${String(Math.random()).slice(2)}`;e.dataset.includeId=r;try{const s=await fetch(n);xo(await s.text(),r,n),t<3&&await _o(e,t+1)}catch(t){lr(`\`data-include\` failed: \`${n}\` (${t.message}).`,$o,{elements:[e],cause:t})}}));await Promise.all(r)}var Co=Object.freeze({__proto__:null,name:$o,run:async function(){await _o(document,1)}});var So=Object.freeze({__proto__:null,name:"core/reindent",run:function(){for(const e of document.getElementsByTagName("pre"))e.innerHTML=br(e.innerHTML)}});const Ro="core/title",Eo=Wn({en:{default_title:"No Title"},de:{default_title:"Kein Titel"},zh:{default_title:"无标题"},cs:{default_title:"Bez názvu"}});var Ao=Object.freeze({__proto__:null,name:Ro,run:function(e){const t=document.querySelector("h1#title")||kn`

      `;if(t.isConnected&&""===t.textContent.trim()){lr('The document is missing a title, so using a default title. To fix this, please give your document a ``. If you need special markup in the document\'s title, please use a `<h1 id="title">`.',Ro,{title:"Document is missing a title",elements:[t]})}t.id||(t.id="title"),t.classList.add("title"),function(e,t){t.isConnected||(t.textContent=document.title||`${Eo.default_title}`);const n=document.createElement("h1");n.innerHTML=t.innerHTML.replace(/:<br>/g,": ").replace(/<br>/g," - ");let r=qn(n.textContent);if(e.isPreview&&e.prNumber){const n=e.prUrl||`${e.github.repoURL}pull/${e.prNumber}`,{childNodes:s}=kn` + Preview of PR <a href="${n}">#${e.prNumber}</a>: + `;t.prepend(...s),r=`Preview of PR #${e.prNumber}: ${r}`}document.title=r,e.title=r}(e,t),document.body.prepend(t)}});const Lo="w3c/level",To=Wn({en:{level:"Level"},ja:{level:"レベル"},nl:{level:"Niveau"},de:{level:"Stufe"},zh:{level:"级别"}});var Po=Object.freeze({__proto__:null,name:Lo,run:function(e){if(!e.hasOwnProperty("level"))return;const t=document.querySelector("h1#title"),n=parseInt(e.level);if(!Number.isInteger(n)||n<0){lr(`The \`level\` configuration option must be a number greater or equal to 0. It is currently set to \`${n}\``,Lo,{title:"Invalid level config.",elements:[t]})}else t.append(` ${To.level} ${n}`),document.title=`${document.title} ${To.level} ${n}`,e.shortName=`${e.shortName}-${n}`,e.level=n}});const Io="w3c/abstract",Do=Wn({en:{abstract:"Abstract"},ko:{abstract:"요약"},zh:{abstract:"摘è¦"},ja:{abstract:"è¦ç´„"},nl:{abstract:"Samenvatting"},es:{abstract:"Resumen"},de:{abstract:"Zusammenfassung"},cs:{abstract:"Abstrakt"}});var No=Object.freeze({__proto__:null,name:Io,run:async function(){const e=function(){const e=document.getElementById("abstract");if(e)switch(e.localName){case"section":return e;case"div":return Jn(e,"section");default:return lr("The abstract should be a `<section>` element.",Io,{elements:[e]}),e}const t=Do.abstract.toLocaleLowerCase(o);for(const e of document.querySelectorAll("h2, h3, h4, h5, h6"))if(qn(e.textContent).toLocaleLowerCase(o)===t)return e.closest("section");return e}();e?(e.classList.add("introductory"),e.id="abstract",e.querySelector("h2")||e.prepend(kn`<h2>${Do.abstract}</h2>`)):lr('Document must have one `<section id="abstract">`.',Io)}});var jo=Object.freeze({__proto__:null,name:"core/data-transform",run:function(){document.querySelectorAll("[data-transform]").forEach((e=>{e.innerHTML=Bn(e.innerHTML,e.dataset.transform),e.removeAttribute("data-transform")}))}});const Oo="core/dfn-abbr";function zo(e){const t=(n=e).dataset.abbr?n.dataset.abbr:n.textContent.match(/\b([a-z])/gi).join("").toUpperCase();var n;const r=e.textContent.replace(/\s\s+/g," ").trim();e.insertAdjacentHTML("afterend",` (<abbr title="${r}">${t}</abbr>)`);const s=e.dataset.lt||"";e.dataset.lt=s.split("|").filter((e=>e.trim())).concat(t).join("|")}var Mo=Object.freeze({__proto__:null,name:Oo,run:function(){const e=document.querySelectorAll("[data-abbr]");for(const t of e){const{localName:e}=t;if("dfn"===e)zo(t);else{lr(`\`data-abbr\` attribute not supported on \`${e}\` elements.`,Oo,{elements:[t],title:"Error: unsupported."})}}}});const qo=/^[a-z]+(\s+[a-z]+)+\??$/,Wo=/\B"([^"]*)"\B/,Uo=/^(\w+)\(([^\\)]*)\)(?:\|(\w+)(?:\((?:([^\\)]*))\))?)?$/,Fo=/\[\[(\w+(?: +\w+)*)\]\](\([^)]*\))?$/,Bo=/^((?:\[\[)?(?:\w+(?: +\w+)*)(?:\]\])?)$/,Ho=/^(?:\w+)\??$/,Vo=/^(\w+)\["([\w- ]*)"\]$/,Go=/\.?(\w+\(.*\)$)/,Yo=/\/(.+)/,Ko=/\[\[.+\]\]/;function Zo(e){const{identifier:t,renderParent:n,nullable:r}=e;if(n)return kn`<a + data-xref-type="_IDL_" + data-link-type="idl" + data-lt="${t}" + ><code>${t+(r?"?":"")}</code></a + >`}function Jo(e){const{identifier:t,parent:n,slotType:r,renderParent:s,args:o}=e,{identifier:i}=n||{},a="method"===r,c=a?kn`(${Vn(o,Qo)})`:null,l=a?`(${o.join(", ")})`:"";return kn`${n&&s?".":""}<a + data-xref-type="${r}" + data-link-type="${r}" + data-link-for="${i}" + data-xref-for="${i}" + data-lt="${`[[${t}]]${l}`}" + ><code>[[${t}]]${c}</code></a + >`}function Qo(e,t,n){if(t<n.length-1)return kn`<var>${e}</var>`;const r=e.split(/(^\.{3})(.+)/),s=r.length>1,o=s?r[2]:r[0];return kn`${s?"...":null}<var>${o}</var>`}function Xo(e){const{parent:t,identifier:n,renderParent:r}=e,{identifier:s}=t||{};return kn`${r?".":""}<a + data-link-type="idl" + data-xref-type="attribute|dict-member|const" + data-link-for="${s}" + data-xref-for="${s}" + ><code>${n}</code></a + >`}function ei(e){const{args:t,identifier:n,type:r,parent:s,renderParent:o}=e,{renderText:i,renderArgs:a}=e,{identifier:c}=s||{},l=Vn(a||t,Qo),u=`${n}(${t.join(", ")})`;return kn`${s&&o?".":""}<a + data-link-type="idl" + data-xref-type="${r}" + data-link-for="${c}" + data-xref-for="${c}" + data-lt="${u}" + ><code>${i||n}</code></a + >${!i||a?kn`<code>(${l})</code>`:""}`}function ti(e){const{identifier:t,enumValue:n,parent:r}=e,s=r?r.identifier:t;return kn`"<a + data-link-type="idl" + data-xref-type="enum-value" + data-link-for="${s}" + data-xref-for="${s}" + data-lt="${n?null:"the-empty-string"}" + ><code>${n}</code></a + >"`}function ni(e){const{identifier:t}=e;return kn`"<a + data-link-type="idl" + data-cite="webidl" + data-xref-type="exception" + ><code>${t}</code></a + >"`}function ri(e){const{identifier:t,nullable:n}=e;return kn`<a + data-link-type="idl" + data-cite="webidl" + data-xref-type="interface" + data-lt="${t}" + ><code>${t+(n?"?":"")}</code></a + >`}function si(e){let t;try{t=function(e){const t=Ko.test(e),n=t?Yo:Go,[r,s]=e.split(n);if(t&&r&&!s)throw new SyntaxError(`Internal slot missing "for" part. Expected \`{{ InterfaceName/${r}}}\` }.`);const o=r.split(/[./]/).concat(s).filter((e=>e&&e.trim())).map((e=>e.trim())),i=!e.includes("/"),a=[];for(;o.length;){const t=o.pop();if(Uo.test(t)){const[,e,n,r,s]=t.match(Uo),o=n.split(/,\s*/).filter((e=>e)),c=r?.trim(),l=s?.split(/,\s*/).filter((e=>e));a.push({type:"method",identifier:e,args:o,renderParent:i,renderText:c,renderArgs:l})}else if(Vo.test(t)){const[,e,n]=t.match(Vo);a.push({type:"enum",identifier:e,enumValue:n,renderParent:i})}else if(Wo.test(t)){const[,e]=t.match(Wo);i?a.push({type:"exception",identifier:e}):a.push({type:"enum",enumValue:e,renderParent:i})}else if(Fo.test(t)){const[,e,n]=t.match(Fo),r=n?"method":"attribute",s=n?.slice(1,-1).split(/,\s*/).filter((e=>e));a.push({type:"internal-slot",slotType:r,identifier:e,args:s,renderParent:i})}else if(Bo.test(t)&&o.length){const[,e]=t.match(Bo);a.push({type:"attribute",identifier:e,renderParent:i})}else if(qo.test(t)){const e=t.endsWith("?"),n=e?t.slice(0,-1):t;a.push({type:"idl-primitive",identifier:n,renderParent:i,nullable:e})}else{if(!Ho.test(t)||0!==o.length)throw new SyntaxError(`IDL micro-syntax parsing error in \`{{ ${e} }}\``);{const e=t.endsWith("?"),n=e?t.slice(0,-1):t;a.push({type:"base",identifier:n,renderParent:i,nullable:e})}}}return a.forEach(((e,t,n)=>{e.parent=n[t+1]||null})),a.reverse()}(e)}catch(t){const n=kn`<span>{{ ${e} }}</span>`,r="Error: Invalid inline IDL string.";return lr(t.message,"core/inlines",{title:r,elements:[n]}),n}const n=kn(document.createDocumentFragment()),r=[];for(const e of t)switch(e.type){case"base":{const t=Zo(e);t&&r.push(t);break}case"attribute":r.push(Xo(e));break;case"internal-slot":r.push(Jo(e));break;case"method":r.push(ei(e));break;case"enum":r.push(ti(e));break;case"exception":r.push(ni(e));break;case"idl-primitive":r.push(ri(e));break;default:throw new Error("Unknown type.")}return n`${r}`}const oi=new Set(["alias","reference"]),ii=async function(){const e=await $n.openDB("respec-biblio2",12,{upgrade(e){Array.from(e.objectStoreNames).map((t=>e.deleteObjectStore(t)));e.createObjectStore("alias",{keyPath:"id"}).createIndex("aliasOf","aliasOf",{unique:!1}),e.createObjectStore("reference",{keyPath:"id"})}}),t=Date.now();for(const n of[...oi]){const r=e.transaction(n,"readwrite").store,s=IDBKeyRange.lowerBound(t);let o=await r.openCursor(s);for(;o?.value;){const e=o.value;(void 0===e.expires||e.expires<t)&&await r.delete(e.id),o=await o.continue()}}return e}();const ai={get ready(){return ii},async find(e){return await this.isAlias(e)&&(e=await this.resolveAlias(e)),await this.get("reference",e)},async has(e,t){if(!oi.has(e))throw new TypeError(`Invalid type: ${e}`);if(!t)throw new TypeError("id is required");const n=(await this.ready).transaction(e,"readonly").store,r=IDBKeyRange.only(t);return!!await n.openCursor(r)},async isAlias(e){return await this.has("alias",e)},async resolveAlias(e){if(!e)throw new TypeError("id is required");const t=(await this.ready).transaction("alias","readonly").store,n=IDBKeyRange.only(e),r=await t.openCursor(n);return r?r.value.aliasOf:null},async get(e,t){if(!oi.has(e))throw new TypeError(`Invalid type: ${e}`);if(!t)throw new TypeError("id is required");const n=(await this.ready).transaction(e,"readonly").store,r=IDBKeyRange.only(t),s=await n.openCursor(r);return s?s.value:null},async addAll(e,t){if(!e)return;const n={alias:[],reference:[]};for(const r of Object.keys(e)){const s={id:r,...e[r],expires:t};s.aliasOf?n.alias.push(s):n.reference.push(s)}const r=[...oi].flatMap((e=>n[e].map((t=>this.add(e,t)))));await Promise.all(r)},async add(e,t){if(!oi.has(e))throw new TypeError(`Invalid type: ${e}`);if("object"!=typeof t)throw new TypeError("details should be an object");if("alias"===e&&!t.hasOwnProperty("aliasOf"))throw new TypeError("Invalid alias object.");const n=await this.ready;let r=await this.has(e,t.id);if(r){const s=await this.get(e,t.id);if(s?.expires<Date.now()){const{store:s}=n.transaction(e,"readwrite");await s.delete(t.id),r=!1}}const{store:s}=n.transaction(e,"readwrite");return r?await s.put(t):await s.add(t)},async close(){(await this.ready).close()},async clear(){const e=await this.ready,t=[...oi],n=e.transaction(t,"readwrite"),r=t.map((e=>n.objectStore(e).clear()));await Promise.all(r)}},ci={},li=new URL("https://api.specref.org/bibrefs?refs="),ui=Pn({hint:"dns-prefetch",href:li.origin});let di;document.head.appendChild(ui);const pi=new Promise((e=>{di=e}));async function fi(e,t={forceUpdate:!1}){const n=[...new Set(e)].filter((e=>e.trim()));if(!n.length||!1===navigator.onLine)return null;let r;try{r=await fetch(li.href+n.join(","))}catch(e){return console.error(e),null}if(!t.forceUpdate&&!r.ok||200!==r.status)return null;const s=await r.json(),o=Date.now()+36e5;try{const e=r.headers.has("Expires")?Math.min(Date.parse(r.headers.get("Expires")),o):o;await ai.addAll(s,e)}catch(e){console.error(e)}return s}async function hi(e){const t=await pi;if(!t.hasOwnProperty(e))return null;const n=t[e];return n.aliasOf?await hi(n.aliasOf):n}var mi=Object.freeze({__proto__:null,Plugin:class{constructor(e){this.conf=e}normalizeReferences(){const e=new Set([...this.conf.normativeReferences].map((e=>e.toLowerCase())));Array.from(this.conf.informativeReferences).filter((t=>e.has(t.toLowerCase()))).forEach((e=>this.conf.informativeReferences.delete(e)))}getRefKeys(){return{informativeReferences:Array.from(this.conf.informativeReferences),normativeReferences:Array.from(this.conf.normativeReferences)}}async run(){this.conf.localBiblio||(this.conf.localBiblio={}),this.conf.biblio=ci;const e=Object.keys(this.conf.localBiblio).filter((e=>this.conf.localBiblio[e].hasOwnProperty("aliasOf"))).map((e=>this.conf.localBiblio[e].aliasOf)).filter((e=>!this.conf.localBiblio.hasOwnProperty(e)));this.normalizeReferences();const t=this.getRefKeys(),n=Array.from(new Set(t.normativeReferences.concat(t.informativeReferences).filter((e=>!this.conf.localBiblio.hasOwnProperty(e))).concat(e).sort())),r=n.length?await async function(e){const t=[];try{await ai.ready;const n=e.map((async e=>({id:e,data:await ai.find(e)})));t.push(...await Promise.all(n))}catch(n){t.push(...e.map((e=>({id:e,data:null})))),console.warn(n)}return t}(n):[],s={hasData:[],noData:[]};r.forEach((e=>{(e.data?s.hasData:s.noData).push(e)})),s.hasData.forEach((e=>{ci[e.id]=e.data}));const o=s.noData.map((e=>e.id));if(o.length){const e=await fi(o,{forceUpdate:!0});Object.assign(ci,e)}Object.assign(ci,this.conf.localBiblio),(()=>{di(this.conf.biblio)})()}},biblio:ci,name:"core/biblio",resolveRef:hi,updateFromNetwork:fi});const gi="core/render-biblio",bi=Wn({en:{info_references:"Informative references",norm_references:"Normative references",references:"References",reference_not_found:"Reference not found."},ko:{references:"참조"},nl:{info_references:"Informatieve referenties",norm_references:"Normatieve referenties",references:"Referenties"},es:{info_references:"Referencias informativas",norm_references:"Referencias normativas",references:"Referencias",reference_not_found:"Referencia no encontrada."},ja:{info_references:"å‚照用å‚考文献",norm_references:"è¦ç¯„çš„å‚考文献",references:"å‚考文献"},de:{info_references:"Weiterführende Informationen",norm_references:"Normen und Spezifikationen",references:"Referenzen"},zh:{info_references:"éžè§„范性引用",norm_references:"规范性引用",references:"å‚考文献"},cs:{info_references:"Informativní odkazy",norm_references:"Normativní odkazy",references:"Odkazy",reference_not_found:"Odkaz nebyl nalezen."}}),yi=new Map([["CR","W3C Candidate Recommendation"],["ED","W3C Editor's Draft"],["LCWD","W3C Last Call Working Draft"],["NOTE","W3C Working Group Note"],["PR","W3C Proposed Recommendation"],["REC","W3C Recommendation"],["WD","W3C Working Draft"]]),wi=(vi=".",e=>{const t=e.trim();return!t||t.endsWith(vi)?t:t+vi});var vi;function ki(e,t){const{goodRefs:n,badRefs:r}=function(e){const t=[],n=[];for(const r of e)r.refcontent?t.push(r):n.push(r);return{goodRefs:t,badRefs:n}}(e.map($i)),s=function(e){const t=new Map;for(const n of e)t.has(n.refcontent.id)||t.set(n.refcontent.id,n);return[...t.values()]}(n),o=s.concat(r).sort(((e,t)=>e.ref.toLocaleLowerCase().localeCompare(t.ref.toLocaleLowerCase()))),i=kn`<section> + <h3>${t}</h3> + <dl class="bibliography">${o.map(_i)}</dl> + </section>`;Kn(i,"",t);const a=function(e){return e.reduce(((e,t)=>{const n=t.refcontent.id;return(e.has(n)?e.get(n):e.set(n,[]).get(n)).push(t.ref),e}),new Map)}(n);return function(e,t){e.map((({ref:e,refcontent:n})=>{const r=`#bib-${e.toLowerCase()}`,s=t.get(n.id).map((e=>`a.bibref[href="#bib-${e.toLowerCase()}"]`)).join(",");return{refUrl:r,elems:document.querySelectorAll(s),refcontent:n}})).forEach((({refUrl:e,elems:t,refcontent:n})=>{t.forEach((t=>{t.setAttribute("href",e),t.setAttribute("title",n.title),t.dataset.linkType="biblio"}))}))}(s,a),function(e){for(const{ref:t}of e){const e=[...document.querySelectorAll(`a.bibref[href="#bib-${t.toLowerCase()}"]`)].filter((({textContent:e})=>e.toLowerCase()===t.toLowerCase()));lr(`Reference "[${t}]" not found.`,gi,{hint:`Search for ["${t}"](https://www.specref.org?q=${t}) on Specref to see if it exists or if it's misspelled.`,elements:e})}}(r),i}function $i(e){let t=ci[e],n=e;const r=new Set([n]);for(;t&&t.aliasOf;)if(r.has(t.aliasOf)){t=null;lr(`Circular reference in biblio DB between [\`${e}\`] and [\`${n}\`].`,gi)}else n=t.aliasOf,t=ci[n],r.add(n);return t&&!t.id&&(t.id=e.toLowerCase()),{ref:e,refcontent:t}}function xi(e,t){const n=e.replace(/^(!|\?)/,""),r=`#bib-${n.toLowerCase()}`,s=kn`<cite + ><a class="bibref" href="${r}" data-link-type="biblio">${t||n}</a></cite + >`;return t?s:kn`[${s}]`}function _i(e){const{ref:t,refcontent:n}=e,r=`bib-${t.toLowerCase()}`;return kn` + <dt id="${r}">[${t}]</dt> + <dd> + ${n?{html:Ci(n)}:kn`<em class="respec-offending-element" + >${bi.reference_not_found}</em + >`} + </dd> + `}function Ci(e){if("string"==typeof e)return e;let t=`<cite>${e.title}</cite>`;return t=e.href?`<a href="${e.href}">${t}</a>. `:`${t}. `,e.authors&&e.authors.length&&(t+=e.authors.join("; "),e.etAl&&(t+=" et al"),t.endsWith(".")||(t+=". ")),e.publisher&&(t=`${t} ${wi(e.publisher)} `),e.date&&(t+=`${e.date}. `),e.status&&(t+=`${yi.get(e.status)||e.status}. `),e.href&&(t+=`URL: <a href="${e.href}">${e.href}</a>`),t}var Si=Object.freeze({__proto__:null,name:gi,renderInlineCitation:xi,run:function(e){const t=Array.from(e.informativeReferences),n=Array.from(e.normativeReferences);if(!t.length&&!n.length)return;const r=document.querySelector("section#references")||kn`<section id="references"></section>`;if(document.querySelector("section#references > :is(h2, h1)")||r.prepend(kn`<h1>${bi.references}</h1>`),r.classList.add("appendix"),n.length){const e=ki(n,bi.norm_references);r.appendChild(e)}if(t.length){const e=ki(t,bi.info_references);r.appendChild(e)}document.body.appendChild(r)}});const Ri="core/inlines",Ei={},Ai=e=>new RegExp(e.map((e=>e.source)).join("|")),Li=Wn({en:{rfc2119Keywords:()=>Ai([/\bMUST(?:\s+NOT)?\b/,/\bSHOULD(?:\s+NOT)?\b/,/\bSHALL(?:\s+NOT)?\b/,/\bMAY\b/,/\b(?:NOT\s+)?REQUIRED\b/,/\b(?:NOT\s+)?RECOMMENDED\b/,/\bOPTIONAL\b/])},de:{rfc2119Keywords:()=>Ai([/\bMUSS\b/,/\bMÜSSEN\b/,/\bERFORDERLICH\b/,/\b(?:NICHT\s+)?NÖTIG\b/,/\bDARF(?:\s+NICHT)?\b/,/\bDÜRFEN(?:\s+NICHT)?\b/,/\bVERBOTEN\b/,/\bSOLL(?:\s+NICHT)?\b/,/\bSOLLEN(?:\s+NICHT)?\b/,/\b(?:NICHT\s+)?EMPFOHLEN\b/,/\bKANN\b/,/\bKÖNNEN\b/,/\bOPTIONAL\b/])}}),Ti=/(?:`[^`]+`)(?!`)/,Pi=/(?:{{[^}]+\?*}})/,Ii=/\B\|\w[\w\s]*(?:\s*:[\w\s&;"?<>]+\??)?\|\B/,Di=/(?:\[\[(?:!|\\|\?)?[\w.-]+(?:|[^\]]+)?\]\])/,Ni=/(?:\[\[\[(?:!|\\|\?)?#?[\w-.]+\]\]\])/,ji=/(?:\[=[^=]+=\])/,Oi=/(?:\[\^[^^]+\^\])/;function zi(e){const t=e.slice(2,-2).trim(),[n,r,s]=t.split("/",3).map((e=>e&&e.trim())).filter((e=>!!e)),[o,i,a]=t.startsWith("/")?["element-attr",null,n]:s?["attr-value",`${n}/${r}`,s]:r?["element-attr",n,r]:["element",null,n];return kn`<code + ><a + data-xref-type="${o}" + data-xref-for="${i}" + data-link-type="${o}" + data-link-for="${i}" + >${a}</a + ></code + >`}function Mi(e){const t=qn(e),n=kn`<em class="rfc2119">${t}</em>`;return Ei[t]=!0,n}function qi(e){const t=e.slice(3,-3).trim();return t.startsWith("#")?kn`<a href="${t}" data-matched-text="${e}"></a>`:kn`<a data-cite="${t}" data-matched-text="${e}"></a>`}function Wi(e,t){const n=qn(e.slice(2,-2));if(n.startsWith("\\"))return e.replace("\\","");const r=si(n);return!!t.parentElement.closest("dfn,a")?Vi(`\`${r.textContent}\``):r}function Ui(e,t,n){const r=e.slice(2,-2);if(r.startsWith("\\"))return[`[[${r.slice(1)}]]`];const[s,o]=r.split("|").map(qn),{type:i,illegal:a}=Qn(s,t.parentElement),c=xi(s,o),l=s.replace(/^(!|\?)/,"");if(a&&!n.normativeReferences.has(l)){const e=c.childNodes[1]||c;ur("Normative references in informative sections are not allowed. ",Ri,{elements:[e],hint:`Remove '!' from the start of the reference \`[[${r}]]\``})}return"informative"!==i||a?n.normativeReferences.add(l):n.informativeReferences.add(l),c.childNodes[1]?c.childNodes:[c]}function Fi(e,t,n){return"ABBR"===t.parentElement.tagName?e:kn`<abbr title="${n.get(e)}">${e}</abbr>`}function Bi(e){const t=e.slice(1,-1).split(":",2),[n,r]=t.map((e=>e.trim()));return kn`<var data-type="${r}">${n}</var>`}function Hi(e){const t=function(e){const t=e=>e.replace("%%","/").split("/").map(qn).join("/"),n=e.replace("\\/","%%"),r=n.lastIndexOf("/");if(-1===r)return[t(n)];const s=n.substring(0,r),o=n.substring(r+1,n.length);return[t(s),t(o)]}(e=e.slice(2,-2)),[n,r]=2===t.length?t:[null,t[0]],[s,o]=r.includes("|")?r.split("|",2).map((e=>e.trim())):[null,r],i=Gi(o),a=n?qn(n):null;return kn`<a + data-link-type="dfn|abstract-op" + data-link-for="${a}" + data-xref-for="${a}" + data-lt="${s}" + >${i}</a + >`}function Vi(e){const t=e.slice(1,-1);return kn`<code>${t}</code>`}function Gi(e){return Ti.test(e)?e.split(/(`[^`]+`)(?!`)/).map((e=>e.startsWith("`")?Vi(e):Gi(e))):document.createTextNode(e)}var Yi=Object.freeze({__proto__:null,name:Ri,rfc2119Usage:Ei,run:function(e){const t=new Map;document.normalize(),document.querySelector("section#conformance")||document.body.classList.add("informative"),e.normativeReferences=new rr,e.informativeReferences=new rr,e.respecRFC2119||(e.respecRFC2119=Ei);const n=document.querySelectorAll("abbr[title]:not(.exclude)");for(const{textContent:e,title:r}of n){const n=qn(e),s=qn(r);t.set(n,s)}const r=t.size?new RegExp(`(?:\\b${[...t.keys()].join("\\b)|(?:\\b")}\\b)`):null,s=function(e,t=[],n={wsNodes:!0}){const r=t.join(", "),s=document.createNodeIterator(e,NodeFilter.SHOW_TEXT,(e=>n.wsNodes||e.data.trim()?r&&e.parentElement.closest(r)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT)),o=[];let i;for(;i=s.nextNode();)o.push(i);return o}(document.body,["#respec-ui",".head","pre","svg","script","style"],{wsNodes:!1}),o=Li.rfc2119Keywords(),i=new RegExp(`(${Ai([o,Pi,Ii,Di,Ni,ji,Ti,Oi,...r?[r]:[]]).source})`);for(const n of s){const r=n.data.split(i);if(1===r.length)continue;const s=document.createDocumentFragment();let a=!0;for(const i of r)if(a=!a,a)switch(!0){case i.startsWith("{{"):s.append(Wi(i,n));break;case i.startsWith("[[["):s.append(qi(i));break;case i.startsWith("[["):s.append(...Ui(i,n,e));break;case i.startsWith("|"):s.append(Bi(i));break;case i.startsWith("[="):s.append(Hi(i));break;case i.startsWith("`"):s.append(Vi(i));break;case i.startsWith("[^"):s.append(zi(i));break;case t.has(i):s.append(Fi(i,n,t));break;case o.test(i):s.append(Mi(i))}else s.append(i);n.replaceWith(s)}}});const Ki="w3c/conformance",Zi=Wn({en:{conformance:"Conformance",normativity:"As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.",keywordInterpretation:(e,t)=>kn`<p> + The key word${t?"s":""} ${e} in this document + ${t?"are":"is"} to be interpreted as described in + <a href="https://www.rfc-editor.org/info/bcp14">BCP 14</a> + ${xi("RFC2119")} ${xi("RFC8174")} + when, and only when, ${t?"they appear":"it appears"} in all + capitals, as shown here. + </p>`},de:{conformance:"Anforderungen",normativity:"Neben den explizit als nicht-normativ gekennzeichneten Abschnitten sind auch alle Diagramme, Beispiele und Hinweise in diesem Dokument nicht normativ. Alle anderen Angaben sind normativ.",keywordInterpretation:(e,t)=>kn`<p> + ${t?"Die Schlüsselwörter":"Das Schlüsselwort"} ${e} in + diesem Dokument ${t?"sind":"ist"} gemäß + <a href="https://www.rfc-editor.org/info/bcp14">BCP 14</a> + ${xi("RFC2119")} ${xi("RFC8174")} + und unter Berücksichtigung von + <a href="https://github.com/adfinis-sygroup/2119/blob/master/2119de.rst" + >2119de</a + > + zu interpretieren, wenn und nur wenn ${t?"sie":"es"} wie hier + gezeigt durchgehend groß geschrieben wurde${t?"n":""}. + </p>`}});var Ji=Object.freeze({__proto__:null,name:Ki,run:function(e){const t=document.querySelector("section#conformance");if(t&&!t.classList.contains("override")&&function(e,t){const n=[...Object.keys(Ei)];n.length&&(t.normativeReferences.add("RFC2119"),t.normativeReferences.add("RFC8174"));const r=Gn(n.sort(),(e=>kn`<em class="rfc2119">${e}</em>`)),s=n.length>1,o=kn` + <h1>${Zi.conformance}</h1> + <p>${Zi.normativity}</p> + ${n.length?Zi.keywordInterpretation(r,s):null} + `;e.prepend(...o.childNodes)}(t,e),!t&&Object.keys(Ei).length){ur("Document uses RFC2119 keywords but lacks a conformance section.",Ki,{hint:'Please add a `<section id="conformance">`.'})}}});function Qi(e,t,n,r){try{switch(t){case"element-attr":return document.createAttribute(e),!0;case"element":return document.createElement(e),!0}}catch(s){lr(`Invalid ${t} name "${e}": ${s.message}`,r,{hint:`Check that the ${t} name is allowed per the XML's Name production for ${t}.`,elements:[n]})}return!1}function Xi(e,t,n,r){if(/^[a-z]+(-[a-z]+)*$/i.test(e))return!0;return lr(`Invalid ${t} name "${e}".`,r,{hint:`Check that the ${t} name is allowed per the naming rules for this type.`,elements:[n]}),!1}const ea=new ar;function ta(e,t){for(const n of t)ea.has(n)||ea.set(n,new Set),ea.get(n).add(e)}const na="core/dfn",ra=new Map([["abstract-op",{requiresFor:!1}],["attr-value",{requiresFor:!0,associateWith:"a markup attribute",validator:Xi}],["element",{requiresFor:!1,validator:Qi}],["element-attr",{requiresFor:!1,validator:Qi}],["element-state",{requiresFor:!0,associateWith:"a markup attribute",validator:Xi}],["event",{requiresFor:!1,validator:Xi}],["http-header",{requiresFor:!1}],["media-type",{requiresFor:!1,validator:function(e,t,n,r){try{const t=new _n(e);if(t.toString()!==e)throw new Error(`Input doesn't match its canonical form: "${t}".`)}catch(s){return lr(`Invalid ${t} "${e}": ${s.message}.`,r,{hint:"Check that the MIME type has both a type and a sub-type, and that it's in a canonical form (e.g., `text/plain`).",elements:[n]}),!1}return!0}}],["scheme",{requiresFor:!1,validator:Xi}],["permission",{requiresFor:!1,validator:function(e,t,n,r){return e.startsWith('"')&&e.endsWith('"')?Xi(e.slice(1,-1),t,n,r):(lr(`Invalid ${t} "${e}".`,r,{hint:`Check that the ${t} is quoted with double quotes.`,elements:[n]}),!1)}}]]),sa=[...ra.keys()];function oa(e,t){let n="";switch(!0){case sa.some((t=>e.classList.contains(t))):n=[...e.classList].find((e=>ra.has(e))),function(e,t,n){const r=ra.get(t);if(r.requiresFor&&!n.dataset.dfnFor){const e=gr`Definition of type "\`${t}\`" requires a ${"[data-dfn-for]"} attribute.`,{associateWith:s}=r,o=gr`Use a ${"[data-dfn-for]"} attribute to associate this with ${s}.`;lr(e,na,{hint:o,elements:[n]})}r.validator&&r.validator(e,t,n,na)}(t,n,e);break;case Fo.test(t):n=function(e,t){t.dataset.hasOwnProperty("idl")||(t.dataset.idl="");const n=t.closest("[data-dfn-for]");t!==n&&n?.dataset.dfnFor&&(t.dataset.dfnFor=n.dataset.dfnFor);if(!t.dataset.dfnFor){const n=gr`Use a ${"[data-dfn-for]"} attribute to associate this dfn with a WebIDL interface.`;lr(`Internal slot "${e}" must be associated with a WebIDL interface.`,na,{hint:n,elements:[t]})}t.matches(".export, [data-export]")||(t.dataset.noexport="");const r=e.endsWith(")")?"method":"attribute";if(!t.dataset.dfnType)return r;const s=["attribute","method"],{dfnType:o}=t.dataset;if(!s.includes(o)||r!==o){const n=gr`Invalid ${"[data-dfn-type]"} attribute on internal slot.`,o=`The only allowed types are: ${fr(s,{quotes:!0})}. The slot "${e}" seems to be a "${pr(r)}"?`;return lr(n,na,{hint:o,elements:[t]}),"dfn"}return o}(t,e)}if(!n&&!e.matches("[data-dfn-type]")){const t=e.closest("[data-dfn-type]");n=t?.dataset.dfnType}n&&!e.dataset.dfnType&&(e.dataset.dfnType=n)}function ia(e){switch(!0){case e.matches(".export.no-export"):lr(gr`Declares both "${"[no-export]"}" and "${"[export]"}" CSS class.`,na,{elements:[e],hint:"Please use only one."});break;case e.matches(".no-export, [data-noexport]"):if(e.matches("[data-export]")){lr(gr`Declares ${"[no-export]"} CSS class, but also has a "${"[data-export]"}" attribute.`,na,{elements:[e],hint:"Please chose only one."}),delete e.dataset.export}e.dataset.noexport="";break;case e.matches(":is(.export):not([data-noexport], .no-export)"):e.dataset.export=""}}var aa=Object.freeze({__proto__:null,name:na,run:function(){for(const e of document.querySelectorAll("dfn")){const t=Zn(e);if(ta(e,t),e.dataset.cite&&/\b#\b/.test(e.dataset.cite))continue;const[n]=t;oa(e,n),ia(e);const r=(e.dataset.localLt||"").split("|").map(qn),s=t.filter((e=>!r.includes(e)));(s.length>1||n!==qn(e.textContent))&&(e.dataset.lt=s.join("|"))}}});var ca=Object.freeze({__proto__:null,name:"core/pluralize",run:function(e){if(!e.pluralize)return;const t=function(){const e=new Set;document.querySelectorAll("a:not([href])").forEach((t=>{const n=qn(t.textContent).toLowerCase();e.add(n),t.dataset.lt&&e.add(t.dataset.lt)}));const t=new Set,n=document.querySelectorAll("dfn:not([data-lt-noDefault])");return n.forEach((e=>{const n=qn(e.textContent).toLowerCase();t.add(n),e.dataset.lt&&e.dataset.lt.split("|").forEach((e=>t.add(e))),e.dataset.localLt&&e.dataset.localLt.split("|").forEach((e=>t.add(e)))})),function(n){const r=qn(n).toLowerCase(),s=Cn.isSingular(r)?Cn.plural(r):Cn.singular(r);return e.has(s)&&!t.has(s)?s:""}}();document.querySelectorAll("dfn:not([data-lt-no-plural]):not([data-lt-noDefault])").forEach((e=>{const n=[e.textContent];e.dataset.lt&&n.push(...e.dataset.lt.split("|")),e.dataset.localLt&&n.push(...e.dataset.localLt.split("|"));const r=new Set(n.map(t).filter((e=>e)));if(r.size){const t=e.dataset.plurals?e.dataset.plurals.split("|"):[],n=[...new Set([...t,...r])];e.dataset.plurals=n.join("|"),ta(e,n)}}))}});var la=String.raw`span.example-title{text-transform:none} +:is(aside,div).example,div.illegal-example{padding:.5em;margin:1em 0;position:relative;clear:both} +div.illegal-example{color:red} +div.illegal-example p{color:#000} +aside.example div.example{border-left-width:.1em;border-color:#999;background:#fff}`;const ua=Wn({en:{example:"Example"},nl:{example:"Voorbeeld"},es:{example:"Ejemplo"},ko:{example:"예시"},ja:{example:"例"},de:{example:"Beispiel"},zh:{example:"例"},cs:{example:"Příklad"}});function da(e,t,n){n.title=e.title,n.title&&e.removeAttribute("title");const r=t>0?` ${t}`:"",s=n.title?kn`<span class="example-title">: ${n.title}</span>`:"";return kn`<div class="marker"> + <a class="self-link">${ua.example}<bdi>${r}</bdi></a + >${s} + </div>`}var pa=Object.freeze({__proto__:null,name:"core/examples",run:function(){const e=document.querySelectorAll("pre.example, pre.illegal-example, aside.example");if(!e.length)return;document.head.insertBefore(kn`<style> + ${la} + </style>`,document.querySelector("link"));let t=0;e.forEach((e=>{e.classList.contains("illegal-example");const n={},{title:r}=e;if("aside"===e.localName){++t;const s=da(e,t,n);e.prepend(s);const o=Kn(e,"example",r||String(t));s.querySelector("a.self-link").href=`#${o}`}else{const s=!!e.closest("aside");s||++t,n.content=e.innerHTML,e.classList.remove("example","illegal-example");const o=e.id?e.id:null;o&&e.removeAttribute("id");const i=da(e,s?0:t,n),a=kn`<div class="example" id="${o}"> + ${i} ${e.cloneNode(!0)} + </div>`;Kn(a,"example",r||String(t));a.querySelector("a.self-link").href=`#${a.id}`,e.replaceWith(a)}}))}});var fa=String.raw`.issue-label{text-transform:initial} +.warning>p:first-child{margin-top:0} +.warning{padding:.5em;border-left-width:.5em;border-left-style:solid} +span.warning{padding:.1em .5em .15em} +.issue.closed span.issue-number{text-decoration:line-through} +.issue.closed span.issue-number::after{content:" (Closed)";font-size:smaller} +.warning{border-color:#f11;border-color:var(--warning-border,#f11);border-width:.2em;border-style:solid;background:#fbe9e9;background:var(--warning-bg,#fbe9e9);color:#000;color:var(--text,#000)} +.warning-title:before{content:"âš ";font-size:1.3em;float:left;padding-right:.3em;margin-top:-.3em} +li.task-list-item{list-style:none} +input.task-list-item-checkbox{margin:0 .35em .25em -1.6em;vertical-align:middle} +.issue a.respec-gh-label{padding:5px;margin:0 2px 0 2px;font-size:10px;text-transform:none;text-decoration:none;font-weight:700;border-radius:4px;position:relative;bottom:2px;border:none;display:inline-block}`;const ha="core/issues-notes",ma=Wn({en:{editors_note:"Editor's note",feature_at_risk:"(Feature at Risk) Issue",issue:"Issue",issue_summary:"Issue summary",no_issues_in_spec:"There are no issues listed in this specification.",note:"Note",warning:"Warning"},ja:{note:"注",editors_note:"編者注",feature_at_risk:"(変更ã®å¯èƒ½æ€§ã®ã‚る機能) Issue",issue:"Issue",issue_summary:"Issue ã®è¦ç´„",no_issues_in_spec:"ã“ã®ä»•様ã«ã¯æœªè§£æ±ºã® issues ã¯å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“.",warning:"警告"},nl:{editors_note:"Redactionele noot",issue_summary:"Lijst met issues",no_issues_in_spec:"Er zijn geen problemen vermeld in deze specificatie.",note:"Noot",warning:"Waarschuwing"},es:{editors_note:"Nota de editor",issue:"Cuestión",issue_summary:"Resumen de la cuestión",note:"Nota",no_issues_in_spec:"No hay problemas enumerados en esta especificación.",warning:"Aviso"},de:{editors_note:"Redaktioneller Hinweis",issue:"Frage",issue_summary:"Offene Fragen",no_issues_in_spec:"Diese Spezifikation enthält keine offenen Fragen.",note:"Hinweis",warning:"Warnung"},zh:{editors_note:"编者注",feature_at_risk:"(有å¯èƒ½å˜åŠ¨çš„ç‰¹æ€§ï¼‰Issue",issue:"Issue",issue_summary:"Issue 总结",no_issues_in_spec:"本规范中未列出任何 issue。",note:"注",warning:"警告"},cs:{editors_note:"Poznámka editora",feature_at_risk:"(Funkce v ohrožení) Problém",issue:"Problém",issue_summary:"Souhrn problémů",no_issues_in_spec:"V této specifikaci nejsou uvedeny žádné problémy.",note:"Poznámka",warning:"Varování"}});function ga(e,t,n){const r=function(){if(document.querySelector(".issue[data-number]"))return e=>{if(e.dataset.number)return Number(e.dataset.number)};let e=0;return t=>{if(t.classList.contains("issue")&&"span"!==t.localName)return++e}}(),s=document.createElement("ul");e.forEach((e=>{const{type:o,displayType:i,isFeatureAtRisk:a}=function(e){const t=e.classList.contains("issue"),n=e.classList.contains("warning"),r=e.classList.contains("ednote"),s=e.classList.contains("atrisk"),o=t?"issue":n?"warning":r?"ednote":"note",i=t?s?ma.feature_at_risk:ma.issue:n?ma.warning:r?ma.editors_note:ma.note;return{type:o,displayType:i,isFeatureAtRisk:s}}(e),c="issue"===o,l="span"===e.localName,{number:u}=e.dataset,d={title:e.title,number:r(e)};if(!l){const r=kn`<div class="${a?`${o} atrisk`:o}" role="${"note"===o?"note":null}"></div>`,l=document.createElement("span"),p=kn`<div role="heading" class="${`${o}-title marker`}">${l}</div>`;Kn(p,"h",o);let f,h=i;if(e.id?(r.id=e.id,e.removeAttribute("id")):Kn(r,"issue-container",d.number?`number-${d.number}`:""),c){if(void 0!==d.number&&(h+=` ${d.number}`),e.dataset.hasOwnProperty("number")){const e=function(e,t,{isFeatureAtRisk:n=!1}={}){if(!n&&t.issueBase)return kn`<a href="${t.issueBase+e}" />`;if(n&&t.atRiskBase)return kn`<a href="${t.atRiskBase+e}" />`}(u,n,{isFeatureAtRisk:a});if(e&&(l.before(e),e.append(l)),l.classList.add("issue-number"),f=t.get(u),!f){ur(`Failed to fetch issue number ${u}.`,ha)}f&&!d.title&&(d.title=f.title)}s.append(function(e,t,n){const r=`${e}${t.number?` ${t.number}`:""}`,s=t.title?kn`<span style="text-transform: none">: ${t.title}</span>`:"";return kn`<li><a href="${`#${n}`}">${r}</a>${s}</li>`}(ma.issue,d,r.id))}if(l.textContent=h,d.title){e.removeAttribute("title");const{repoURL:t=""}=n.github||{},s=f?f.labels:[];f&&"CLOSED"===f.state&&r.classList.add("closed"),p.append(function(e,t,n){const r=e.map((e=>function(e,t){const{color:n,name:r}=e,s=new URL("./issues/",t);s.searchParams.set("q",`is:issue is:open label:"${e.name}"`);const o=function(e){const[t,n,r]=[e.slice(0,2),e.slice(2,4),e.slice(4,6)],[s,o,i]=[t,n,r].map((e=>parseInt(e,16)/255)).map((e=>e<=.04045?e/12.92:((e+.055)/1.055)**2.4));return.2126*s+.7152*o+.0722*i>.179?"#000":"#fff"}(n),i=`background-color: #${n}; color: ${o}`,a=`GitHub label: ${r}`;return kn` <a + class="respec-gh-label" + style="${i}" + href="${s.href}" + aria-label="${a}" + >${r}</a + >`}(e,n)));r.length&&r.unshift(document.createTextNode(" "));return kn`<span class="issue-label">: ${t}${r}</span>`}(s,d.title,t))}let m=e;e.replaceWith(r),m.classList.remove(o),m.removeAttribute("data-number"),f&&!m.innerHTML.trim()&&(m=document.createRange().createContextualFragment(f.bodyHTML)),r.append(p,m);const g=tr(p,"section").length+2;p.setAttribute("aria-level",g)}})),function(e){const t=document.getElementById("issue-summary");if(!t)return;const n=t.querySelector("h2, h3, h4, h5, h6");e.hasChildNodes()?t.append(e):t.append(kn`<p>${ma.no_issues_in_spec}</p>`),(!n||n&&n!==t.firstElementChild)&&t.insertAdjacentHTML("afterbegin",`<h1>${ma.issue_summary}</h1>`)}(s)}var ba=Object.freeze({__proto__:null,name:ha,run:async function(e){const t=document.querySelectorAll(".issue, .note, .warning, .ednote"),n=Array.from(t).filter((e=>e instanceof HTMLElement));if(!n.length)return;const r=await async function(e){if(!e||!e.apiBase)return new Map;const t=[...document.querySelectorAll(".issue[data-number]")].map((e=>Number.parseInt(e.dataset.number,10))).filter((e=>e));if(!t.length)return new Map;const n=new URL("issues",`${e.apiBase}/${e.fullName}/`);n.searchParams.set("issues",t.join(","));const r=await fetch(n.href);if(!r.ok)return lr(`Error fetching issues from GitHub. (HTTP Status ${r.status}).`,ha),new Map;const s=await r.json();return new Map(Object.entries(s))}(e.github),{head:s}=document;s.insertBefore(kn`<style> + ${fa} + </style>`,s.querySelector("link")),ga(n,r,e),document.querySelectorAll(".ednote").forEach((e=>{e.classList.remove("ednote"),e.classList.add("note")}))}});const ya="core/best-practices",wa={en:{best_practice:"Best Practice "},ja:{best_practice:"最良実施例 "},de:{best_practice:"Musterbeispiel "},zh:{best_practice:"最佳实践 "}},va=Wn(wa),ka=o in wa?o:"en";var $a=Object.freeze({__proto__:null,name:ya,run:function(){const e=document.querySelectorAll(".practicelab"),t=document.getElementById("bp-summary"),n=t?document.createElement("ul"):null;if([...e].forEach(((e,t)=>{const r=Kn(e,"bp"),s=kn`<a class="marker self-link" href="${`#${r}`}" + ><bdi lang="${ka}">${va.best_practice}${t+1}</bdi></a + >`;if(n){const t=kn`<li>${s}: ${sr(e)}</li>`;n.appendChild(t)}const o=e.closest("div");if(!o)return void e.classList.add("advisement");o.classList.add("advisement");const i=kn`${s.cloneNode(!0)}: ${e}`;o.prepend(...i.childNodes)})),e.length)t&&(t.appendChild(kn`<h1>Best Practices Summary</h1>`),t.appendChild(n));else if(t){ur("Using best practices summary (#bp-summary) but no best practices found.",ya),t.remove()}}});const xa="core/figures",_a=Wn({en:{list_of_figures:"List of Figures",fig:"Figure "},ja:{fig:"図 ",list_of_figures:"図ã®ãƒªã‚¹ãƒˆ"},ko:{fig:"그림 ",list_of_figures:"그림 목ë¡"},nl:{fig:"Figuur ",list_of_figures:"Lijst met figuren"},es:{fig:"Figura ",list_of_figures:"Lista de Figuras"},zh:{fig:"图 ",list_of_figures:"规范中包å«çš„图"},de:{fig:"Abbildung",list_of_figures:"Abbildungsverzeichnis"}});var Ca=Object.freeze({__proto__:null,name:xa,run:function(){const e=function(){const e=[];return document.querySelectorAll("figure").forEach(((t,n)=>{const r=t.querySelector("figcaption");if(r)!function(e,t,n){const r=t.textContent;Kn(e,"fig",r),Xn(t,kn`<span class="fig-title"></span>`),t.prepend(kn`<a class="self-link" href="#${e.id}" + >${_a.fig}<bdi class="figno">${n+1}</bdi></a + >`," ")}(t,r,n),e.push(function(e,t){const n=t.cloneNode(!0);return n.querySelectorAll("a").forEach((e=>{Jn(e,"span").removeAttribute("href")})),kn`<li class="tofline"> + <a class="tocxref" href="${`#${e}`}">${n.childNodes}</a> + </li>`}(t.id,r));else{ur("Found a `<figure>` without a `<figcaption>`.",xa,{elements:[t]})}})),e}(),t=document.getElementById("tof");e.length&&t&&(!function(e){if(e.classList.contains("appendix")||e.classList.contains("introductory")||e.closest("section"))return;const t=er(e);t.every((e=>e.classList.contains("introductory")))?e.classList.add("introductory"):t.some((e=>e.classList.contains("appendix")))&&e.classList.add("appendix")}(t),t.append(kn`<h1>${_a.list_of_figures}</h1>`,kn`<ul class="tof"> + ${e} + </ul>`))}});const Sa=Wn({en:{list_of_tables:"List of Tables",table:"Table "}});var Ra=Object.freeze({__proto__:null,name:"core/tables",run:function(){const e=function(){const e=[],t=document.querySelectorAll("table.numbered");return[...t].filter((e=>!!e.querySelector("caption"))).forEach(((t,n)=>{const r=t.querySelector("caption");!function(e,t,n){const r=t.textContent;Kn(e,"table",r),Xn(t,kn`<span class="table-title"></span>`),t.prepend(kn`<a class="self-link" href="#${e.id}" + >${Sa.table}<bdi class="tableno">${n+1}</bdi></a + >`," ")}(t,r,n),e.push(function(e,t){const n=t.cloneNode(!0);for(const e of n.querySelectorAll("a"))Jn(e,"span",{copyAttributes:!1});return kn`<li> + <a class="tocxref" href="${`#${e}`}" + >${n.childNodes}</a + > + </li>`}(t.id,r))})),e}(),t=document.querySelector("section#list-of-tables");e.length&&t&&(!function(e){if(e.matches(".appendix, .introductory")||e.closest("section"))return;const t=er(e);t.every((e=>e.classList.contains("introductory")))?e.classList.add("introductory"):t.some((e=>e.classList.contains("appendix")))&&e.classList.add("appendix")}(t),t.append(kn`<h1>${Sa.list_of_tables}</h1>`,kn`<ul class="list-of-tables"> + ${e} + </ul>`))}});const Ea=new Set(["callback interface","callback","dictionary","enum","interface mixin","interface","typedef"]);function Aa(e,t,{parent:n=""}={}){switch(e.type){case"constructor":case"operation":return function(e,t,n){if(n.includes("!overload"))return La(e,t,n);const r=`${n}()`;return La(e,t,r,n)}(e,n,t);default:return La(e,n,t)}}function La(e,t,...n){const{type:r}=e;for(const e of n){let n="enum-value"===r&&""===e?"the-empty-string":e,s=Pa(n,t,e,r);if(0===s.length&&""!==t){n=`${t}.${n}`;const e=ea.get(n);e&&1===e.size&&(s=[...e],ta(s[0],[n]))}else n=e;if(s.length>1){lr(`WebIDL identifier \`${e}\` ${t?`for \`${t}\``:""} is defined multiple times`,e,{title:"Duplicate definition.",elements:s})}if(s.length)return s[0]}}function Ta(e,t,n,r){if(!e.id){const t=n.toLowerCase(),s=t?`${t}-`:"";let o=r.toLowerCase().replace(/[()]/g,"").replace(/\s/g,"-");""===o&&(o="the-empty-string",e.setAttribute("aria-label","the empty string")),e.id=`dom-${s}${o}`}switch(e.dataset.idl=t.type,e.dataset.title=e.textContent,e.dataset.dfnFor=n,t.type){case"operation":case"attribute":case"field":e.dataset.type=Ia(t)}switch(e.querySelector("code")||e.closest("code")||!e.children||Xn(e,e.ownerDocument.createElement("code")),t.type){case"attribute":case"constructor":case"operation":!function(e,t){const{local:n,exportable:r}=t,s=e.dataset.lt?new Set(e.dataset.lt.split("|")):new Set;for(const e of r)s.add(e);n.filter((e=>s.has(e))).forEach((e=>s.delete(e))),e.dataset.lt=[...s].join("|"),e.dataset.localLt=n.join("|"),ta(e,[...n,...r])}(e,function(e,t,n){const{type:r}=e,s=`${t}.${n}`;switch(r){case"constructor":case"operation":{const t=`${n}()`,r=`${s}()`,o=function(e,t){const n=[];if(0===t.length)return n;const r=[],s=[];for(const{name:e,optional:n,variadic:o}of t)n||o?s.push(e):r.push(e);const o=r.join(", "),i=`${e}(${o})`;n.push(i);const a=s.map(((t,n)=>{const o=[...r,...s.slice(0,n+1)].join(", ");return`${e}(${o})`}));return n.push(...a),n}(n,e.arguments);return{local:[s,r,n],exportable:[t,...o]}}case"attribute":return{local:[s],exportable:[n]}}}(t,n,r))}return e}function Pa(e,t,n,r){const s=ea.get(e);if(!s||0===s.size)return[];const o=[...s],i=o.filter((e=>{if("dfn"===e.dataset.dfnType)return!1;const n=e.closest("[data-dfn-for]");return n&&n.dataset.dfnFor===t}));if(0===i.length&&""===t&&1===o.length)return o[0].textContent===n?o:[];if(Ea.has(r)&&o.length){const e=o.find((e=>e.textContent.trim()===n));if(e)return[e]}return i}function Ia(e={}){const{idlType:t,generic:n,union:r}=e;return void 0===t?"":"string"==typeof t?t:n||(r?t.map(Ia).join("|"):Ia(t))}const Da=function(){const e=document.createElement("button");return e.innerHTML='<svg height="16" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z"/></svg>',e.title="Copy IDL to clipboard",e.classList.add("respec-button-copy-paste","removeOnSave"),e}();function Na(e){const t=e.closest("pre.idl").cloneNode(!0);t.querySelector(".idlHeader").remove();const{textContent:n}=t,r=Da.cloneNode(!0);r.addEventListener("click",(()=>{navigator.clipboard.writeText(n)})),e.append(r)}var ja=Object.freeze({__proto__:null,addCopyIDLButton:Na,name:"core/webidl-clipboard"});var Oa=String.raw`pre.idl{padding:1em;position:relative} +pre.idl>code{color:#000;color:var(--text,#000)} +@media print{ +pre.idl{white-space:pre-wrap} +} +.idlHeader{display:block;width:150px;background:#8ccbf2;background:var(--def-border,#8ccbf2);color:#fff;color:var(--defrow-border,#fff);font-family:sans-serif;font-weight:700;margin:-1em 0 1em -1em;height:28px;line-height:28px} +.idlHeader a.self-link{margin-left:.3cm;text-decoration:none;border-bottom:none;color:inherit} +.idlID{font-weight:700;color:#005a9c} +.idlType{color:#005a9c} +.idlName{color:#ff4500} +.idlName a{color:#ff4500;border-bottom:1px dotted #ff4500;text-decoration:none} +a.idlEnumItem{color:#000;border-bottom:1px dotted #ccc;text-decoration:none} +.idlSuperclass{font-style:italic;color:#005a9c} +.idlDefaultValue,.idlParamName{font-style:italic} +.extAttr{color:#666} +.idlSectionComment{color:gray} +.idlIncludes a{font-weight:700} +.respec-button-copy-paste:focus{text-decoration:none;border-color:#51a7e8;outline:0;box-shadow:0 0 5px rgba(81,167,232,.5)} +.respec-button-copy-paste:is(:focus:hover,.selected:focus){border-color:#51a7e8} +.respec-button-copy-paste:is(:hover,:active,.zeroclipboard-is-hover,.zeroclipboard-is-active){text-decoration:none;background-color:#ddd;background-image:linear-gradient(#eee,#ddd);border-color:#ccc} +.respec-button-copy-paste:is(:active,.selected,.zeroclipboard-is-active){background-color:#dcdcdc;background-image:none;border-color:#b5b5b5;box-shadow:inset 0 2px 4px rgba(0,0,0,.15)} +.respec-button-copy-paste.selected:hover{background-color:#cfcfcf} +.respec-button-copy-paste:is(:disabled,:disabled:hover,.disabled,.disabled:hover){color:rgba(102,102,102,.5);cursor:default;background-color:rgba(229,229,229,.5);background-image:none;border-color:rgba(197,197,197,.5);box-shadow:none} +@media print{ +.respec-button-copy-paste{visibility:hidden} +}`;const za="core/webidl",Ma=za,qa={},Wa={},Ua={wrap:e=>e.flat().filter((e=>""!==e)).map((e=>"string"==typeof e?new Text(e):e)),trivia:e=>e.trim()?kn`<span class="idlSectionComment">${e}</span>`:e,generic:e=>/^[A-Z]/.test(e)?kn`<a data-xref-type="interface" data-cite="WEBIDL">${e}</a>`:kn`<a data-xref-type="dfn" data-cite="WEBIDL">${e}</a>`,reference(e,t,n){if("extended-attribute"===n.type)return e;let r="_IDL_",s=null;if("object"===t)r="interface",s="WEBIDL";return kn`<a + data-link-type="${"_IDL_"===r?"idl":r}" + data-xref-type="${r}" + data-cite="${s}" + data-lt="${undefined}" + >${e}</a + >`},name(e,{data:t,parent:n}){if(t.idlType&&"argument-type"===t.idlType.type)return kn`<span class="idlParamName">${e}</span>`;const r=Fa(e,t,n);if("enum-value"!==t.type){const e=n?"idlName":"idlID";r.classList.add(e)}return r},nameless(e,{data:t,parent:n}){switch(t.type){case"operation":case"constructor":return Fa(e,t,n);default:return e}},type:e=>kn`<span class="idlType">${e}</span>`,inheritance:e=>kn`<span class="idlSuperclass">${e}</span>`,definition(e,{data:t,parent:n}){const r=function(e){switch(e.type){case"callback interface":return"idlInterface";case"operation":return"idlMethod";case"field":return"idlMember";case"enum-value":return"idlEnumItem";case"callback function":return"idlCallback"}return`idl${e.type[0].toUpperCase()}${e.type.slice(1)}`}(t);switch(t.type){case"includes":case"enum-value":return kn`<span class="${r}">${e}</span>`}const s=n?n.name:"",{name:o,idlId:i}=Ha(t,s);return kn`<span + class="${r}" + id="${i}" + data-idl + data-title="${o}" + >${e}</span + >`},extendedAttribute:e=>kn`<span class="extAttr">${e}</span>`,extendedAttributeReference:e=>kn`<a data-xref-type="extended-attribute">${e}</a>`};function Fa(e,t,n){const r=n?n.name:"",{name:s}=Ha(t,r),o=Aa(t,s,{parent:r}),i=function(e){switch(e){case"operation":return"method";case"field":return"dict-member";case"callback interface":case"interface mixin":return"interface";default:return e}}(t.type);if(o){t.partial||(o.matches("[data-noexport]")||(o.dataset.export=""),o.dataset.dfnType=i),Ta(o,t,r,s);const n=`#${o.id}`;return kn`<a + data-link-for="${r}" + data-link-type="${i}" + href="${n}" + class="internalDFN" + ><code>${e}</code></a + >`}const a="operation"===t.type&&"toJSON"===t.name&&t.extAttrs.some((({name:e})=>"Default"===e));if(a)return kn`<a data-link-type="dfn" data-lt="default toJSON steps" + >${e}</a + >`;if(!t.partial){const n=kn`<dfn data-export data-dfn-type="${i}" + >${e}</dfn + >`;return ta(n,[s]),Ta(n,t,r,s),n}const c=kn`<a + data-idl="${t.partial?"partial":null}" + data-link-type="${i}" + data-title="${t.name}" + data-xref-type="${i}" + >${e}</a + >`;if(s&&"typedef"!==t.type&&!(t.partial&&!o)){const e=gr`See ${"using `data-dfn-for`|#data-dfn-for"} in ReSpec's documentation.`;ur(`Missing \`<dfn>\` for${r?` \`${r}\`'s`:""} \`${"operation"===t.type?`${s}()`:s}\` ${t.type}.`,Ma,{elements:[c],hint:e})}return c}const Ba=new WeakMap;function Ha(e,t=""){if(Ba.has(e))return Ba.get(e);const n=function(e,t){let n=function(e){switch(e.type){case"enum-value":return e.value;case"operation":return e.name||e.special;default:return e.name||e.type}}(e);const r=e.special&&""===e.name?"anonymous-":"";let s=function(e,t){if(!t)return`idl-def-${e.toLowerCase()}`;return`idl-def-${t.toLowerCase()}-${e.toLowerCase()}`}(r+n,t);switch(e.type){case"callback interface":case"dictionary":case"interface":case"interface mixin":s+=function(e){if(!e.partial)return"";Wa[e.name]||(Wa[e.name]=0);return Wa[e.name]+=1,`-partial-${Wa[e.name]}`}(e);break;case"constructor":case"operation":{const r=function(e,t){const n=`${t}.${e}`,r=`${n}()`;let s;qa[r]||(qa[r]=0);qa[n]?s=`!overload-${qa[n]}`:qa[n]=0;return qa[r]+=1,qa[n]+=1,s||""}(n,t);r?(n+=r,s+=r):e.arguments.length&&(s+=e.arguments.map((e=>`-${e.name.toLowerCase()}`)).join(""));break}}return{name:n,idlId:s}}(e,t);return Ba.set(e,n),n}const Va=["interface","interface mixin","dictionary","namespace","enum","typedef","callback"];function Ga(e,t){let n;try{n=Sn.parse(e.textContent,{sourceName:String(t)})}catch(t){return lr(`Failed to parse WebIDL: ${t.bareMessage}.`,Ma,{title:t.bareMessage,details:`<pre>${t.context}</pre>`,elements:[e]}),[]}e.classList.add("def","idl");const r=Sn.write(n,{templates:Ua});kn.bind(e)`${r}`,Xn(e,document.createElement("code")),e.querySelectorAll("[data-idl]").forEach((e=>{if(e.dataset.dfnFor)return;const t=e.dataset.title,n=e.dataset.dfnType,r=e.parentElement.closest("[data-idl][data-title]");r&&!Va.includes(n)&&(e.dataset.dfnFor=r.dataset.title),"dfn"===e.localName&&ta(e,[t])}));const s=e.closest("[data-cite], body"),{dataset:o}=s;if(o.cite||(o.cite="WEBIDL"),!/\bwebidl\b/i.test(o.cite)){const e=o.cite.trim().split(/\s+/);o.cite=["WEBIDL",...e].join(" ")}return Ya(e),n}function Ya(e){Yn(e,"webidl");const t=kn`<span class="idlHeader" + ><a class="self-link" href="${`#${e.id}`}">WebIDL</a></span + >`;e.prepend(t),Na(t)}var Ka=Object.freeze({__proto__:null,addIDLHeader:Ya,name:za,run:async function(){const e=document.querySelectorAll("pre.idl, pre.webidl");if(!e.length)return;const t=document.createElement("style");t.textContent=Oa,document.querySelector("head link, head > *:last-child").before(t);const n=[...e].map(Ga),r=Sn.validate(n);for(const t of r){let r=`<pre>${Mn(t.context)}</pre>`;if(t.autofix){t.autofix();r+=`Try fixing as:\n <pre>${Mn(Sn.write(n[t.sourceName]))}</pre>`}lr(`WebIDL validation error: ${t.bareMessage}`,Ma,{details:r,elements:[e[t.sourceName]],title:t.bareMessage})}document.normalize()}});const Za="core/data-cite",Ja="__SPEC__";async function Qa(e){const{key:t,frag:n,path:r,href:s}=e;let o="",i="";if(t===Ja)o=document.location.href;else{const e=await hi(t);if(!e)return null;o=e.href,i=e.title}if(s)o=s;else{if(r){const e=r.startsWith("/")?`.${r}`:r;o=new URL(e,o).href}n&&(o=new URL(n,o).href)}return{href:o,title:i}}function Xa(e,t,n){const{href:r,title:s}=t,o=!n.path&&!n.frag;switch(e.localName){case"a":{const t=e;if(""===t.textContent&&"the-empty-string"!==t.dataset.lt&&(t.textContent=s),t.href=r,o){const e=document.createElement("cite");t.replaceWith(e),e.append(t)}break}case"dfn":{const t=document.createElement("a");if(t.href=r,t.dataset.cite=n.key,t.dataset.citePath=n.path,t.dataset.citeFrag=n.frag,e.textContent?Xn(e,t):(t.textContent=s,e.append(t)),o){const n=document.createElement("cite");n.append(t),e.append(n)}if("export"in e.dataset){lr("Exporting a linked external definition is not allowed.",Za,{hint:"Please remove the `data-export` attribute.",elements:[e]}),delete e.dataset.export}e.classList.add("externalDFN"),e.dataset.noExport="";break}}}function ec(e){return t=>{const n=t.search(e);return-1!==n?t.substring(n):""}}const tc=ec("#"),nc=ec("/");function rc(e){const{dataset:t}=e,{cite:n,citeFrag:r,citePath:s,citeHref:o}=t;if(n.startsWith("#")&&!r){const r=e.parentElement.closest('[data-cite]:not([data-cite^="#"])'),{key:s,isNormative:o}=r?rc(r):{key:Ja,isNormative:!1};return t.cite=o?s:`?${s}`,t.citeFrag=n.replace("#",""),rc(e)}const i=r?`#${r}`:tc(n),a=s||nc(n).split("#")[0],{type:c}=Qn(n,e),l="normative"===c,u=/^[?|!]/.test(n);return{key:n.split(/[/|#]/)[0].substring(Number(u)),isNormative:l,frag:i,path:a,href:o}}function sc(e){const t=["data-cite","data-cite-frag","data-cite-path"];e.querySelectorAll("a[data-cite], dfn[data-cite]").forEach((e=>t.forEach((t=>e.removeAttribute(t)))))}var oc=Object.freeze({__proto__:null,THIS_SPEC:Ja,name:Za,run:async function(){const e=document.querySelectorAll("dfn[data-cite]:not([data-cite='']), a[data-cite]:not([data-cite=''])");await async function(e){const t=e.map(rc).map((async e=>({entry:e,result:await hi(e.key)}))),n=(await Promise.all(t)).filter((({result:e})=>null===e)).map((({entry:{key:e}})=>e)),r=await fi(n);r&&Object.assign(ci,r)}([...e]);for(const t of e){const e=t.dataset.cite,n=rc(t),r=await Qa(n);if(r)Xa(t,r,n);else{const n=`Couldn't find a match for "${e}"`;t.dataset.matchedText&&(t.textContent=t.dataset.matchedText),ur(n,Za,{elements:[t]})}}vr("beforesave",sc)},toCiteDetails:rc});const ic="core/link-to-dfn",ac=[],cc={en:{duplicateMsg:e=>`Duplicate definition(s) of '${e}'`,duplicateTitle:"This is defined more than once in the document."},ja:{duplicateMsg:e=>`'${e}' ã®é‡è¤‡å®šç¾©`,duplicateTitle:"ã“ã®æ–‡æ›¸å†…ã§è¤‡æ•°å›žå®šç¾©ã•れã¦ã„ã¾ã™ï¼Ž"},de:{duplicateMsg:e=>`Mehrfache Definition von '${e}'`,duplicateTitle:"Das Dokument enthält mehrere Definitionen dieses Eintrags."},zh:{duplicateMsg:e=>`'${e}' çš„é‡å¤å®šä¹‰`,duplicateTitle:"在文档中有é‡å¤çš„定义。"},cs:{duplicateMsg:e=>`Duplicitní definice '${e}'`,duplicateTitle:"Toto je v dokumentu definováno vícekrát."}},lc=Wn(cc);function uc(e){const t=new Map,n=[];for(const r of ea.get(e)){const{dfnType:s="dfn"}=r.dataset,o=r.dataset.dfnFor?.split(",").map((e=>e.trim()))??[""];for(const i of o){if(t.has(i)&&t.get(i).has(s)){const e=t.get(i).get(s),o="dfn"===e.localName,a="dfn"===r.localName,c=s===(e.dataset.dfnType||"dfn"),l=!i&&!e.dataset.dfnFor||e.dataset.dfnFor?.split(",").map((e=>e.trim())).includes(i);if(o&&a&&c&&l){n.push(r);continue}}t.has(i)||t.set(i,new Map),t.get(i).set(s,r),("idl"in r.dataset||"dfn"!==s)&&t.get(i).set("idl",r),Kn(r,"dfn",e)}}return{result:t,duplicates:n}}function dc(e,t){const n=function(e){const t=e.closest("[data-link-for]"),n=t?t.dataset.linkFor:"",r=Zn(e).reduce(((e,r)=>{const s=r.split(".");return 2===s.length&&e.push({for:s[0],title:s[1]}),e.push({for:n,title:r}),t||e.push({for:r,title:r}),""!==n&&e.push({for:"",title:r}),e}),[]);return r}(e),r=n.find((e=>t.has(e.title)&&t.get(e.title).has(e.for)));if(!r)return;const s=t.get(r.title).get(r.for),{linkType:o}=e.dataset;if(o){for(const e of o.split("|"))if(s.get(e))return s.get(e);return s.get("dfn")}{const e=r.for?"idl":"dfn";return s.get(e)||s.get("idl")}}function pc(e,t,n){let r=!1;const{linkFor:s}=e.dataset,{dfnFor:o}=t.dataset;if(t.dataset.cite)e.dataset.cite=t.dataset.cite;else if(s&&!n.get(s)&&o&&!o.split(",").map((e=>e.trim())).includes(s))r=!0;else if(t.classList.contains("externalDFN")){const n=t.dataset.lt?t.dataset.lt.split("|"):[];e.dataset.lt=n[0]||t.textContent,r=!0}else"partial"!==e.dataset.idl?(e.href=`#${t.id}`,e.classList.add("internalDFN")):r=!0;return e.hasAttribute("data-link-type")||(e.dataset.linkType="idl"in t.dataset?"idl":"dfn"),function(e){if(e.closest("code,pre"))return!0;if(1!==e.childNodes.length)return!1;const[t]=e.childNodes;return"code"===t.localName}(t)&&function(e,t){const n=e.textContent.trim(),r=t.dataset.hasOwnProperty("idl"),s=fc(e)&&fc(t,n);r&&!s||Xn(e,document.createElement("code"))}(e,t),!r}function fc(e,t=""){if("a"===e.localName){if(!e.querySelector("code"))return!0}else{const{dataset:n}=e;if(e.textContent.trim()===t)return!0;if(n.title===t)return!0;if(n.lt||n.localLt){const e=[];return n.lt&&e.push(...n.lt.split("|")),n.localLt&&e.push(...n.localLt.split("|")),e.includes(t)}}return!1}function hc(e){e.forEach((e=>{ur(`Found linkless \`<a>\` element with text "${e.textContent}" but no matching \`<dfn>\``,ic,{title:"Linking error: not matching `<dfn>`",elements:[e]})}))}var mc=Object.freeze({__proto__:null,name:ic,possibleExternalLinks:ac,run:async function(e){const t=function(){const e=new ar;for(const t of ea.keys()){const{result:n,duplicates:r}=uc(t);e.set(t,n),r.length>0&&lr(lc.duplicateMsg(t),ic,{title:lc.duplicateTitle,elements:r})}return e}(),n=[],r=document.querySelectorAll("a[data-cite=''], a:not([href]):not([data-cite]):not(.logo):not(.externalDFN)");for(const e of r){if(!e.dataset?.linkType&&e.dataset?.xrefType){ac.push(e);continue}const r=dc(e,t);if(r){pc(e,r,t)||ac.push(e)}else""===e.dataset.cite?n.push(e):ac.push(e)}hc(n),function(e){const{shortName:t=""}=e,n=new RegExp(String.raw`^([?!])?${t}\b([^-])`,"i"),r=document.querySelectorAll("dfn[data-cite]:not([data-cite='']), a[data-cite]:not([data-cite=''])");for(const t of r){t.dataset.cite=t.dataset.cite.replace(n,`$1${Ja}$2`);const{key:r,isNormative:s}=rc(t);r!==Ja&&(s||e.normativeReferences.has(r)?(e.normativeReferences.add(r),e.informativeReferences.delete(r)):e.informativeReferences.add(r))}}(e),e.xref||hc(ac)}});const gc="xrefs",bc=3e5;async function yc(){return await $n.openDB("xref",2,{upgrade(e){[...e.objectStoreNames].forEach((t=>e.deleteObjectStore(t)));e.createObjectStore(gc,{keyPath:"query.id"}).createIndex("byTerm","query.term",{unique:!1})}})}async function wc(e){const t=new Map;if(await async function(){const e="XREF:LAST_VERSION_CHECK",t=parseInt(localStorage.getItem(e),10),n=Date.now();if(!t)return localStorage.setItem(e,n.toString()),!1;if(n-t<bc)return!1;const r=new URL("meta/version",$c).href,s=await fetch(r);if(!s.ok)return!1;const o=await s.text();return localStorage.setItem(e,n.toString()),parseInt(o,10)>t}())return await async function(){try{await yc().then((e=>e.clear(gc)))}catch(e){console.error(e)}}(),t;const n=new Set(e.map((e=>e.id)));try{const e=await yc();let r=await e.transaction(gc).store.openCursor();for(;r;)n.has(r.key)&&t.set(r.key,r.value.result),r=await r.continue()}catch(e){console.error(e)}return t}const vc="core/xref",kc={"web-platform":["HTML","INFRA","URL","WEBIDL","DOM","FETCH"]},$c="https://respec.org/xref/",xc=[];if(!document.querySelector("link[rel='preconnect'][href='https://respec.org']")){const e=Pn({hint:"preconnect",href:"https://respec.org"});document.head.appendChild(e)}function _c(e){const t="xrefType"in e.dataset;let n=Cc(e);t||(n=n.toLowerCase());const r=function(e){const t=[];let n=e.closest("[data-cite]");for(;n;){const r=n.dataset.cite.toLowerCase().replace(/[!?]/g,"").split(/\s+/).filter((e=>e));if(r.length&&t.push(r),n===e)break;n=n.parentElement.closest("[data-cite]")}if(n!==e){const n=e.closest("section"),r=[...n?n.querySelectorAll("a.bibref"):[]].map((e=>e.textContent.toLowerCase()));r.length&&t.push(r)}const r=function(e){const t=[];for(const n of e){const e=t[t.length-1]||[],r=[...new Set(n)].filter((t=>!e.includes(t)));t.push(r.sort())}return t}(t);return r}(e),s=function(e,t){if(t)return e.dataset.xrefType?e.dataset.xrefType.split("|"):["_IDL_"];return["_CONCEPT_"]}(e,t),o=function(e,t){if(e.dataset.xrefFor)return qn(e.dataset.xrefFor);if(t){const t=e.closest("[data-xref-for]");if(t)return qn(t.dataset.xrefFor)}return null}(e,t);return{id:"",term:n,types:s,...r.length&&{specs:r},..."string"==typeof o&&{for:o}}}function Cc(e){const{lt:t}=e.dataset;let n=t?t.split("|",1)[0]:e.textContent;return n=qn(n),"the-empty-string"===n?"":n}function Sc(e,t,n,r){const{term:s,specs:o=[]}=t,{uri:i,shortname:a,spec:c,normative:l,type:u,for:d}=n,p=o.flat().includes(c)?c:a,f=new URL(i,"https://partial");let{pathname:h}=f;"/"===h&&(h="");const m={cite:p,citePath:h,citeFrag:f.hash.slice(1),linkType:u};d&&(m.linkFor=d[0]),f.origin&&"https://partial"!==f.origin&&(m.citeHref=f.href),Object.assign(e.dataset,m),function(e,t,n,r,s){const o=function(e){const t=e.closest(".normative"),n=e.closest(Tn);return!n||e===t||t&&n&&n.contains(t)}(e);if(!o)return void(s.normativeReferences.has(t)||s.informativeReferences.add(t));if(n){const e=s.informativeReferences.has(t)?s.informativeReferences.getCanonicalKey(t):t;return s.normativeReferences.add(e),void s.informativeReferences.delete(e)}xc.push({term:r,spec:t,element:e})}(e,p,l,s,r)}function Rc(e){const t=JSON.stringify(e,Object.keys(e).sort()),n=(new TextEncoder).encode(t);return crypto.subtle.digest("SHA-1",n).then(Ec)}function Ec(e){return[...new Uint8Array(e)].map((e=>e.toString(16).padStart(2,"0"))).join("")}function Ac(e){const t=e.querySelectorAll("a[data-xref-for], a[data-xref-type], a[data-link-for]"),n=["data-xref-for","data-xref-type","data-link-for"];t.forEach((e=>{n.forEach((t=>e.removeAttribute(t)))}))}var Lc=Object.freeze({__proto__:null,API_URL:$c,getTermFromElement:Cc,informativeRefsInNormative:xc,name:vc,run:async function(e){if(!e.xref)return;const t=function(e){const t={url:new URL("search/",$c).href,specs:null},n=Object.assign({},t);switch(Array.isArray(e)?"array":typeof e){case"boolean":break;case"string":e.toLowerCase()in kc?Object.assign(n,{specs:kc[e.toLowerCase()]}):r(e);break;case"array":Object.assign(n,{specs:e});break;case"object":if(Object.assign(n,e),e.profile){const t=e.profile.toLowerCase();if(t in kc){const r=(e.specs??[]).concat(kc[t]);Object.assign(n,{specs:r})}else r(e.profile)}break;default:lr(`Invalid value for \`xref\` configuration option. Received: "${e}".`,vc)}return n;function r(e){lr(`Invalid profile "${e}" in \`respecConfig.xref\`. Please use one of the supported profiles: ${zn(Object.keys(kc),(e=>`"${e}"`))}.`,vc)}}(e.xref);if(t.specs){const e=document.body.dataset.cite?document.body.dataset.cite.split(/\s+/):[];document.body.dataset.cite=e.concat(t.specs).join(" ")}const n=ac.concat(function(){const e=document.querySelectorAll(":is(a,dfn)[data-cite]:not([data-cite=''],[data-cite*='#'])"),t=document.querySelectorAll("dfn.externalDFN");return[...e].filter((e=>{if(""===e.textContent.trim())return!1;const t=e.closest("[data-cite]");return!t||""!==t.dataset.cite})).concat(...t)}());if(!n.length)return;const r=[];for(const e of n){const t=_c(e);t.id=await Rc(t),r.push(t)}const s=await async function(e,t){const n=new Set,r=e.filter((e=>!n.has(e.id)&&(n.add(e.id)&&!0))),s=await wc(r),o=r.filter((e=>!s.get(e.id))),i=await async function(e,t){if(!e.length)return new Map;const n={method:"POST",body:JSON.stringify({queries:e}),headers:{"Content-Type":"application/json"}},r=await fetch(t,n),s=await r.json();return new Map(s.results.map((({id:e,result:t})=>[e,t])))}(o,t);i.size&&await async function(e,t){try{const n=(await yc()).transaction(gc,"readwrite");for(const r of e){const e=t.get(r.id);n.objectStore(gc).add({query:r,result:e})}await n.done}catch(e){console.error(e)}}(r,i);return new Map([...s,...i])}(r,t.url);!function(e,t,n,r){const s={ambiguous:new Map,notFound:new Map};for(let o=0,i=e.length;o<i;o++){if(e[o].closest("[data-no-xref]"))continue;const i=e[o],a=t[o],{id:c}=a,l=n.get(c);if(1===l.length)Sc(i,a,l[0],r);else{const e=s[0===l.length?"notFound":"ambiguous"];e.has(c)||e.set(c,{elems:[],results:l,query:a}),e.get(c).elems.push(i)}}!function({ambiguous:e,notFound:t}){const n=(e,t,n=[])=>{const r=new URL($c);return r.searchParams.set("term",e),t.for&&r.searchParams.set("for",t.for),r.searchParams.set("types",t.types.join(",")),n.length&&r.searchParams.set("specs",n.join(",")),r.href},r=(e,t)=>gr`[See search matches for "${t}"](${e}) or ${"[Learn about this error|#error-term-not-found]"}.`;for(const{query:e,elems:s}of t.values()){const t=e.specs?[...new Set(e.specs.flat())].sort():[],o=Cc(s[0]),i=n(o,e),a=On(t,(e=>`**[${e}]**`)),c=r(i,o);lr(`Couldn't find "**${o}**"${e.for?`, for **"${e.for}"**, `:""} in this document or other cited documents: ${a}.`,vc,{title:"No matching definition found.",elements:s,hint:c})}for(const{query:t,elems:s,results:o}of e.values()){const e=[...new Set(o.map((e=>e.shortname)))].sort(),i=On(e,(e=>`**[${e}]**`)),a=Cc(s[0]),c=n(a,t,e),l=t.for?`, for **"${t.for}"**, `:"",u=r(c,a),d=gr`To fix, use the ${"[data-cite]"} attribute to pick the one you mean from the appropriate specification.`+String.raw` ${u}`;lr(`The term "**${a}**"${l} is ambiguous because it's defined in ${i}.`,vc,{title:"Definition is ambiguous.",elements:s,hint:d})}}(s)}(n,r,s,e),vr("beforesave",Ac)}});var Tc=String.raw`ul.index{columns:30ch;column-gap:1.5em} +ul.index li{list-style:inherit} +ul.index li span{color:inherit;cursor:pointer;white-space:normal} +#index-defined-here ul.index li{font-size:.9rem} +ul.index code{color:inherit} +#index-defined-here .print-only{display:none} +@media print{ +#index-defined-here .print-only{display:initial} +}`;const Pc=Wn({en:{heading:"Index",headingExternal:"Terms defined by reference",headingLocal:"Terms defined by this specification",dfnOf:"definition of",definesFollowing:"defines the following:"},cs:{heading:"Glosář",headingExternal:"Termíny definované odkazem",headingLocal:"Termíny definované touto specifikací",dfnOf:"definice",definesFollowing:"definuje následující:"},de:{heading:"Index",headingExternal:"Begriffe, die durch Verweis definiert sind",headingLocal:"Begriffe, die in dieser Spezifikation definiert sind",dfnOf:"Definition von",definesFollowing:"definiert Folgendes:"},es:{heading:"Ãndice",headingExternal:"Términos definidos por referencia",headingLocal:"Términos definidos por esta especificación",dfnOf:"definición de",definesFollowing:"define lo siguiente:"},ja:{heading:"索引",headingExternal:"å‚ç…§ã«ã‚ˆã£ã¦å®šç¾©ã•れãŸç”¨èªž",headingLocal:"ã“ã®ä»•様ã§å®šç¾©ã•れãŸç”¨èªž",dfnOf:"ã®å®šç¾©",definesFollowing:"以下を定義ã—ã¾ã™:"},ko:{heading:"색ì¸",headingExternal:"참조로 ì •ì˜ëœ 용어",headingLocal:"ì´ ëª…ì„¸ì„œì—서 ì •ì˜ëœ 용어",dfnOf:"ì •ì˜",definesFollowing:"다ìŒì„ ì •ì˜í•©ë‹ˆë‹¤:"},nl:{heading:"Index",headingExternal:"Termen gedefinieerd door verwijzing",headingLocal:"Termen gedefinieerd door deze specificatie",dfnOf:"definitie van",definesFollowing:"definieert het volgende:"},zh:{heading:"索引",headingExternal:"通过引用定义的术语",headingLocal:"由本规范定义的术语",dfnOf:"的定义",definesFollowing:"定义以下内容:"}}),Ic=new Set(["attribute","callback","dict-member","dictionary","element-attr","element","enum-value","enum","exception","extended-attribute","interface","method","typedef"]);function Dc(e){const t=e.dataset,n=t.dfnType||t.idl||t.linkType||"";switch(n){case"":case"dfn":return"";default:return n}}function Nc(e){const t=e.closest("[data-dfn-for]:not([data-dfn-for=''])");return t?t.dataset.dfnFor:""}function jc(e,t,n=""){if(n.startsWith("[[")){return`internal slot for <code>${Nc(e)}</code>`}switch(t){case"dict-member":case"method":case"attribute":case"enum-value":return`${"dict-member"===t?"member":t.replace("-"," ")} for <code>${Nc(e)}</code>`;case"interface":case"dictionary":case"enum":return t;case"constructor":return`for <code>${Nc(e)}</code>`;default:return""}}function Oc(){document.querySelectorAll("#index-defined-here li[data-id]").forEach((e=>e.append((e=>{const t=`§${document.getElementById(e).closest("section:not(.notoc)").querySelector(".secno").textContent.trim()}`;return kn`<span class="print-only">${t}</span>`})(e.dataset.id))))}function zc(){const e=new Set,t=new Map,n=document.querySelectorAll("a[data-cite]");for(const r of n){if(!r.dataset.cite)continue;const{cite:n,citeFrag:s,xrefType:o,linkType:i}=r.dataset;if(!(o||i||n.includes("#")||s))continue;const a=r.href;if(e.has(a))continue;const{linkType:c,linkFor:l}=r.dataset,u=Cc(r);if(!u)continue;const d=rc(r).key.toUpperCase();(t.get(d)||t.set(d,[]).get(d)).push({term:u,type:c,linkFor:l,elem:r}),e.add(a)}return t}function Mc(e){const{elem:t}=e,n=function(e){const{term:t,type:n,linkFor:r}=e;let s=Mn(t);Ic.has(n)&&("extended-attribute"===n&&(s=`[${s}]`),s=`<code>${s}</code>`);const o=Wc.has(t)?"type":qc.get(n);o&&(s+=` ${o}`);if(r){let e=r;/\s/.test(r)||(e=`<code>${e}</code>`),"element-attr"===n&&(e+=" element"),s+=` (for ${e})`}return s}(e);return kn`<li> + <span class="index-term" data-href="${t.href}">${{html:n}}</span> + </li>`}const qc=new Map([["attribute","attribute"],["element-attr","attribute"],["element","element"],["enum","enum"],["exception","exception"],["extended-attribute","extended attribute"],["interface","interface"]]),Wc=new Set(["boolean","byte","octet","short","unsigned short","long","unsigned long","long long","unsigned long long","float","unrestricted float","double","unrestricted double","undefined","any","object","symbol"]);function Uc(e){e.querySelectorAll("#index-defined-elsewhere li[data-spec]").forEach((e=>e.removeAttribute("data-spec"))),e.querySelectorAll("#index-defined-here li[data-id]").forEach((e=>e.removeAttribute("data-id")))}var Fc=Object.freeze({__proto__:null,name:"core/dfn-index",run:function(){const e=document.querySelector("section#index");if(!e)return void vr("toc",(()=>{}),{once:!0});const t=document.createElement("style");t.textContent=Tc,document.head.appendChild(t),e.classList.add("appendix"),e.querySelector("h2, h1")||e.prepend(kn`<h1>${Pc.heading}</h1>`);const n=kn`<section id="index-defined-here"> + <h3>${Pc.headingLocal}</h3> + ${function(){const e=function(){const e=new Map,t=document.querySelectorAll("dfn:not([data-cite])");for(const n of t){if(!n.id)continue;const t=qn(n.textContent);(e.get(t)||e.set(t,[]).get(t)).push(n)}const n=[...e].sort((([e],[t])=>e.slice(e.search(/\w/)).localeCompare(t.slice(t.search(/\w/)))));return n}();return kn`<ul class="index"> + ${e.map((([e,t])=>function(e,t){const n=(e,t,n)=>{const r=`#${e.id}`;return kn`<li data-id=${e.id}> + <a class="index-term" href="${r}">${{html:t}}</a> ${n?{html:n}:""} + </li>`};if(1===t.length){const r=t[0],s=Dc(r),o=function(e,t,n){let r=n;"enum-value"===t&&(r=`"${r}"`);(Ic.has(t)||e.dataset.idl||e.closest("code"))&&(r=`<code>${r}</code>`);return r}(r,s,e),i=jc(r,s,e);return n(r,o,i)}return kn`<li> + ${e} + <ul> + ${t.map((t=>{const r=jc(t,Dc(t),e)||Pc.dfnOf;return n(t,r)}))} + </ul> + </li>`}(e,t)))} + </ul>`}()} + </section>`;e.append(n);const r=kn`<section id="index-defined-elsewhere"> + <h3>${Pc.headingExternal}</h3> + ${function(){const e=[...zc().entries()].sort((([e],[t])=>e.localeCompare(t))),t=document.querySelector("section#index"),n=!!t?.classList.contains("prefer-full-spec-title");return kn`<ul class="index"> + ${e.map((([e,t])=>{let r;return r=n&&ci[e]?.title?xi(e,ci[e].title):xi(e),kn`<li data-spec="${e}"> + ${r} ${Pc.definesFollowing} + <ul> + ${t.sort(((e,t)=>e.term.localeCompare(t.term))).map(Mc)} + </ul> + </li>`}))} + </ul>`}()} + </section>`;e.append(r);for(const e of r.querySelectorAll(".index-term"))Kn(e,"index-term");vr("toc",Oc,{once:!0}),vr("beforesave",Uc)}});const Bc="core/contrib";var Hc=Object.freeze({__proto__:null,name:Bc,run:async function(e){if(!document.getElementById("gh-contributors"))return;if(!e.github){return void lr(gr`Requested list of contributors from GitHub, but ${"[github]"} configuration option is not set.`,Bc)}const t=e.editors.map((e=>e.name)),n=`${e.github.apiBase}/${e.github.fullName}/`;await async function(e,t){const n=document.getElementById("gh-contributors");if(!n)return;n.textContent="Fetching list of contributors...";const r=await s();null!==r?function(e,t){const n=e.sort(((e,t)=>{const n=e.name||e.login,r=t.name||t.login;return n.toLowerCase().localeCompare(r.toLowerCase())}));if("UL"===t.tagName)return void kn(t)`${n.map((({name:e,login:t})=>`<li><a href="https://github.com/${t}">${e||t}</a></li>`))}`;const r=n.map((e=>e.name||e.login));t.textContent=On(r)}(r,n):n.textContent="Failed to fetch contributors.";async function s(){const{href:n}=new URL("contributors",t);try{const t=await Hn(n);if(!t.ok)throw new Error(`Request to ${n} failed with status code ${t.status}`);return(await t.json()).filter((t=>!e.includes(t.name||t.login)&&!t.login.includes("[bot]")))}catch(e){return lr("Error loading contributors from GitHub.",Bc,{cause:e}),null}}}(t,n)}});var Vc=Object.freeze({__proto__:null,name:"core/fix-headers",run:function(){[...document.querySelectorAll("section:not(.introductory)")].map((e=>e.querySelector("h1, h2, h3, h4, h5, h6"))).filter((e=>e)).forEach((e=>{const t=Math.min(function(e,t){const n=[];for(;e!=e.ownerDocument.body;)e.matches(t)&&n.push(e),e=e.parentElement;return n}(e,"section").length+1,6);Jn(e,`h${t}`)}))}});var Gc=Object.freeze({__proto__:null,name:"core/webidl-index",run:function(){const e=document.querySelector("section#idl-index");if(!e)return;const t=[2,3,4,5,6].map((e=>`h${e}:first-child`)).join(",");if(!e.querySelector(t)){const t=document.createElement("h2");e.title?(t.textContent=e.title,e.removeAttribute("title")):t.textContent="IDL Index",e.prepend(t)}const n=Array.from(document.querySelectorAll("pre.idl:not(.exclude) > code")).filter((e=>!e.closest(Tn)));if(0===n.length){const t="This specification doesn't normatively declare any Web IDL.";return void e.append(t)}const r=document.createElement("pre");r.classList.add("idl","def"),r.id="actual-idl-index",n.map((e=>{const t=document.createDocumentFragment();for(const n of e.children)t.appendChild(n.cloneNode(!0));return t})).forEach((e=>{r.lastChild&&r.append("\n\n"),r.appendChild(e)})),r.querySelectorAll("*[id]").forEach((e=>e.removeAttribute("id"))),e.appendChild(r),Xn(r,document.createElement("code")),Ya(r)}});const Yc=["h2","h3","h4","h5","h6"],Kc="core/structure",Zc=Wn({en:{toc:"Table of Contents",back_to_top:"Back to Top"},zh:{toc:"内容大纲",back_to_top:"返回顶部"},ko:{toc:"목차",back_to_top:"맨 위로"},ja:{toc:"目次",back_to_top:"å…ˆé ­ã«æˆ»ã‚‹"},nl:{toc:"Inhoudsopgave",back_to_top:"Terug naar boven"},es:{toc:"Tabla de Contenidos",back_to_top:"Volver arriba"},de:{toc:"Inhaltsverzeichnis",back_to_top:"Zurück nach oben"},cs:{toc:"Obsah",back_to_top:"ZpÄ›t na zaÄátek"}});function Jc(e,t,{prefix:n=""}={}){let r=!1,s=0,o=1;if(n.length&&!n.endsWith(".")&&(n+="."),0===e.length)return null;const i=kn`<ol class="toc"></ol>`;for(const a of e){!a.isAppendix||n||r||(s=o,r=!0);let e=a.isIntro?"":r?Qc(o-s+1):n+o;const c=e.split(".").length;if(1===c&&(e+=".",a.header.before(document.createComment("OddPage"))),a.isIntro||(o+=1,a.header.prepend(kn`<bdi class="secno">${e} </bdi>`)),c<=t){const n=a.header.id||a.element.id,r=el(a.header,n),s=Jc(a.subsections,t,{prefix:e});s&&r.append(s),i.append(r)}}return i}function Qc(e){let t="";for(;e>0;)e-=1,t=String.fromCharCode(65+e%26)+t,e=Math.floor(e/26);return t}function Xc(e){const t=e.querySelectorAll(":scope > section"),n=[];for(const e of t){const t=e.classList.contains("notoc");if(!e.children.length||t)continue;const r=e.children[0];if(!Yc.includes(r.localName))continue;const s=r.textContent;Kn(e,null,s),n.push({element:e,header:r,title:s,isIntro:Boolean(e.closest(".introductory")),isAppendix:e.classList.contains("appendix"),subsections:Xc(e)})}return n}function el(e,t){const n=kn`<a href="${`#${t}`}" class="tocxref" />`;var r;return n.append(...e.cloneNode(!0).childNodes),(r=n).querySelectorAll("a").forEach((e=>{const t=Jn(e,"span");t.className="formerLink",t.removeAttribute("href")})),r.querySelectorAll("dfn").forEach((e=>{Jn(e,"span").removeAttribute("id")})),kn`<li class="tocline">${n}</li>`}var tl=Object.freeze({__proto__:null,name:Kc,run:function(e){if("maxTocLevel"in e==!1&&(e.maxTocLevel=1/0),function(){const e=[...document.querySelectorAll("section:not(.introductory) :is(h1,h2,h3,h4,h5,h6):first-child")].filter((e=>!e.closest("section.introductory")));if(!e.length)return;e.forEach((e=>{const t=`h${Math.min(tr(e,"section").length+1,6)}`;e.localName!==t&&Jn(e,t)}))}(),!e.noTOC){!function(){const e=document.querySelectorAll("section[data-max-toc]");for(const t of e){const e=parseInt(t.dataset.maxToc,10);if(e<0||e>6||Number.isNaN(e)){lr("`data-max-toc` must have a value between 0-6 (inclusive).",Kc,{elements:[t]});continue}if(0===e){t.classList.add("notoc");continue}const n=t.querySelectorAll(`:scope > ${Array.from({length:e},(()=>"section")).join(" > ")}`);for(const e of n)e.classList.add("notoc")}}();const t=Jc(Xc(document.body),e.maxTocLevel);t&&function(e){if(!e)return;const t=kn`<nav id="toc"></nav>`,n=kn`<h2 class="introductory">${Zc.toc}</h2>`;Kn(n),t.append(n,e);const r=document.getElementById("toc")||document.getElementById("sotd")||document.getElementById("abstract");r&&("toc"===r.id?r.replaceWith(t):r.after(t));const s=kn`<p role="navigation" id="back-to-top"> + <a href="#title"><abbr title="${Zc.back_to_top}">↑</abbr></a> + </p>`;document.body.append(s)}(t)}wr("toc")}});const nl=Wn({en:{informative:"This section is non-normative."},nl:{informative:"Dit onderdeel is niet normatief."},ko:{informative:"ì´ ë¶€ë¶„ì€ ë¹„ê·œë²”ì ìž…니다."},ja:{informative:"ã“ã®ç¯€ã¯ä»•様ã«ã¯å«ã¾ã‚Œã¾ã›ã‚“."},de:{informative:"Dieser Abschnitt ist nicht normativ."},zh:{informative:"本章节ä¸åŒ…å«è§„范性内容。"},cs:{informative:"Tato sekce není normativní."}});var rl=Object.freeze({__proto__:null,name:"core/informative",run:function(){Array.from(document.querySelectorAll("section.informative")).map((e=>e.querySelector("h2, h3, h4, h5, h6"))).filter((e=>e)).forEach((e=>{e.after(kn`<p><em>${nl.informative}</em></p>`)}))}});const sl=Wn({en:{permalinkLabel(e,t){let n=`Permalink for${t?"":" this"} ${e}`;return t&&(n+=` ${qn(t.textContent)}`),n}}});var ol=Object.freeze({__proto__:null,name:"core/id-headers",run:function(e){const t=document.querySelectorAll("section:not(.head,#abstract,#sotd) h2, h3, h4, h5, h6");for(const n of t){let t=n.id;if(t||(Kn(n),t=n.parentElement.id||n.id),!e.addSectionLinks)continue;const r=sl.permalinkLabel(n.closest(".appendix")?"Appendix":"Section",n.querySelector(":scope > bdi.secno")),s=kn`<div class="header-wrapper"></div>`;n.replaceWith(s);const o=kn`<a + href="#${t}" + class="self-link" + aria-label="${r}" + ></a>`;s.append(n,o)}}});var il=String.raw`.caniuse-stats{display:flex;column-gap:2em} +.caniuse-group{display:flex;flex:1;flex-direction:column;justify-content:flex-end;flex-basis:auto} +.caniuse-browsers{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;margin-top:.2em;column-gap:.4em;border-bottom:1px solid #ccc;row-gap:.4em;padding-bottom:.4cm} +.caniuse-type{align-self:center;border-top:none;text-transform:capitalize;font-size:.8em;margin-top:-.8em;font-weight:700} +.caniuse-type span{background-color:var(--bg,#fff);padding:0 .4em} +.caniuse-cell{align-items:center;border-radius:1cm;color:#fff;display:flex;font-size:90%;min-width:1.5cm;padding:.3rem;justify-content:space-evenly;--supported:#2a8436dd;--no-support:#c44230dd;--no-support-alt:#b43b2bdd;--partial:#807301dd;--partial-alt:#746c00dd;--unknown:#757575;background:repeating-linear-gradient(var(--caniuse-angle,45deg),var(--caniuse-bg) 0,var(--caniuse-bg-alt) 1px,var(--caniuse-bg-alt) .4em,var(--caniuse-bg) calc(.25em + 1px),var(--caniuse-bg) .75em)} +img.caniuse-browser{filter:drop-shadow(0 0 .1cm #666);background:0 0} +.caniuse-cell span.browser-version{margin-left:.4em;text-shadow:0 0 .1em #fff;font-weight:100;font-size:.9em} +.caniuse-stats a[href]{white-space:nowrap;align-self:flex-end} +.caniuse-cell.y{background:var(--supported)} +.caniuse-cell:is(.n,.d){--caniuse-angle:45deg;--caniuse-bg:var(--no-support);--caniuse-bg-alt:var(--no-support-alt)} +.caniuse-cell.u{background:var(--unknown)} +.caniuse-cell.d{--caniuse-angle:180deg} +.caniuse-cell:is(.a,.x,.p){--caniuse-angle:90deg;--caniuse-bg:var(--partial);--caniuse-bg-alt:var(--partial-alt)} +@media print{ +.caniuse-cell.y::before{content:"✔ï¸";padding:.5em} +.caniuse-cell.n::before{content:"âŒ";padding:.5em} +.caniuse-cell:is(.a,.d,.p,.x,.u)::before{content:"âš ï¸";padding:.5em} +}`;const al="core/caniuse",cl="https://respec.org/caniuse/",ll=new Map([["and_chr",{name:"Android Chrome",path:"chrome",type:"mobile"}],["and_ff",{name:"Android Firefox",path:"firefox",type:"mobile"}],["and_uc",{name:"Android UC",path:"uc",type:"mobile"}],["chrome",{name:"Chrome",type:"desktop"}],["edge",{name:"Edge",type:"desktop"}],["firefox",{name:"Firefox",type:"desktop"}],["ios_saf",{name:"iOS Safari",path:"safari-ios",type:"mobile"}],["op_mob",{name:"Opera Mobile",path:"opera",type:"mobile"}],["opera",{name:"Opera",type:"desktop"}],["safari",{name:"Safari",type:"desktop"}],["samsung",{name:"Samsung Internet",path:"samsung-internet",type:"mobile"}]]),ul=new Map([["a","almost supported (aka Partial support)"],["d","disabled by default"],["n","no support, or disabled by default"],["p","no support, but has Polyfill"],["u","unknown support"],["x","requires prefix to work"],["y","supported by default"]]);var dl=Object.freeze({__proto__:null,BROWSERS:ll,name:al,prepare:function(e){if(!e.caniuse)return;!function(e){const t=new Set(ll.keys());t.delete("op_mob"),t.delete("opera");const n={removeOnSave:!0,browsers:[...t]};if("string"==typeof e.caniuse)return void(e.caniuse={feature:e.caniuse,...n});e.caniuse={...n,...e.caniuse}}(e),function({caniuse:e}){const{browsers:t}=e,n=t.filter((e=>!ll.has(e)));if(n.length){ur(gr`Invalid browser(s): (${hr(n,{quotes:!0})}) in the \`browser\` property of ${"[caniuse]"}.`,al)}}(e);const t=e.caniuse;t.feature&&document.head.appendChild(kn`<style + id="caniuse-stylesheet" + class="${t.removeOnSave?"removeOnSave":""}" + > + ${il} + </style>`)},run:async function(e){const t=e.caniuse;if(!t?.feature)return;const n=new URL(t.feature,"https://caniuse.com/").href,r=document.querySelector(".head dl"),s=async function(e){const{feature:t,browsers:n,apiURL:r}=e,s=new URL(r||`./${t}`,cl);n.forEach((e=>s.searchParams.append("browsers",e)));const o=await fetch(s);if(!o.ok){const{status:e,statusText:t}=o;throw new Error(`Failed to get caniuse data: (${e}) ${t}`)}return o.json()}(e.caniuse).then((e=>async function(e,{feature:t}){const n=e.result,r=new Map([["desktop",[]],["mobile",[]]]),s=function(e){return(t,{browser:n,version:r,caniuse:s})=>{const{name:o,type:i}=ll.get(n),a=`${o}${r?` version ${r}`:""}`,c=ul.get(s),l=`${e} is ${c} since ${a} on ${i}.`,u=`caniuse-cell ${s}`,d=(p=`${c} since ${a}.`).charAt(0).toUpperCase()+p.slice(1);var p;const f=r||"—",h=function(e){const t=ll.get(e).path??e;return`https://www.w3.org/assets/logos/browser-logos/${t}/${t}.svg`}(n),m=kn` + <div class="${u}" title="${d}" aria-label="${l}"> + <img + class="caniuse-browser" + width="20" + height="20" + src="${h}" + alt="${o} logo" + /><span class="browser-version">${f}</span> + </div> + `;return t.get(i).push(m),t}}(t);n.reduce(s,r);const o=[...r].filter((([,e])=>e.length)).map((([e,t])=>kn`<div class="caniuse-group"> + <div class="caniuse-browsers">${t}</div> + <div class="caniuse-type"><span>${e}</div> + </div>`));return o.push(kn`<a class="caniuse-cell" href="https://caniuse.com/${t}" + >More info</a + >`),o}(e,t))).catch((e=>function(e,t,n){const r=`Failed to retrieve feature "${t.feature}".`,s=gr`Please check the feature key on [caniuse.com](https://caniuse.com) and update ${"[caniuse]"}.`;return lr(r,al,{hint:s,cause:e}),kn`<a href="${n}">caniuse.com</a>`}(e,t,n))),o=kn`<dt class="caniuse-title">Browser support:</dt> + <dd class="caniuse-stats"> + ${{any:s,placeholder:"Fetching data from caniuse.com..."}} + </dd>`;r.append(...o.childNodes),await s,wr("amend-user-config",{caniuse:t.feature}),t.removeOnSave&&(r.querySelectorAll(".caniuse-browser").forEach((e=>e.classList.add("removeOnSave"))),vr("beforesave",(e=>{kn.bind(e.querySelector(".caniuse-stats"))` + <a href="${n}">caniuse.com</a>`})))}});var pl=String.raw`.mdn{font-size:.75em;position:absolute;right:.3em;min-width:0;margin-top:3rem} +.mdn details{width:100%;margin:1px 0;position:relative;z-index:10;box-sizing:border-box;padding:.4em;padding-top:0} +.mdn details[open]{min-width:25ch;max-width:32ch;background:#fff;background:var(--indextable-hover-bg,#fff);color:#000;color:var(--indextable-hover-text,#000);box-shadow:0 1em 3em -.4em rgba(0,0,0,.3),0 0 1px 1px rgba(0,0,0,.05);box-shadow:0 1em 3em -.4em var(--tocsidebar-shadow,rgba(0,0,0,.3)),0 0 1px 1px var(--tocsidebar-shadow,rgba(0,0,0,.05));border-radius:2px;z-index:11;margin-bottom:.4em} +.mdn summary{text-align:right;cursor:default;margin-right:-.4em} +.mdn summary span{font-family:zillaslab,Palatino,"Palatino Linotype",serif;color:#fff;color:var(--bg,#fff);background-color:#000;background-color:var(--text,#000);display:inline-block;padding:3px} +.mdn a{display:inline-block;word-break:break-all} +.mdn p{margin:0} +.mdn .engines-all{color:#058b00} +.mdn .engines-some{color:#b00} +.mdn table{width:100%;font-size:.9em} +.mdn td{border:none} +.mdn td:nth-child(2){text-align:right} +.mdn .nosupportdata{font-style:italic;margin:0} +.mdn tr::before{content:"";display:table-cell;width:1.5em;height:1.5em;background:no-repeat center center/contain;font-size:.75em} +.mdn .no,.mdn .unknown{color:#ccc;filter:grayscale(100%)} +.mdn .no::before,.mdn .unknown::before{opacity:.5} +.mdn .chrome::before,.mdn .chrome_android::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/chrome/chrome.svg)} +.mdn .edge::before,.mdn .edge_mobile::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/edge/edge.svg)} +.mdn .firefox::before,.mdn .firefox_android::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/firefox/firefox.svg)} +.mdn .opera::before,.mdn .opera_android::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/opera/opera.svg)} +.mdn .safari::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/safari/safari.svg)} +.mdn .safari_ios::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/safari-ios/safari-ios.svg)} +.mdn .samsunginternet_android::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/samsung-internet/samsung-internet.svg)} +.mdn .webview_android::before{background-image:url(https://www.w3.org/assets/logos/browser-logos/android-webview/android-webview.png)}`;const fl="core/mdn-annotation",hl="https://w3c.github.io/mdn-spec-links/",ml="https://developer.mozilla.org/en-US/docs/Web/",gl={chrome:"Chrome",chrome_android:"Chrome Android",edge:"Edge",edge_mobile:"Edge Mobile",firefox:"Firefox",firefox_android:"Firefox Android",opera:"Opera",opera_android:"Opera Android",safari:"Safari",safari_ios:"Safari iOS",samsunginternet_android:"Samsung Internet",webview_android:"WebView Android"},bl=Wn({en:{inAllEngines:"This feature is in all major engines.",inSomeEngines:"This feature has limited support."},zh:{inAllEngines:"所有主è¦å¼•æ“Žå‡æ”¯æŒæ­¤ç‰¹æ€§ã€‚",inSomeEngines:"æ­¤åŠŸèƒ½æ”¯æŒæœ‰é™ã€‚"},cs:{inAllEngines:"Tato funkce je podporována ve vÅ¡ech hlavních prohlížeÄích.",inSomeEngines:"Tato funkce má omezenou podporu."}});function yl(e){const t=e.closest("section");if(!t)return;const{previousElementSibling:n}=t;if(n&&n.classList.contains("mdn"))return n;const r=kn`<aside class="mdn"></aside>`;return t.before(r),r}function wl(e){const{name:t,slug:n,summary:r,support:s,engines:o}=e,i=n.slice(n.indexOf("/")+1),a=`${ml}${n}`,c=`Expand MDN details for ${t}`,l=function(e){if(3===e.length)return kn`<span title="${bl.inAllEngines}">✅</span>`;if(e.length<2)return kn`<span title="${bl.inSomeEngines}">🚫</span>`;return kn`<span> </span>`}(o);return kn`<details> + <summary aria-label="${c}"><span>MDN</span>${l}</summary> + <a title="${r}" href="${a}">${i}</a> + ${function(e){if(3===e.length)return kn`<p class="engines-all">${bl.inAllEngines}</p>`;if(e.length<2)return kn`<p class="engines-some">${bl.inSomeEngines}</p>`}(o)} + ${s?function(e){function t(e,t,n){const r="Unknown"===t?"?":t,s=`${e} ${t.toLowerCase()}`;return kn`<tr class="${s}"> + <td>${gl[e]}</td> + <td>${n||r}</td> + </tr>`}function n(e,n){if(n.version_removed)return t(e,"No","");const r=n.version_added;return"boolean"==typeof r?t(e,r?"Yes":"No",""):r?t(e,"Yes",`${r}+`):t(e,"Unknown","")}return kn`<table> + ${Object.keys(gl).map((r=>e[r]?n(r,e[r]):t(r,"Unknown","")))} + </table>`}(s):kn`<p class="nosupportdata">No support data.</p>`} + </details>`}var vl=Object.freeze({__proto__:null,name:fl,run:async function(e){const t=function(e){const{shortName:t,mdn:n}=e;if(!n)return;return"string"==typeof n?n:n.key||t}(e);if(!t)return;const n=await async function(e,t){const{baseJsonPath:n=hl,maxAge:r=864e5}=t,s=new URL(`${e}.json`,n).href,o=await Hn(s,r);if(404===o.status){return void lr(`Could not find MDN data associated with key "${e}".`,fl,{hint:"Please add a valid key to `respecConfig.mdn`"})}return await o.json()}(t,e.mdn);if(!n)return;const r=document.createElement("style");r.textContent=pl,document.head.append(r);for(const e of function(e){return[...document.body.querySelectorAll("[id]:not(script)")].filter((({id:t})=>Array.isArray(e[t])))}(n)){const t=n[e.id],r=yl(e);if(r)for(const e of t)r.append(wl(e))}}});const kl="ui/save-html",$l=Wn({en:{save_snapshot:"Export"},nl:{save_snapshot:"Bewaar Snapshot"},ja:{save_snapshot:"ä¿å­˜ã™ã‚‹"},de:{save_snapshot:"Exportieren"},zh:{save_snapshot:"导出"}}),xl=[{id:"respec-save-as-html",ext:"html",title:"HTML",type:"text/html",get href(){return xr(this.type)}},{id:"respec-save-as-xml",ext:"xhtml",title:"XML",type:"application/xml",get href(){return xr(this.type)}},{id:"respec-save-as-epub",ext:"epub",title:"EPUB 3",type:"application/epub+zip",get href(){const e=new URL("https://labs.w3.org/r2epub/");return e.searchParams.append("respec","true"),e.searchParams.append("url",document.location.href),e.href}}];var _l=Object.freeze({__proto__:null,exportDocument:function(e,t){return ur("Exporting via ui/save-html module's `exportDocument()` is deprecated and will be removed.",kl,{hint:"Use core/exporter `rsDocToDataURL()` instead."}),xr(t)},name:kl,run:function(e){const t={async show(t){await document.respec.ready;const n=kn`<div class="respec-save-buttons"> + ${xl.map((t=>function(e,t){const{id:n,href:r,ext:s,title:o,type:i}=e,a=Fn(t.publishDate||new Date),c=[t.specStatus,t.shortName||"spec",a].join("-");return kn`<a + href="${r}" + id="${n}" + download="${c}.${s}" + type="${i}" + class="respec-save-button" + onclick=${()=>es.closeModal()} + >${o}</a + >`}(t,e)))} + </div>`;es.freshModal($l.save_snapshot,n,t)}},n="download"in HTMLAnchorElement.prototype;let r;n&&(r=es.addCommand($l.save_snapshot,(function(){if(!n)return;t.show(r)}),"Ctrl+Shift+Alt+S","💾"))}});const Cl="https://respec.org/specref/",Sl=Wn({en:{search_specref:"Search Specref"},nl:{search_specref:"Doorzoek Specref"},ja:{search_specref:"仕様検索"},de:{search_specref:"Spezifikationen durchsuchen"},zh:{search_specref:"æœç´¢ Specref"},cs:{search_specref:"Hledat ve Specref"}}),Rl=es.addCommand(Sl.search_specref,(function(){const e=kn` + <iframe class="respec-iframe" src="${Cl}" onload=${e=>e.target.classList.add("ready")}></iframe> + <a href="${Cl}" target="_blank">Open Search UI in a new tab</a> + `;es.freshModal(Sl.search_specref,e,Rl)}),"Ctrl+Shift+Alt+space","🔎");var El=Object.freeze({__proto__:null});const Al="https://respec.org/xref/",Ll=Wn({en:{title:"Search definitions"},ja:{title:"定義検索"},de:{title:"Definitionen durchsuchen"},zh:{title:"æœç´¢å®šä¹‰"},cs:{title:"Hledat definice"}}),Tl=es.addCommand(Ll.title,(function(){const e=kn` + <iframe class="respec-iframe" src="${Al}" onload="${e=>e.target.classList.add("ready")}"></iframe> + <a href="${Al}" target="_blank">Open Search UI in a new tab</a> + `;es.freshModal(Ll.title,e,Tl)}),"Ctrl+Shift+Alt+x","📚");var Pl=Object.freeze({__proto__:null});const Il=Wn({en:{about_respec:"About"},zh:{about_respec:"关于"},nl:{about_respec:"Over"},ja:{about_respec:"ã“れã«ã¤ã„ã¦"},de:{about_respec:"Über"},cs:{about_respec:"O aplikaci"}});window.respecVersion=window.respecVersion||"Developer Edition";const Dl=document.createElement("div"),Nl=kn.bind(Dl),jl=es.addCommand(`${Il.about_respec} ${window.respecVersion}`,(function(){const e=[];"getEntriesByType"in performance&&performance.getEntriesByType("measure").sort(((e,t)=>t.duration-e.duration)).map((({name:e,duration:t})=>({name:e,duration:t>1e3?`${Math.round(t/1e3)} second(s)`:`${t.toFixed(2)} milliseconds`}))).map(Ol).forEach((t=>{e.push(t)}));Nl` + <p> + ReSpec is a document production toolchain, with a notable focus on W3C specifications. + </p> + <p> + <a href='https://respec.org/docs'>Documentation</a>, + <a href='https://github.com/speced/respec/issues'>Bugs</a>. + </p> + <table border="1" width="100%" hidden="${!e.length}"> + <caption> + Loaded plugins + </caption> + <thead> + <tr> + <th> + Plugin Name + </th> + <th> + Processing time + </th> + </tr> + </thead> + <tbody>${e}</tbody> + </table> +`,es.freshModal(`${Il.about_respec} - ${window.respecVersion}`,Dl,jl)}),"Ctrl+Shift+Alt+A","ℹï¸");function Ol({name:e,duration:t}){return kn` + <tr> + <td><a href="${`https://github.com/speced/respec/blob/develop/src/${e}.js`}">${e}</a></td> + <td>${t}</td> + </tr> + `}var zl=Object.freeze({__proto__:null});var Ml=Object.freeze({__proto__:null,name:"core/seo",run:function(e){if(e.gitRevision){const t=kn`<meta + name="revision" + content="${e.gitRevision}" + />`;document.head.appendChild(t)}const t=document.querySelector("#abstract p:first-of-type");if(!t)return;const n=t.textContent.replace(/\s+/," ").trim(),r=document.createElement("meta");r.name="description",r.content=n,document.head.appendChild(r)}});const ql="w3c/seo",Wl={NOTE:"w3p:NOTE",WD:"w3p:WD",LC:"w3p:LastCall",CR:"w3p:CR",CRD:"w3p:CRD",PR:"w3p:PR",REC:"w3p:REC",RSCND:"w3p:RSCND"},Ul=new Set([...Os,...zs,...Ms,"BG-FINAL","CG-FINAL","CRY","DRY","draft-finding","finding"]);function Fl({name:e,url:t,mailto:n,company:r,companyURL:s}){const o={type:"Person",name:e,url:t,"foaf:mbox":n};return(r||s)&&(o.worksFor={name:r,url:s}),o}function Bl(e){const{href:t,title:n,href:r}=e,s={id:t,type:"TechArticle",name:n,url:r};return e.authors&&(s.creator=e.authors.map((e=>({name:e})))),e.rawDate&&(s.publishedDate=e.rawDate),e.isbn&&(s.identifier=e.isbn),e.publisher&&(s.publisher={name:e.publisher}),s}var Hl=Object.freeze({__proto__:null,name:ql,requiresCanonicalLink:Ul,run:async function(e){if((e.canonicalURI||Ul.has(e.specStatus))&&e.shortName){switch(e.canonicalURI){case"edDraft":if(e.edDraftURI)e.canonicalURI=new URL(e.edDraftURI,document.location.href).href;else{ur("Canonical URI set to edDraft, but no edDraftURI is set in configuration",ql),e.canonicalURI=null}break;case"TR":if(e.latestVersion)e.canonicalURI=e.latestVersion;else{ur("Canonical URI set to TR, but no shortName is set in configuration",ql),e.canonicalURI=null}break;default:e.latestVersion&&!e.canonicalURI&&(e.canonicalURI=e.latestVersion)}if(e.canonicalURI){const t=kn`<link rel="canonical" href="${e.canonicalURI}" />`;document.head.appendChild(t)}e.doJsonLd&&await async function(e,t){const n=Wl[e.specStatus],r=["TechArticle"];n&&r.push(n);const s={"@context":["http://schema.org",{"@vocab":"http://schema.org/","@language":t.documentElement.lang||"en",w3p:"http://www.w3.org/2001/02pd/rec54#",foaf:"http://xmlns.com/foaf/0.1/",datePublished:{"@type":"http://www.w3.org/2001/XMLSchema#date"},inLanguage:{"@language":null},isBasedOn:{"@type":"@id"},license:{"@type":"@id"}}],id:e.canonicalURI||e.thisVersion,type:r,name:document.title,inLanguage:t.documentElement.lang||"en",license:e.licenseInfo?.url,datePublished:e.dashDate,copyrightHolder:{name:"World Wide Web Consortium",url:"https://www.w3.org/"},discussionUrl:e.issueBase,alternativeHeadline:e.subtitle,isBasedOn:e.prevVersion};if(e.additionalCopyrightHolders){const t=Array.isArray(e.additionalCopyrightHolders)?e.additionalCopyrightHolders:[e.additionalCopyrightHolders];s.copyrightHolder=[s.copyrightHolder,...t.map((e=>({name:e})))]}const o=t.head.querySelector("meta[name=description]");o&&(s.description=o.content);e.editors&&(s.editor=e.editors.map(Fl));e.authors&&(s.contributor=e.authors.map(Fl));const i=[...e.normativeReferences,...e.informativeReferences],a=await Promise.all(i.map((e=>hi(e))));s.citation=a.filter((e=>"object"==typeof e)).map(Bl);const c=t.createElement("script");c.type="application/ld+json",c.textContent=JSON.stringify(s,null,2),t.head.appendChild(c)}(e,document)}}});var Vl=String.raw`.hljs{--base:#fafafa;--mono-1:#383a42;--mono-2:#686b77;--mono-3:#717277;--hue-1:#0b76c5;--hue-2:#336ae3;--hue-3:#a626a4;--hue-4:#42803c;--hue-5:#ca4706;--hue-5-2:#c91243;--hue-6:#986801;--hue-6-2:#9a6a01} +@media (prefers-color-scheme:dark){ +.hljs{--base:#282c34;--mono-1:#abb2bf;--mono-2:#818896;--mono-3:#5c6370;--hue-1:#56b6c2;--hue-2:#61aeee;--hue-3:#c678dd;--hue-4:#98c379;--hue-5:#e06c75;--hue-5-2:#be5046;--hue-6:#d19a66;--hue-6-2:#e6c07b} +} +.hljs{display:block;overflow-x:auto;padding:.5em;color:#383a42;color:var(--mono-1,#383a42);background:#fafafa;background:var(--base,#fafafa)} +.hljs-comment,.hljs-quote{color:#717277;color:var(--mono-3,#717277);font-style:italic} +.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4;color:var(--hue-3,#a626a4)} +.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#ca4706;color:var(--hue-5,#ca4706);font-weight:700} +.hljs-literal{color:#0b76c5;color:var(--hue-1,#0b76c5)} +.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#42803c;color:var(--hue-4,#42803c)} +.hljs-built_in,.hljs-class .hljs-title{color:#9a6a01;color:var(--hue-6-2,#9a6a01)} +.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801;color:var(--hue-6,#986801)} +.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#336ae3;color:var(--hue-2,#336ae3)} +.hljs-emphasis{font-style:italic} +.hljs-strong{font-weight:700} +.hljs-link{text-decoration:underline}`;async function Gl(t){const n=await fetch(new URL(`../../${t}`,e&&"SCRIPT"===e.tagName.toUpperCase()&&e.src||new URL("respec-w3c.js",document.baseURI).href));return await n.text()}const Yl=Pn({hint:"preload",href:"https://www.w3.org/Tools/respec/respec-highlight",as:"script"});document.head.appendChild(Yl);const Kl=async function(){const e=await async function(){try{return(await Promise.resolve().then((function(){return Pd}))).default}catch{return Gl("worker/respec-worker.js")}}(),t=URL.createObjectURL(new Blob([e],{type:"application/javascript"}));return new Worker(t)}();n("core/worker",Kl.then((e=>({worker:e}))));const Zl=function(e,t=0){const n=function*(e,t){for(;;)yield`${e}:${t}`,t++}(e,t);return()=>n.next().value}("highlight");async function Jl(e){e.setAttribute("aria-busy","true");const t=(n=e.classList,Array.from(n).filter((e=>"highlight"!==e&&"nolinks"!==e)).map((e=>e.toLowerCase())));var n;let r;try{r=await async function(e,t){const n={action:"highlight",code:e,id:Zl(),languages:t},r=await Kl;return r.postMessage(n),new Promise(((e,t)=>{const s=setTimeout((()=>{t(new Error("Timed out waiting for highlight."))}),4e3);r.addEventListener("message",(function t(o){const{data:{id:i,language:a,value:c}}=o;i===n.id&&(r.removeEventListener("message",t),clearTimeout(s),e({language:a,value:c}))}))}))}(e.innerText,t)}catch(e){return void console.error(e)}const{language:s,value:o}=r;switch(e.localName){case"pre":e.classList.remove(s),e.innerHTML=`<code class="hljs${s?` ${s}`:""}">${o}</code>`,e.classList.length||e.removeAttribute("class");break;case"code":e.innerHTML=o,e.classList.add("hljs"),s&&e.classList.add(s)}e.setAttribute("aria-busy","false")}var Ql=Object.freeze({__proto__:null,name:"core/highlight",run:async function(e){if(e.noHighlightCSS)return;const t=[...document.querySelectorAll("\n pre:not(.idl):not(.nohighlight) > code:not(.nohighlight),\n pre:not(.idl):not(.nohighlight),\n code.highlight\n ")].filter((e=>"pre"!==e.localName||!e.querySelector("code")));if(!t.length)return;const n=t.filter((e=>e.textContent.trim())).map(Jl);document.head.appendChild(kn`<style> + ${Vl} + </style>`),await Promise.all(n)}});const Xl=Wn({en:{missing_test_suite_uri:gr`Found tests in your spec, but missing ${"[testSuiteURI]"} in your ReSpec config.`,tests:"tests",test:"test"},ja:{missing_test_suite_uri:gr`ã“ã®ä»•様内ã«ãƒ†ã‚¹ãƒˆã®é …目を検出ã—ã¾ã—ãŸãŒï¼ŒReSpec ã®è¨­å®šã« ${"[testSuiteURI]"} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“.`,tests:"テスト",test:"テスト"},de:{missing_test_suite_uri:gr`Die Spezifikation enthält Tests, aber in der ReSpec-Konfiguration ist keine ${"[testSuiteURI]"} angegeben.`,tests:"Tests",test:"Test"},zh:{missing_test_suite_uri:gr`æœ¬è§„èŒƒä¸­åŒ…å«æµ‹è¯•,但在 ReSpec é…置中缺少 ${"[testSuiteURI]"}。`,tests:"测试",test:"测试"}}),eu="core/data-tests";function tu(e){const t=[],[n]=new URL(e).pathname.split("/").reverse(),r=n.split(".");let[s]=r;if(r.find((e=>"https"===e))){const e=document.createElement("span");e.textContent="🔒",e.setAttribute("aria-label","requires a secure connection"),e.setAttribute("title","Test requires HTTPS"),s=s.replace(".https",""),t.push(e)}if(s.split(".").join("-").split("-").find((e=>"manual"===e))){const e=document.createElement("span");e.textContent="💪",e.setAttribute("aria-label","the test must be run manually"),e.setAttribute("title","Manual test"),s=s.replace("-manual",""),t.push(e)}return kn` + <li> + <a href="${e}">${s}</a> + ${t} + </li> + `}function nu(e,t,n){return e.map((e=>{try{return new URL(e,t).href}catch{ur(gr`Invalid URL in ${"[data-tests]"} attribute: ${e}.`,eu,{elements:[n]})}})).filter((e=>e))}function ru(e,t){const n=e.filter(((e,t,n)=>n.indexOf(e)!==t));if(n.length){const e=gr`Duplicate tests found in the ${"[data-tests]"} attribute.`,r=gr`To fix, remove duplicates from ${"[data-tests]"}: ${hr(n,{quotes:!0})}.`;ur(e,eu,{hint:r,elements:[t]})}}function su(e){const t=[...new Set(e)];return kn` + <details class="respec-tests-details removeOnSave"> + <summary>tests: ${t.length}</summary> + <ul> + ${t.map(tu)} + </ul> + </details> + `}var ou=Object.freeze({__proto__:null,name:eu,run:function(e){const t=[...document.querySelectorAll("[data-tests]")].filter((e=>e.dataset.tests));if(t.length)if(e.testSuiteURI)for(const n of t){const t=nu(n.dataset.tests.split(/,/gm).map((e=>e.trim())),e.testSuiteURI,n);ru(t,n);const r=su(t);n.append(r)}else lr(Xl.missing_test_suite_uri,eu)}});const iu="core/list-sorter";function au(e){const t="ascending"===e?1:-1;return({textContent:e},{textContent:n})=>t*e.trim().localeCompare(n.trim())}function cu(e,t){return[...e.querySelectorAll(":scope > li")].sort(au(t)).reduce(((e,t)=>(e.appendChild(t),e)),document.createDocumentFragment())}function lu(e,t){return[...e.querySelectorAll(":scope > dt")].sort(au(t)).reduce(((e,t)=>{const{nodeType:n,nodeName:r}=t,s=document.createDocumentFragment();let{nextSibling:o}=t;for(;o&&o.nextSibling;){s.appendChild(o.cloneNode(!0));const{nodeType:e,nodeName:t}=o.nextSibling;if(e===n&&t===r)break;o=o.nextSibling}return s.prepend(t.cloneNode(!0)),e.appendChild(s),e}),document.createDocumentFragment())}var uu=Object.freeze({__proto__:null,name:iu,run:function(){const e=document.querySelectorAll("[data-sort]");for(const t of e){let e;const n=t.dataset.sort||"ascending";switch(t.localName){case"dl":e=lu(t,n);break;case"ol":case"ul":e=cu(t,n);break;default:ur(`ReSpec can't sort ${t.localName} elements.`,iu,{elements:[t]})}if(e){const n=document.createRange();n.selectNodeContents(t),n.deleteContents(),t.appendChild(e)}}},sortDefinitionTerms:lu,sortListItems:cu});var du=String.raw`var:hover{text-decoration:underline;cursor:pointer} +var.respec-hl{color:var(--color,#000);background-color:var(--bg-color);box-shadow:0 0 0 2px var(--bg-color)} +@media (prefers-color-scheme:dark){ +var.respec-hl{filter:saturate(.9) brightness(.9)} +} +var.respec-hl-c1{--bg-color:#f4d200} +var.respec-hl-c2{--bg-color:#ff87a2} +var.respec-hl-c3{--bg-color:#96e885} +var.respec-hl-c4{--bg-color:#3eeed2} +var.respec-hl-c5{--bg-color:#eacfb6} +var.respec-hl-c6{--bg-color:#82ddff} +var.respec-hl-c7{--bg-color:#ffbcf2} +@media print{ +var.respec-hl{background:0 0;color:#000;box-shadow:unset} +}`;var pu=Object.freeze({__proto__:null,name:"core/highlight-vars",run:async function(e){if(!e.highlightVars)return;const t=document.createElement("style");t.textContent=du,document.head.appendChild(t);const n=document.createElement("script");n.id="respec-highlight-vars",n.textContent=await async function(){try{return(await Promise.resolve().then((function(){return Id}))).default}catch{return Gl("./src/core/highlight-vars.runtime.js")}}(),document.body.append(n),vr("beforesave",(e=>{e.querySelectorAll("var.respec-hl").forEach((e=>{const t=[...e.classList.values()].filter((e=>e.startsWith("respec-hl")));e.classList.remove(...t),e.classList.length||e.removeAttribute("class")}))}))}});var fu=String.raw`var{position:relative;cursor:pointer} +var[data-type]::after,var[data-type]::before{position:absolute;left:50%;top:-6px;opacity:0;transition:opacity .4s;pointer-events:none} +var[data-type]::before{content:"";transform:translateX(-50%);border-width:4px 6px 0 6px;border-style:solid;border-color:transparent;border-top-color:#222} +var[data-type]::after{content:attr(data-type);transform:translateX(-50%) translateY(-100%);background:#222;text-align:center;font-family:"Dank Mono","Fira Code",monospace;font-style:normal;padding:6px;border-radius:3px;color:#daca88;text-indent:0;font-weight:400} +var[data-type]:hover::after,var[data-type]:hover::before{opacity:1}`;var hu=Object.freeze({__proto__:null,name:"core/data-type",run:function(e){if(!e.highlightVars)return;const t=document.createElement("style");t.textContent=fu,document.head.appendChild(t);let n=null;const r=new Map,s=document.querySelectorAll("section var");for(const e of s){const t=e.closest("section");if(n!==t&&(n=t,r.clear()),e.dataset.type){r.set(e.textContent.trim(),e.dataset.type);continue}const s=r.get(e.textContent.trim());s&&(e.dataset.type=s)}}});var mu=String.raw`:root{--assertion-border:#aaa;--assertion-bg:#eee;--assertion-text:black} +.assert{border-left:.5em solid #aaa;padding:.3em;border-color:#aaa;border-color:var(--assertion-border);background:#eee;background:var(--assertion-bg);color:#000;color:var(--assertion-text)} +@media (prefers-color-scheme:dark){ +:root{--assertion-border:#444;--assertion-bg:var(--borderedblock-bg);--assertion-text:var(--text)} +}`;var gu=Object.freeze({__proto__:null,name:"core/algorithms",run:function(){const e=Array.from(document.querySelectorAll("ol.algorithm li")).filter((e=>e.textContent.trim().startsWith("Assert: ")));if(!e.length)return;for(const t of e){t.classList.add("assert");const e=t.firstChild;e instanceof Text&&e.textContent.startsWith("Assert: ")&&(e.textContent=e.textContent.replace("Assert: ",""),t.prepend(kn`<a href="https://infra.spec.whatwg.org/#assert">Assert</a>`,": "))}const t=document.createElement("style");t.textContent=mu,document.head.appendChild(t)}});const bu="core/anchor-expander";function yu(e,t,n){const r=e.querySelector(".marker .self-link");if(!r){n.textContent=n.getAttribute("href");return void lr(`Found matching element "${t}", but it has no title or marker.`,bu,{title:"Missing title.",elements:[n]})}const s=sr(r);n.append(...s.childNodes),n.classList.add("box-ref")}function wu(e,t,n){const r=e.querySelector("figcaption");if(!r){n.textContent=n.getAttribute("href");return void lr(`Found matching figure "${t}", but figure is lacking a \`<figcaption>\`.`,bu,{title:"Missing figcaption in referenced figure.",elements:[n]})}const s=[...sr(r.querySelector(".self-link")).childNodes].map((e=>(e.classList?.remove("figno"),e)));n.append(...s),n.classList.add("fig-ref");const o=r.querySelector(".fig-title");!n.hasAttribute("title")&&o&&(n.title=qn(o.textContent))}function vu(e,t,n){if(!e.classList.contains("numbered"))return;const r=e.querySelector("caption");if(!r){n.textContent=n.getAttribute("href");return void lr(`Found matching table "${t}", but table is lacking a \`<caption>\`.`,bu,{title:"Missing caption in referenced table.",elements:[n]})}const s=[...sr(r.querySelector(".self-link")).childNodes].map((e=>(e.classList?.remove("tableno"),e)));n.append(...s),n.classList.add("table-ref");const o=r.querySelector(".table-title");!n.hasAttribute("title")&&o&&(n.title=qn(o.textContent))}function ku(e,t,n){const r=e.querySelector("h6, h5, h4, h3, h2");if(r)$u(r,n),xu(r,n);else{n.textContent=n.getAttribute("href");lr("Found matching section, but the section was lacking a heading element.",bu,{title:`No matching id in document: "${t}".`,elements:[n]})}}function $u(e,t){const n=e.querySelector(".self-link"),r=[...sr(e).childNodes].filter((e=>!e.classList||!e.classList.contains("self-link")));t.append(...r),n&&t.prepend("§ "),t.classList.add("sec-ref"),t.lastChild.nodeType===Node.TEXT_NODE&&(t.lastChild.textContent=t.lastChild.textContent.trimEnd()),t.querySelectorAll("a").forEach((e=>{const t=Jn(e,"span");for(const e of[...t.attributes])t.removeAttributeNode(e)}))}function xu(e,t){for(const n of["dir","lang"]){if(t.hasAttribute(n))continue;const r=e.closest(`[${n}]`);if(!r)continue;const s=t.closest(`[${n}]`);s&&s.getAttribute(n)===r.getAttribute(n)||t.setAttribute(n,r.getAttribute(n))}}var _u=Object.freeze({__proto__:null,name:bu,run:function(){const e=[...document.querySelectorAll("a[href^='#']:not(.self-link):not([href$='the-empty-string'])")].filter((e=>""===e.textContent.trim()));for(const t of e){const e=t.getAttribute("href").slice(1),n=document.getElementById(e);if(n){switch(n.localName){case"h6":case"h5":case"h4":case"h3":case"h2":$u(n,t);break;case"section":ku(n,e,t);break;case"figure":wu(n,e,t);break;case"table":vu(n,e,t);break;case"aside":case"div":yu(n,e,t);break;default:t.textContent=t.getAttribute("href");lr("ReSpec doesn't support expanding this kind of reference.",bu,{title:`Can't expand "#${e}".`,elements:[t]})}xu(n,t),t.normalize()}else{t.textContent=t.getAttribute("href");lr(`Couldn't expand inline reference. The id "${e}" is not in the document.`,bu,{title:`No matching id in document: ${e}.`,elements:[t]})}}}});var Cu=String.raw`dfn{cursor:pointer} +.dfn-panel{position:absolute;z-index:35;min-width:300px;max-width:500px;padding:.5em .75em;margin-top:.6em;font-family:"Helvetica Neue",sans-serif;font-size:small;background:#fff;background:var(--indextable-hover-bg,#fff);color:#000;color:var(--text,#000);box-shadow:0 1em 3em -.4em rgba(0,0,0,.3),0 0 1px 1px rgba(0,0,0,.05);box-shadow:0 1em 3em -.4em var(--tocsidebar-shadow,rgba(0,0,0,.3)),0 0 1px 1px var(--tocsidebar-shadow,rgba(0,0,0,.05));border-radius:2px} +.dfn-panel:not(.docked)>.caret{position:absolute;top:-9px} +.dfn-panel:not(.docked)>.caret::after,.dfn-panel:not(.docked)>.caret::before{content:"";position:absolute;border:10px solid transparent;border-top:0;border-bottom:10px solid #fff;border-bottom-color:var(--indextable-hover-bg,#fff);top:0} +.dfn-panel:not(.docked)>.caret::before{border-bottom:9px solid #a2a9b1;border-bottom-color:var(--indextable-hover-bg,#a2a9b1)} +.dfn-panel *{margin:0} +.dfn-panel b{display:block;color:#000;color:var(--text,#000);margin-top:.25em} +.dfn-panel ul a[href]{color:#333;color:var(--text,#333)} +.dfn-panel>div{display:flex} +.dfn-panel a.self-link{font-weight:700;margin-right:auto} +.dfn-panel .marker{padding:.1em;margin-left:.5em;border-radius:.2em;text-align:center;white-space:nowrap;font-size:90%;color:#040b1c} +.dfn-panel .marker.dfn-exported{background:#d1edfd;box-shadow:0 0 0 .125em #1ca5f940} +.dfn-panel .marker.idl-block{background:#8ccbf2;box-shadow:0 0 0 .125em #0670b161} +.dfn-panel a:not(:hover){text-decoration:none!important;border-bottom:none!important} +.dfn-panel a[href]:hover{border-bottom-width:1px} +.dfn-panel ul{padding:0} +.dfn-panel li{margin-left:1em} +.dfn-panel.docked{position:fixed;left:.5em;top:unset;bottom:2em;margin:0 auto;max-width:calc(100vw - .75em * 2 - .5em - .2em * 2);max-height:30vh;overflow:auto}`;function Su(e){const{id:t}=e,n=e.dataset.href||`#${t}`,r=document.querySelectorAll(`a[href="${n}"]:not(.index-term)`),s=`dfn-panel-for-${e.id}`,o=e.getAttribute("aria-label")||qn(e.textContent),i=kn` + <div + class="dfn-panel" + id="${s}" + hidden + role="dialog" + aria-modal="true" + aria-label="Links in this document to definition: ${o}" + > + <span class="caret"></span> + <div> + <a + class="self-link" + href="${n}" + aria-label="Permalink for definition: ${o}. Activate to close this dialog." + >Permalink</a + > + ${function(e){return e.matches("dfn[data-export]")?kn`<span + class="marker dfn-exported" + title="Definition can be referenced by other specifications" + >exported</span + >`:null}(e)} ${function(e,t){if(!e.hasAttribute("data-idl"))return null;for(const n of t){if(n.dataset.linkType!==e.dataset.dfnType)continue;const t=n.closest("pre.idl");if(t&&t.id){const e=`#${t.id}`;return kn`<a + href="${e}" + class="marker idl-block" + title="Jump to IDL declaration" + >IDL</a + >`}}return null}(e,r)} + </div> + <p><b>Referenced in:</b></p> + ${function(e,t){if(!t.length)return kn`<ul> + <li>Not referenced in this document.</li> + </ul>`;const n=new Map;t.forEach(((t,r)=>{const s=t.id||`ref-for-${e}-${r+1}`;t.id||(t.id=s);const o=function(e){const t=e.closest("section");if(!t)return null;const n=t.querySelector("h1, h2, h3, h4, h5, h6");return n?`§ ${qn(n.textContent)}`:null}(t);(n.get(o)||n.set(o,[]).get(o)).push(s)}));const r=([e,t])=>[{title:e,id:t[0],text:e}].concat(t.slice(1).map(((e,t)=>({title:`Reference ${t+2}`,text:`(${t+2})`,id:e})))),s=e=>kn`<li> + ${r(e).map((e=>kn`<a href="#${e.id}" title="${e.title}">${e.text}</a + >${" "}`))} + </li>`;return kn`<ul> + ${[...n].map(s)} + </ul>`}(t,r)} + </div> + `;return i}var Ru=Object.freeze({__proto__:null,name:"core/dfn-panel",run:async function(){document.head.insertBefore(kn`<style> + ${Cu} + </style>`,document.querySelector("link"));const e=document.querySelectorAll("dfn[id]:not([data-cite]), #index-defined-elsewhere .index-term"),t=document.createDocumentFragment();for(const n of e)t.append(Su(n)),n.tabIndex=0,n.setAttribute("aria-haspopup","dialog");document.body.querySelector("script")?document.body.querySelector("script").before(t):document.body.append(t);const n=document.createElement("script");n.id="respec-dfn-panel",n.textContent=await async function(){try{return(await Promise.resolve().then((function(){return Dd}))).default}catch{return Gl("./src/core/dfn-panel.runtime.js")}}(),document.body.append(n)}});const Eu="rs-changelog",Au=class extends HTMLElement{constructor(){super(),this.props={from:this.getAttribute("from"),to:this.getAttribute("to")||"HEAD",filter:"function"==typeof window[this.getAttribute("filter")]?window[this.getAttribute("filter")]:()=>!0}}connectedCallback(){const{from:e,to:t,filter:n}=this.props;kn.bind(this)` + <ul> + ${{any:Lu(e,t,n).then((e=>async function(e){const{repoURL:t}=await mo;return e.map((e=>{const[n,r=null]=e.message.split(/\(#(\d+)\)/,2),s=`${t}commit/${e.hash}`,o=r&&kn` (<a href="${r?`${t}pull/${r}`:null}">#${r}</a>)`;return kn`<li><a href="${s}">${n.trim()}</a>${o}</li>`}))}(e))).catch((e=>lr(e.message,Eu,{elements:[this],cause:e}))).finally((()=>{this.dispatchEvent(new CustomEvent("done"))})),placeholder:"Loading list of commits..."}} + </ul> + `}};async function Lu(e,t,n){let r;try{const s=await mo;if(!s)throw new Error("`respecConfig.github` is not set");const o=new URL("commits",`${s.apiBase}/${s.fullName}/`);o.searchParams.set("from",e),o.searchParams.set("to",t);const i=await fetch(o.href);if(!i.ok)throw new Error(`Request to ${o} failed with status code ${i.status}`);if(r=await i.json(),!r.length)throw new Error(`No commits between ${e}..${t}.`);r=r.filter(n)}catch(e){const t=`Error loading commits from GitHub. ${e.message}`;throw new Error(t,{cause:e})}return r}const Tu=[Object.freeze({__proto__:null,element:Au,name:Eu})];var Pu=Object.freeze({__proto__:null,name:"core/custom-elements/index",run:async function(){Tu.forEach((e=>{customElements.define(e.name,e.element)}));const e=Tu.map((e=>e.name)).join(", "),t=[...document.querySelectorAll(e)].map((e=>new Promise((t=>e.addEventListener("done",t,{once:!0})))));await Promise.all(t)}});var Iu=Object.freeze({__proto__:null,name:"core/web-monetization",run:function(e){if(!1===e.monetization)return;const{monetization:t}=e,{removeOnSave:n,paymentPointer:r}=function(e){const t={paymentPointer:"$respec.org",removeOnSave:!0};switch(typeof e){case"string":t.paymentPointer=e;break;case"object":e.paymentPointer&&(t.paymentPointer=String(e.paymentPointer)),!1===e.removeOnSave&&(t.removeOnSave=!1)}return t}(t),s=n?"removeOnSave":null;document.head.append(kn`<meta + name="monetization" + content="${r}" + class="${s}" + />`)}});var Du=Object.freeze({__proto__:null,name:"core/dfn-contract",run:function(){!function(){const e=document.querySelectorAll("dfn:is([data-dfn-type=''],:not([data-dfn-type]))");for(const t of e)t.dataset.dfnType="dfn";const t=document.querySelectorAll("dfn:not([data-noexport], [data-export], [data-dfn-type='dfn'], [data-cite])");for(const e of t)e.dataset.export=""}(),function(){const e=document.querySelectorAll("dl.definitions dt:has(dfn[data-dfn-type])");for(const t of e){const e=t.querySelector("dfn[data-dfn-type]").id,n=t.nextElementSibling;n&&!n.dataset.defines&&e&&(n.dataset.defines=`#${e}`)}const t=document.querySelectorAll(".definition:has(dfn[data-dfn-type])");for(const e of t){const t=e.querySelector("dfn[data-dfn-type]");t.id&&!e.dataset.defines&&(e.dataset.defines=`#${t.id}`)}}()}});const Nu="core/before-save";var ju=Object.freeze({__proto__:null,name:Nu,run:function(e){if(e.beforeSave)if(Array.isArray(e.beforeSave)&&!e.beforeSave.some((e=>"function"!=typeof e||"AsyncFunction"===e.constructor.name)))vr("beforesave",(t=>{!function(e,t){let n=0;for(const r of e)try{r(t)}catch(e){lr(gr`Function ${`\`${r.name}\``||`at position ${n}`}\` threw an error during processing of ${"[beforeSave]"}.`,Nu,{hint:"See developer console.",cause:e})}finally{n++}}(e.beforeSave,t.ownerDocument)}),{once:!0});else{lr(gr`${"[beforeSave]"} configuration option must be an array of synchronous JS functions.`,Nu)}}});const Ou="core/linter-rules/check-charset",zu=Wn({en:{msg:"Document must only contain one `<meta>` tag with charset set to 'utf-8'",hint:'Add this line in your document `<head>` section - `<meta charset="utf-8">` or set charset to "utf-8" if not set already.'},zh:{msg:"文档åªèƒ½åŒ…å«ä¸€ä¸ª charset 属性为 utf-8 çš„ `<meta>` 标签",hint:'将此行添加到文档的 `<head>` 部分—— `<meta charset="utf-8">` 或将 charset 设置为 utf-8(如果尚未设置)。'},cs:{msg:"Dokument smí obsahovat pouze jeden tag `<meta>` s charset nastaveným na 'utf-8'",hint:'PÅ™idejte tento řádek do sekce `<head>` vaÅ¡eho dokumentu - `<meta charset="utf-8">` nebo nastavte charset na "utf-8", pokud jeÅ¡tÄ› není nastaven.'}});var Mu=Object.freeze({__proto__:null,name:Ou,run:function(e){if(!e.lint?.["check-charset"])return;const t=document.querySelectorAll("meta[charset]"),n=[];for(const e of t)n.push(e.getAttribute("charset").trim().toLowerCase());n.includes("utf-8")&&1===t.length||ur(zu.msg,Ou,{hint:zu.hint,elements:[...t]})}});const qu="core/linter-rules/check-punctuation",Wu=[".",":","!","?"],Uu=Wu.map((e=>`"${e}"`)).join(", "),Fu=Wn({en:{msg:"`p` elements should end with a punctuation mark.",hint:`Please make sure \`p\` elements end with one of: ${Uu}.`},cs:{msg:"Elementy `p` by mÄ›ly konÄit interpunkÄním znaménkem.",hint:`UjistÄ›te se, že elementy \`p\` konÄí jedním z tÄ›chto znaků: ${Uu}.`}});var Bu=Object.freeze({__proto__:null,name:qu,run:function(e){if(!e.lint?.["check-punctuation"])return;const t=new RegExp(`[${Wu.join("")}\\]]$|^ *$`,"m"),n=[...document.querySelectorAll("p:not(#back-to-top,#w3c-state)")].filter((e=>!t.test(e.textContent.trim())));n.length&&ur(Fu.msg,qu,{hint:Fu.hint,elements:n})}});const Hu="core/linter-rules/check-internal-slots",Vu=Wn({en:{msg:"Internal slots should be preceded by a '.'",hint:"Add a '.' between the elements mentioned."},cs:{msg:"Interní sloty by mÄ›ly být uvedeny s teÄkou '.' pÅ™ed názvem",hint:"PÅ™idejte teÄku '.' mezi uvedené prvky."}});var Gu=Object.freeze({__proto__:null,name:Hu,run:function(e){if(!e.lint?.["check-internal-slots"])return;const t=[...document.querySelectorAll("var+a")].filter((({previousSibling:{nodeName:e}})=>e&&"VAR"===e));t.length&&ur(Vu.msg,Hu,{hint:Vu.hint,elements:t})}});const Yu="core/linter-rules/local-refs-exist",Ku=Wn({en:{msg:"Broken local reference found in document.",hint:"Please fix the links mentioned."},cs:{msg:"V dokumentu byla nalezena nefunkÄní lokální reference.",hint:"Opravte prosím uvedené odkazy."}});function Zu(e){const t=e.getAttribute("href").substring(1),n=e.ownerDocument;return!n.getElementById(t)&&!n.getElementsByName(t).length}var Ju=Object.freeze({__proto__:null,name:Yu,run:function(e){if(!e.lint?.["local-refs-exist"])return;const t=[...document.querySelectorAll("a[href^='#']")].filter(Zu);t.length&&ur(Ku.msg,Yu,{hint:Ku.hint,elements:t})}});const Qu="core/linter-rules/no-captionless-tables",Xu=Wn({en:{msg:"All tables marked with class='numbered' must start with a caption element.",hint:"Add a `caption` to the offending table."},cs:{msg:"VÅ¡echny tabulky oznaÄené class='numbered' musí zaÄínat elementem caption.",hint:"PÅ™idejte k dané tabulce element `caption`."}});var ed=Object.freeze({__proto__:null,name:Qu,run:function(e){if(!e.lint?.["no-captionless-tables"])return;const t=[...document.querySelectorAll("table.numbered")].filter((e=>!(e.firstElementChild instanceof HTMLTableCaptionElement)));t.length&&ur(Xu.msg,Qu,{hint:Xu.hint,elements:t})}});const td="no-unused-dfns",nd="core/linter-rules/no-unused-dfns",rd=Wn({en:{msg:e=>`Found definition for "${e}", but nothing links to it. This is usually a spec bug!`,get hint(){return gr` + You can do one of the following... + + * Add a \`class="lint-ignore"\` attribute the definition. + * Either remove the definition or change \`<dfn>\` to another type of HTML element. + * If you meant to ${"[export|#data-export]"} the definition, add \`class="export"\` to the definition. + + To silence this warning entirely, set \`lint: { "no-unused-dfns": false }\` in your \`respecConfig\`.`}},cs:{msg:e=>`Nalezena definice pro "${e}", ale nic na ni neodkazuje. Toto je obvykle chyba ve specifikaci!`,get hint(){return gr` + Můžete udÄ›lat jedno z následujícího... + + * PÅ™idejte k definici atribut \`class="lint-ignore"\`. + * Definici buÄ odstraňte, nebo změňte \`<dfn>\` na jiný typ HTML elementu. + * Pokud jste chtÄ›li ${"[export|#data-export]"} tuto definici, pÅ™idejte k ní \`class="export"\`. + + Pro úplné potlaÄení tohoto varování nastavte \`lint: { "no-unused-dfns": false }\` ve vaší \`respecConfig\`.`}}});function sd(e){return!document.querySelector(`a[href="#${e.id}"]:not(.index-term, .self-link)`)}var od=Object.freeze({__proto__:null,name:nd,run:function(e){if(!e.lint?.[td])return;const t="error"===e.lint[td]?lr:ur;[...document.querySelectorAll("dfn:not(.lint-ignore, [data-export], [data-cite])")].filter(sd).forEach((e=>{const n=[e],r=qn(e.textContent);t(rd.msg(r),nd,{elements:n,hint:rd.hint})}))}});const id="core/linter-rules/no-headingless-sections",ad=Wn({en:{msg:"All sections must start with a `h2-6` element.",hint:"Add a `h2-6` to the offending section or use a `<div>`."},nl:{msg:"Alle secties moeten beginnen met een `h2-6` element.",hint:"Voeg een `h2-6` toe aan de conflicterende sectie of gebruik een `<div>`."},zh:{msg:"所有章节(section)都必须以 `h2-6` 元素开头。",hint:"å°† `h2-6` 添加到有问题的章节或使用 `<div>`。"},cs:{msg:"VÅ¡echny sekce musí zaÄínat elementem `h2-6`.",hint:"PÅ™idejte do problematické sekce `h2-6` nebo použijte `<div>`."}});var cd=Object.freeze({__proto__:null,name:id,run:function(e){if(!e.lint?.["no-headingless-sections"])return;const t=[...document.querySelectorAll("section:not(.head,#abstract,#sotd)")].filter((({firstElementChild:e})=>!e||!(e.matches(".header-wrapper")||e instanceof HTMLHeadingElement)));t.length&&ur(ad.msg,id,{hint:ad.hint,elements:t})}});const ld="core/linter-rules/no-unused-vars",ud=Wn({en:{msg:"Variable was defined, but never used.",hint:"Add a `data-ignore-unused` attribute to the `<var>`."},cs:{msg:"PromÄ›nná byla definována, ale nikdy nebyla použita.",hint:"PÅ™idejte atribut `data-ignore-unused` k elementu `<var>`."}});var dd=Object.freeze({__proto__:null,name:ld,run:function(e){if(!e.lint?.["no-unused-vars"])return;const t=[],n=e=>!!e.querySelector(":scope > :not(section) ~ .algorithm, :scope > :not(section) .algorithm");for(const e of document.querySelectorAll("section")){if(!n(e))continue;const r=e.querySelectorAll(":scope > :not(section) var");if(!r.length)continue;const s=new Map;for(const e of r){const t=qn(e.textContent);(s.get(t)||s.set(t,[]).get(t)).push(e)}for(const e of s.values())1!==e.length||e[0].hasAttribute("data-ignore-unused")||t.push(e[0])}t.length&&ur(ud.msg,ld,{hint:ud.hint,elements:t})}});const pd="required-sections",fd="w3c/linter-rules/required-sections",hd={en:{msg:e=>`W3C Recommendation track documents require a separate "${e}" section.`,hint:e=>gr`Add a \`<section>\` with a "${e}" header. See the [Horizontal review guidelines](https://www.w3.org/Guide/documentreview/#how_to_get_horizontal_review). + If the document is not intended for the W3C Recommendation track, set ${"[noRecTrack]"} to \`true\` + or turn off the ${`[${pd}]`} linter rule.`,privacy_considerations:"Privacy Considerations",security_considerations:"Security Considerations"},es:{msg:e=>`Documentos que van a ser "W3C Recommendation" requieren una sección "${e}" separada.`,hint:e=>gr`Agrega una \`<section>\` con título "${e}". Ver los [Horizontal review guidelines](https://www.w3.org/Guide/documentreview/#how_to_get_horizontal_review). + Si el documento no está destinado a ser un W3C Recommendation, puedes poner ${"[noRecTrack]"} a \`true\` + o apaga la regla de linter ${`[${pd}]`}.`,privacy_considerations:"Consideraciones de privacidad",security_considerations:"Consideraciones de Seguridad"},cs:{msg:e=>`Dokumenty na "W3C Recommendation track" vyžadují samostatnou sekci "${e}".`,hint:e=>gr`PÅ™idejte \`<section>\` s nadpisem "${e}". Viz [Horizontal review guidelines](https://www.w3.org/Guide/documentreview/#how_to_get_horizontal_review). + Pokud dokument není urÄen pro "W3C Recommendation track", nastavte ${"[noRecTrack]"} na \`true\` + nebo vypnÄ›te linter pravidlo ${`[${pd}]`}. + `,privacy_considerations:"Zásady ochrany soukromí",security_considerations:"Zásady bezpeÄnosti"}},md=Wn(hd),gd=new Set([...zs]);gd.delete("DISC"),Os.forEach((e=>gd.delete(e)));var bd=Object.freeze({__proto__:null,name:fd,requiresSomeSectionStatus:gd,run:function(e){if(!e.lint?.[pd])return;if(!Un(hd,"privacy_considerations")){return void ur("Cannot check for required sections as translations are not available.",fd,{hint:"File an issue to add translations or use a supported language."})}if(e.noRecTrack||!gd.has(e.specStatus))return;const t="error"===e.lint[pd]?lr:ur,n=new rr([md.privacy_considerations,md.security_considerations]),r=document.querySelectorAll("h2, h3, h4, h5, h6");for(const e of r){const t=e.cloneNode(!0);t.querySelectorAll("bdi")?.forEach((e=>e.remove()));const r=qn(t.textContent);if(n.has(r)&&(n.delete(r),0===n.size))return}for(const e of n)t(md.msg(e),fd,{hint:md.hint(e)})}});const yd="core/linter-rules/wpt-tests-exist",wd=Wn({en:{msg:"The following test could not be found in Web Platform Tests:",hint:"Check [wpt.live](https://wpt.live) to see if it was deleted or renamed."},cs:{msg:"Následující test nebyl nalezen ve Web Platform Tests:",hint:"Zkontrolujte [wpt.live](https://wpt.live), zda nebyl smazán nebo pÅ™ejmenován."}});var vd=Object.freeze({__proto__:null,name:yd,run:async function(e){if(!e.lint?.["wpt-tests-exist"])return;const t=await async function(e,t){let n;try{const t=new URL(e);if(t.pathname.startsWith("/web-platform-tests/wpt/tree/master/")){const e=/web-platform-tests\/wpt\/tree\/master\/(.+)/;n=t.pathname.match(e)[1].replace(/\//g,"")}else n=t.pathname.replace(/\//g,"")}catch(e){return ur("Failed to parse WPT directory from testSuiteURI",`linter/${yd}`),console.error(e),null}const r=new URL("web-platform-tests/wpt/files",`${t}/`);r.searchParams.set("path",n);const s=await fetch(r);if(!s.ok){return ur(`Failed to fetch files from WPT repository. Request failed with error: ${await s.text()} (${s.status})`,`linter/${yd}`),null}const{entries:o}=await s.json(),i=o.filter((e=>!e.endsWith("/")));return new Set(i)}(e.testSuiteURI,e.githubAPI);if(!t)return;const n=[...document.querySelectorAll("[data-tests]")].filter((e=>e.dataset.tests));for(const e of n)e.dataset.tests.split(/,/gm).map((e=>e.trim().split(/\?|#/)[0])).filter((e=>e&&!t.has(e))).map((t=>{ur(`${wd.msg} \`${t}\`.`,yd,{hint:wd.hint,elements:[e]})}))}});const kd="core/linter-rules/no-http-props",$d=Wn({en:{msg:gr`Insecure URLs are not allowed in ${"[respecConfig]"}.`,hint:"Please change the following properties to 'https://': "},zh:{msg:gr`${"[respecConfig]"} 中ä¸å…许使用ä¸å®‰å…¨çš„URL.`,hint:"请将以下属性更改为 https://:"},cs:{msg:gr`V ${"[respecConfig]"} nejsou povoleny nezabezpeÄené URL adresy.`,hint:"Změňte prosím následující vlastnosti na 'https://': "}});var xd=Object.freeze({__proto__:null,name:kd,run:function(e){if(!e.lint?.["no-http-props"])return;if(!parent.location.href.startsWith("http"))return;const t=Object.getOwnPropertyNames(e).filter((t=>t.endsWith("URI")&&e[t]||"prevED"===t)).filter((t=>new URL(e[t],parent.location.href).href.startsWith("http://")));if(t.length){const e=On(t,(e=>gr`${`[${e}]`}`));ur($d.msg,kd,{hint:$d.hint+e})}}});const _d="core/linter-rules/a11y",Cd=["color-contrast","landmark-one-main","landmark-unique","region"];function Sd(e){const t=[];for(const n of e.split("\n\n")){const[e,...r]=n.split(/^\s{2}/m),s=r.map((e=>`- ${e.trimEnd()}`)).join("\n");t.push(`${e}${s}`)}return t.join("\n\n")}var Rd=Object.freeze({__proto__:null,name:_d,run:async function(e){if(!e.lint?.a11y&&!e.a11y)return;const t=e.lint?.a11y||e.a11y,n=!0===t?{}:t,r=await async function(e){const{rules:t,...n}=e,r={rules:{...Object.fromEntries(Cd.map((e=>[e,{enabled:!1}]))),...t},...n,elementRef:!0,resultTypes:["violations"],reporter:"v1"};let s;try{s=await function(){const e=document.createElement("script");return e.classList.add("remove"),e.src="https://cdn.jsdelivr.net/npm/axe-core@4/axe.min.js",document.head.appendChild(e),new Promise(((t,n)=>{e.onload=()=>t(window.axe),e.onerror=n}))}()}catch(e){return lr("Failed to load a11y linter.",_d),console.error(e),[]}try{return(await s.run(document,r)).violations}catch(e){return lr("Error while looking for a11y issues.",_d),console.error(e),[]}}(n);for(const e of r){const t=new Map;for(const n of e.nodes){const{failureSummary:e,element:r}=n;(t.get(e)||t.set(e,[]).get(e)).push(r)}const{id:n,help:r,description:s,helpUrl:o}=e,i=`a11y/${n}: ${r}.`;for(const[e,n]of t){const t=Sd(e);ur(i,_d,{details:`\n\n${s}.\n\n${t}. ([Learn more](${o}))`,elements:n})}}}});const Ed="informative-dfn",Ad="core/linter-rules/informative-dfn",Ld=Wn({en:{msg:(e,t)=>`Normative reference to "${e}" found but term is defined "informatively" in "${t}".`,get hint(){return gr` + You can do one of the following... + + * Get the source definition to be made normative + * Add a \`class="lint-ignore"\` attribute to the link. + * Use a local normative proxy for the definition à la \`<dfn data-cite="spec">term</dfn>\` + + To silence this warning entirely, set \`lint: { "${Ed}": false }\` in your \`respecConfig\`.`}},cs:{msg:(e,t)=>`Nalezen normativní odkaz na "${e}", ale pojem je definován pouze informativnÄ› v "${t}".`,get hint(){return gr` + Můžete udÄ›lat jedno z následujícího... + + * Požádejte o to, aby zdrojová definice byla normativní + * PÅ™idejte atribut \`class=\"lint-ignore\"\` k odkazu. + * Použijte lokální normativní proxy pro definici, napÅ™. \`<dfn data-cite=\"spec\">term</dfn>\` + + Pro úplné potlaÄení tohoto varování nastavte \`lint: { \"${Ed}\": false }\` ve vaší \`respecConfig\`.`}}});var Td=Object.freeze({__proto__:null,name:Ad,run:function(e){if(!e.lint?.[Ed])return;const t="error"===e.lint[Ed]?lr:ur;xc.forEach((({term:e,spec:n,element:r})=>{r.classList.contains("lint-ignore")||t(Ld.msg(e,n),Ad,{title:"Normative reference to non-normative term.",elements:[r],hint:Ld.hint})}))}}),Pd=Object.freeze({__proto__:null,default:'// ReSpec Worker v1.0.0\n"use strict";\ntry {\n importScripts("https://www.w3.org/Tools/respec/respec-highlight");\n} catch (err) {\n console.error("Network error loading highlighter", err);\n}\n\nself.addEventListener("message", ({ data: originalData }) => {\n const data = Object.assign({}, originalData);\n switch (data.action) {\n case "highlight-load-lang": {\n const { langURL, propName, lang } = data;\n importScripts(langURL);\n self.hljs.registerLanguage(lang, self[propName]);\n break;\n }\n case "highlight": {\n const { code } = data;\n const langs = data.languages.length ? data.languages : undefined;\n try {\n const { value, language } = self.hljs.highlightAuto(code, langs);\n Object.assign(data, { value, language });\n } catch (err) {\n console.error("Could not transform some code?", err);\n // Post back the original code\n Object.assign(data, { value: code, language: "" });\n }\n break;\n }\n }\n self.postMessage(data);\n});\n'}),Id=Object.freeze({__proto__:null,default:'(() => {\n// @ts-check\n\nif (document.respec) {\n document.respec.ready.then(setupVarHighlighter);\n} else {\n setupVarHighlighter();\n}\n\nfunction setupVarHighlighter() {\n document\n .querySelectorAll("var")\n .forEach(varElem => varElem.addEventListener("click", highlightListener));\n}\n\nfunction highlightListener(ev) {\n ev.stopPropagation();\n const { target: varElem } = ev;\n const hightligtedElems = highlightVars(varElem);\n const resetListener = () => {\n const hlColor = getHighlightColor(varElem);\n hightligtedElems.forEach(el => removeHighlight(el, hlColor));\n [...HL_COLORS.keys()].forEach(key => HL_COLORS.set(key, true));\n };\n if (hightligtedElems.length) {\n document.body.addEventListener("click", resetListener, { once: true });\n }\n}\n\n// availability of highlight colors. colors from var.css\nconst HL_COLORS = new Map([\n ["respec-hl-c1", true],\n ["respec-hl-c2", true],\n ["respec-hl-c3", true],\n ["respec-hl-c4", true],\n ["respec-hl-c5", true],\n ["respec-hl-c6", true],\n ["respec-hl-c7", true],\n]);\n\nfunction getHighlightColor(target) {\n // return current colors if applicable\n const { value } = target.classList;\n const re = /respec-hl-\\w+/;\n const activeClass = re.test(value) && value.match(re);\n if (activeClass) return activeClass[0];\n\n // first color preference\n if (HL_COLORS.get("respec-hl-c1") === true) return "respec-hl-c1";\n\n // otherwise get some other available color\n return [...HL_COLORS.keys()].find(c => HL_COLORS.get(c)) || "respec-hl-c1";\n}\n\nfunction highlightVars(varElem) {\n const textContent = norm(varElem.textContent);\n const parent = varElem.closest(".algorithm, section");\n const highlightColor = getHighlightColor(varElem);\n\n const varsToHighlight = [...parent.querySelectorAll("var")].filter(\n el =>\n norm(el.textContent) === textContent &&\n el.closest(".algorithm, section") === parent\n );\n\n // update availability of highlight color\n const colorStatus = varsToHighlight[0].classList.contains("respec-hl");\n HL_COLORS.set(highlightColor, colorStatus);\n\n // highlight vars\n if (colorStatus) {\n varsToHighlight.forEach(el => removeHighlight(el, highlightColor));\n return [];\n } else {\n varsToHighlight.forEach(el => addHighlight(el, highlightColor));\n }\n return varsToHighlight;\n}\n\nfunction removeHighlight(el, highlightColor) {\n el.classList.remove("respec-hl", highlightColor);\n // clean up empty class attributes so they don\'t come in export\n if (!el.classList.length) el.removeAttribute("class");\n}\n\nfunction addHighlight(elem, highlightColor) {\n elem.classList.add("respec-hl", highlightColor);\n}\n\n/**\n * Same as `norm` from src/core/utils, but our build process doesn\'t allow\n * imports in runtime scripts, so duplicated here.\n * @param {string} str\n */\nfunction norm(str) {\n return str.trim().replace(/\\s+/g, " ");\n}\n})()'}),Dd=Object.freeze({__proto__:null,default:'(() => {\n// @ts-check\nif (document.respec) {\n document.respec.ready.then(setupPanel);\n} else {\n setupPanel();\n}\n\nfunction setupPanel() {\n const listener = panelListener();\n document.body.addEventListener("keydown", listener);\n document.body.addEventListener("click", listener);\n}\n\nfunction panelListener() {\n /** @type {HTMLElement} */\n let panel = null;\n return event => {\n const { target, type } = event;\n\n if (!(target instanceof HTMLElement)) return;\n\n // For keys, we only care about Enter key to activate the panel\n // otherwise it\'s activated via a click.\n if (type === "keydown" && event.key !== "Enter") return;\n\n const action = deriveAction(event);\n\n switch (action) {\n case "show": {\n hidePanel(panel);\n /** @type {HTMLElement} */\n const dfn = target.closest("dfn, .index-term");\n panel = document.getElementById(`dfn-panel-for-${dfn.id}`);\n const coords = deriveCoordinates(event);\n displayPanel(dfn, panel, coords);\n break;\n }\n case "dock": {\n panel.style.left = null;\n panel.style.top = null;\n panel.classList.add("docked");\n break;\n }\n case "hide": {\n hidePanel(panel);\n panel = null;\n break;\n }\n }\n };\n}\n\n/**\n * @param {MouseEvent|KeyboardEvent} event\n */\nfunction deriveCoordinates(event) {\n const target = /** @type HTMLElement */ (event.target);\n\n // We prevent synthetic AT clicks from putting\n // the dialog in a weird place. The AT events sometimes\n // lack coordinates, so they have clientX/Y = 0\n const rect = target.getBoundingClientRect();\n if (\n event instanceof MouseEvent &&\n event.clientX >= rect.left &&\n event.clientY >= rect.top\n ) {\n // The event probably happened inside the bounding rect...\n return { x: event.clientX, y: event.clientY };\n }\n\n // Offset to the middle of the element\n const x = rect.x + rect.width / 2;\n // Placed at the bottom of the element\n const y = rect.y + rect.height;\n return { x, y };\n}\n\n/**\n * @param {Event} event\n */\nfunction deriveAction(event) {\n const target = /** @type {HTMLElement} */ (event.target);\n const hitALink = !!target.closest("a");\n if (target.closest("dfn:not([data-cite]), .index-term")) {\n return hitALink ? "none" : "show";\n }\n if (target.closest(".dfn-panel")) {\n if (hitALink) {\n return target.classList.contains("self-link") ? "hide" : "dock";\n }\n const panel = target.closest(".dfn-panel");\n return panel.classList.contains("docked") ? "hide" : "none";\n }\n if (document.querySelector(".dfn-panel:not([hidden])")) {\n return "hide";\n }\n return "none";\n}\n\n/**\n * @param {HTMLElement} dfn\n * @param {HTMLElement} panel\n * @param {{ x: number, y: number }} clickPosition\n */\nfunction displayPanel(dfn, panel, { x, y }) {\n panel.hidden = false;\n // distance (px) between edge of panel and the pointing triangle (caret)\n const MARGIN = 20;\n\n const dfnRects = dfn.getClientRects();\n // Find the `top` offset when the `dfn` can be spread across multiple lines\n let closestTop = 0;\n let minDiff = Infinity;\n for (const rect of dfnRects) {\n const { top, bottom } = rect;\n const diffFromClickY = Math.abs((top + bottom) / 2 - y);\n if (diffFromClickY < minDiff) {\n minDiff = diffFromClickY;\n closestTop = top;\n }\n }\n\n const top = window.scrollY + closestTop + dfnRects[0].height;\n const left = x - MARGIN;\n panel.style.left = `${left}px`;\n panel.style.top = `${top}px`;\n\n // Find if the panel is flowing out of the window\n const panelRect = panel.getBoundingClientRect();\n const SCREEN_WIDTH = Math.min(window.innerWidth, window.screen.width);\n if (panelRect.right > SCREEN_WIDTH) {\n const newLeft = Math.max(MARGIN, x + MARGIN - panelRect.width);\n const newCaretOffset = left - newLeft;\n panel.style.left = `${newLeft}px`;\n /** @type {HTMLElement} */\n const caret = panel.querySelector(".caret");\n caret.style.left = `${newCaretOffset}px`;\n }\n\n // As it\'s a dialog, we trap focus.\n // TODO: when <dialog> becomes a implemented, we should really\n // use that.\n trapFocus(panel, dfn);\n}\n\n/**\n * @param {HTMLElement} panel\n * @param {HTMLElement} dfn\n * @returns\n */\nfunction trapFocus(panel, dfn) {\n /** @type NodeListOf<HTMLAnchorElement> elements */\n const anchors = panel.querySelectorAll("a[href]");\n // No need to trap focus\n if (!anchors.length) return;\n\n // Move focus to first anchor element\n const first = anchors.item(0);\n first.focus();\n\n const trapListener = createTrapListener(anchors, panel, dfn);\n panel.addEventListener("keydown", trapListener);\n\n // Hiding the panel releases the trap\n const mo = new MutationObserver(records => {\n const [record] = records;\n const target = /** @type HTMLElement */ (record.target);\n if (target.hidden) {\n panel.removeEventListener("keydown", trapListener);\n mo.disconnect();\n }\n });\n mo.observe(panel, { attributes: true, attributeFilter: ["hidden"] });\n}\n\n/**\n *\n * @param {NodeListOf<HTMLAnchorElement>} anchors\n * @param {HTMLElement} panel\n * @param {HTMLElement} dfn\n * @returns\n */\nfunction createTrapListener(anchors, panel, dfn) {\n const lastIndex = anchors.length - 1;\n let currentIndex = 0;\n return event => {\n switch (event.key) {\n // Hitting "Tab" traps us in a nice loop around elements.\n case "Tab": {\n event.preventDefault();\n currentIndex += event.shiftKey ? -1 : +1;\n if (currentIndex < 0) {\n currentIndex = lastIndex;\n } else if (currentIndex > lastIndex) {\n currentIndex = 0;\n }\n anchors.item(currentIndex).focus();\n break;\n }\n\n // Hitting "Enter" on an anchor releases the trap.\n case "Enter":\n hidePanel(panel);\n break;\n\n // Hitting "Escape" returns focus to dfn.\n case "Escape":\n hidePanel(panel);\n dfn.focus();\n return;\n }\n };\n}\n\n/** @param {HTMLElement} panel */\nfunction hidePanel(panel) {\n if (!panel) return;\n panel.hidden = true;\n panel.classList.remove("docked");\n}\n})()'})}(); +//# sourceMappingURL=respec-w3c.js.map diff --git a/rumgooglesyndicationpagead.js b/rumgooglesyndicationpagead.js new file mode 100644 index 0000000..abe90cf --- /dev/null +++ b/rumgooglesyndicationpagead.js @@ -0,0 +1,133 @@ +(function(){var aa,ca=typeof Object.create=="function"?Object.create:function(a){function b(){}b.prototype=a;return new b},ea=typeof Object.defineProperties=="function"?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a}; +function fa(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var ha=fa(this),ja=typeof Symbol==="function"&&typeof Symbol("x")==="symbol",q={},ka={};function r(a,b,c){if(!c||a!=null){c=ka[b];if(c==null)return a[b];c=a[c];return c!==void 0?c:a[b]}} +function t(a,b,c){if(b)a:{var d=a.split(".");a=d.length===1;var e=d[0],f;!a&&e in q?f=q:f=ha;for(e=0;e<d.length-1;e++){var g=d[e];if(!(g in f))break a;f=f[g]}d=d[d.length-1];c=ja&&c==="es6"?f[d]:null;b=b(c);b!=null&&(a?ea(q,d,{configurable:!0,writable:!0,value:b}):b!==c&&(ka[d]===void 0&&(a=Math.random()*1E9>>>0,ka[d]=ja?ha.Symbol(d):"$jscp$"+a+"$"+d),ea(f,ka[d],{configurable:!0,writable:!0,value:b})))}}var la; +if(ja&&typeof r(Object,"setPrototypeOf")=="function")la=r(Object,"setPrototypeOf");else{var ma;a:{var na={a:!0},oa={};try{oa.__proto__=na;ma=oa.a;break a}catch(a){}ma=!1}la=ma?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var pa=la; +function x(a,b){a.prototype=ca(b.prototype);a.prototype.constructor=a;if(pa)pa(a,b);else for(var c in b)if(c!="prototype")if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.La=b.prototype}function qa(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}} +function y(a){var b=typeof q.Symbol!="undefined"&&r(q.Symbol,"iterator")&&a[r(q.Symbol,"iterator")];if(b)return b.call(a);if(typeof a.length=="number")return{next:qa(a)};throw Error(String(a)+" is not an iterable or ArrayLike");}function sa(a){if(!(a instanceof Array)){a=y(a);for(var b,c=[];!(b=a.next()).done;)c.push(b.value);a=c}return a}function ta(a){return ua(a,a)}function ua(a,b){a.raw=b;Object.freeze&&(Object.freeze(a),Object.freeze(b));return a} +function va(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function wa(){for(var a=Number(this),b=[],c=a;c<arguments.length;c++)b[c-a]=arguments[c];return b}t("globalThis",function(a){return a||ha},"es_2020");t("Reflect.setPrototypeOf",function(a){return a?a:pa?function(b,c){try{return pa(b,c),!0}catch(d){return!1}}:null},"es6"); +t("Symbol",function(a){function b(f){if(this instanceof b)throw new TypeError("Symbol is not a constructor");return new c(d+(f||"")+"_"+e++,f)}function c(f,g){this.g=f;ea(this,"description",{configurable:!0,writable:!0,value:g})}if(a)return a;c.prototype.toString=function(){return this.g};var d="jscomp_symbol_"+(Math.random()*1E9>>>0)+"_",e=0;return b},"es6"); +t("Symbol.iterator",function(a){if(a)return a;a=(0,q.Symbol)("Symbol.iterator");ea(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return xa(qa(this))}});return a},"es6");function xa(a){a={next:a};a[r(q.Symbol,"iterator")]=function(){return this};return a}t("Object.setPrototypeOf",function(a){return a||pa},"es6"); +t("Array.prototype.find",function(a){return a?a:function(b,c){a:{var d=this;d instanceof String&&(d=String(d));for(var e=d.length,f=0;f<e;f++){var g=d[f];if(b.call(c,g,f,d)){b=g;break a}}b=void 0}return b}},"es6"); +t("WeakMap",function(a){function b(g){this.g=(f+=Math.random()+1).toString();if(g){g=y(g);for(var h;!(h=g.next()).done;)h=h.value,this.set(h[0],h[1])}}function c(){}function d(g){var h=typeof g;return h==="object"&&g!==null||h==="function"}if(function(){if(!a||!Object.seal)return!1;try{var g=Object.seal({}),h=Object.seal({}),k=new a([[g,2],[h,3]]);if(k.get(g)!=2||k.get(h)!=3)return!1;k.delete(g);k.set(h,4);return!k.has(g)&&k.get(h)==4}catch(l){return!1}}())return a;var e="$jscomp_hidden_"+Math.random(), +f=0;b.prototype.set=function(g,h){if(!d(g))throw Error("Invalid WeakMap key");if(!va(g,e)){var k=new c;ea(g,e,{value:k})}if(!va(g,e))throw Error("WeakMap key fail: "+g);g[e][this.g]=h;return this};b.prototype.get=function(g){return d(g)&&va(g,e)?g[e][this.g]:void 0};b.prototype.has=function(g){return d(g)&&va(g,e)&&va(g[e],this.g)};b.prototype.delete=function(g){return d(g)&&va(g,e)&&va(g[e],this.g)?delete g[e][this.g]:!1};return b},"es6"); +t("Map",function(a){function b(){var h={};return h.A=h.next=h.head=h}function c(h,k){var l=h[1];return xa(function(){if(l){for(;l.head!=h[1];)l=l.A;for(;l.next!=l.head;)return l=l.next,{done:!1,value:k(l)};l=null}return{done:!0,value:void 0}})}function d(h,k){var l=k&&typeof k;l=="object"||l=="function"?f.has(k)?l=f.get(k):(l=""+ ++g,f.set(k,l)):l="p_"+k;var m=h[0][l];if(m&&va(h[0],l))for(h=0;h<m.length;h++){var n=m[h];if(k!==k&&n.key!==n.key||k===n.key)return{id:l,list:m,index:h,entry:n}}return{id:l, +list:m,index:-1,entry:void 0}}function e(h){this[0]={};this[1]=b();this.size=0;if(h){h=y(h);for(var k;!(k=h.next()).done;)k=k.value,this.set(k[0],k[1])}}if(function(){if(!a||typeof a!="function"||!a.prototype.entries||typeof Object.seal!="function")return!1;try{var h=Object.seal({x:4}),k=new a(y([[h,"s"]]));if(k.get(h)!="s"||k.size!=1||k.get({x:4})||k.set({x:4},"t")!=k||k.size!=2)return!1;var l=k.entries(),m=l.next();if(m.done||m.value[0]!=h||m.value[1]!="s")return!1;m=l.next();return m.done||m.value[0].x!= +4||m.value[1]!="t"||!l.next().done?!1:!0}catch(n){return!1}}())return a;var f=new q.WeakMap;e.prototype.set=function(h,k){h=h===0?0:h;var l=d(this,h);l.list||(l.list=this[0][l.id]=[]);l.entry?l.entry.value=k:(l.entry={next:this[1],A:this[1].A,head:this[1],key:h,value:k},l.list.push(l.entry),this[1].A.next=l.entry,this[1].A=l.entry,this.size++);return this};e.prototype.delete=function(h){h=d(this,h);return h.entry&&h.list?(h.list.splice(h.index,1),h.list.length||delete this[0][h.id],h.entry.A.next= +h.entry.next,h.entry.next.A=h.entry.A,h.entry.head=null,this.size--,!0):!1};e.prototype.clear=function(){this[0]={};this[1]=this[1].A=b();this.size=0};e.prototype.has=function(h){return!!d(this,h).entry};e.prototype.get=function(h){return(h=d(this,h).entry)&&h.value};e.prototype.entries=function(){return c(this,function(h){return[h.key,h.value]})};e.prototype.keys=function(){return c(this,function(h){return h.key})};e.prototype.values=function(){return c(this,function(h){return h.value})};e.prototype.forEach= +function(h,k){for(var l=this.entries(),m;!(m=l.next()).done;)m=m.value,h.call(k,m[1],m[0],this)};e.prototype[r(q.Symbol,"iterator")]=e.prototype.entries;var g=0;return e},"es6");t("Object.is",function(a){return a?a:function(b,c){return b===c?b!==0||1/b===1/c:b!==b&&c!==c}},"es6");t("Number.isFinite",function(a){return a?a:function(b){return typeof b!=="number"?!1:!isNaN(b)&&b!==Infinity&&b!==-Infinity}},"es6");t("Number.MAX_SAFE_INTEGER",function(){return 9007199254740991},"es6"); +t("Number.MIN_SAFE_INTEGER",function(){return-9007199254740991},"es6");t("Number.isInteger",function(a){return a?a:function(b){return r(Number,"isFinite").call(Number,b)?b===Math.floor(b):!1}},"es6");t("Number.isSafeInteger",function(a){return a?a:function(b){return r(Number,"isInteger").call(Number,b)&&Math.abs(b)<=r(Number,"MAX_SAFE_INTEGER")}},"es6"); +function ya(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&c<a.length){var f=c++;return{value:b(f,a[f]),done:!1}}d=!0;return{done:!0,value:void 0}}};e[r(q.Symbol,"iterator")]=function(){return e};return e}t("Math.trunc",function(a){return a?a:function(b){b=Number(b);if(isNaN(b)||b===Infinity||b===-Infinity||b===0)return b;var c=Math.floor(Math.abs(b));return b<0?-c:c}},"es6");t("Number.isNaN",function(a){return a?a:function(b){return typeof b==="number"&&isNaN(b)}},"es6"); +t("Array.prototype.keys",function(a){return a?a:function(){return ya(this,function(b){return b})}},"es6");/* + + Copyright The Closure Library Authors. + SPDX-License-Identifier: Apache-2.0 +*/ +var A=this||self;function za(a,b){a:{var c=["CLOSURE_FLAGS"];for(var d=A,e=0;e<c.length;e++)if(d=d[c[e]],d==null){c=null;break a}c=d}a=c&&c[a];return a!=null?a:b}function Aa(a){var b=typeof a;return b!="object"?b:a?Array.isArray(a)?"array":b:"null"}function Ba(a){return a};var Ca;var Da,Ea=typeof String.prototype.isWellFormed==="function",Fa=typeof TextEncoder!=="undefined"; +function Ga(a){var b=!1;b=b===void 0?!1:b;if(Fa){if(b&&(Ea?!a.isWellFormed():/(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/.test(a)))throw Error("Found an unpaired surrogate");a=(Da||(Da=new TextEncoder)).encode(a)}else{for(var c=0,d=new Uint8Array(3*a.length),e=0;e<a.length;e++){var f=a.charCodeAt(e);if(f<128)d[c++]=f;else{if(f<2048)d[c++]=f>>6|192;else{if(f>=55296&&f<=57343){if(f<=56319&&e<a.length){var g=a.charCodeAt(++e);if(g>=56320&&g<=57343){f=(f-55296)*1024+g-56320+ +65536;d[c++]=f>>18|240;d[c++]=f>>12&63|128;d[c++]=f>>6&63|128;d[c++]=f&63|128;continue}else e--}if(b)throw Error("Found an unpaired surrogate");f=65533}d[c++]=f>>12|224;d[c++]=f>>6&63|128}d[c++]=f&63|128}}a=c===d.length?d:d.subarray(0,c)}return a};function Ha(a){A.setTimeout(function(){throw a;},0)};function Ia(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};var Ja=za(610401301,!1),Ka=za(748402147,!0),Ma=za(824656860,za(1,!0));function Na(){var a=A.navigator;return a&&(a=a.userAgent)?a:""}var Oa,Qa=A.navigator;Oa=Qa?Qa.userAgentData||null:null;function Ra(a){if(!Ja||!Oa)return!1;for(var b=0;b<Oa.brands.length;b++){var c=Oa.brands[b].brand;if(c&&c.indexOf(a)!=-1)return!0}return!1}function B(a){return Na().indexOf(a)!=-1};function Sa(){return Ja?!!Oa&&Oa.brands.length>0:!1};function Ta(a,b){if(typeof a==="string")return typeof b!=="string"||b.length!=1?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1}function Ua(a,b){for(var c=a.length,d=typeof a==="string"?a.split(""):a,e=0;e<c;e++)e in d&&b.call(void 0,d[e],e,a)}function Va(a,b){for(var c=a.length,d=[],e=0,f=typeof a==="string"?a.split(""):a,g=0;g<c;g++)if(g in f){var h=f[g];b.call(void 0,h,g,a)&&(d[e++]=h)}return d} +function Wa(a,b){for(var c=a.length,d=Array(c),e=typeof a==="string"?a.split(""):a,f=0;f<c;f++)f in e&&(d[f]=b.call(void 0,e[f],f,a));return d}function Xa(a,b){a:{for(var c=a.length,d=typeof a==="string"?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return b<0?null:typeof a==="string"?a.charAt(b):a[b]} +function Ya(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c],e=Aa(d);if(e=="array"||e=="object"&&typeof d.length=="number"){e=a.length||0;var f=d.length||0;a.length=e+f;for(var g=0;g<f;g++)a[e+g]=d[g]}else a.push(d)}}function Za(a,b){a.sort(b||ab)}function ab(a,b){return a>b?1:a<b?-1:0};function bb(a){bb[" "](a);return a}bb[" "]=function(){};var cb=Na().toLowerCase().indexOf("webkit")!=-1&&!B("Edge");var db=B("Safari")&&!((Sa()?Ra("Chromium"):(B("Chrome")||B("CriOS"))&&(Sa()||!B("Edge"))||B("Silk"))||(Sa()?0:B("Coast"))||(Sa()?0:B("Opera"))||(Sa()?0:B("Edge"))||(Sa()?Ra("Microsoft Edge"):B("Edg/"))||(Sa()?Ra("Opera"):B("OPR"))||B("Firefox")||B("FxiOS")||B("Silk")||B("Android"))&&!(B("iPhone")&&!B("iPod")&&!B("iPad")||B("iPad")||B("iPod"));var eb={},fb=null,ib=B("Gecko")&&!(Na().toLowerCase().indexOf("webkit")!=-1&&!B("Edge"))&&!(B("Trident")||B("MSIE"))&&!B("Edge")||cb||!db&&typeof A.atob=="function";function jb(a){if(ib)return A.atob(a);var b="";kb(a,function(c){b+=String.fromCharCode(c)});return b} +function kb(a,b){function c(k){for(;d<a.length;){var l=a.charAt(d++),m=fb[l];if(m!=null)return m;if(!/^[\s\xa0]*$/.test(l))throw Error("Unknown base64 encoding at char: "+l);}return k}lb();for(var d=0;;){var e=c(-1),f=c(0),g=c(64),h=c(64);if(h===64&&e===-1)break;b(e<<2|f>>4);g!=64&&(b(f<<4&240|g>>2),h!=64&&b(g<<6&192|h))}} +function lb(){if(!fb){fb={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;c<5;c++){var d=a.concat(b[c].split(""));eb[c]=d;for(var e=0;e<d.length;e++){var f=d[e];fb[f]===void 0&&(fb[f]=e)}}}};function mb(a,b){a.__closure__error__context__984382||(a.__closure__error__context__984382={});a.__closure__error__context__984382.severity=b};var nb=void 0;function ob(a){a=Error(a);mb(a,"warning");return a}function pb(a,b){if(a!=null){var c;var d=(c=nb)!=null?c:nb={};c=d[a]||0;c>=b||(d[a]=c+1,a=Error(),mb(a,"incident"),Ha(a))}};function qb(){return typeof BigInt==="function"};var rb=typeof q.Symbol==="function"&&typeof(0,q.Symbol)()==="symbol";function sb(a,b,c){return typeof q.Symbol==="function"&&typeof(0,q.Symbol)()==="symbol"?(c===void 0?0:c)&&q.Symbol.for&&a?q.Symbol.for(a):a!=null?(0,q.Symbol)(a):(0,q.Symbol)():b}var tb=sb("jas",void 0,!0),ub=sb(void 0,"1oa"),vb=sb(void 0,"0ubsb"),wb=sb(void 0,"0actk"),xb=sb("m_m","Ka",!0);var yb={oa:{value:0,configurable:!0,writable:!0,enumerable:!1}},zb=Object.defineProperties,E=rb?tb:"oa",Ab,Bb=[];F(Bb,7);Ab=Object.freeze(Bb);function Cb(a,b){rb||E in a||zb(a,yb);a[E]|=b}function F(a,b){rb||E in a||zb(a,yb);a[E]=b};var Db={};function I(a,b){return b===void 0?a.g!==Eb&&!!(2&(a.j[E]|0)):!!(2&b)&&a.g!==Eb}var Eb={},Fb=Object.freeze({});function Gb(a,b,c){var d=b&128?0:-1,e=a.length,f;if(f=!!e)f=a[e-1],f=f!=null&&typeof f==="object"&&f.constructor===Object;var g=e+(f?-1:0);for(b=b&128?1:0;b<g;b++)c(b-d,a[b]);if(f){a=a[e-1];for(var h in a)Object.prototype.hasOwnProperty.call(a,h)&&!isNaN(h)&&c(+h,a[h])}};function Hb(a){a.Ja=!0;return a};var Ib=Hb(function(a){return typeof a==="number"}),Jb=Hb(function(a){return typeof a==="string"}),Kb=Hb(function(a){return typeof a==="boolean"});var Lb=typeof A.BigInt==="function"&&typeof A.BigInt(0)==="bigint";function Mb(a){var b=a;if(Jb(b)){if(!/^\s*(?:-?[1-9]\d*|0)?\s*$/.test(b))throw Error(String(b));}else if(Ib(b)&&!r(Number,"isSafeInteger").call(Number,b))throw Error(String(b));return Lb?BigInt(a):a=Kb(a)?a?"1":"0":Jb(a)?a.trim()||"0":String(a)}var Sb=Hb(function(a){return Lb?a>=Nb&&a<=Ob:a[0]==="-"?Pb(a,Qb):Pb(a,Rb)}),Qb=r(Number,"MIN_SAFE_INTEGER").toString(),Nb=Lb?BigInt(r(Number,"MIN_SAFE_INTEGER")):void 0,Rb=r(Number,"MAX_SAFE_INTEGER").toString(),Ob=Lb?BigInt(r(Number,"MAX_SAFE_INTEGER")):void 0; +function Pb(a,b){if(a.length>b.length)return!1;if(a.length<b.length||a===b)return!0;for(var c=0;c<a.length;c++){var d=a[c],e=b[c];if(d>e)return!1;if(d<e)return!0}};var J=0,K=0;function Tb(a){var b=a>>>0;J=b;K=(a-b)/4294967296>>>0}function Ub(a){if(a<0){Tb(-a);var b=y(Vb(J,K));a=b.next().value;b=b.next().value;J=a>>>0;K=b>>>0}else Tb(a)}function Wb(a,b){b>>>=0;a>>>=0;if(b<=2097151)var c=""+(4294967296*b+a);else qb()?c=""+(BigInt(b)<<BigInt(32)|BigInt(a)):(c=(a>>>24|b<<8)&16777215,b=b>>16&65535,a=(a&16777215)+c*6777216+b*6710656,c+=b*8147497,b*=2,a>=1E7&&(c+=a/1E7>>>0,a%=1E7),c>=1E7&&(b+=c/1E7>>>0,c%=1E7),c=b+Xb(c)+Xb(a));return c} +function Xb(a){a=String(a);return"0000000".slice(a.length)+a}function Yb(){var a=J,b=K;b&2147483648?qb()?a=""+(BigInt(b|0)<<BigInt(32)|BigInt(a>>>0)):(b=y(Vb(a,b)),a=b.next().value,b=b.next().value,a="-"+Wb(a,b)):a=Wb(a,b);return a} +function Zb(a){if(a.length<16)Ub(Number(a));else if(qb())a=BigInt(a),J=Number(a&BigInt(4294967295))>>>0,K=Number(a>>BigInt(32)&BigInt(4294967295));else{var b=+(a[0]==="-");K=J=0;for(var c=a.length,d=b,e=(c-b)%6+b;e<=c;d=e,e+=6)d=Number(a.slice(d,e)),K*=1E6,J=J*1E6+d,J>=4294967296&&(K+=r(Math,"trunc").call(Math,J/4294967296),K>>>=0,J>>>=0);b&&(b=y(Vb(J,K)),a=b.next().value,b=b.next().value,J=a,K=b)}}function Vb(a,b){b=~b;a?a=~a+1:b+=1;return[a,b]};function $b(a){return Array.prototype.slice.call(a)};var ac=typeof BigInt==="function"?BigInt.asIntN:void 0,bc=r(Number,"isSafeInteger"),cc=r(Number,"isFinite"),dc=r(Math,"trunc");function ec(a){if(a==null||typeof a==="boolean")return a;if(typeof a==="number")return!!a}var fc=/^-?([1-9][0-9]*|0)(\.[0-9]+)?$/;function hc(a){switch(typeof a){case "bigint":return!0;case "number":return cc(a);case "string":return fc.test(a);default:return!1}} +function ic(a){if(a==null)return a;if(typeof a==="string"&&a)a=+a;else if(typeof a!=="number")return;return cc(a)?a|0:void 0} +function jc(a){var b=void 0;b!=null||(b=Ma?1024:0);if(!hc(a))throw ob("int64");var c=typeof a;switch(b){case 512:switch(c){case "string":return kc(a);case "bigint":return String(ac(64,a));default:return lc(a)}case 1024:switch(c){case "string":return mc(a);case "bigint":return Mb(ac(64,a));default:return nc(a)}case 0:switch(c){case "string":return kc(a);case "bigint":return Mb(ac(64,a));default:return oc(a)}default:throw Error("Unknown format requested type for int64");}} +function pc(a){var b=a.length;if(a[0]==="-"?b<20||b===20&&a<="-9223372036854775808":b<19||b===19&&a<="9223372036854775807")return a;Zb(a);return Yb()}function oc(a){a=dc(a);if(!bc(a)){Ub(a);var b=J,c=K;if(a=c&2147483648)b=~b+1>>>0,c=~c>>>0,b==0&&(c=c+1>>>0);var d=c*4294967296+(b>>>0);b=r(Number,"isSafeInteger").call(Number,d)?d:Wb(b,c);a=typeof b==="number"?a?-b:b:a?"-"+b:b}return a}function lc(a){a=dc(a);bc(a)?a=String(a):(Ub(a),a=Yb());return a} +function kc(a){var b=dc(Number(a));if(bc(b))return String(b);b=a.indexOf(".");b!==-1&&(a=a.substring(0,b));return pc(a)}function mc(a){var b=dc(Number(a));if(bc(b))return Mb(b);b=a.indexOf(".");b!==-1&&(a=a.substring(0,b));return qb()?Mb(ac(64,BigInt(a))):Mb(pc(a))}function nc(a){return bc(a)?Mb(oc(a)):Mb(lc(a))}function qc(a){var b=typeof a;if(a==null)return a;if(b==="bigint")return Mb(ac(64,a));if(hc(a))return b==="string"?mc(a):nc(a)} +function rc(a){if(a==null)return a;var b=typeof a;if(b==="bigint")return String(ac(64,a));if(hc(a)){if(b==="string")return kc(a);if(b==="number")return oc(a)}}function sc(a){if(typeof a!=="string")throw Error();return a}function tc(a){return a==null||typeof a==="string"?a:void 0}function uc(a,b,c){if(a!=null&&a[xb]===Db)return a;if(Array.isArray(a)){var d=a[E]|0;c=d|c&32|c&2;c!==d&&F(a,c);return new b(a)}};function vc(a){return a};function wc(a,b,c,d){var e=d!==void 0;d=!!d;var f=[],g=a.length,h=4294967295,k=!1,l=!!(b&64),m=l?b&128?0:-1:void 0;if(!(b&1)){var n=g&&a[g-1];n!=null&&typeof n==="object"&&n.constructor===Object?(g--,h=g):n=void 0;if(l&&!(b&128)&&!e){k=!0;var p;h=((p=xc)!=null?p:vc)(h-m,m,a,n,void 0)+m}}b=void 0;for(e=0;e<g;e++)if(p=a[e],p!=null&&(p=c(p,d))!=null)if(l&&e>=h){var C=e-m,v=void 0;((v=b)!=null?v:b={})[C]=p}else f[e]=p;if(n)for(var D in n)Object.prototype.hasOwnProperty.call(n,D)&&(a=n[D],a!=null&&(a= +c(a,d))!=null&&(g=+D,e=void 0,l&&!r(Number,"isNaN").call(Number,g)&&(e=g+m)<h?f[e]=a:(g=void 0,((g=b)!=null?g:b={})[D]=a)));b&&(k?f.push(b):f[h]=b);return f}function yc(a){switch(typeof a){case "number":return r(Number,"isFinite").call(Number,a)?a:""+a;case "bigint":return Sb(a)?Number(a):""+a;case "boolean":return a?1:0;case "object":if(Array.isArray(a)){var b=a[E]|0;return a.length===0&&b&1?void 0:wc(a,b,yc)}if(a!=null&&a[xb]===Db)return zc(a);return}return a}var xc; +function zc(a){a=a.j;return wc(a,a[E]|0,yc)};var Ac,Bc;function Cc(a){switch(typeof a){case "boolean":return Ac||(Ac=[0,void 0,!0]);case "number":return a>0?void 0:a===0?Bc||(Bc=[0,void 0]):[-a,void 0];case "string":return[0,a];case "object":return a}} +function L(a,b,c,d){d=d===void 0?0:d;if(a==null){var e=32;c?(a=[c],e|=128):a=[];b&&(e=e&-16760833|(b&1023)<<14)}else{if(!Array.isArray(a))throw Error("narr");e=a[E]|0;if(Ka&&1&e)throw Error("rfarr");2048&e&&!(2&e)&&Dc();if(e&256)throw Error("farr");if(e&64)return(e|d)!==e&&F(a,e|d),a;if(c&&(e|=128,c!==a[0]))throw Error("mid");a:{c=a;e|=64;var f=c.length;if(f){var g=f-1,h=c[g];if(h!=null&&typeof h==="object"&&h.constructor===Object){b=e&128?0:-1;g-=b;if(g>=1024)throw Error("pvtlmt");for(var k in h)Object.prototype.hasOwnProperty.call(h, +k)&&(f=+k,f<g&&(c[f+b]=h[k],delete h[k]));e=e&-16760833|(g&1023)<<14;break a}}if(b){k=Math.max(b,f-(e&128?0:-1));if(k>1024)throw Error("spvt");e=e&-16760833|(k&1023)<<14}}}F(a,e|64|d);return a}function Dc(){if(Ka)throw Error("carr");pb(wb,5)};function Ec(a,b){if(typeof a!=="object")return a;if(Array.isArray(a)){var c=a[E]|0;a.length===0&&c&1?a=void 0:c&2||(!b||4096&c||16&c?a=Fc(a,c,!1,b&&!(c&16)):(Cb(a,34),c&4&&Object.freeze(a)));return a}if(a!=null&&a[xb]===Db)return b=a.j,c=b[E]|0,I(a,c)?a:Gc(a,b,c)?Hc(a,b):Fc(b,c)}function Hc(a,b,c){a=new a.constructor(b);c&&(a.g=Eb);a.i=Eb;return a}function Fc(a,b,c,d){d!=null||(d=!!(34&b));a=wc(a,b,Ec,d);d=32;c&&(d|=2);b=b&16769217|d;F(a,b);return a} +function Ic(a){if(a.g!==Eb)return!1;var b=a.j;b=Fc(b,b[E]|0);Cb(b,2048);a.j=b;a.g=void 0;a.i=void 0;return!0}function Jc(a){if(!Ic(a)&&I(a,a.j[E]|0))throw Error();}function Kc(a,b){b===void 0&&(b=a[E]|0);b&32&&!(b&4096)&&F(a,b|4096)}function Gc(a,b,c){return c&2?!0:c&32&&!(c&4096)?(F(b,c|2),a.g=Eb,!0):!1};var Lc=Mb(0);function Mc(a,b,c,d){a=Nc(a.j,b,c,d);if(a!==null)return a}function Nc(a,b,c,d){if(b===-1)return null;var e=b+(c?0:-1),f=a.length-1;if(!(f<1+(c?0:-1))){if(e>=f){var g=a[f];if(g!=null&&typeof g==="object"&&g.constructor===Object){c=g[b];var h=!0}else if(e===f)c=g;else return}else c=a[e];if(d&&c!=null){d=d(c);if(d==null)return d;if(!r(Object,"is").call(Object,d,c))return h?g[b]=d:a[e]=d,d}return c}} +function M(a,b,c,d){var e=c+-1,f=a.length-1;if(f>=0&&e>=f){var g=a[f];if(g!=null&&typeof g==="object"&&g.constructor===Object)return g[c]=d,b}if(e<=f)return a[e]=d,b;if(d!==void 0){var h;f=((h=b)!=null?h:b=a[E]|0)>>14&1023||536870912;c>=f?d!=null&&(e={},a[f+-1]=(e[c]=d,e)):a[e]=d}return b} +function Oc(a,b,c,d,e){var f=a.j,g=f[E]|0;d=I(a,g)?1:d;e=!!e||d===3;d===2&&Ic(a)&&(f=a.j,g=f[E]|0);a=Pc(f,b);var h=a===Ab?7:a[E]|0,k=Qc(h,g);var l=4&k?!1:!0;if(l){4&k&&(a=$b(a),h=0,k=Rc(k,g),g=M(f,g,b,a));for(var m=0,n=0;m<a.length;m++){var p=c(a[m]);p!=null&&(a[n++]=p)}n<m&&(a.length=n);c=(k|4)&-513;k=c&=-1025;k&=-4097}k!==h&&(F(a,k),2&k&&Object.freeze(a));return a=Sc(a,k,f,g,b,d,l,e)} +function Sc(a,b,c,d,e,f,g,h){var k=b;f===1||(f!==4?0:2&b||!(16&b)&&32&d)?Tc(b)||(b|=!a.length||g&&!(4096&b)||32&d&&!(4096&b||16&b)?2:256,b!==k&&F(a,b),Object.freeze(a)):(f===2&&Tc(b)&&(a=$b(a),k=0,b=Rc(b,d),d=M(c,d,e,a)),Tc(b)||(h||(b|=16),b!==k&&F(a,b)));2&b||!(4096&b||16&b)||Kc(c,d);return a}function Pc(a,b){a=Nc(a,b);return Array.isArray(a)?a:Ab}function Qc(a,b){2&b&&(a|=2);return a|1}function Tc(a){return!!(2&a)&&!!(4&a)||!!(256&a)} +function Uc(a,b,c,d){Jc(a);var e=a.j;M(e,e[E]|0,b,(d==="0"?Number(c)===0:c===d)?void 0:c);return a}function Vc(a){if(rb){var b;return(b=a[ub])!=null?b:a[ub]=new q.Map}if(ub in a)return a[ub];b=new q.Map;Object.defineProperty(a,ub,{value:b});return b}function Wc(a,b,c){var d=Xc,e=a.get(d);if(e!=null)return e;for(var f=e=0;f<d.length;f++){var g=d[f];Nc(b,g)!=null&&(e!==0&&(c=M(b,c,e)),e=g)}a.set(d,e);return e} +function Yc(a,b,c,d){var e=!1;d=Nc(a,d,void 0,function(f){var g=uc(f,c,b);e=g!==f&&g!=null;return g});if(d!=null)return e&&!I(d)&&Kc(a,b),d}function Zc(a,b,c){var d=a.j,e=d[E]|0;b=Yc(d,e,b,c);if(b==null)return b;e=d[E]|0;if(!I(a,e)){var f,g=b,h=g.j,k=h[E]|0;I(g,k)?Gc(g,h,k)?f=Hc(g,h,!0):f=new g.constructor(Fc(h,k,!1)):f=g;f!==b&&(Ic(a)&&(d=a.j,e=d[E]|0),b=f,e=M(d,e,c,b),Kc(d,e))}return b}function $c(a){a==null&&(a=void 0);return a} +function ad(a,b,c){var d=c=$c(c);Jc(a);var e=a.j;M(e,e[E]|0,b,d);c&&!I(c)&&Kc(a.j)}function Rc(a,b){return a=(2&b?a|2:a&-3)&-273} +function bd(a,b,c,d){Jc(a);var e=a.j,f=e,g=e[E]|0,h=I(a,g)?1:2;h===2&&Ic(a)&&(f=a.j,g=f[E]|0);a=Pc(f,b);var k=a===Ab?7:a[E]|0,l=Qc(k,g),m=!(4&l);if(m){var n=a,p=g,C=!!(2&l);C&&(p|=2);for(var v=!C,D=!0,T=0,P=0;T<n.length;T++){var ba=uc(n[T],c,p);if(ba instanceof c){if(!C){var ra=I(ba);v&&(v=!ra);D&&(D=ra)}n[P++]=ba}}P<T&&(n.length=P);l|=4;l=D?l&-4097:l|4096;l=v?l|8:l&-9}l!==k&&(F(a,l),2&l&&Object.freeze(a));b=a=Sc(a,l,f,g,b,h,m,!0);d=d!=null?d:new c;b.push(d);f=c=b===Ab?7:b[E]|0;(d=I(d))?(c&=-9,b.length=== +1&&(c&=-4097)):c|=4096;c!==f&&F(b,c);d||Kc(e)}function N(a,b){var c=c===void 0?!1:c;a=ec(Mc(a,b));return a!=null?a:c}function cd(a){var b=b===void 0?0:b;a=ic(Mc(a,3));return a!=null?a:b}function dd(a,b){var c=c===void 0?"":c;a=tc(Mc(a,b));return a!=null?a:c}function ed(a,b){var c=c===void 0?0:c;a=Mc(a,b);a=a==null?a:cc(a)?a|0:void 0;return a!=null?a:c}function fd(a,b,c){if(c!=null&&typeof c!=="boolean")throw Error("Expected boolean but got "+Aa(c)+": "+c);return Uc(a,b,c,!1)} +function R(a,b,c){return Uc(a,b,c==null?c:jc(c),"0")}function gd(a,b,c){if(c!=null&&typeof c!=="string")throw Error();return Uc(a,b,c,"")}function hd(a,b,c){if(c!=null){if(!cc(c))throw ob("enum");c|=0}return Uc(a,b,c,0)};function id(a,b){this.h=a>>>0;this.g=b>>>0}function jd(a){if(!a)return kd||(kd=new id(0,0));if(!/^-?\d+$/.test(a))return null;Zb(a);return new id(J,K)}var kd;function ld(){this.g=[]}ld.prototype.length=function(){return this.g.length};ld.prototype.end=function(){var a=this.g;this.g=[];return a};function md(a,b,c){for(;c>0||b>127;)a.g.push(b&127|128),b=(b>>>7|c<<25)>>>0,c>>>=7;a.g.push(b)}function nd(a,b){for(;b>127;)a.g.push(b&127|128),b>>>=7;a.g.push(b)};function od(){this.i=[];this.h=0;this.g=new ld}function pd(a,b){b.length!==0&&(a.i.push(b),a.h+=b.length)}function qd(a,b){nd(a.g,b*8+2);b=a.g.end();pd(a,b);b.push(a.h);return b}function rd(a,b){var c=b.pop();for(c=a.h+a.g.length()-c;c>127;)b.push(c&127|128),c>>>=7,a.h++;b.push(c);a.h++}function sd(a,b,c){nd(a.g,b*8+2);nd(a.g,c.length);pd(a,a.g.end());pd(a,c)};function td(){function a(){throw Error();}r(Object,"setPrototypeOf").call(Object,a,a.prototype);return a}var ud=td(),vd=td(),wd=td(),xd=td(),yd=td();function S(a,b,c){this.j=L(a,b,c,2048)}S.prototype.toJSON=function(){var a=zc(this);return a};S.prototype[xb]=Db;S.prototype.toString=function(){return this.j.toString()};function zd(a,b){this.g=a;a=Ba(ud);this.h=!!a&&b===a||!1}function Ad(a){var b=b===void 0?ud:b;return new zd(a,b)}function Bd(a,b,c,d,e){b=Cd(b,d);b!=null&&(c=qd(a,c),e(b,a),rd(a,c))}var Dd=Ad(Bd),Ed=Ad(Bd),Fd=(0,q.Symbol)(),Gd=(0,q.Symbol)(),Hd,Id; +function Jd(a){var b=Kd,c=Ld,d=a[Fd];if(d)return d;d={};d.za=a;d.S=Cc(a[0]);var e=a[1],f=1;e&&e.constructor===Object&&(d.ia=e,e=a[++f],typeof e==="function"&&(d.pa=!0,Hd!=null||(Hd=e),Id!=null||(Id=a[f+1]),e=a[f+=2]));for(var g={};e&&Array.isArray(e)&&e.length&&typeof e[0]==="number"&&e[0]>0;){for(var h=0;h<e.length;h++)g[e[h]]=e;e=a[++f]}for(h=1;e!==void 0;){typeof e==="number"&&(h+=e,e=a[++f]);var k=void 0;if(e instanceof zd)var l=e;else l=Dd,f--;e=void 0;if((e=l)==null?0:e.h){e=a[++f];k=a;var m= +f;typeof e==="function"&&(e=e(),k[m]=e);k=e}e=a[++f];m=h+1;typeof e==="number"&&e<0&&(m-=e,e=a[++f]);for(;h<m;h++){var n=g[h];k?c(d,h,l,k,n):b(d,h,l,n)}}return a[Fd]=d}function Cd(a,b){if(a instanceof S)return a.j;if(Array.isArray(a))return L(a,b[0],b[1])};function Kd(a,b,c){a[b]=c.g}function Ld(a,b,c,d){var e,f,g=c.g;a[b]=function(h,k,l){return g(h,k,l,f||(f=Jd(d).S),e||(e=Md(d)))}}function Md(a){var b=a[Gd];if(!b){var c=Jd(a);b=function(d,e){return Nd(d,e,c)};a[Gd]=b}return b}function Nd(a,b,c){Gb(a,a[E]|0,function(d,e){if(e!=null){var f=Od(c,d);f?f(b,e,d):d<500||pb(vb,3)}})} +function Od(a,b){var c=a[b];if(c)return c;if(c=a.ia)if(c=c[b]){c=Array.isArray(c)?c[0]instanceof zd?c:[Ed,c]:[c,void 0];var d=c[0].g;if(c=c[1]){var e=Md(c),f=Jd(c).S;c=a.pa?Id(f,e):function(g,h,k){return d(g,h,k,f,e)}}else c=d;return a[b]=c}};function Pd(a,b){var c=new od;Nd(a.j,c,Jd(b));pd(c,c.g.end());a=new Uint8Array(c.h);b=c.i;for(var d=b.length,e=0,f=0;f<d;f++){var g=b[f];a.set(g,e);e+=g.length}c.i=[a];return a}function Qd(a,b){return new zd(a,b)}function Rd(a,b,c,d,e){b=Cd(b,d);b!=null&&(c=qd(a,c),e(b,a),rd(a,c))} +var Sd=Qd(function(a,b,c){b=rc(b);if(b!=null){switch(typeof b){case "string":jd(b)}if(b!=null)switch(nd(a.g,c*8),typeof b){case "number":a=a.g;Ub(b);md(a,J,K);break;case "bigint":c=BigInt.asUintN(64,b);c=new id(Number(c&BigInt(4294967295)),Number(c>>BigInt(32)));md(a.g,c.h,c.g);break;default:c=jd(b),md(a.g,c.h,c.g)}}},xd),Td=Qd(function(a,b,c){b=ec(b);b!=null&&(nd(a.g,c*8),a.g.g.push(b?1:0))},vd),Ud; +Ud=new zd(function(a,b,c){if(Array.isArray(b)){var d=b[E]|0;if(!(d&4)){for(var e=0,f=0;e<b.length;e++){var g=tc(b[e]);g!=null&&(b[f++]=g)}f<e&&(b.length=f);e=(d|5)&-1537;e!==d&&F(b,e);e&2&&Object.freeze(b)}}else b=void 0;if(b!=null)for(d=0;d<b.length;d++)e=a,f=c,g=b[d],g!=null&&sd(e,f,Ga(g))},wd);var Vd=Qd(function(a,b,c){b=tc(b);b!=null&&sd(a,c,Ga(b))},wd),Wd,Xd=void 0;Xd=Xd===void 0?ud:Xd; +Wd=new zd(function(a,b,c,d,e){if(Array.isArray(b)){for(var f=0;f<b.length;f++)Rd(a,b[f],c,d,e);a=b[E]|0;a&1||F(b,a|1)}},Xd);var Yd=Ad(Rd),Zd=Qd(function(a,b,c){b=ic(b);if(b!=null)if(b=parseInt(b,10),nd(a.g,c*8),a=a.g,c=b,c>=0)nd(a,c);else{for(b=0;b<9;b++)a.g.push(c&127|128),c>>=7;a.g.push(1)}},yd);function $d(a){return function(){return Pd(this,a)}};function ae(a,b){if(a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b(a[c],c,a)}function be(a,b){if(a)return(aa=r(Object,"keys").call(Object,a),r(aa,"find")).call(aa,function(c){return Object.prototype.hasOwnProperty.call(a,c)&&b(a[c],c)})};function ce(a){try{var b;if(b=!!a&&a.location.href!=null)a:{try{bb(a.foo);b=!0;break a}catch(c){}b=!1}return b}catch(c){return!1}}function de(a){return ce(a.top)?a.top:null};function ee(a){var b=!1,c;return function(){b||(c=a(),b=!0);return c}}function fe(a){function b(){d=A.setTimeout(c,1E3);var g=f;f=[];a.apply(void 0,g)}function c(){d=0;e&&(e=!1,b())}var d=0,e=!1,f=[];return function(g){f=arguments;d?e=!0:b()}};/* + + Copyright Google LLC + SPDX-License-Identifier: Apache-2.0 +*/ +var ge=q.globalThis.trustedTypes,he;function ie(){var a=null;if(!ge)return a;try{var b=function(c){return c};a=ge.createPolicy("goog#html",{createHTML:b,createScript:b,createScriptURL:b})}catch(c){}return a};function je(a){this.g=a}je.prototype.toString=function(){return this.g+""};function ke(a){var b;he===void 0&&(he=ie());a=(b=he)?b.createScriptURL(a):a;return new je(a)};function le(a){var b=wa.apply(1,arguments);if(b.length===0)return ke(a[0]);for(var c=a[0],d=0;d<b.length;d++)c+=encodeURIComponent(b[d])+a[d+1];return ke(c)};function me(a,b){b=b===void 0?document:b;return b.createElement(String(a).toLowerCase())};function ne(a){a=a&&a.toString&&a.toString();return typeof a==="string"&&a.indexOf("[native code]")!=-1};function oe(a){return Array.prototype.reduce.call(arguments,function(b,c){return b+c},0)}function pe(a){return oe.apply(null,arguments)/arguments.length};function qe(a,b){this.x=a!==void 0?a:0;this.y=b!==void 0?b:0}qe.prototype.equals=function(a){return a instanceof qe&&(this==a?!0:this&&a?this.x==a.x&&this.y==a.y:!1)};qe.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};qe.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};qe.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function re(a,b){this.width=a;this.height=b}re.prototype.aspectRatio=function(){return this.width/this.height};re.prototype.isEmpty=function(){return!(this.width*this.height)};re.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};re.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};re.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function se(a){for(var b in a)delete a[b]};function te(a,b){for(;a&&a.nodeType!=1;)a=b?a.nextSibling:a.previousSibling;return a}function ue(a){return a.nodeType==9?a:a.ownerDocument||a.document}function ve(a){var b=we;a&&(a=a.parentNode);for(var c=0;a&&c<=6;){if(b(a))return a;a=a.parentNode;c++}return null}function xe(a){this.g=a||A.document||document};function ye(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d}ye.prototype.ceil=function(){this.left=Math.ceil(this.left);this.top=Math.ceil(this.top);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};ye.prototype.floor=function(){this.left=Math.floor(this.left);this.top=Math.floor(this.top);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this}; +ye.prototype.round=function(){this.left=Math.round(this.left);this.top=Math.round(this.top);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function ze(a){try{return a.getBoundingClientRect()}catch(b){return{left:0,top:0,right:0,bottom:0}}}function Ae(a){var b=a.offsetWidth,c=a.offsetHeight,d=cb&&!b&&!c;return(b===void 0||d)&&a.getBoundingClientRect?(a=ze(a),new re(a.right-a.left,a.bottom-a.top)):new re(b,c)};var Be=ee(function(){var a=!1;try{var b=Object.defineProperty({},"passive",{get:function(){a=!0}});A.addEventListener("test",null,b)}catch(c){}return a});function Ce(a){return a?a.passive&&Be()?a:a.capture||!1:!1}function De(a,b,c,d){typeof a.addEventListener==="function"&&a.addEventListener(b,c,Ce(d))}function Ee(a,b,c){typeof a.removeEventListener==="function"&&a.removeEventListener(b,c,Ce())};function Fe(a,b){a.google_image_requests||(a.google_image_requests=[]);var c=me("IMG",a.document);c.src=b;a.google_image_requests.push(c)};function Ge(a,b){var c=c===void 0?{}:c;this.error=a;this.meta=c;this.context=b.context;this.msg=b.message||"";this.id=b.id||"jserror"};function He(a){var b=a.toString();a.name&&b.indexOf(a.name)==-1&&(b+=": "+a.name);a.message&&b.indexOf(a.message)==-1&&(b+=": "+a.message);if(a.stack)a:{a=a.stack;var c=b;try{a.indexOf(c)==-1&&(a=c+"\n"+a);for(var d;a!=d;)d=a,a=a.replace(RegExp("((https?:/..*/)[^/:]*:\\d+(?:.|\n)*)\\2"),"$1");b=a.replace(RegExp("\n *","g"),"\n");break a}catch(e){b=c;break a}b=void 0}return b};var Ie=RegExp("^https?://(\\w|-)+\\.cdn\\.ampproject\\.(net|org)(\\?|/|$)");function Ke(a,b){this.g=a;this.h=b}function Le(a,b){this.url=a;this.g=!!b;this.depth=null};var Me=null;function Ne(){var a=a===void 0?A:a;return(a=a.performance)&&a.now&&a.timing?Math.floor(a.now()+a.timing.navigationStart):Date.now()}function Oe(){var a=a===void 0?A:a;return(a=a.performance)&&a.now?a.now():null};function Pe(a,b,c,d){this.label=a;this.type=b;this.value=c;this.duration=d===void 0?0:d;this.taskId=this.slotId=void 0;this.uniqueId=Math.random()};var U=A.performance,Qe=!!(U&&U.mark&&U.measure&&U.clearMarks),Re=ee(function(){var a;if(a=Qe){var b=b===void 0?window:b;if(Me===null){Me="";try{a="";try{a=b.top.location.hash}catch(d){a=b.location.hash}if(a){var c=a.match(/\bdeid=([\d,]+)/);Me=c?c[1]:""}}catch(d){}}b=Me;a=!!b.indexOf&&b.indexOf("1337")>=0}return a}); +function Se(a,b){this.l=[];this.g=b||A;var c=null;b&&(b.google_js_reporting_queue=b.google_js_reporting_queue||[],this.l=b.google_js_reporting_queue,c=b.google_measure_js_timing);this.h=Re()||(c!=null?c:Math.random()<a)}Se.prototype.B=function(){this.h=!1;this.l!==this.g.google_js_reporting_queue&&(Re()&&Ua(this.l,Te),this.l.length=0)};Se.prototype.F=function(a){!this.h||this.l.length>2048||this.l.push(a)}; +function Te(a){a&&U&&Re()&&(U.clearMarks("goog_"+a.label+"_"+a.uniqueId+"_start"),U.clearMarks("goog_"+a.label+"_"+a.uniqueId+"_end"))}function Ue(a,b,c,d,e){a.h&&a.F(new Pe(b,c,d,e===void 0?0:e))}Se.prototype.start=function(a,b){if(!this.h)return null;a=new Pe(a,b,Oe()||Ne());b="goog_"+a.label+"_"+a.uniqueId+"_start";U&&Re()&&U.mark(b);return a}; +Se.prototype.end=function(a){if(this.h&&typeof a.value==="number"){a.duration=(Oe()||Ne())-a.value;var b="goog_"+a.label+"_"+a.uniqueId+"_end";U&&Re()&&U.mark(b);this.F(a)}};function Ve(a,b){if(a.h){var c=a.start("243",3);try{b()}catch(d){throw Te(c),d;}a.end(c)}else b()};function We(){this.i="&";this.h={};this.l=0;this.g=[]}function Xe(a,b){var c={};c[a]=b;return[c]}function Ye(a,b,c,d,e){var f=[];ae(a,function(g,h){(g=Ze(g,b,c,d,e))&&f.push(h+"="+g)});return f.join(b)} +function Ze(a,b,c,d,e){if(a==null)return"";b=b||"&";c=c||",$";typeof c==="string"&&(c=c.split(""));if(a instanceof Array){if(d||(d=0),d<c.length){for(var f=[],g=0;g<a.length;g++)f.push(Ze(a[g],b,c,d+1,e));return f.join(c[d])}}else if(typeof a==="object")return e||(e=0),e<2?encodeURIComponent(Ye(a,b,c,d,e+1)):"...";return encodeURIComponent(String(a))} +function $e(a,b,c){b="https://"+b+c;var d=af(a)-c.length;if(d<0)return"";a.g.sort(function(m,n){return m-n});c=null;for(var e="",f=0;f<a.g.length;f++)for(var g=a.g[f],h=a.h[g],k=0;k<h.length;k++){if(!d){c=c==null?g:c;break}var l=Ye(h[k],a.i,",$");if(l){l=e+l;if(d>=l.length){d-=l.length;b+=l;e=a.i;break}c=c==null?g:c}}a="";c!=null&&(a=e+"trn="+c);return b+a}function af(a){var b=1,c;for(c in a.h)c.length>b&&(b=c.length);return 3997-b-a.i.length-1};var bf=RegExp("^(?:([^:/?#.]+):)?(?://(?:([^\\\\/?#]*)@)?([^\\\\/?#]*?)(?::([0-9]+))?(?=[\\\\/?#]|$))?([^?#]+)?(?:\\?([^#]*))?(?:#([\\s\\S]*))?$");function cf(a){return a?decodeURI(a):a};function df(){var a=ef;this.m=ff;this.h=a===void 0?null:a;this.i=null;this.l=!1;this.v=this.g}df.prototype.H=function(a,b){try{if(this.h&&this.h.h){var c=this.h.start(a.toString(),3);var d=b();this.h.end(c)}else d=b()}catch(g){b=!0;try{Te(c),b=this.v(a,new Ge(g,{message:He(g)}),void 0,void 0)}catch(h){this.g(217,h)}if(b){var e,f;(e=window.console)==null||(f=e.error)==null||f.call(e,g)}else throw g;}return d}; +df.prototype.T=function(a,b){var c=this;return function(){var d=wa.apply(0,arguments);return c.H(a,function(){return b.apply(void 0,d)})}}; +df.prototype.g=function(a,b,c,d,e){e=e||"jserror";var f=void 0;try{var g=new We;g.g.push(1);g.h[1]=Xe("context",a);b.error&&b.meta&&b.id||(b=new Ge(b,{message:He(b)}));if(b.msg){var h=b.msg.substring(0,512);g.g.push(2);g.h[2]=Xe("msg",h)}var k=b.meta||{};if(this.i)try{this.i(k)}catch(Q){}if(d)try{d(k)}catch(Q){}d=[k];g.g.push(3);g.h[3]=d;var l;if(!(l=v)){h=A;d=[];k=null;do{var m=h;if(ce(m)){var n=m.location.href;k=m.document&&m.document.referrer||null}else n=k,k=null;d.push(new Le(n||""));try{h=m.parent}catch(Q){h= +null}}while(h&&m!==h);n=0;for(var p=d.length-1;n<=p;++n)d[n].depth=p-n;m=A;if(m.location&&m.location.ancestorOrigins&&m.location.ancestorOrigins.length===d.length-1)for(p=1;p<d.length;++p){var C=d[p];C.url||(C.url=m.location.ancestorOrigins[p-1]||"",C.g=!0)}l=d}var v=l;var D=new Le(A.location.href,!1);l=null;var T=v.length-1;for(m=T;m>=0;--m){var P=v[m];!l&&Ie.test(P.url)&&(l=P);if(P.url&&!P.g){D=P;break}}P=null;var ba=v.length&&v[T].url;D.depth!==0&&ba&&(P=v[T]);f=new Ke(D,P);if(f.h){var ra=f.h.url|| +"";g.g.push(4);g.h[4]=Xe("top",ra)}var La={url:f.g.url||""};if(f.g.url){var da=f.g.url.match(bf),ia=da[1],$a=da[3],H=da[4];v="";ia&&(v+=ia+":");$a&&(v+="//",v+=$a,H&&(v+=":"+H));var G=v}else G="";La=[La,{url:G}];g.g.push(5);g.h[5]=La;gf(this.m,e,g,this.l,c)}catch(Q){try{var u,w;gf(this.m,e,{context:"ecmserr",rctx:a,msg:He(Q),url:(w=(u=f)==null?void 0:u.g.url)!=null?w:""},this.l,c)}catch(Je){}}return!0};function hf(a){this.j=L(a,void 0,void 0,2048)}x(hf,S);function jf(a){this.j=L(a,void 0,void 0,2048)}x(jf,S);function kf(a){this.j=L(a,void 0,void 0,2048)}x(kf,S);kf.prototype.getName=function(){return dd(this,1)};var Xc=[5];function lf(a){this.j=L(a,void 0,void 0,2048)}x(lf,S);function of(a){this.j=L(a,void 0,void 0,2048)}x(of,S);var pf=[0,Xc,Vd,Zd,Sd,-1,Yd,[0,Zd,Wd,[0,Zd,-1,Vd,-2,Td]]];of.prototype.h=$d([0,Zd,-2,Sd,-16,[0,Ud,Sd,Zd],Td,Zd,Sd,Td]);function qf(a){this.j=L(a,void 0,void 0,2048)}x(qf,S);qf.prototype.h=$d([0,Sd,Zd]);function rf(){};function sf(){this.domain="pagead2.googlesyndication.com";this.path="/pagead/gen_204?id=";this.g=Math.random()}function tf(){var a=ff,b=window.google_srt;b>=0&&b<=1&&(a.g=b)}function gf(a,b,c,d,e){if(((d===void 0?0:d)?a.g:Math.random())<(e||.01))try{if(c instanceof We)var f=c;else f=new We,ae(c,function(h,k){var l=f,m=l.l++;h=Xe(k,h);l.g.push(m);l.h[m]=h});var g=$e(f,a.domain,a.path+b+"&");g&&Fe(A,g)}catch(h){}};var ff,uf,ef=new Se(1,window);(function(a){ff=a!=null?a:new sf;typeof window.google_srt!=="number"&&(window.google_srt=Math.random());tf();uf=new df;uf.i=function(){};uf.l=!0;window.document.readyState==="complete"?window.google_measure_js_timing||ef.B():ef.h&&De(window,"load",function(){window.google_measure_js_timing||ef.B()})})();function vf(a,b){return uf.T(a,b)};function wf(a){this.j=L(a,void 0,void 0,2048)}x(wf,S);wf.prototype.h=$d([0,Wd,pf]);var xf=ta(["https://pagead2.googlesyndication.com/pagead/js/err_rep.js"]);function yf(){var a=a===void 0?"jserror":a;var b=b===void 0?.01:b;var c=c===void 0?le(xf):c;this.h=a;this.i=b;this.l=c} +yf.prototype.g=function(a,b,c,d){c=c===void 0?this.i:c;d=d===void 0?this.h:d;if(Math.random()>c)return!1;b.error&&b.meta&&b.id||(b=new Ge(b,{context:a,id:d}));A.google_js_errors=A.google_js_errors||[];A.google_js_errors.push(b);if(!A.error_rep_loaded){b=A.document;a=me("SCRIPT",b);c=this.l;if(c instanceof je)c=c.g;else throw Error("");a.src=c;var e;c=a.ownerDocument;c=c===void 0?document:c;var f;c=(f=(e=c).querySelector)==null?void 0:f.call(e,"script[nonce]");(e=c==null?"":c.nonce||c.getAttribute("nonce")|| +"")&&a.setAttribute("nonce",e);(e=b.getElementsByTagName("script")[0])&&e.parentNode&&e.parentNode.insertBefore(a,e);A.error_rep_loaded=!0}return!1};yf.prototype.H=function(a,b){try{return b()}catch(c){if(!this.g(a,c,this.i,this.h))throw c;}};yf.prototype.T=function(a,b){var c=this;return function(){var d=wa.apply(0,arguments);return c.H(a,function(){return b.apply(void 0,d)})}};function zf(a){var b;a.visibilityState?b="visibilitychange":a.mozVisibilityState?b="mozvisibilitychange":a.webkitVisibilityState&&(b="webkitvisibilitychange");return b};function Af(a){this.j=L(a,void 0,void 0,2048)}x(Af,S);function Bf(a){this.j=L(a,void 0,void 0,2048)}x(Bf,S);Bf.prototype.getCorrelator=function(){var a=a===void 0?Lc:a;var b=Ma?Mc(this,1,void 0,qc):qc(Mc(this,1));return b!=null?b:a};Bf.prototype.setCorrelator=function(a){return R(this,1,a)};function Cf(a){this.j=L(a,void 0,void 0,2048)}x(Cf,S);function Df(a){return a._google_rum_ns_=a._google_rum_ns_||{}}function Ef(a){a=Df(a);return a.pq=a.pq||[]};function Ff(){if(!A._google_rum_ns_)return!1;var a=Df(A);return!(!a.raf||!a.ric)}function Gf(){var a=Df(A);a.raf=a.raf||[];a.ric=a.ric||[];return{la:a.raf,ma:a.ric}};function Hf(a,b,c){ae(b,function(d,e){var f=c&&c[e];!d&&d!==0||f||(a+="&"+encodeURIComponent(e)+"="+encodeURIComponent(String(d)),c&&(c[e]=!0))});return a} +function If(a,b,c,d,e,f,g,h){function k(){var m=wa.apply(0,arguments)[0],n=m[0];m=m[1];var p=n.length+m.length+2;l.v+l.i+p>8E3&&Jf(l);l.J.push([n,m]);l.i+=p;l.v+l.i>=6E3&&Jf(l);return 0}f=f===void 0?Infinity:f;g=g===void 0?!1:g;Se.call(this,a,h);var l=this;this.U=b;this.domain=c;this.path=d;this.V=e;this.C=0;this.D={};this.K={};this.I=[];this.m={};this.i=0;this.J=[];this.N=f;a=this.g.navigator;this.M=!(this.domain!=="csi.gstatic.com"||!a||!a.sendBeacon);this.g.performance&&this.g.performance.now|| +V(this,"dat",1);a&&a.deviceMemory&&V(this,"dmc",a.deviceMemory);this.g===this.g.top&&V(this,"top",1);this.W=!g;this.O=function(){l.g.setTimeout(function(){Jf(l)},1100)};this.P=function(){for(var m=y(l.I),n=m.next();!n.done;n=m.next()){n=n.value;try{n()}catch(C){}}m=l.g;var p=p===void 0?{}:p;typeof window.CustomEvent==="function"?n=new CustomEvent("rum_blp",p):(n=document.createEvent("CustomEvent"),n.initCustomEvent("rum_blp",!!p.bubbles,!!p.cancelable,p.detail));m.dispatchEvent(n);Jf(l)};this.L=fe(function(){Jf(l)}); +this.X=function(){var m=l.g.document;(m.hidden!=null?m.hidden:m.mozHidden!=null?m.mozHidden:m.webkitHidden!=null&&m.webkitHidden)&&l.L()};this.G=this.g.setTimeout(function(){Jf(l)},5E3);this.v=b.length+c.length+d.length+e.length+3;Ua(this.l,function(m){Kf(l,m)});b=Ef(this.g);Ua(b,function(m){return k(m)});b.length=0;b.push=k;V(this,"puid",(this.C+1).toString(36)+"~"+Date.now().toString(36));Lf(this)}x(If,Se);function Mf(a,b){a.I.push(b)} +function Lf(a){a.g.document.readyState==="complete"?a.g.setTimeout(function(){Jf(a)},0):De(a.g,"load",a.O);var b=zf(a.g.document);typeof b!=="undefined"&&De(a.g,b,a.X);De(a.g,"pagehide",a.P)}function V(a,b,c){c=String(c);a.v=a.D[b]!=null?a.v+(c.length-a.D[b].length):a.v+(b.length+c.length+2);a.D[b]=c}function Nf(a,b){var c="ec="+b;a.K[c]||(Of(a,"ec",b,!1),c.length<1E3&&(a.K[c]=!0))} +function Of(a,b,c,d,e){e=e===void 0?"":e;var f=a.m[b]==null?b.length+c.length+2:d?c.length+(e===void 0?"":e).length:c.length-a.m[b].length;a.v+a.i+f>8E3&&(Jf(a),f=b.length+c.length+2);a.m[b]=d&&a.m[b]!=null?a.m[b]+((e===void 0?"":e)+c):c;a.i+=f;a.v+a.i>=6E3&&Jf(a)}function Jf(a){if(a.h&&a.W){try{a.i&&(a.sendBeacon(a.m),a.C===a.N&&a.B())}catch(b){(new yf).g(358,b)}a.m={};a.i=0;a.l.length=0;a.g.clearTimeout(a.G);a.G=0}} +function Pf(a,b){var c=a.U+"//"+a.domain+a.path+a.V,d={};c=Hf(c,a.D,d);c=Hf(c,b,d);b=a.g;b.google_timing_params&&(c=Hf(c,b.google_timing_params,d),b.google_timing_params=void 0);Ua(a.J,function(e){var f=y(e);e=f.next().value;f=f.next().value;var g={};c=Hf(c,(g[e]=f,g))});a.J.length=0;return c} +If.prototype.sendBeacon=function(a){this.C++;a=Pf(this,a);var b=!1;try{b=!!(this.M&&this.g.navigator&&this.g.navigator.sendBeacon(a,null))}catch(c){this.M=!1}b||Fe(this.g,a);V(this,"puid",(this.C+1).toString(36)+"~"+Date.now().toString(36))};function Qf(a,b,c,d,e){Of(a,"met."+b,c,d===void 0?!1:d,e===void 0?"~":e)}function Rf(a,b){var c=""+a;ae(b,function(d,e){d!=null&&(c+="."+e+"_"+d)});return c}function Sf(a,b,c){c=Rf(b,c);var d={};b=(d["met."+b]=c,d);a.sendBeacon(b)} +function Kf(a,b){var c="met."+b.type,d=typeof b.value==="number"?Math.round(b.value).toString(36):b.value,e=Math.round(b.duration);b=b.label+(b.slotId!=null?"_"+b.slotId:"")+("."+d)+(e>0?"_"+e.toString(36):"")+(b.taskId!=null?"__"+Math.round(b.taskId).toString(36):"");Of(a,c,b,!0,"~")}If.prototype.F=function(a){this.h&&this.C<this.N&&(Se.prototype.F.call(this,a),Kf(this,a))}; +If.prototype.B=function(){Se.prototype.B.call(this);this.g.clearTimeout(this.G);this.i=this.G=0;this.m={};se(this.K);se(this.D);Ee(this.g,"load",this.O);Ee(this.g,"pagehide",this.P)};function Tf(a){var b=4;b===void 0&&(b=0);lb();b=eb[b];for(var c=Array(Math.floor(a.length/3)),d=b[64]||"",e=0,f=0;e<a.length-2;e+=3){var g=a[e],h=a[e+1],k=a[e+2],l=b[g>>2];g=b[(g&3)<<4|h>>4];h=b[(h&15)<<2|k>>6];k=b[k&63];c[f++]=l+g+h+k}l=0;k=d;switch(a.length-e){case 2:l=a[e+1],k=b[(l&15)<<2]||d;case 1:a=a[e],c[f]=b[a>>2]+b[(a&3)<<4|l>>4]+k+d}return c.join("")};var Uf={self:1,"same-origin-ancestor":2,"same-origin-descendant":3,"same-origin":4,"cross-origin-ancestor":5,"cross-origin-descendant":6,"cross-origin-unreachable":7,"multiple-contexts":8},Vf={script:1,layout:2},Wf={iframe:1,embed:2,object:3};function Xf(a){var b=new jf;hd(b,1,Uf[a.name]);Ua(a.attribution,function(c){var d=new hf;hd(d,1,Vf[c.name]);hd(d,2,Wf[c.containerType]);typeof c.containerId==="string"&&fd(d,6,c.containerId.lastIndexOf("google_ads_iframe",0)==0);bd(b,2,hf,d)});return b} +function Yf(a,b){b=Tf(b.h());var c={};Sf(a,6,(c[1]=b,c))} +function Zf(a,b){if(b.PerformanceLongTaskTiming&&b.PerformanceObserver){var c=0;(new b.PerformanceObserver(vf(246,function(d,e){var f=new wf;Ua(d.getEntries(),function(g){var h=new kf;R(h,3,Math.round(g.startTime));R(h,4,Math.round(g.duration));g=Xf(g);g=$c(g);a:{var k=g;Jc(h);var l=h.j,m=l[E]|0;if(k==null){var n=Vc(l);if(Wc(n,l,m)===5)n.set(Xc,0);else break a}else{n=Vc(l);var p=Wc(n,l,m);p!==5&&(p&&(m=M(l,m,p)),n.set(Xc,5))}M(l,m,5,k)}g&&!I(g)&&Kc(h.j);bd(f,1,kf,h)});Yf(a,f);++c>=10&&e.disconnect()}))).observe({type:"longtask", +buffered:!0})}};function $f(a){this.j=L(a,void 0,void 0,2048)}x($f,S);var ag=[0,Vd,Sd];function bg(a){this.j=L(a,void 0,void 0,2048)}x(bg,S);var cg=function(a){return function(b){return Pd(b,a)}}([0,Vd,Td,Wd,ag,Sd]);function dg(a){var b=A;b=b===void 0?A:b;this.l=a;this.g=b;this.h=0;var c;this.i=((c=this.g.navigator)==null?void 0:c.sendBeacon)!=null} +function eg(a,b,c){c=c===void 0?0:c;var d=a.g!==a.g.top,e=b.slice(a.h);b=e.splice(0,250-a.h);if(d&&a.i&&b){d=new bg;d=gd(d,1,a.l);e=fd(d,2,!!e.length);d=b;Jc(e);var f=e.j,g=f[E]|0;if(d==null)M(f,g,3);else{for(var h=d===Ab?7:d[E]|0,k=h,l=Tc(h),m=l||Object.isFrozen(d),n=!0,p=!0,C=0;C<d.length;C++){var v=d[C];l||(v=I(v),n&&(n=!v),p&&(p=v))}l||(h=n?13:5,h=p?h&-4097:h|4096);m&&h===k||(d=$b(d),k=0,h=Rc(h,g));h!==k&&F(d,h);g=M(f,g,3,d);2&h||!(4096&h||16&h)||Kc(f,g)}c=R(e,4,c);c=Tf(cg(c));try{var D;a.i&& +((D=a.g.navigator)==null||D.sendBeacon("https://pagead2.googlesyndication.com/pagead/gen_204?id=urind",c))}catch(T){a.i=!1}a.h+=b.length}};function fg(a){var b=a.position;a=a.timestamp;return Math.round(b).toString(36)+"."+Math.round(a).toString(36)}function gg(a){var b=this;this.i=-1;this.l=-Infinity;this.g=[];this.h=a;this.m=0;this.B=vf(456,function(){return hg(b)});this.v=function(){return ig(b)}}gg.prototype.install=function(){A.performance&&(hg(this),De(A,"scroll",this.B,{passive:!0}),Mf(this.h,this.v))}; +function hg(a){var b=A.pageYOffset||0,c=Oe()||0;if(Math.abs(b-a.i)>100||c-a.l>200)a.i=b,a.l=c,a.g.push({position:b,timestamp:c})>=400&&(ig(a),a.m>=8&&(Ee(A,"scroll",a.B),b=a.h.I,a=Ta(b,a.v),a>=0&&Array.prototype.splice.call(b,a,1)))}function ig(a){a.g.length&&(Qf(a.h,12,Wa(a.g,fg).join("~")),a.g=[],a.m++)};function jg(a){return Sb(a)?Number(a):String(a)};var kg=void 0;kg=kg===void 0?A:kg;var lg=kg.context||kg.AMP_CONTEXT_DATA;if(!lg)try{lg=kg.parent.context||kg.parent.AMP_CONTEXT_DATA}catch(a){}var mg,ng,og=!!(((mg=lg)==null?0:mg.pageViewId)&&((ng=lg)==null?0:ng.canonicalUrl)&&lg)&&A!==A.top;function pg(a){var b;a=((b=a===void 0?null:a)!=null?b:window).googletag;return(a==null?0:a.apiReady)?a:void 0};function qg(a){var b=pg(a);return b?Va(Wa(b.pubads().getSlots(),function(c){return a.document.getElementById(c.getSlotElementId())}),function(c){return c!=null}):null}function W(a,b){a=a.document.querySelectorAll(b);b=a.length;if(b>0){for(var c=Array(b),d=0;d<b;d++)c[d]=a[d];a=c}else a=[];return a}function rg(a){return a.filter(function(b){return!b.querySelector('[data-google-ad-efd="true"]')})} +function sg(a){var b=[];a=y(a);for(var c=a.next();!c.done;c=a.next()){c=c.value;for(var d=!0,e=0;e<b.length;e++){var f=b[e];if(f.contains(c)){d=!1;break}if(c.contains(f)){d=!1;b[e]=c;break}}d&&b.push(c)}return b};function tg(a){a=a.document;var b={};a&&(b=a.compatMode=="CSS1Compat"?a.documentElement:a.body);return b||{}}function ug(a){var b;return(b=tg(a).clientWidth)!=null?b:void 0};function vg(a,b){this.i=[];this.h=a;this.g=b} +function wg(a,b){var c=(Ja&&Oa?Oa.mobile:!(Ja&&Oa?!Oa.mobile&&(B("iPad")||B("Android")||B("Silk")):B("iPad")||B("Android")&&!B("Mobile")||B("Silk"))&&(B("iPod")||B("iPhone")||B("Android")||B("IEMobile")))&&!(ug(a.h)>=900),d=Va([],function(f){return Ta(a.i,f)>=0}).join(","),e;b={wpc:"",su:b,eid:d,doc:(e=a.g.ga)!=null?e:null,pg_h:X(a.g.va),pg_w:X(a.g.xa),pg_hs:X(a.g.wa),c:X(a.g.qa),aa_c:X(a.g.aa),av_h:X(a.g.ca),av_w:X(a.g.da),av_a:X(a.g.ba),s:X(a.g.ua),all_s:X(a.g.ta),b:X(a.g.sa),all_b:X(a.g.ra),d:X(a.g.fa), +all_d:X(a.g.ea),ard:X(a.g.Z),all_ard:X(a.g.Y),pd_h:X(a.g.ya),dt:c?"m":"d"};c={};e=y(r(Object,"keys").call(Object,b));for(d=e.next();!d.done;d=e.next())d=d.value,b[d]!==null&&(c[d]=b[d]);return c}function xg(a){return pe.apply(null,Va(a,function(b){return b>0}))||null}function yg(a,b){return a<=0?null:oe.apply(null,b)/a} +function zg(a){for(var b=Infinity,c=0;c<a.length-1;c++)for(var d=c+1;d<a.length;d++){var e=a[c],f=a[d];e=Math.max(Math.max(0,e.left-f.right,f.left-e.right),Math.max(0,e.top-f.bottom,f.top-e.bottom));e>0&&(b=Math.min(e,b))}return b!==Infinity?b:null}function X(a){return a==null?null:r(Number,"isInteger").call(Number,a)?a.toString():a.toFixed(3)};function Ag(a,b){var c=navigator;c=c.getBattery&&c.getBattery();c!=null&&c.then?c.then(function(d){var e=d.level,f=d.charging;setTimeout(function(){b(e*100|0,d.level*100|0,f||d.charging)},a)}):b()};function Bg(a){var b=a.length;if(b===0)return 0;for(var c=305419896,d=0;d<b;d++)c^=(c<<5)+(c>>2)+a.charCodeAt(d)&4294967295;return c>0?c:4294967296+c};var Cg=/^.+\.((googlesyndication|googletagservices)\.com|doubleclick\.net)$/,Dg=/^(aswift_\d+|google_ads_iframe_.+)$/,Eg=/^div-gpt-ad-.+$/,Fg=["ZGl2LnRhYm9vbGE=","ZGl2Lk9VVEJSQUlO"];function Gg(a){if(!a)return"";var b=Math.floor(Math.random()*a.length);return b.toString(36)+encodeURIComponent(a.charAt(b))+"."+Bg(a).toString(36)}function Hg(a){return(a=cf(Ia(a).match(bf)[3]||null))?a.toLowerCase():""}function Ig(a){return a.offsetWidth>=10&&a.offsetHeight>=10} +function we(a){return a&&a.nodeType===1&&a.nodeName==="DIV"?Eg.test(a.id)||a.hasAttribute("data-google-query-id"):!1} +function Jg(a){var b=[];if(!a.body)return b;var c=a.body;a=c.getElementsByTagName("script");for(var d=a.length,e=0;e<d;e++){var f=a[e],g=f.src;g&&(f=(f.nextElementSibling!==void 0?f.nextElementSibling:te(f.nextSibling,!0))||f.parentElement||null)&&f.nodeName==="DIV"&&Ig(f)&&(g=Hg(g))&&!Cg.test(g)&&b.push(new Kg(f,g))}if(!c.querySelectorAll)return b;Ua(Fg,function(h){for(var k=c.querySelectorAll(jb(h)),l=k.length,m=0;m<l;m++){var n=k[m];Ig(n)&&b.push(new Kg(n,h))}});return b} +function Kg(a,b,c){this.id=b;this.g=c===void 0?null:c;var d=ue(a);b=new qe(0,0);if(a!=(d?ue(d):document).documentElement){c=ze(a);var e=(d?new xe(ue(d)):Ca||(Ca=new xe)).g;d=e.scrollingElement?e.scrollingElement:cb||e.compatMode!="CSS1Compat"?e.body||e.documentElement:e.documentElement;e=e.defaultView;d=new qe((e==null?void 0:e.pageXOffset)||d.scrollLeft,(e==null?void 0:e.pageYOffset)||d.scrollTop);b.x=c.left+d.x;b.y=c.top+d.y}b:{c=ue(a);if(c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a, +null))){c=c.display||c.getPropertyValue("display")||"";break b}c=""}c||(c=a.currentStyle?a.currentStyle.display:null);if((c||a.style&&a.style.display)!="none")a=Ae(a);else{c=a.style;d=c.display;e=c.visibility;var f=c.position;c.visibility="hidden";c.position="absolute";c.display="inline";a=Ae(a);c.display=d;c.position=f;c.visibility=e}b=new ye(b.x,b.y,a.width,a.height);this.top=b.top;this.left=b.left;this.width=b.width;this.height=b.height} +function Lg(a){a=de(a);if(!a)return null;var b=a.document;a=Jg(b);var c=[];Ya(c,b.getElementsByTagName("iframe"));for(b=0;b<Math.min(c.length,50);b++){var d=c[b],e=d.src?Ia(d.src):"",f=d.id||d.name||"";if(!Dg.test(f))try{var g=d.contentDocument||d.contentWindow.document;if(e&&d.src!=="about:blank")Ya(a,Jg(g)),Ya(c,g.getElementsByTagName("iframe"));else{var h=null,k=d.previousElementSibling!==void 0?d.previousElementSibling:te(d.previousSibling,!1);if(k&&k.nodeName==="SCRIPT"&&k.src){var l=Hg(k.src); +h=Cg.test(l)?null:l}((h=h||f)||!ve(d))&&Ig(d)&&a.push(new Kg(d,h))}}catch(n){h=Hg(e),e=(e=cf(e.match(bf)[5]||null))&&e.charAt(0)==="/"?e.split("/",2)[1]:"",Ig(d)&&!Cg.test(h)&&a.push(new Kg(d,h||f,e))}}Za(a,function(n,p){return n.top!==p.top?n.top-p.top:n.left-p.left});var m=null;return Va(a,function(n){if(m!=null&&n.top+n.height<=m.top+m.height&&n.left+n.width<=m.left+m.width)return!1;m=n;return!0})};var Mg=!1;function Ng(a,b,c){function d(m){Mg&&(b.push(m-f),f=m,l&&(c.push(g||0),h||(g=0,h=l(k))),e(d))}if(!Mg){Mg=!0;var e=a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.msRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;if(ne(e)){var f,g,h,k,l=a.requestIdleCallback;l&&(k=function(m){g=m.timeRemaining();h=0});e(function(m){f=m;l&&(h=l(k));e(d)})}}};function Og(a){var b=0,c=0,d,e,f;a=(f=(d=a.performance)==null?void 0:(e=d.getEntriesByType)==null?void 0:e.call(d,"paint"))!=null?f:[];d=y(a);for(e=d.next();!e.done;e=d.next())switch(e=e.value,f=e.startTime,e.name){case "first-paint":b=f;break;case "first-contentful-paint":c=f}return{ka:b,ja:c}};function Pg(a){return new RegExp("/pagead/js/(r\\d+|dev)/r\\d+/(.*/)?"+a+"(_fy20\\d\\d)?\\.js")} +var Y={},Qg={},Z={},Rg={},Sg={},Tg={},Ug={},Vg={},Wg={},Xg={},Yg={},Zg=[{u:RegExp("^https?://((tpc|pagead2)\\.googlesyndication\\.com|static\\.googleadsserving\\.cn)/pagead/"),resources:(Y[1]=/adsbygoogle\.js/,Y[83]=/adsbygoogle_direct\.js/,Y[2]=/show_ads\.js/,Y[3]=/show_ads_impl(_with_ama)?(_fy20\d\d)?\.js/,Y[21]=/js\/r\d+\/r\d+\/osd\.js/,Y[22]=/\/osd\.js/,Y[7]=/activeview\/osd_listener\.js/,Y[8]=/lidar\.js/,Y[4]=/imgad\?id=/,Y[24]=/js\/(r\d+|dev)\/r\d+\/rum\.js/,Y[25]=/js\/rum\.js/,Y[33]=/\/pagead\/adview\?ai=/, +Y[60]=/\/pagead\/ppub_config/,Y[67]=/pagead\/managed\/js\/gpt\/m\d+\/pubads_impl(_fy\d+)?\.js/,Y[82]=/\/pagead\/managed\/dict\//,Y[10]=Pg("m_js_controller"),Y[9]=Pg("abg_lite"),Y[65]=Pg("spam_signals_bundle"),Y[66]=Pg("bgl"),Y[30]=Pg("window_focus"),Y[75]=Pg("interstitial_ad_frame"),Y[76]=Pg("fullscreen_api_adapter"),Y),o:28},{u:/^https?:\/\/(tpc|pagead2)\.googlesyndication\.com\//,resources:(Qg[4]=/pageadimg(\/imgad)?\?id=/,Qg[23]=/(daca_images\/)?simgad\/\d+/,Qg[29]=/icore_images\/\d+/,Qg[11]=/pub-config\/r\d+\/ca-pub-\d+\.js/, +Qg[16]=/\/safeframe\/\d+-\d+-\d+\/html\/container\.html/,Qg[17]=/\/safeframe\/\d+-\d+-\d+\/js\/ext\.js/,Qg[31]=/\/sadbundle\//,Qg[32]=/(\/pcs)?\/activeview\?(xai|avi)=/,Qg[80]=/\/tag\/js\/gpt\.js/,Qg),o:39},{u:/^https?:\/\/\w+\.g\.doubleclick\.net/,resources:(Z[59]=/\/tag\/js\/gpt\.js/,Z[14]=/\/gpt\/pubads_impl_\d+\.js/,Z[67]=/pagead\/managed\/js\/gpt\/m\d+\/pubads_impl(_fy\d+)?\.js/,Z[43]=/\/gpt\/pubads_impl_core_\d+\.js/,Z[15]=/\/gampad\/ads\?/,Z[34]=/\/pcs\/view\?xai=/,Z[36]=/^https?:\/\/cm\.g\./, +Z[5]=/pagead\/ads\?/,Z[12]=/pagead\/html\/.*\/zrt_lookup\.html/,Z[33]=/\/pagead\/adview\?ai=/,Z[61]=/\/pagead\/managed\/js\/config_2_5__\d+\.json\?domain=/,Z[62]=/\/pagead\/managed\/js\/config_12_5__\d+\.json\?domain=/,Z[60]=/\/pagead\/ppub_config/,Z[70]=/\/td\/sts/,Z[71]=/\/td\/sjs/,Z[72]=/\/td\/bts/,Z[73]=/\/td\/bjs/,Z[74]=/\/td\/adfetch\/gda\?/,Z[82]=/\/pagead\/managed\/dict\//,Z),o:40},{u:/^https?:\/\/www\.googletagservices\.com/,resources:(Rg[13]=/\/tag\/js\/gpt\.js/,Rg[37]=/\/dcmads\.js/,Rg[38]= +/\/dcm\/impl_v\d+\.js/,Rg[77]=/\/activeview\/js\/current\/rx_lidar\.js/,Rg[81]=/\/activeview\/js\/current\/ufs_web_display\.js/,Rg),o:42},{u:/^https?:\/\/fonts\.googleapis\.com\/css/,resources:(Sg[18]=/[?&]family=/,Sg),o:27},{u:/^https?:\/\/fonts\.gstatic\.com/,resources:(Tg[19]=/\/s\//,Tg[20]=/\/l\//,Tg),o:27},{u:/^https:\/\/[\w.]+.2mdn.net/,resources:(Ug[31]=/\/sadbundle\//,Ug),o:41},{u:/^https?:\/\/cdn\.ampproject\.org/,resources:(Vg[49]=/\/rtv\/\d{15,20}\/amp4ads-host-v0\.js\b/,Vg[50]=/\.org\/amp4ads-host-v0\.js\b/, +Vg),o:51},{u:/^https?:\/\/imasdk.googleapis.com/,resources:(Wg[54]=/js\/sdkloader\/ima3.js/,Wg[55]=/js\/core\/bridge3.*html/,Wg[56]=/js\/sdkloader\/loader.js/,Wg[57]=/js\/sdkloader\/vpaid_adapter.js/,Wg),o:58},{u:/^https?:\/\/fundingchoicesmessages\.google\.com/,resources:(Xg[64]=/\/i\/.*\?ers=\d.*/,Xg),o:63},{u:/^https?:\/\/.*\.googlevideo\.com/,resources:(Yg[78]=/\/videoplayback/,Yg),o:79},{u:/./,resources:{},o:27}],$g={},ah=[{u:/^https?:\/\//,resources:($g[26]=function(a){return og&&!/^https:\/\/d-\d+\.ampproject\.net\/\d+\/frame\.html$/.test(a)}, +$g),o:27}];function bh(a){switch(a){case "audio":return 15;case "beacon":return 1;case "css":return 2;case "fetch":return 4;case "iframe":return 5;case "img":return 6;case "link":return 7;case "navigation":return 8;case "object":return 9;case "script":return 10;case "subdocument":return 11;case "svg":return 12;case "track":return 16;case "video":return 14;case "xmlhttprequest":return 13;default:return 0}} +var ch={woff:1,woff2:2,eot:3,ttf:4},dh=/^https?:\/\/[^/?#]*\b(google(adservices|tag(manager|services)|apis|usercontent|syndication|video)?|doubleclick|gstatic|2mdn|cdn.ampproject)\./,eh={},fh=(eh[1]=!0,eh[4]=!0,eh[13]=!0,eh); +function gh(a,b,c,d){d=d===void 0?!1:d;var e=dh.test(a)?1:0,f=e!==1,g=Xa(f?ah:Zg,function(h){return h.u.test(a)});if(!g)return null;g=be(g.resources,function(h){return typeof h==="function"?h(a):h.test(a)})||g.o;return!g||f&&b!==2&&fh[c]&&(!d||c!==13)?null:{ha:e,id:Number(g)}} +function hh(a,b,c,d,e,f){var g=bh(a.initiatorType),h=gh((f===void 0?"":f)||a.name,d,g,e);if(h){d=b.push;f=h.id;h=h.ha;var k=new of;k=hd(k,1,f);k=hd(k,3,h);g=hd(k,2,g);g=R(g,4,Math.round(a.startTime));g=R(g,7,Math.round(a.duration));k=a.name;try{if(e){e=125;var l=/[\?#;]/.exec(k);l&&l.index!==-1&&l.index<e&&(e=l.index);R(g,24,Bg(k.substr(0,e)))}}catch(D){}if(h===1||f===26){l=R(g,5,Math.round(a.fetchStart));R(l,6,Math.round(a.responseEnd));b:{e=a.name;f=ed(g,1);l=new lf;switch(f){case 18:if(e=e.match(/[?&]family=([^&]+)/))if(e= +A.decodeURIComponent(e[1]).split("|"),Jc(l),f=l.j,h=f[E]|0,e==null)M(f,h,1);else{var m=k=e===Ab?7:e[E]|0,n=Tc(k),p=n||Object.isFrozen(e);n||(k=0);p||(e=$b(e),m=0,k=Rc(k,h),p=!1);k|=5;n=4&k?512&k?512:1024&k?1024:0:void 0;k|=n!=null?n:Ma?1024:0;for(n=0;n<e.length;n++){var C=e[n],v=sc(C);r(Object,"is").call(Object,C,v)||(p&&(e=$b(e),m=0,k=Rc(k,h),p=!1),e[n]=v)}k!==m&&(p&&(e=$b(e),k=Rc(k,h)),F(e,k));M(f,h,1,e)}break;case 19:if(e=e.match(/\/s\/(\w+)\/v(\d+)\/[^.\/]+\.(\w+)$/))f=A.parseInt(e[2],10),f=R(l, +2,f),f=hd(f,3,ch[e[3]]||0),e=e[1],Jc(f),Oc(f,1,tc,2,!0).push(sc(e));break;case 20:if(f=e.match(/[?&]skey=([^&]+)/))f=f[1],Jc(l),Oc(l,1,tc,2,!0).push(sc(f));if(e=e.match(/[?&]v=v(\d+)/))e=A.parseInt(e[1],10),R(l,2,e);break;default:break b}ad(g,21,l)}a.responseStart&&(fd(g,22,!0),a.domainLookupStart!==a.domainLookupEnd&&(l=R(g,8,Math.round(a.domainLookupStart)),R(l,9,Math.round(a.domainLookupEnd))),a.connectStart!==a.connectEnd&&(l=R(g,10,Math.round(a.connectStart)),R(l,11,Math.round(a.connectEnd)), +a.secureConnectionStart&&R(g,12,Math.round(a.secureConnectionStart))),l=R(g,13,Math.round(a.requestStart)),R(l,14,Math.round(a.responseStart)),a.transferSize!==void 0&&(l=R(g,15,a.transferSize),l=R(l,17,a.decodedBodySize||0),R(l,16,a.encodedBodySize||0),a.transferSize>0?hd(g,23,a.transferSize>(a.encodedBodySize||0)?3:2):hd(g,23,1)),a.redirectStart&&(l=R(g,18,Math.round(a.redirectStart)),R(l,19,Math.round(a.redirectEnd))),c&&window.performance.timing&&R(g,20,c))}d.call(b,g)}} +function ih(a){return a.performance&&a.performance.timing&&a!==A&&A.performance!=null&&A.performance.timing!=null?a.performance.timing.navigationStart-A.performance.timing.navigationStart:0}function jh(a,b,c,d,e){if(d&&d.length){var f=[],g=!1;d=y(d);for(var h=d.next();!h.done;h=d.next())h=h.value,h.entryType==="resource"?hh(h,f,ih(b),c,e):h.entryType!=="navigation"||g||(hh(h,f,ih(b),c,e,b.location?b.location.href:""),g=!0);b=Wa(f,function(k){return Tf(k.h())}).join("~");Qf(a,7,b,!0)}} +function kh(a){return Wa(a.performance&&a.performance.getEntriesByType?a.performance.getEntriesByType("resource"):[],function(b){var c=(b&&b.name||"").replace(/\?.*$/,""),d=new $f;c=gd(d,1,c);return R(c,2,b.startTime)})};var lh=window==window.top?32:16,mh={unloadEventStart:2,unloadEventEnd:3,redirectStart:4,redirectEnd:5,fetchStart:6,domainLookupStart:7,domainLookupEnd:8,connectStart:9,connectEnd:10,secureConnectionStart:11,requestStart:12,responseStart:13,responseEnd:14,domLoading:15,domInteractive:16,domContentLoadedEventStart:17,domContentLoadedEventEnd:18,domComplete:19,loadEventStart:20,loadEventEnd:21};function nh(a){return(a=Zc(a,Bf,1))?ed(a,2):0} +function oh(a){var b=Zc(a,Af,2);b||(b=new Af,ad(a,2,b));nh(a)==2&&(a=fd(b,7,!0),a=fd(a,9,!0),fd(a,10,!0));return b}function ph(a,b){ed(b,2)!==2||Df(A).chp||V(a,"chm",1);jg(b.getCorrelator())&&V(a,"c",jg(b.getCorrelator()));dd(b,5)&&V(a,"e",dd(b,5));V(a,"ctx",ed(b,2));V(a,"gqid",dd(b,3));V(a,"qqid",dd(b,4))} +function qh(a){var b=new Cf(A.google_rum_config||null),c=oh(b),d=Oc(c,15,ic,void 0===Fb?2:4),e=Zc(b,Bf,1)||new Bf;d.length&&gd(e,5,d.join());ph(a,e);d=new dg(dd(e,4));if(e=A.google_js_reporting_queue){var f=function(g){a.F(g);Te(g)};e.push=f;Ua(e,f);e.length=0}Mf(a,function(){var g=Oe();g&&Ue(a,"24",1,g,0)});rh(A,a,b,c,d);nh(b)===2&&sh()&&rh(A.parent,a,b,c,d)}function sh(){var a=A.parent;return ce(a)&&a!==a.top&&a.document.querySelector("iframe#ad_iframe")!=null} +function rh(a,b,c,d,e){(N(d,12)||N(d,9)&&Math.random()<.1)&&Zf(b,a);var f=nh(c),g=null;if(N(d,7)&&a.PerformanceObserver){g=new a.PerformanceObserver(function(h){jh(b,a,f,h==null?void 0:h.getEntries(),N(d,13))});try{try{g.observe({type:"resource",buffered:!0}),g.observe({type:"navigation",buffered:!0})}catch(h){g.observe({entryTypes:["resource","navigation"]})}Mf(b,function(){var h,k;jh(b,a,f,(k=(h=g).takeRecords)==null?void 0:k.call(h),N(d,13))});f==1&&th(a,b,d,f,g)}catch(h){}}Mf(b,function(){if(N(d, +18)&&N(d,19)){var h;eg(e,kh(a),(h=Oe())!=null?h:0)}else N(d,18)&&eg(e,kh(a))});a==a.top&&N(d,14)&&(new gg(b)).install();uh(b,a,d,f,g,e)} +function uh(a,b,c,d,e,f){var g=vf(113,function(){N(c,10)&&vh(a,b);wh(a,b);xh(a,b,c,d,e,f);if(d==1&&N(c,16)){var h=tg(b);h=h.scrollHeight===tg(b).clientHeight?h.offsetHeight:h.scrollHeight;var k=tg(b).scrollWidth,l=tg(b).scrollHeight,m="unknown";b&&b.document&&b.document.readyState&&(m=b.document.readyState);var n=b.pageYOffset===void 0?(b.document.documentElement||b.document.body.parentNode||b.document.body).scrollTop:b.pageYOffset,p=[],C=[],v=[],D=[],T=[],P=[],ba=[],ra=0,La=0,da=Infinity,ia=Infinity, +$a=null;var H={na:!1};var G=W(b,".google-auto-placed"),u=W(b,"ins.adsbygoogle[data-anchor-status]"),w=W(b,"ins.adsbygoogle[data-ad-format=autorelaxed]");var Q=(qg(b)||W(b,"div[id^=div-gpt-ad]")).concat(W(b,"iframe[id^=google_ads_iframe]"));var Je=W(b,"div.trc_related_container,div.OUTBRAIN,div[id^=rcjsload],div[id^=ligatusframe],div[id^=crt-],iframe[id^=cto_iframe],div[id^=yandex_], div[id^=Ya_sync],iframe[src*=adnxs],div.advertisement--appnexus,div[id^=apn-ad],div[id^=amzn-native-ad],iframe[src*=amazon-adsystem],iframe[id^=ox_],iframe[src*=openx],img[src*=openx],div[class*=adtech],div[id^=adtech],iframe[src*=adtech],div[data-content-ad-placement=true],div.wpcnt div[id^=atatags-]"), +zh=W(b,"ins.adsbygoogle-ablated-ad-slot"),Ah=W(b,"div.googlepublisherpluginad"),Bh=W(b,"html > ins.adsbygoogle"),O=[].concat.apply([],[].concat(sa(W(b,"iframe[id^=aswift_],iframe[id^=google_ads_frame]")),sa(W(b,"body ins.adsbygoogle")))),z=[];H.Ba&&(z=z.concat(W(b,"ins.adsbygoogle[data-ad-hi]")));G=y([[H.Da,G],[H.na,u],[H.Ga,w],[H.Ea,Q],[H.Ha,Je],[H.Ca,zh],[H.Fa,Ah],[H.Ia,Bh]]);for(u=G.next();!u.done;u=G.next())w=y(u.value),u=w.next().value,w=w.next().value,u===!1?z=z.concat(w):O=O.concat(w);O=sg(O); +G=sg(z);z=O.slice(0);O=y(G);for(G=O.next();!G.done;G=O.next())for(G=G.value,u=0;u<z.length;u++)(G.contains(z[u])||z[u].contains(G))&&z.splice(u,1);H=H.Aa?rg(z):z;H=y(H);for(z=H.next();!z.done;z=H.next()){z=z.value;O=z.getBoundingClientRect();G=h-(O.bottom+n);if(z.className&&z.className.indexOf("adsbygoogle-ablated-ad-slot")!=-1){w=z.getAttribute("google_element_uid");u=void 0;if(Q=b.fqjyf){if(w&&Q[w]&&(u=Q[w].LmpfC),!u)continue}else continue;a:{w=Number(u.google_ad_width);Q=Number(u.google_ad_height); +if(!(w>0&&Q>0)){b:{try{var gb=String(u.google_ad_format);if(gb&&gb.match){var hb=gb.match(/(\d+)x(\d+)/i);if(hb){var mf=parseInt(hb[1],10),nf=parseInt(hb[2],10);if(mf>0&&nf>0){var Pa={width:mf,height:nf};break b}}}}catch(Hh){}Pa=null}if(!Pa){u=null;break a}w=w>0?w:Pa.width;Q=Q>0?Q:Pa.height}u={width:w,height:Q}}u=(w=u)?w.height:0;w=w?w.width:0}else if(u=O.bottom-O.top,w=O.right-O.left,u<=1||w<=1)continue;p.push(u);v.push(w);D.push(u*w);z.className&&z.className.indexOf("google-auto-placed")!=-1?(La+= +1,z.className&&z.className.indexOf("pedestal_container")!=-1&&($a=u)):(da=Math.min(da,G),P.push(O),ra+=1,C.push(u),T.push(u*w));ia=Math.min(ia,G);ba.push(O)}da=da===Infinity?null:da;ia=ia===Infinity?null:ia;Pa=zg(P);ba=zg(ba);C=yg(h,C);gb=yg(h,p);T=yg(h*k,T);hb=yg(h*k,D);h=new vg(b,{ga:m,va:h,xa:k,wa:l,qa:ra,aa:La,ca:xg(p),da:xg(v),ba:xg(D),ua:Pa,ta:ba,sa:da,ra:ia,fa:C,ea:gb,Z:T,Y:hb,ya:$a});h=wg(h,b.location.hostname);k="R";rf.R&&rf.hasOwnProperty(k)||(k=new rf,rf.R=k);k=[];!h.eid&&k.length&&(h.eid= +k.toString());gf(ff,"ama_stats",h,!0,1)}});b.document.readyState!="complete"?De(b,"load",function(){b.setTimeout(g,0)}):g()}function wh(a,b){var c=b.google_rum_values||Df(b).rv;b.google_rum_values=void 0;Df(b).rv=void 0;if(c&&!(c.dt<0)&&(b=b.performance&&b.performance.timing)){var d=c.dt-b.navigationStart;ae(c,function(e,f){if(e!=-1&&typeof e==="number"){switch(f){case "dt":e=d;break;case "bdt":e=d-e;break;default:e=d+e}Ue(a,f,4,e)}})}} +function xh(a,b,c,d,e,f){N(c,1)&&yh(a,b);N(c,2)&&cd(c)>0&&Ch(a,cd(c));N(c,7)&&Dh(a,b,c,d,e);N(c,8)&&Math.random()<.1&&Ve(a,function(){return Eh(a,b)});N(c,18)&&eg(f,kh(b))}function Dh(a,b,c,d,e){var f;jh(a,b,d,(f=e.takeRecords)==null?void 0:f.call(e),N(c,13))} +function Fh(a,b,c){var d=Oe();if(d&&(b.length||c.length)){var e={};d=(e[3]=d.toString(36),e);b.length&&(d[1]=Wa(b,function(f){f=Math.min(Math.max(f,0),4095);return"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."[f>>6]+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."[f&63]}).join(""));c.length&&(d[2]=Wa(c,function(f){return"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."[Math.min(Math.max(f,0),63)|0]}).join(""));Qf(a,5,Rf(5,d),!0,".")}} +function Gh(a){if(Ff()){var b=Gf(),c=b.la,d=b.ma,e=vf(400,function(){c.length||d.length?(Fh(a,c,d),c.length=0,d.length=0,A.setTimeout(e,1E4)):(c.push=function(){return 0},d.push=function(){return 0})});A.setTimeout(e,1E4)}}function yh(a,b){var c=[],d=[];Ng(b,c,d);b.setTimeout(vf(400,function(){Mg=!1;Fh(a,c,d)}),1E4)}function Ch(a,b){Ag(b,function(c,d,e){if(c!=null&&d!=null&&e!=null){var f={};f[1]=b;f[2]=c;f[3]=d;f[4]=e;Sf(a,8,f)}})} +function vh(a,b){var c=b.performance&&b.performance.timing;if(c){var d=c.navigationStart;d>0&&(Ue(a,"1",1,d),ae(mh,function(f,g){g=c[g];g>0&&Ue(a,String(f),1,g-d)}));var e=Og(b);b=e.ka;e=e.ja;b&&Ue(a,"22",1,b);e&&Ue(a,"23",1,e)}} +function Eh(a,b){if(b=Lg(b))10<b.length&&(b.length=10),Nf(a,Wa(b,function(c){var d=Gg(c.id)+(c.g?"_"+Gg(c.g):""),e=Math.floor(c.top).toString(36),f=Math.floor(c.left).toString(36),g=Math.floor(c.width).toString(36);c=Math.floor(c.height).toString(36);return d+"_"+e+"_"+f+"_"+g+"_"+c}).join("~"))} +function th(a,b,c,d,e){var f=zf(a.document);f&&De(a,f,function(){var g=Oe();if(g){var h=a.document;if(h.prerendering)h=3;else{var k;h=(k={visible:1,hidden:2,prerender:3,preview:4,unloaded:5,"":0}[h.visibilityState||h.webkitVisibilityState||h.mozVisibilityState||""])!=null?k:0}k=h;if(k==1||k==2){h=new qf;g=R(h,1,Math.round(g));g=hd(g,2,k);g=Tf(g.h());if(N(c,7)){var l;jh(b,a,d,(l=e.takeRecords)==null?void 0:l.call(e),N(c,13))}Ue(b,"1",11,g);k==2&&typeof b.L==="function"&&b.L()}}})};uf.H(112,function(){var a=new If(1,"https:","csi.gstatic.com","/csi?v=2&s=pagead&action=","csi_pagead",lh);a.h=!0;qh(a);Gh(a)});}).call(this); diff --git a/view-source_https___chromestatus.com_static_dist_components.js b/view-source_https___chromestatus.com_static_dist_components.js new file mode 100644 index 0000000..5b6e82b --- /dev/null +++ b/view-source_https___chromestatus.com_static_dist_components.js @@ -0,0 +1,16665 @@ +import{FeatureNotFoundError}from"./cs-client.js";const t$5=globalThis,e$a=t$5.ShadowRoot&&(void 0===t$5.ShadyCSS||t$5.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$4=Symbol(),o$c=new WeakMap;let n$8=class{constructor(t,e,o){if(this._$cssResult$=!0,o!==s$4)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const s=this.t;if(e$a&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o$c.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$c.set(s,t))}return t}toString(){return this.cssText}};const r$a=t=>new n$8("string"==typeof t?t:t+"",void 0,s$4),i$7=(t,...e)=>{const o=1===t.length?t[0]:e.reduce((e,s,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(s)+t[o+1],t[0]);return new n$8(o,t,s$4)},S$2=(s,o)=>{if(e$a)s.adoptedStyleSheets=o.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of o){const o=document.createElement("style"),n=t$5.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=e.cssText,s.appendChild(o)}},c$4=e$a?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$a(e)})(t):t,{is:i$6,defineProperty:e$9,getOwnPropertyDescriptor:h$4,getOwnPropertyNames:r$9,getOwnPropertySymbols:o$b,getPrototypeOf:n$7}=Object,a$2=globalThis,c$3=a$2.trustedTypes,l$3=c$3?c$3.emptyScript:"",p$2=a$2.reactiveElementPolyfillSupport,d$2=t=>t,u$4={toAttribute(t,s){return s===Boolean?t=t?l$3:null:s===Object||s===Array?t=null==t?t:JSON.stringify(t):void 0,t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:+t;break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},f$3=(t,s)=>!i$6(t,s),b$1={attribute:!0,type:String,converter:u$4,reflect:!1,useDefault:!1,hasChanged:f$3};Symbol.metadata??=Symbol("metadata"),a$2.litPropertyMetadata??=new WeakMap;let y$2=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=b$1){if(s.state&&(s.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=!0),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e$9(this.prototype,t,h)}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h$4(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t}};return{get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b$1}static _$Ei(){if(!this.hasOwnProperty(d$2("elementProperties"))){const t=n$7(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}}static finalize(){if(!this.hasOwnProperty(d$2("finalized"))){if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(d$2("properties"))){const t=this.properties,s=[...r$9(t),...o$b(t)];for(const i of s)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(c$4(s))}else void 0!==s&&i.push(c$4(s));return i}static _$Eu(t,s){const i=s.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);0<t.size&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return S$2(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&!0===i.reflect){const h=(void 0===i.converter?.toAttribute?u$4:i.converter).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0===t.converter?.fromAttribute?u$4:t.converter;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null}}requestUpdate(t,s,i){if(void 0!==t){const e=this.constructor,h=this[t];if(i??=e.getPropertyOptions(t),!((i.hasChanged??f$3)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(e._$Eu(t,i))))return;this.C(t,s,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),!0!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),!0===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&(await t),!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0}const t=this.constructor.elementProperties;if(0<t.size)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];!0!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e)}}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(s)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(s)}willUpdate(){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(){return!0}update(){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(){}firstUpdated(){}};y$2.elementStyles=[],y$2.shadowRootOptions={mode:"open"},y$2[d$2("elementProperties")]=new Map,y$2[d$2("finalized")]=new Map,p$2?.({ReactiveElement:y$2}),(a$2.reactiveElementVersions??=[]).push("2.1.1");const t$4=globalThis,i$5=t$4.trustedTypes,s$3=i$5?i$5.createPolicy("lit-html",{createHTML:t=>t}):void 0,e$8="$lit$",h$3=`lit$${Math.random().toFixed(9).slice(2)}$`,o$a="?"+h$3,n$6=`<${o$a}>`,r$8=document,l$2=()=>r$8.createComment(""),c$2=t=>null===t||"object"!=typeof t&&"function"!=typeof t,a$1=Array.isArray,u$3=t=>a$1(t)||"function"==typeof t?.[Symbol.iterator],d$1="[ \t\n\f\r]",f$2=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,v$2=/-->/g,_$1=/>/g,m$2=/>|[ \n\f\r](?:([^\s"'>=/]+)([ \n\f\r]*=[ \n\f\r]*(?:[^ \n\f\r"'`<>=]|("|')|))|$)/g,p$1=/'/g,g=/"/g,$$1=/^(?:script|style|textarea|title)$/i,y$1=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),x$1=y$1(1),T$1=Symbol.for("lit-noChange"),E$1=Symbol.for("lit-nothing"),A=new WeakMap,C$1=r$8.createTreeWalker(r$8,129);function P$1(t,i){if(!a$1(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0===s$3?i:s$3.createHTML(i)}const V=(t,i)=>{const s=t.length-1,o=[];let l=2===i?"<svg>":3===i?"<math>":"",c=f$2,r;for(let i=0;i<s;i++){const s=t[i];let d=-1,y=0,a,u;for(;y<s.length&&(c.lastIndex=y,u=c.exec(s),null!==u);)y=c.lastIndex,c===f$2?"!--"===u[1]?c=v$2:void 0===u[1]?void 0===u[2]?void 0!==u[3]&&(c=m$2):($$1.test(u[2])&&(r=RegExp("</"+u[2],"g")),c=m$2):c=_$1:c===m$2?">"===u[0]?(c=r??f$2,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?m$2:"\""===u[3]?g:p$1):c===g||c===p$1?c=m$2:c===v$2||c===_$1?c=f$2:(c=m$2,r=void 0);const x=c===m$2&&t[i+1].startsWith("/>")?" ":"";l+=c===f$2?s+n$6:0<=d?(o.push(a),s.slice(0,d)+e$8+s.slice(d)+h$3+x):s+h$3+(-2===d?i:x)}return[P$1(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),o]};let N$1=class N{constructor({strings:t,_$litType$:s},n){let r;this.parts=[];let c=0,a=0;const u=t.length-1,d=this.parts,[f,v]=V(t,s);if(this.el=N.createElement(f,n),C$1.currentNode=this.el.content,2===s||3===s){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=C$1.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(e$8)){const i=v[a++],s=r.getAttribute(t).split(h$3),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:c,name:e[2],strings:s,ctor:"."===e[1]?H$1:"?"===e[1]?I$1:"@"===e[1]?L$1:k$1}),r.removeAttribute(t)}else t.startsWith(h$3)&&(d.push({type:6,index:c}),r.removeAttribute(t));if($$1.test(r.tagName)){const t=r.textContent.split(h$3),s=t.length-1;if(0<s){r.textContent=i$5?i$5.emptyScript:"";for(let i=0;i<s;i++)r.append(t[i],l$2()),C$1.nextNode(),d.push({type:2,index:++c});r.append(t[s],l$2())}}}else if(8===r.nodeType)if(r.data===o$a)d.push({type:2,index:c});else for(let t=-1;-1!==(t=r.data.indexOf(h$3,t+1));)d.push({type:7,index:c}),t+=h$3.length-1;c++}}static createElement(t){const s=r$8.createElement("template");return s.innerHTML=t,s}};function S$1(t,i,s=t,e){if(i===T$1)return i;let h=void 0===e?s._$Cl:s._$Co?.[e];const o=c$2(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(!1),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0===e?s._$Cl=h:(s._$Co??=[])[e]=h),void 0!==h&&(i=S$1(t,h._$AS(t,i.values),h,e)),i}let M$2=class{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??r$8).importNode(i,!0);C$1.currentNode=e;for(let h=C$1.nextNode(),o=0,n=0,l=s[0];void 0!==l;){if(o===l.index){let i;2===l.type?i=new R(h,h.nextSibling,this,t):1===l.type?i=new l.ctor(h,l.name,l.strings,this,t):6===l.type&&(i=new z$1(h,this,t)),this._$AV.push(i),l=s[++n]}o!==l?.index&&(h=C$1.nextNode(),o++)}return C$1.currentNode=r$8,e}p(t){let i=0;for(const s of this._$AV)void 0!==s&&(void 0===s.strings?s._$AI(t[i]):(s._$AI(t,s,i),i+=s.strings.length-2)),i++}};class R{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=E$1,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=S$1(this,t,i),c$2(t)?t===E$1||null==t||""===t?(this._$AH!==E$1&&this._$AR(),this._$AH=E$1):t!==this._$AH&&t!==T$1&&this._(t):void 0===t._$litType$?void 0===t.nodeType?u$3(t)?this.k(t):this._(t):this.T(t):this.$(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==E$1&&c$2(this._$AH)?this._$AA.nextSibling.data=t:this.T(r$8.createTextNode(t)),this._$AH=t}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=N$1.createElement(P$1(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else{const t=new M$2(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t}}_$AC(t){let i=A.get(t.strings);return void 0===i&&A.set(t.strings,i=new N$1(t)),i}k(t){a$1(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let e=0,s;for(const h of t)e===i.length?i.push(s=new R(this.O(l$2()),this.O(l$2()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e)}_$AR(t=this._$AA.nextSibling,i){for(this._$AP?.(!1,!0,i);t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}let k$1=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=E$1,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,2<s.length||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=E$1}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=S$1(this,t,i,0),o=!c$2(t)||t!==this._$AH&&t!==T$1,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=S$1(this,e[s+n],i,n),r===T$1&&(r=this._$AH[n]),o||=!c$2(r)||r!==this._$AH[n],r===E$1?t=E$1:t!==E$1&&(t+=(r??"")+h[n+1]),this._$AH[n]=r}o&&!e&&this.j(t)}j(t){t===E$1?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},H$1=class extends k$1{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===E$1?void 0:t}},I$1=class extends k$1{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==E$1)}},L$1=class extends k$1{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5}_$AI(t,i=this){if((t=S$1(this,t,i,0)??E$1)!==T$1){const s=this._$AH,e=t===E$1&&s!==E$1||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==E$1&&(s===E$1||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t}}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},z$1=class{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){S$1(this,t)}};const Z$1={I:R},j$1=t$4.litHtmlPolyfillSupport;j$1?.(N$1,R),(t$4.litHtmlVersions??=[]).push("3.3.1");const B$1=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new R(i.insertBefore(l$2(),t),t,void 0,s??{})}return h._$AI(t),h},s$2=globalThis;let i$4=class extends y$2{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=B$1(r,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return T$1}};i$4._$litElement$=!0,i$4.finalized=!0,s$2.litElementHydrateSupport?.({LitElement:i$4});const o$9=s$2.litElementPolyfillSupport;o$9?.({LitElement:i$4}),(s$2.litElementVersions??=[]).push("4.2.1");var spinner_styles_default=i$7` + :host { + --track-width: 2px; + --track-color: rgb(128 128 128 / 25%); + --indicator-color: var(--sl-color-primary-600); + --speed: 2s; + + display: inline-flex; + width: 1em; + height: 1em; + flex: none; + } + + .spinner { + flex: 1 1 auto; + height: 100%; + width: 100%; + } + + .spinner__track, + .spinner__indicator { + fill: none; + stroke-width: var(--track-width); + r: calc(0.5em - var(--track-width) / 2); + cx: 0.5em; + cy: 0.5em; + transform-origin: 50% 50%; + } + + .spinner__track { + stroke: var(--track-color); + transform-origin: 0% 0%; + } + + .spinner__indicator { + stroke: var(--indicator-color); + stroke-linecap: round; + stroke-dasharray: 150% 75%; + animation: spin var(--speed) linear infinite; + } + + @keyframes spin { + 0% { + transform: rotate(0deg); + stroke-dasharray: 0.05em, 3em; + } + + 50% { + transform: rotate(450deg); + stroke-dasharray: 1.375em, 1.375em; + } + + 100% { + transform: rotate(1080deg); + stroke-dasharray: 0.05em, 3em; + } + } +`;const connectedElements=new Set,translations=new Map;let documentDirection="ltr",documentLanguage="en",fallback;const isClient="undefined"!=typeof MutationObserver&&"undefined"!=typeof document&&"undefined"!=typeof document.documentElement;if(isClient){const documentElementObserver=new MutationObserver(update);documentDirection=document.documentElement.dir||"ltr",documentLanguage=document.documentElement.lang||navigator.language,documentElementObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["dir","lang"]})}function registerTranslation(...translation){translation.map(t=>{const code=t.$code.toLowerCase();translations.has(code)?translations.set(code,Object.assign(Object.assign({},translations.get(code)),t)):translations.set(code,t),fallback||(fallback=t)}),update()}function update(){isClient&&(documentDirection=document.documentElement.dir||"ltr",documentLanguage=document.documentElement.lang||navigator.language),[...connectedElements.keys()].map(el=>{"function"==typeof el.requestUpdate&&el.requestUpdate()})}let LocalizeController$1=class{constructor(host){this.host=host,this.host.addController(this)}hostConnected(){connectedElements.add(this.host)}hostDisconnected(){connectedElements.delete(this.host)}dir(){return`${this.host.dir||documentDirection}`.toLowerCase()}lang(){return`${this.host.lang||documentLanguage}`.toLowerCase()}getTranslationData(lang){var _a,_b;const locale=new Intl.Locale(lang.replace(/_/g,"-")),language=null===locale||void 0===locale?void 0:locale.language.toLowerCase(),region=null!==(_b=null===(_a=null===locale||void 0===locale?void 0:locale.region)||void 0===_a?void 0:_a.toLowerCase())&&void 0!==_b?_b:"",primary=translations.get(`${language}-${region}`),secondary=translations.get(language);return{locale,language,region,primary,secondary}}exists(key,options){var _a;const{primary,secondary}=this.getTranslationData(null!==(_a=options.lang)&&void 0!==_a?_a:this.lang());return options=Object.assign({includeFallback:!1},options),!!(primary&&primary[key]||secondary&&secondary[key]||options.includeFallback&&fallback&&fallback[key])}term(key,...args){const{primary,secondary}=this.getTranslationData(this.lang());let term;if(primary&&primary[key])term=primary[key];else if(secondary&&secondary[key])term=secondary[key];else if(fallback&&fallback[key])term=fallback[key];else return console.error(`No translation found for: ${key+""}`),key+"";return"function"==typeof term?term(...args):term}date(dateToFormat,options){return dateToFormat=new Date(dateToFormat),new Intl.DateTimeFormat(this.lang(),options).format(dateToFormat)}number(numberToFormat,options){return numberToFormat=+numberToFormat,isNaN(numberToFormat)?"":new Intl.NumberFormat(this.lang(),options).format(numberToFormat)}relativeTime(value,unit,options){return new Intl.RelativeTimeFormat(this.lang(),options).format(value,unit)}};var translation={$code:"en",$name:"English",$dir:"ltr",carousel:"Carousel",clearEntry:"Clear entry",close:"Close",copied:"Copied",copy:"Copy",currentValue:"Current value",error:"Error",goToSlide:(slide,count)=>`Go to slide ${slide} of ${count}`,hidePassword:"Hide password",loading:"Loading",nextSlide:"Next slide",numOptionsSelected:num=>0===num?"No options selected":1===num?"1 option selected":`${num} options selected`,previousSlide:"Previous slide",progress:"Progress",remove:"Remove",resize:"Resize",scrollToEnd:"Scroll to end",scrollToStart:"Scroll to start",selectAColorFromTheScreen:"Select a color from the screen",showPassword:"Show password",slideNum:slide=>`Slide ${slide}`,toggleColorFormat:"Toggle color format"};registerTranslation(translation);var en_default=translation,LocalizeController=class extends LocalizeController$1{};registerTranslation(en_default);var component_styles_default=i$7` + :host { + box-sizing: border-box; + } + + :host *, + :host *::before, + :host *::after { + box-sizing: inherit; + } + + [hidden] { + display: none !important; + } +`,__defProp=Object.defineProperty,__defProps=Object.defineProperties,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropDescs=Object.getOwnPropertyDescriptors,__getOwnPropSymbols=Object.getOwnPropertySymbols,__hasOwnProp=Object.prototype.hasOwnProperty,__propIsEnum=Object.prototype.propertyIsEnumerable,__knownSymbol=(name,symbol)=>(symbol=Symbol[name])?symbol:Symbol.for("Symbol."+name),__typeError=msg=>{throw TypeError(msg)},__defNormalProp=(obj,key,value)=>key in obj?__defProp(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value,__spreadValues=(a,b)=>{for(var prop in b||(b={}))__hasOwnProp.call(b,prop)&&__defNormalProp(a,prop,b[prop]);if(__getOwnPropSymbols)for(var prop of __getOwnPropSymbols(b))__propIsEnum.call(b,prop)&&__defNormalProp(a,prop,b[prop]);return a},__spreadProps=(a,b)=>__defProps(a,__getOwnPropDescs(b)),__decorateClass=(decorators,target,key,kind)=>{for(var result=1<kind?void 0:kind?__getOwnPropDesc(target,key):target,i=decorators.length-1,decorator;0<=i;i--)(decorator=decorators[i])&&(result=(kind?decorator(target,key,result):decorator(result))||result);return kind&&result&&__defProp(target,key,result),result},__accessCheck=(obj,member,msg)=>member.has(obj)||__typeError("Cannot "+msg),__privateGet=(obj,member)=>(__accessCheck(obj,member,"read from private field"),member.get(obj)),__privateAdd=(obj,member,value)=>member.has(obj)?__typeError("Cannot add the same private member more than once"):member instanceof WeakSet?member.add(obj):member.set(obj,value),__privateSet=(obj,member,value)=>(__accessCheck(obj,member,"write to private field"),member.set(obj,value),value),__await=function(promise,isYieldStar){this[0]=promise,this[1]=isYieldStar},__yieldStar=value=>{var obj=value[__knownSymbol("asyncIterator")],isAwait=!1,it={},method;return null==obj?(obj=value[__knownSymbol("iterator")](),method=k=>it[k]=x=>obj[k](x)):(obj=obj.call(value),method=k=>it[k]=v=>{if(isAwait){if(isAwait=!1,"throw"===k)throw v;return v}return isAwait=!0,{done:!1,value:new __await(new Promise(resolve=>{var x=obj[k](v);x instanceof Object||__typeError("Object expected"),resolve(x)}),1)}}),it[__knownSymbol("iterator")]=()=>it,method("next"),"throw"in obj?method("throw"):it.throw=x=>{throw x},"return"in obj&&method("return"),it};const t$3=t=>(e,o)=>{void 0===o?customElements.define(t,e):o.addInitializer(()=>{customElements.define(t,e)})},o$8={attribute:!0,type:String,converter:u$4,reflect:!1,hasChanged:f$3},r$7=(t=o$8,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),"setter"===n&&((t=Object.create(t)).wrapped=!0),s.set(r.name,t),"accessor"===n){const{name:o}=r;return{set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t)},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t)}}throw Error("Unsupported decorator location: "+n)};function n$5(t){return(e,o)=>"object"==typeof o?r$7(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}function r$6(r){return n$5({...r,state:!0,attribute:!1})}function t$2(t){return(n,o)=>{const c="function"==typeof n?n:n[o];Object.assign(c,t)}}const e$7=(e,t,c)=>(c.configurable=!0,c.enumerable=!0,Reflect.decorate&&"object"!=typeof t&&Object.defineProperty(e,t,c),c);function e$6(e){return(n,s)=>{const o=t=>t.renderRoot?.querySelector(e)??null;return e$7(n,s,{get(){return o(this)}})}}let e$5;function r$5(r){return(n,o)=>e$7(n,o,{get(){return(this.renderRoot??(e$5??=document.createDocumentFragment())).querySelectorAll(r)}})}function r$4(r){return(n,e)=>e$7(n,e,{async get(){return await this.updateComplete,this.renderRoot?.querySelector(r)??null}})}var ShoelaceElement=class extends i$4{constructor(){super(),__privateAdd(this,_hasRecordedInitialProperties,!1),this.initialReflectedProperties=new Map,Object.entries(this.constructor.dependencies).forEach(([name,component])=>{this.constructor.define(name,component)})}emit(name,options){const event=new CustomEvent(name,__spreadValues({bubbles:!0,cancelable:!1,composed:!0,detail:{}},options));return this.dispatchEvent(event),event}static define(name,elementConstructor=this,options={}){const currentlyRegisteredConstructor=customElements.get(name);if(!currentlyRegisteredConstructor){try{customElements.define(name,elementConstructor,options)}catch(_err){customElements.define(name,class extends elementConstructor{},options)}return}let newVersion=" (unknown version)",existingVersion=newVersion;"version"in elementConstructor&&elementConstructor.version&&(newVersion=" v"+elementConstructor.version),"version"in currentlyRegisteredConstructor&¤tlyRegisteredConstructor.version&&(existingVersion=" v"+currentlyRegisteredConstructor.version);newVersion&&existingVersion&&newVersion===existingVersion||console.warn(`Attempted to register <${name}>${newVersion}, but <${name}>${existingVersion} has already been registered.`)}attributeChangedCallback(name,oldValue,newValue){__privateGet(this,_hasRecordedInitialProperties)||(this.constructor.elementProperties.forEach((obj,prop)=>{obj.reflect&&null!=this[prop]&&this.initialReflectedProperties.set(prop,this[prop])}),__privateSet(this,_hasRecordedInitialProperties,!0)),super.attributeChangedCallback(name,oldValue,newValue)}willUpdate(changedProperties){super.willUpdate(changedProperties),this.initialReflectedProperties.forEach((value,prop)=>{changedProperties.has(prop)&&null==this[prop]&&(this[prop]=value)})}},_hasRecordedInitialProperties;_hasRecordedInitialProperties=new WeakMap,ShoelaceElement.version="2.20.1",ShoelaceElement.dependencies={},__decorateClass([n$5()],ShoelaceElement.prototype,"dir",2),__decorateClass([n$5()],ShoelaceElement.prototype,"lang",2);var SlSpinner=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this)}render(){return x$1` + <svg part="base" class="spinner" role="progressbar" aria-label=${this.localize.term("loading")}> + <circle class="spinner__track"></circle> + <circle class="spinner__indicator"></circle> + </svg> + `}};SlSpinner.styles=[component_styles_default,spinner_styles_default];var formCollections=new WeakMap,reportValidityOverloads=new WeakMap,checkValidityOverloads=new WeakMap,userInteractedControls=new WeakSet,interactions=new WeakMap,FormControlController=class{constructor(host,options){this.handleFormData=event=>{const disabled=this.options.disabled(this.host),name=this.options.name(this.host),value=this.options.value(this.host),isButton="sl-button"===this.host.tagName.toLowerCase();this.host.isConnected&&!disabled&&!isButton&&"string"==typeof name&&0<name.length&&"undefined"!=typeof value&&(Array.isArray(value)?value.forEach(val=>{event.formData.append(name,val.toString())}):event.formData.append(name,value.toString()))},this.handleFormSubmit=event=>{var _a;const disabled=this.options.disabled(this.host),reportValidity=this.options.reportValidity;this.form&&!this.form.noValidate&&(null==(_a=formCollections.get(this.form))?void 0:_a.forEach(control=>{this.setUserInteracted(control,!0)})),!this.form||this.form.noValidate||disabled||reportValidity(this.host)||(event.preventDefault(),event.stopImmediatePropagation())},this.handleFormReset=()=>{this.options.setValue(this.host,this.options.defaultValue(this.host)),this.setUserInteracted(this.host,!1),interactions.set(this.host,[])},this.handleInteraction=event=>{const emittedEvents=interactions.get(this.host);emittedEvents.includes(event.type)||emittedEvents.push(event.type),emittedEvents.length===this.options.assumeInteractionOn.length&&this.setUserInteracted(this.host,!0)},this.checkFormValidity=()=>{if(this.form&&!this.form.noValidate){const elements=this.form.querySelectorAll("*");for(const element of elements)if("function"==typeof element.checkValidity&&!element.checkValidity())return!1}return!0},this.reportFormValidity=()=>{if(this.form&&!this.form.noValidate){const elements=this.form.querySelectorAll("*");for(const element of elements)if("function"==typeof element.reportValidity&&!element.reportValidity())return!1}return!0},(this.host=host).addController(this),this.options=__spreadValues({form:input=>{const formId=input.form;if(formId){const root=input.getRootNode(),form=root.querySelector(`#${formId}`);if(form)return form}return input.closest("form")},name:input=>input.name,value:input=>input.value,defaultValue:input=>input.defaultValue,disabled:input=>{var _a;return null!=(_a=input.disabled)&&_a},reportValidity:input=>"function"!=typeof input.reportValidity||input.reportValidity(),checkValidity:input=>"function"!=typeof input.checkValidity||input.checkValidity(),setValue:(input,value)=>input.value=value,assumeInteractionOn:["sl-input"]},options)}hostConnected(){const form=this.options.form(this.host);form&&this.attachForm(form),interactions.set(this.host,[]),this.options.assumeInteractionOn.forEach(event=>{this.host.addEventListener(event,this.handleInteraction)})}hostDisconnected(){this.detachForm(),interactions.delete(this.host),this.options.assumeInteractionOn.forEach(event=>{this.host.removeEventListener(event,this.handleInteraction)})}hostUpdated(){const form=this.options.form(this.host);form||this.detachForm(),form&&this.form!==form&&(this.detachForm(),this.attachForm(form)),this.host.hasUpdated&&this.setValidity(this.host.validity.valid)}attachForm(form){form?(this.form=form,formCollections.has(this.form)?formCollections.get(this.form).add(this.host):formCollections.set(this.form,new Set([this.host])),this.form.addEventListener("formdata",this.handleFormData),this.form.addEventListener("submit",this.handleFormSubmit),this.form.addEventListener("reset",this.handleFormReset),!reportValidityOverloads.has(this.form)&&(reportValidityOverloads.set(this.form,this.form.reportValidity),this.form.reportValidity=()=>this.reportFormValidity()),!checkValidityOverloads.has(this.form)&&(checkValidityOverloads.set(this.form,this.form.checkValidity),this.form.checkValidity=()=>this.checkFormValidity())):this.form=void 0}detachForm(){if(this.form){const formCollection=formCollections.get(this.form);formCollection&&(formCollection.delete(this.host),0>=formCollection.size&&(this.form.removeEventListener("formdata",this.handleFormData),this.form.removeEventListener("submit",this.handleFormSubmit),this.form.removeEventListener("reset",this.handleFormReset),reportValidityOverloads.has(this.form)&&(this.form.reportValidity=reportValidityOverloads.get(this.form),reportValidityOverloads.delete(this.form)),checkValidityOverloads.has(this.form)&&(this.form.checkValidity=checkValidityOverloads.get(this.form),checkValidityOverloads.delete(this.form)),this.form=void 0))}}setUserInteracted(el,hasInteracted){hasInteracted?userInteractedControls.add(el):userInteractedControls.delete(el),el.requestUpdate()}doAction(type,submitter){if(this.form){const button=document.createElement("button");button.type=type,button.style.position="absolute",button.style.width="0",button.style.height="0",button.style.clipPath="inset(50%)",button.style.overflow="hidden",button.style.whiteSpace="nowrap",submitter&&(button.name=submitter.name,button.value=submitter.value,["formaction","formenctype","formmethod","formnovalidate","formtarget"].forEach(attr=>{submitter.hasAttribute(attr)&&button.setAttribute(attr,submitter.getAttribute(attr))})),this.form.append(button),button.click(),button.remove()}}getForm(){var _a;return null==(_a=this.form)?null:_a}reset(submitter){this.doAction("reset",submitter)}submit(submitter){this.doAction("submit",submitter)}setValidity(isValid){const host=this.host,hasInteracted=!!userInteractedControls.has(host),required=!!host.required;host.toggleAttribute("data-required",required),host.toggleAttribute("data-optional",!required),host.toggleAttribute("data-invalid",!isValid),host.toggleAttribute("data-valid",isValid),host.toggleAttribute("data-user-invalid",!isValid&&hasInteracted),host.toggleAttribute("data-user-valid",isValid&&hasInteracted)}updateValidity(){const host=this.host;this.setValidity(host.validity.valid)}emitInvalidEvent(originalInvalidEvent){const slInvalidEvent=new CustomEvent("sl-invalid",{bubbles:!1,composed:!1,cancelable:!0,detail:{}});originalInvalidEvent||slInvalidEvent.preventDefault(),this.host.dispatchEvent(slInvalidEvent)||(null==originalInvalidEvent?void 0:originalInvalidEvent.preventDefault())}},validValidityState=Object.freeze({badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:!0,valueMissing:!1}),valueMissingValidityState=Object.freeze(__spreadProps(__spreadValues({},validValidityState),{valid:!1,valueMissing:!0})),customErrorValidityState=Object.freeze(__spreadProps(__spreadValues({},validValidityState),{valid:!1,customError:!0})),button_styles_default=i$7` + :host { + display: inline-block; + position: relative; + width: auto; + cursor: pointer; + } + + .button { + display: inline-flex; + align-items: stretch; + justify-content: center; + width: 100%; + border-style: solid; + border-width: var(--sl-input-border-width); + font-family: var(--sl-input-font-family); + font-weight: var(--sl-font-weight-semibold); + text-decoration: none; + user-select: none; + -webkit-user-select: none; + white-space: nowrap; + vertical-align: middle; + padding: 0; + transition: + var(--sl-transition-x-fast) background-color, + var(--sl-transition-x-fast) color, + var(--sl-transition-x-fast) border, + var(--sl-transition-x-fast) box-shadow; + cursor: inherit; + } + + .button::-moz-focus-inner { + border: 0; + } + + .button:focus { + outline: none; + } + + .button:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .button--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + /* When disabled, prevent mouse events from bubbling up from children */ + .button--disabled * { + pointer-events: none; + } + + .button__prefix, + .button__suffix { + flex: 0 0 auto; + display: flex; + align-items: center; + pointer-events: none; + } + + .button__label { + display: inline-block; + } + + .button__label::slotted(sl-icon) { + vertical-align: -2px; + } + + /* + * Standard buttons + */ + + /* Default */ + .button--standard.button--default { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-input-border-color); + color: var(--sl-color-neutral-700); + } + + .button--standard.button--default:hover:not(.button--disabled) { + background-color: var(--sl-color-primary-50); + border-color: var(--sl-color-primary-300); + color: var(--sl-color-primary-700); + } + + .button--standard.button--default:active:not(.button--disabled) { + background-color: var(--sl-color-primary-100); + border-color: var(--sl-color-primary-400); + color: var(--sl-color-primary-700); + } + + /* Primary */ + .button--standard.button--primary { + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--primary:hover:not(.button--disabled) { + background-color: var(--sl-color-primary-500); + border-color: var(--sl-color-primary-500); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--primary:active:not(.button--disabled) { + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + /* Success */ + .button--standard.button--success { + background-color: var(--sl-color-success-600); + border-color: var(--sl-color-success-600); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--success:hover:not(.button--disabled) { + background-color: var(--sl-color-success-500); + border-color: var(--sl-color-success-500); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--success:active:not(.button--disabled) { + background-color: var(--sl-color-success-600); + border-color: var(--sl-color-success-600); + color: var(--sl-color-neutral-0); + } + + /* Neutral */ + .button--standard.button--neutral { + background-color: var(--sl-color-neutral-600); + border-color: var(--sl-color-neutral-600); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--neutral:hover:not(.button--disabled) { + background-color: var(--sl-color-neutral-500); + border-color: var(--sl-color-neutral-500); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--neutral:active:not(.button--disabled) { + background-color: var(--sl-color-neutral-600); + border-color: var(--sl-color-neutral-600); + color: var(--sl-color-neutral-0); + } + + /* Warning */ + .button--standard.button--warning { + background-color: var(--sl-color-warning-600); + border-color: var(--sl-color-warning-600); + color: var(--sl-color-neutral-0); + } + .button--standard.button--warning:hover:not(.button--disabled) { + background-color: var(--sl-color-warning-500); + border-color: var(--sl-color-warning-500); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--warning:active:not(.button--disabled) { + background-color: var(--sl-color-warning-600); + border-color: var(--sl-color-warning-600); + color: var(--sl-color-neutral-0); + } + + /* Danger */ + .button--standard.button--danger { + background-color: var(--sl-color-danger-600); + border-color: var(--sl-color-danger-600); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--danger:hover:not(.button--disabled) { + background-color: var(--sl-color-danger-500); + border-color: var(--sl-color-danger-500); + color: var(--sl-color-neutral-0); + } + + .button--standard.button--danger:active:not(.button--disabled) { + background-color: var(--sl-color-danger-600); + border-color: var(--sl-color-danger-600); + color: var(--sl-color-neutral-0); + } + + /* + * Outline buttons + */ + + .button--outline { + background: none; + border: solid 1px; + } + + /* Default */ + .button--outline.button--default { + border-color: var(--sl-input-border-color); + color: var(--sl-color-neutral-700); + } + + .button--outline.button--default:hover:not(.button--disabled), + .button--outline.button--default.button--checked:not(.button--disabled) { + border-color: var(--sl-color-primary-600); + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--default:active:not(.button--disabled) { + border-color: var(--sl-color-primary-700); + background-color: var(--sl-color-primary-700); + color: var(--sl-color-neutral-0); + } + + /* Primary */ + .button--outline.button--primary { + border-color: var(--sl-color-primary-600); + color: var(--sl-color-primary-600); + } + + .button--outline.button--primary:hover:not(.button--disabled), + .button--outline.button--primary.button--checked:not(.button--disabled) { + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--primary:active:not(.button--disabled) { + border-color: var(--sl-color-primary-700); + background-color: var(--sl-color-primary-700); + color: var(--sl-color-neutral-0); + } + + /* Success */ + .button--outline.button--success { + border-color: var(--sl-color-success-600); + color: var(--sl-color-success-600); + } + + .button--outline.button--success:hover:not(.button--disabled), + .button--outline.button--success.button--checked:not(.button--disabled) { + background-color: var(--sl-color-success-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--success:active:not(.button--disabled) { + border-color: var(--sl-color-success-700); + background-color: var(--sl-color-success-700); + color: var(--sl-color-neutral-0); + } + + /* Neutral */ + .button--outline.button--neutral { + border-color: var(--sl-color-neutral-600); + color: var(--sl-color-neutral-600); + } + + .button--outline.button--neutral:hover:not(.button--disabled), + .button--outline.button--neutral.button--checked:not(.button--disabled) { + background-color: var(--sl-color-neutral-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--neutral:active:not(.button--disabled) { + border-color: var(--sl-color-neutral-700); + background-color: var(--sl-color-neutral-700); + color: var(--sl-color-neutral-0); + } + + /* Warning */ + .button--outline.button--warning { + border-color: var(--sl-color-warning-600); + color: var(--sl-color-warning-600); + } + + .button--outline.button--warning:hover:not(.button--disabled), + .button--outline.button--warning.button--checked:not(.button--disabled) { + background-color: var(--sl-color-warning-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--warning:active:not(.button--disabled) { + border-color: var(--sl-color-warning-700); + background-color: var(--sl-color-warning-700); + color: var(--sl-color-neutral-0); + } + + /* Danger */ + .button--outline.button--danger { + border-color: var(--sl-color-danger-600); + color: var(--sl-color-danger-600); + } + + .button--outline.button--danger:hover:not(.button--disabled), + .button--outline.button--danger.button--checked:not(.button--disabled) { + background-color: var(--sl-color-danger-600); + color: var(--sl-color-neutral-0); + } + + .button--outline.button--danger:active:not(.button--disabled) { + border-color: var(--sl-color-danger-700); + background-color: var(--sl-color-danger-700); + color: var(--sl-color-neutral-0); + } + + @media (forced-colors: active) { + .button.button--outline.button--checked:not(.button--disabled) { + outline: solid 2px transparent; + } + } + + /* + * Text buttons + */ + + .button--text { + background-color: transparent; + border-color: transparent; + color: var(--sl-color-primary-600); + } + + .button--text:hover:not(.button--disabled) { + background-color: transparent; + border-color: transparent; + color: var(--sl-color-primary-500); + } + + .button--text:focus-visible:not(.button--disabled) { + background-color: transparent; + border-color: transparent; + color: var(--sl-color-primary-500); + } + + .button--text:active:not(.button--disabled) { + background-color: transparent; + border-color: transparent; + color: var(--sl-color-primary-700); + } + + /* + * Size modifiers + */ + + .button--small { + height: auto; + min-height: var(--sl-input-height-small); + font-size: var(--sl-button-font-size-small); + line-height: calc(var(--sl-input-height-small) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-small); + } + + .button--medium { + height: auto; + min-height: var(--sl-input-height-medium); + font-size: var(--sl-button-font-size-medium); + line-height: calc(var(--sl-input-height-medium) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-medium); + } + + .button--large { + height: auto; + min-height: var(--sl-input-height-large); + font-size: var(--sl-button-font-size-large); + line-height: calc(var(--sl-input-height-large) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-large); + } + + /* + * Pill modifier + */ + + .button--pill.button--small { + border-radius: var(--sl-input-height-small); + } + + .button--pill.button--medium { + border-radius: var(--sl-input-height-medium); + } + + .button--pill.button--large { + border-radius: var(--sl-input-height-large); + } + + /* + * Circle modifier + */ + + .button--circle { + padding-left: 0; + padding-right: 0; + } + + .button--circle.button--small { + width: var(--sl-input-height-small); + border-radius: 50%; + } + + .button--circle.button--medium { + width: var(--sl-input-height-medium); + border-radius: 50%; + } + + .button--circle.button--large { + width: var(--sl-input-height-large); + border-radius: 50%; + } + + .button--circle .button__prefix, + .button--circle .button__suffix, + .button--circle .button__caret { + display: none; + } + + /* + * Caret modifier + */ + + .button--caret .button__suffix { + display: none; + } + + .button--caret .button__caret { + height: auto; + } + + /* + * Loading modifier + */ + + .button--loading { + position: relative; + cursor: wait; + } + + .button--loading .button__prefix, + .button--loading .button__label, + .button--loading .button__suffix, + .button--loading .button__caret { + visibility: hidden; + } + + .button--loading sl-spinner { + --indicator-color: currentColor; + position: absolute; + font-size: 1em; + height: 1em; + width: 1em; + top: calc(50% - 0.5em); + left: calc(50% - 0.5em); + } + + /* + * Badges + */ + + .button ::slotted(sl-badge) { + position: absolute; + top: 0; + right: 0; + translate: 50% -50%; + pointer-events: none; + } + + .button--rtl ::slotted(sl-badge) { + right: auto; + left: 0; + translate: -50% -50%; + } + + /* + * Button spacing + */ + + .button--has-label.button--small .button__label { + padding: 0 var(--sl-spacing-small); + } + + .button--has-label.button--medium .button__label { + padding: 0 var(--sl-spacing-medium); + } + + .button--has-label.button--large .button__label { + padding: 0 var(--sl-spacing-large); + } + + .button--has-prefix.button--small { + padding-inline-start: var(--sl-spacing-x-small); + } + + .button--has-prefix.button--small .button__label { + padding-inline-start: var(--sl-spacing-x-small); + } + + .button--has-prefix.button--medium { + padding-inline-start: var(--sl-spacing-small); + } + + .button--has-prefix.button--medium .button__label { + padding-inline-start: var(--sl-spacing-small); + } + + .button--has-prefix.button--large { + padding-inline-start: var(--sl-spacing-small); + } + + .button--has-prefix.button--large .button__label { + padding-inline-start: var(--sl-spacing-small); + } + + .button--has-suffix.button--small, + .button--caret.button--small { + padding-inline-end: var(--sl-spacing-x-small); + } + + .button--has-suffix.button--small .button__label, + .button--caret.button--small .button__label { + padding-inline-end: var(--sl-spacing-x-small); + } + + .button--has-suffix.button--medium, + .button--caret.button--medium { + padding-inline-end: var(--sl-spacing-small); + } + + .button--has-suffix.button--medium .button__label, + .button--caret.button--medium .button__label { + padding-inline-end: var(--sl-spacing-small); + } + + .button--has-suffix.button--large, + .button--caret.button--large { + padding-inline-end: var(--sl-spacing-small); + } + + .button--has-suffix.button--large .button__label, + .button--caret.button--large .button__label { + padding-inline-end: var(--sl-spacing-small); + } + + /* + * Button groups support a variety of button types (e.g. buttons with tooltips, buttons as dropdown triggers, etc.). + * This means buttons aren't always direct descendants of the button group, thus we can't target them with the + * ::slotted selector. To work around this, the button group component does some magic to add these special classes to + * buttons and we style them here instead. + */ + + :host([data-sl-button-group__button--first]:not([data-sl-button-group__button--last])) .button { + border-start-end-radius: 0; + border-end-end-radius: 0; + } + + :host([data-sl-button-group__button--inner]) .button { + border-radius: 0; + } + + :host([data-sl-button-group__button--last]:not([data-sl-button-group__button--first])) .button { + border-start-start-radius: 0; + border-end-start-radius: 0; + } + + /* All except the first */ + :host([data-sl-button-group__button]:not([data-sl-button-group__button--first])) { + margin-inline-start: calc(-1 * var(--sl-input-border-width)); + } + + /* Add a visual separator between solid buttons */ + :host( + [data-sl-button-group__button]:not( + [data-sl-button-group__button--first], + [data-sl-button-group__button--radio], + [variant='default'] + ):not(:hover) + ) + .button:after { + content: ''; + position: absolute; + top: 0; + inset-inline-start: 0; + bottom: 0; + border-left: solid 1px rgb(128 128 128 / 33%); + mix-blend-mode: multiply; + } + + /* Bump hovered, focused, and checked buttons up so their focus ring isn't clipped */ + :host([data-sl-button-group__button--hover]) { + z-index: 1; + } + + /* Focus and checked are always on top */ + :host([data-sl-button-group__button--focus]), + :host([data-sl-button-group__button][checked]) { + z-index: 2; + } +`,HasSlotController=class{constructor(host,...slotNames){this.slotNames=[],this.handleSlotChange=event=>{const slot=event.target;(this.slotNames.includes("[default]")&&!slot.name||slot.name&&this.slotNames.includes(slot.name))&&this.host.requestUpdate()},(this.host=host).addController(this),this.slotNames=slotNames}hasDefaultSlot(){return[...this.host.childNodes].some(node=>{if(node.nodeType===node.TEXT_NODE&&""!==node.textContent.trim())return!0;if(node.nodeType===node.ELEMENT_NODE){const el=node,tagName=el.tagName.toLowerCase();if("sl-visually-hidden"===tagName)return!1;if(!el.hasAttribute("slot"))return!0}return!1})}hasNamedSlot(name){return null!==this.host.querySelector(`:scope > [slot="${name}"]`)}test(slotName){return"[default]"===slotName?this.hasDefaultSlot():this.hasNamedSlot(slotName)}hostConnected(){this.host.shadowRoot.addEventListener("slotchange",this.handleSlotChange)}hostDisconnected(){this.host.shadowRoot.removeEventListener("slotchange",this.handleSlotChange)}};function getTextContent(slot){if(!slot)return"";const nodes=slot.assignedNodes({flatten:!0});let text="";return[...nodes].forEach(node=>{node.nodeType===Node.TEXT_NODE&&(text+=node.textContent)}),text}var basePath="";function setBasePath(path){basePath=path}function getBasePath(subpath=""){if(!basePath){const scripts=[...document.getElementsByTagName("script")],configScript=scripts.find(script=>script.hasAttribute("data-shoelace"));if(configScript)setBasePath(configScript.getAttribute("data-shoelace"));else{const fallbackScript=scripts.find(s=>/shoelace(\.min)?\.js($|\?)/.test(s.src)||/shoelace-autoloader(\.min)?\.js($|\?)/.test(s.src));let path="";fallbackScript&&(path=fallbackScript.getAttribute("src")),setBasePath(path.split("/").slice(0,-1).join("/"))}}return basePath.replace(/\/$/,"")+(subpath?`/${subpath.replace(/^\//,"")}`:``)}var library={name:"default",resolver:name=>getBasePath(`assets/icons/${name}.svg`)},library_default_default=library,icons={caret:` + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> + <polyline points="6 9 12 15 18 9"></polyline> + </svg> + `,check:` + <svg part="checked-icon" class="checkbox__icon" viewBox="0 0 16 16"> + <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round"> + <g stroke="currentColor"> + <g transform="translate(3.428571, 3.428571)"> + <path d="M0,5.71428571 L3.42857143,9.14285714"></path> + <path d="M9.14285714,0 L3.42857143,9.14285714"></path> + </g> + </g> + </g> + </svg> + `,"chevron-down":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/> + </svg> + `,"chevron-left":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> + </svg> + `,"chevron-right":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> + </svg> + `,copy:` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-copy" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M4 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V2Zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H6ZM2 5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h1v1H2Z"/> + </svg> + `,eye:` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> + <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> + <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> + </svg> + `,"eye-slash":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye-slash" viewBox="0 0 16 16"> + <path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/> + <path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/> + <path d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12 .708-.708 12 12-.708.708z"/> + </svg> + `,eyedropper:` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eyedropper" viewBox="0 0 16 16"> + <path d="M13.354.646a1.207 1.207 0 0 0-1.708 0L8.5 3.793l-.646-.647a.5.5 0 1 0-.708.708L8.293 5l-7.147 7.146A.5.5 0 0 0 1 12.5v1.793l-.854.853a.5.5 0 1 0 .708.707L1.707 15H3.5a.5.5 0 0 0 .354-.146L11 7.707l1.146 1.147a.5.5 0 0 0 .708-.708l-.647-.646 3.147-3.146a1.207 1.207 0 0 0 0-1.708l-2-2zM2 12.707l7-7L10.293 7l-7 7H2v-1.293z"></path> + </svg> + `,"grip-vertical":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16"> + <path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"></path> + </svg> + `,indeterminate:` + <svg part="indeterminate-icon" class="checkbox__icon" viewBox="0 0 16 16"> + <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round"> + <g stroke="currentColor" stroke-width="2"> + <g transform="translate(2.285714, 6.857143)"> + <path d="M10.2857143,1.14285714 L1.14285714,1.14285714"></path> + </g> + </g> + </g> + </svg> + `,"person-fill":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-fill" viewBox="0 0 16 16"> + <path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/> + </svg> + `,"play-fill":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-fill" viewBox="0 0 16 16"> + <path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"></path> + </svg> + `,"pause-fill":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pause-fill" viewBox="0 0 16 16"> + <path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"></path> + </svg> + `,radio:` + <svg part="checked-icon" class="radio__icon" viewBox="0 0 16 16"> + <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g fill="currentColor"> + <circle cx="8" cy="8" r="3.42857143"></circle> + </g> + </g> + </svg> + `,"star-fill":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill" viewBox="0 0 16 16"> + <path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/> + </svg> + `,"x-lg":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16"> + <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"/> + </svg> + `,"x-circle-fill":` + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-circle-fill" viewBox="0 0 16 16"> + <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"></path> + </svg> + `},systemLibrary={name:"system",resolver:name=>name in icons?`data:image/svg+xml,${encodeURIComponent(icons[name])}`:""},library_system_default=systemLibrary,registry=[library_default_default,library_system_default],watchedIcons=[];function watchIcon(icon){watchedIcons.push(icon)}function unwatchIcon(icon){watchedIcons=watchedIcons.filter(el=>el!==icon)}function getIconLibrary(name){return registry.find(lib=>lib.name===name)}function registerIconLibrary(name,options){unregisterIconLibrary(name),registry.push({name,resolver:options.resolver,mutator:options.mutator,spriteSheet:options.spriteSheet}),watchedIcons.forEach(icon=>{icon.library===name&&icon.setIcon()})}function unregisterIconLibrary(name){registry=registry.filter(lib=>lib.name!==name)}var icon_styles_default=i$7` + :host { + display: inline-block; + width: 1em; + height: 1em; + box-sizing: content-box !important; + } + + svg { + display: block; + height: 100%; + width: 100%; + } +`;function watch(propertyName,options){const resolvedOptions=__spreadValues({waitUntilFirstUpdate:!1},options);return(proto,decoratedFnName)=>{const{update}=proto,watchedProperties=Array.isArray(propertyName)?propertyName:[propertyName];proto.update=function(changedProps){watchedProperties.forEach(property=>{const key=property;if(changedProps.has(key)){const oldValue=changedProps.get(key),newValue=this[key];oldValue!==newValue&&(!resolvedOptions.waitUntilFirstUpdate||this.hasUpdated)&&this[decoratedFnName](oldValue,newValue)}}),update.call(this,changedProps)}}}const{I:t$1}=Z$1,e$4=o=>void 0!==o?._$litType$,f$1=o=>void 0===o.strings,r$3=()=>document.createComment(""),s$1=(o,i,n)=>{const e=o._$AA.parentNode,l=void 0===i?o._$AB:i._$AA;if(void 0===n){const i=e.insertBefore(r$3(),l),d=e.insertBefore(r$3(),l);n=new t$1(i,d,o,o.options)}else{const t=n._$AB.nextSibling,i=n._$AM,d=i!==o;if(d){let t;n._$AQ?.(o),n._$AM=o,void 0!==n._$AP&&(t=o._$AU)!==i._$AU&&n._$AP(t)}if(t!==l||d)for(let o=n._$AA;o!==t;){const t=o.nextSibling;e.insertBefore(o,l),o=t}}return n},v$1=(o,t,i=o)=>(o._$AI(t,i),o),u$2={},m$1=(o,t=u$2)=>o._$AH=t,p=o=>o._$AH,M$1=o=>{o._$AR(),o._$AA.remove()};var CACHEABLE_ERROR=Symbol(),RETRYABLE_ERROR=Symbol(),iconCache=new Map,SlIcon=class extends ShoelaceElement{constructor(){super(...arguments),this.initialRender=!1,this.svg=null,this.label="",this.library="default"}async resolveIcon(url,library){var _a;let fileData;if(null==library?void 0:library.spriteSheet)return this.svg=x$1`<svg part="svg"> + <use part="use" href="${url}"></use> + </svg>`,this.svg;try{if(fileData=await fetch(url,{mode:"cors"}),!fileData.ok)return 410===fileData.status?CACHEABLE_ERROR:RETRYABLE_ERROR}catch(e){return RETRYABLE_ERROR}try{const div=document.createElement("div");div.innerHTML=await fileData.text();const svg=div.firstElementChild;if("svg"!==(null==(_a=null==svg?void 0:svg.tagName)?void 0:_a.toLowerCase()))return CACHEABLE_ERROR;parser||(parser=new DOMParser);const doc=parser.parseFromString(svg.outerHTML,"text/html"),svgEl=doc.body.querySelector("svg");return svgEl?(svgEl.part.add("svg"),document.adoptNode(svgEl)):CACHEABLE_ERROR}catch(e){return CACHEABLE_ERROR}}connectedCallback(){super.connectedCallback(),watchIcon(this)}firstUpdated(){this.initialRender=!0,this.setIcon()}disconnectedCallback(){super.disconnectedCallback(),unwatchIcon(this)}getIconSource(){const library=getIconLibrary(this.library);return this.name&&library?{url:library.resolver(this.name),fromLibrary:!0}:{url:this.src,fromLibrary:!1}}handleLabelChange(){const hasLabel="string"==typeof this.label&&0<this.label.length;hasLabel?(this.setAttribute("role","img"),this.setAttribute("aria-label",this.label),this.removeAttribute("aria-hidden")):(this.removeAttribute("role"),this.removeAttribute("aria-label"),this.setAttribute("aria-hidden","true"))}async setIcon(){var _a;const{url,fromLibrary}=this.getIconSource(),library=fromLibrary?getIconLibrary(this.library):void 0;if(!url)return void(this.svg=null);let iconResolver=iconCache.get(url);if(iconResolver||(iconResolver=this.resolveIcon(url,library),iconCache.set(url,iconResolver)),!!this.initialRender){const svg=await iconResolver;if(svg===RETRYABLE_ERROR&&iconCache.delete(url),url===this.getIconSource().url){if(e$4(svg)){if(this.svg=svg,library){await this.updateComplete;const shadowSVG=this.shadowRoot.querySelector("[part='svg']");"function"==typeof library.mutator&&shadowSVG&&library.mutator(shadowSVG)}return}svg===RETRYABLE_ERROR||svg===CACHEABLE_ERROR?(this.svg=null,this.emit("sl-error")):(this.svg=svg.cloneNode(!0),null==(_a=null==library?void 0:library.mutator)?void 0:_a.call(library,this.svg),this.emit("sl-load"))}}}render(){return this.svg}},parser;SlIcon.styles=[component_styles_default,icon_styles_default],__decorateClass([r$6()],SlIcon.prototype,"svg",2),__decorateClass([n$5({reflect:!0})],SlIcon.prototype,"name",2),__decorateClass([n$5()],SlIcon.prototype,"src",2),__decorateClass([n$5()],SlIcon.prototype,"label",2),__decorateClass([n$5({reflect:!0})],SlIcon.prototype,"library",2),__decorateClass([watch("label")],SlIcon.prototype,"handleLabelChange",1),__decorateClass([watch(["name","src","library"])],SlIcon.prototype,"setIcon",1);const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4},e$3=t=>(...e)=>({_$litDirective$:t,values:e});let i$3=class{constructor(){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};const e$2=e$3(class extends i$3{constructor(t$1){if(super(t$1),t$1.type!==t.ATTRIBUTE||"class"!==t$1.name||2<t$1.strings?.length)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter(s=>t[s]).join(" ")+" "}update(s,[i]){if(void 0===this.st){for(const t in this.st=new Set,void 0!==s.strings&&(this.nt=new Set(s.strings.join(" ").split(/\s/).filter(t=>""!==t))),i)i[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(i)}const r=s.element.classList;for(const t of this.st)t in i||(r.remove(t),this.st.delete(t));for(const t in i){const s=!!i[t];s===this.st.has(t)||this.nt?.has(t)||(s?(r.add(t),this.st.add(t)):(r.remove(t),this.st.delete(t)))}return T$1}}),a=Symbol.for(""),o$7=t=>{if(t?.r===a)return t?._$litStatic$},i$2=(t,...r)=>({_$litStatic$:r.reduce((r,e,a)=>r+(t=>{if(void 0!==t._$litStatic$)return t._$litStatic$;throw Error(`Value passed to 'literal' function must be a 'literal' result: ${t}. Use 'unsafeStatic' to pass non-literal values, but\n take care to ensure page security.`)})(e)+t[a+1],t[0]),r:a}),l$1=new Map,n$4=t=>(r,...e)=>{const a=e.length;let s,i;const n=[],u=[];let $=0,f=!1,c;for(;$<a;){for(c=r[$];$<a&&void 0!==(i=e[$],s=o$7(i));)c+=s+r[++$],f=!0;$!==a&&u.push(i),n.push(c),$++}if($===a&&n.push(r[a]),f){const t=n.join("$$lit$$");void 0===(r=l$1.get(t))&&(n.raw=n,l$1.set(t,r=n)),e=u}return t(r,...e)},u$1=n$4(x$1),o$6=o=>o??E$1;var SlButton=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this,{assumeInteractionOn:["click"]}),this.hasSlotController=new HasSlotController(this,"[default]","prefix","suffix"),this.localize=new LocalizeController(this),this.hasFocus=!1,this.invalid=!1,this.title="",this.variant="default",this.size="medium",this.caret=!1,this.disabled=!1,this.loading=!1,this.outline=!1,this.pill=!1,this.circle=!1,this.type="button",this.name="",this.value="",this.href="",this.rel="noreferrer noopener"}get validity(){return this.isButton()?this.button.validity:validValidityState}get validationMessage(){return this.isButton()?this.button.validationMessage:""}firstUpdated(){this.isButton()&&this.formControlController.updateValidity()}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleClick(){"submit"===this.type&&this.formControlController.submit(this),"reset"===this.type&&this.formControlController.reset(this)}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}isButton(){return!this.href}isLink(){return!!this.href}handleDisabledChange(){this.isButton()&&this.formControlController.setValidity(this.disabled)}click(){this.button.click()}focus(options){this.button.focus(options)}blur(){this.button.blur()}checkValidity(){return!this.isButton()||this.button.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return!this.isButton()||this.button.reportValidity()}setCustomValidity(message){this.isButton()&&(this.button.setCustomValidity(message),this.formControlController.updateValidity())}render(){const isLink=this.isLink(),tag=isLink?i$2`a`:i$2`button`;return u$1` + <${tag} + part="base" + class=${e$2({button:!0,"button--default":"default"===this.variant,"button--primary":"primary"===this.variant,"button--success":"success"===this.variant,"button--neutral":"neutral"===this.variant,"button--warning":"warning"===this.variant,"button--danger":"danger"===this.variant,"button--text":"text"===this.variant,"button--small":"small"===this.size,"button--medium":"medium"===this.size,"button--large":"large"===this.size,"button--caret":this.caret,"button--circle":this.circle,"button--disabled":this.disabled,"button--focused":this.hasFocus,"button--loading":this.loading,"button--standard":!this.outline,"button--outline":this.outline,"button--pill":this.pill,"button--rtl":"rtl"===this.localize.dir(),"button--has-label":this.hasSlotController.test("[default]"),"button--has-prefix":this.hasSlotController.test("prefix"),"button--has-suffix":this.hasSlotController.test("suffix")})} + ?disabled=${o$6(isLink?void 0:this.disabled)} + type=${o$6(isLink?void 0:this.type)} + title=${this.title} + name=${o$6(isLink?void 0:this.name)} + value=${o$6(isLink?void 0:this.value)} + href=${o$6(isLink&&!this.disabled?this.href:void 0)} + target=${o$6(isLink?this.target:void 0)} + download=${o$6(isLink?this.download:void 0)} + rel=${o$6(isLink?this.rel:void 0)} + role=${o$6(isLink?void 0:"button")} + aria-disabled=${this.disabled?"true":"false"} + tabindex=${this.disabled?"-1":"0"} + @blur=${this.handleBlur} + @focus=${this.handleFocus} + @invalid=${this.isButton()?this.handleInvalid:null} + @click=${this.handleClick} + > + <slot name="prefix" part="prefix" class="button__prefix"></slot> + <slot part="label" class="button__label"></slot> + <slot name="suffix" part="suffix" class="button__suffix"></slot> + ${this.caret?u$1` <sl-icon part="caret" class="button__caret" library="system" name="caret"></sl-icon> `:""} + ${this.loading?u$1`<sl-spinner part="spinner"></sl-spinner>`:""} + </${tag}> + `}};SlButton.styles=[component_styles_default,button_styles_default],SlButton.dependencies={"sl-icon":SlIcon,"sl-spinner":SlSpinner},__decorateClass([e$6(".button")],SlButton.prototype,"button",2),__decorateClass([r$6()],SlButton.prototype,"hasFocus",2),__decorateClass([r$6()],SlButton.prototype,"invalid",2),__decorateClass([n$5()],SlButton.prototype,"title",2),__decorateClass([n$5({reflect:!0})],SlButton.prototype,"variant",2),__decorateClass([n$5({reflect:!0})],SlButton.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"caret",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"disabled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"loading",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"outline",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"pill",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlButton.prototype,"circle",2),__decorateClass([n$5()],SlButton.prototype,"type",2),__decorateClass([n$5()],SlButton.prototype,"name",2),__decorateClass([n$5()],SlButton.prototype,"value",2),__decorateClass([n$5()],SlButton.prototype,"href",2),__decorateClass([n$5()],SlButton.prototype,"target",2),__decorateClass([n$5()],SlButton.prototype,"rel",2),__decorateClass([n$5()],SlButton.prototype,"download",2),__decorateClass([n$5()],SlButton.prototype,"form",2),__decorateClass([n$5({attribute:"formaction"})],SlButton.prototype,"formAction",2),__decorateClass([n$5({attribute:"formenctype"})],SlButton.prototype,"formEnctype",2),__decorateClass([n$5({attribute:"formmethod"})],SlButton.prototype,"formMethod",2),__decorateClass([n$5({attribute:"formnovalidate",type:Boolean})],SlButton.prototype,"formNoValidate",2),__decorateClass([n$5({attribute:"formtarget"})],SlButton.prototype,"formTarget",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlButton.prototype,"handleDisabledChange",1),SlButton.define("sl-button");var checkbox_styles_default=i$7` + :host { + display: inline-block; + } + + .checkbox { + position: relative; + display: inline-flex; + align-items: flex-start; + font-family: var(--sl-input-font-family); + font-weight: var(--sl-input-font-weight); + color: var(--sl-input-label-color); + vertical-align: middle; + cursor: pointer; + } + + .checkbox--small { + --toggle-size: var(--sl-toggle-size-small); + font-size: var(--sl-input-font-size-small); + } + + .checkbox--medium { + --toggle-size: var(--sl-toggle-size-medium); + font-size: var(--sl-input-font-size-medium); + } + + .checkbox--large { + --toggle-size: var(--sl-toggle-size-large); + font-size: var(--sl-input-font-size-large); + } + + .checkbox__control { + flex: 0 0 auto; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: var(--toggle-size); + height: var(--toggle-size); + border: solid var(--sl-input-border-width) var(--sl-input-border-color); + border-radius: 2px; + background-color: var(--sl-input-background-color); + color: var(--sl-color-neutral-0); + transition: + var(--sl-transition-fast) border-color, + var(--sl-transition-fast) background-color, + var(--sl-transition-fast) color, + var(--sl-transition-fast) box-shadow; + } + + .checkbox__input { + position: absolute; + opacity: 0; + padding: 0; + margin: 0; + pointer-events: none; + } + + .checkbox__checked-icon, + .checkbox__indeterminate-icon { + display: inline-flex; + width: var(--toggle-size); + height: var(--toggle-size); + } + + /* Hover */ + .checkbox:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__control:hover { + border-color: var(--sl-input-border-color-hover); + background-color: var(--sl-input-background-color-hover); + } + + /* Focus */ + .checkbox:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + /* Checked/indeterminate */ + .checkbox--checked .checkbox__control, + .checkbox--indeterminate .checkbox__control { + border-color: var(--sl-color-primary-600); + background-color: var(--sl-color-primary-600); + } + + /* Checked/indeterminate + hover */ + .checkbox.checkbox--checked:not(.checkbox--disabled) .checkbox__control:hover, + .checkbox.checkbox--indeterminate:not(.checkbox--disabled) .checkbox__control:hover { + border-color: var(--sl-color-primary-500); + background-color: var(--sl-color-primary-500); + } + + /* Checked/indeterminate + focus */ + .checkbox.checkbox--checked:not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control, + .checkbox.checkbox--indeterminate:not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + /* Disabled */ + .checkbox--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .checkbox__label { + display: inline-block; + color: var(--sl-input-label-color); + line-height: var(--toggle-size); + margin-inline-start: 0.5em; + user-select: none; + -webkit-user-select: none; + } + + :host([required]) .checkbox__label::after { + content: var(--sl-input-required-content); + color: var(--sl-input-required-content-color); + margin-inline-start: var(--sl-input-required-content-offset); + } +`,defaultValue=(propertyName="value")=>(proto,key)=>{const ctor=proto.constructor,attributeChangedCallback=ctor.prototype.attributeChangedCallback;ctor.prototype.attributeChangedCallback=function(name,old,value){var _a;const options=ctor.getPropertyOptions(propertyName),attributeName="string"==typeof options.attribute?options.attribute:propertyName;if(name===attributeName){const converter=options.converter||u$4,fromAttribute="function"==typeof converter?converter:null==(_a=null==converter?void 0:converter.fromAttribute)?u$4.fromAttribute:_a,newValue=fromAttribute(value,options.type);this[propertyName]!==newValue&&(this[key]=newValue)}attributeChangedCallback.call(this,name,old,value)}},form_control_styles_default=i$7` + .form-control .form-control__label { + display: none; + } + + .form-control .form-control__help-text { + display: none; + } + + /* Label */ + .form-control--has-label .form-control__label { + display: inline-block; + color: var(--sl-input-label-color); + margin-bottom: var(--sl-spacing-3x-small); + } + + .form-control--has-label.form-control--small .form-control__label { + font-size: var(--sl-input-label-font-size-small); + } + + .form-control--has-label.form-control--medium .form-control__label { + font-size: var(--sl-input-label-font-size-medium); + } + + .form-control--has-label.form-control--large .form-control__label { + font-size: var(--sl-input-label-font-size-large); + } + + :host([required]) .form-control--has-label .form-control__label::after { + content: var(--sl-input-required-content); + margin-inline-start: var(--sl-input-required-content-offset); + color: var(--sl-input-required-content-color); + } + + /* Help text */ + .form-control--has-help-text .form-control__help-text { + display: block; + color: var(--sl-input-help-text-color); + margin-top: var(--sl-spacing-3x-small); + } + + .form-control--has-help-text.form-control--small .form-control__help-text { + font-size: var(--sl-input-help-text-font-size-small); + } + + .form-control--has-help-text.form-control--medium .form-control__help-text { + font-size: var(--sl-input-help-text-font-size-medium); + } + + .form-control--has-help-text.form-control--large .form-control__help-text { + font-size: var(--sl-input-help-text-font-size-large); + } + + .form-control--has-help-text.form-control--radio-group .form-control__help-text { + margin-top: var(--sl-spacing-2x-small); + } +`;const l=e$3(class extends i$3{constructor(r){if(super(r),r.type!==t.PROPERTY&&r.type!==t.ATTRIBUTE&&r.type!==t.BOOLEAN_ATTRIBUTE)throw Error("The `live` directive is not allowed on child or event bindings");if(!f$1(r))throw Error("`live` bindings can only contain a single expression")}render(r){return r}update(i,[t$1]){if(t$1===T$1||t$1===E$1)return t$1;const o=i.element,l=i.name;if(i.type===t.PROPERTY){if(t$1===o[l])return T$1;}else if(i.type===t.BOOLEAN_ATTRIBUTE){if(!!t$1===o.hasAttribute(l))return T$1;}else if(i.type===t.ATTRIBUTE&&o.getAttribute(l)===t$1+"")return T$1;return m$1(i),t$1}});var SlCheckbox=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this,{value:control=>control.checked?control.value||"on":void 0,defaultValue:control=>control.defaultChecked,setValue:(control,checked)=>control.checked=checked}),this.hasSlotController=new HasSlotController(this,"help-text"),this.hasFocus=!1,this.title="",this.name="",this.size="medium",this.disabled=!1,this.checked=!1,this.indeterminate=!1,this.defaultChecked=!1,this.form="",this.required=!1,this.helpText=""}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}firstUpdated(){this.formControlController.updateValidity()}handleClick(){this.checked=!this.checked,this.indeterminate=!1,this.emit("sl-change")}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleInput(){this.emit("sl-input")}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleDisabledChange(){this.formControlController.setValidity(this.disabled)}handleStateChange(){this.input.checked=this.checked,this.input.indeterminate=this.indeterminate,this.formControlController.updateValidity()}click(){this.input.click()}focus(options){this.input.focus(options)}blur(){this.input.blur()}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.input.reportValidity()}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){const hasHelpTextSlot=this.hasSlotController.test("help-text"),hasHelpText=!!this.helpText||!!hasHelpTextSlot;return x$1` + <div + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--has-help-text":hasHelpText})} + > + <label + part="base" + class=${e$2({checkbox:!0,"checkbox--checked":this.checked,"checkbox--disabled":this.disabled,"checkbox--focused":this.hasFocus,"checkbox--indeterminate":this.indeterminate,"checkbox--small":"small"===this.size,"checkbox--medium":"medium"===this.size,"checkbox--large":"large"===this.size})} + > + <input + class="checkbox__input" + type="checkbox" + title=${this.title} + name=${this.name} + value=${o$6(this.value)} + .indeterminate=${l(this.indeterminate)} + .checked=${l(this.checked)} + .disabled=${this.disabled} + .required=${this.required} + aria-checked=${this.checked?"true":"false"} + aria-describedby="help-text" + @click=${this.handleClick} + @input=${this.handleInput} + @invalid=${this.handleInvalid} + @blur=${this.handleBlur} + @focus=${this.handleFocus} + /> + + <span + part="control${this.checked?" control--checked":""}${this.indeterminate?" control--indeterminate":""}" + class="checkbox__control" + > + ${this.checked?x$1` + <sl-icon part="checked-icon" class="checkbox__checked-icon" library="system" name="check"></sl-icon> + `:""} + ${!this.checked&&this.indeterminate?x$1` + <sl-icon + part="indeterminate-icon" + class="checkbox__indeterminate-icon" + library="system" + name="indeterminate" + ></sl-icon> + `:""} + </span> + + <div part="label" class="checkbox__label"> + <slot></slot> + </div> + </label> + + <div + aria-hidden=${hasHelpText?"false":"true"} + class="form-control__help-text" + id="help-text" + part="form-control-help-text" + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlCheckbox.styles=[component_styles_default,form_control_styles_default,checkbox_styles_default],SlCheckbox.dependencies={"sl-icon":SlIcon},__decorateClass([e$6("input[type=\"checkbox\"]")],SlCheckbox.prototype,"input",2),__decorateClass([r$6()],SlCheckbox.prototype,"hasFocus",2),__decorateClass([n$5()],SlCheckbox.prototype,"title",2),__decorateClass([n$5()],SlCheckbox.prototype,"name",2),__decorateClass([n$5()],SlCheckbox.prototype,"value",2),__decorateClass([n$5({reflect:!0})],SlCheckbox.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCheckbox.prototype,"disabled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCheckbox.prototype,"checked",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCheckbox.prototype,"indeterminate",2),__decorateClass([defaultValue("checked")],SlCheckbox.prototype,"defaultChecked",2),__decorateClass([n$5({reflect:!0})],SlCheckbox.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCheckbox.prototype,"required",2),__decorateClass([n$5({attribute:"help-text"})],SlCheckbox.prototype,"helpText",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlCheckbox.prototype,"handleDisabledChange",1),__decorateClass([watch(["checked","indeterminate"],{waitUntilFirstUpdate:!0})],SlCheckbox.prototype,"handleStateChange",1),SlCheckbox.define("sl-checkbox");function*activeElements(activeElement=document.activeElement){null===activeElement||void 0===activeElement||(yield activeElement,"shadowRoot"in activeElement&&activeElement.shadowRoot&&"closed"!==activeElement.shadowRoot.mode&&(yield*__yieldStar(activeElements(activeElement.shadowRoot.activeElement))))}function getDeepestActiveElement(){return[...activeElements()].pop()}var computedStyleMap=new WeakMap;function getCachedComputedStyle(el){let computedStyle=computedStyleMap.get(el);return computedStyle||(computedStyle=window.getComputedStyle(el,null),computedStyleMap.set(el,computedStyle)),computedStyle}function isVisible(el){if("function"==typeof el.checkVisibility)return el.checkVisibility({checkOpacity:!1,checkVisibilityCSS:!0});const computedStyle=getCachedComputedStyle(el);return"hidden"!==computedStyle.visibility&&"none"!==computedStyle.display}function isOverflowingAndTabbable(el){const computedStyle=getCachedComputedStyle(el),{overflowY,overflowX}=computedStyle;if("scroll"===overflowY||"scroll"===overflowX)return!0;if("auto"!==overflowY||"auto"!==overflowX)return!1;const isOverflowingY=el.scrollHeight>el.clientHeight;if(isOverflowingY&&"auto"===overflowY)return!0;const isOverflowingX=el.scrollWidth>el.clientWidth;return!!(isOverflowingX&&"auto"===overflowX)}function isTabbable(el){const tag=el.tagName.toLowerCase(),tabindex=+el.getAttribute("tabindex"),hasTabindex=el.hasAttribute("tabindex");if(hasTabindex&&(isNaN(tabindex)||-1>=tabindex))return!1;if(el.hasAttribute("disabled"))return!1;if(el.closest("[inert]"))return!1;if("input"===tag&&"radio"===el.getAttribute("type")){const rootNode=el.getRootNode(),findRadios=`input[type='radio'][name="${el.getAttribute("name")}"]`,firstChecked=rootNode.querySelector(`${findRadios}:checked`);if(firstChecked)return firstChecked===el;const firstRadio=rootNode.querySelector(findRadios);return firstRadio===el}if(!isVisible(el))return!1;if(("audio"===tag||"video"===tag)&&el.hasAttribute("controls"))return!0;if(el.hasAttribute("tabindex"))return!0;if(el.hasAttribute("contenteditable")&&"false"!==el.getAttribute("contenteditable"))return!0;const isNativelyTabbable=["button","input","select","textarea","a","audio","video","summary","iframe"].includes(tag);return!!isNativelyTabbable||isOverflowingAndTabbable(el)}function getTabbableBoundary(root){var _a,_b;const tabbableElements=getTabbableElements(root),start=null==(_a=tabbableElements[0])?null:_a,end=null==(_b=tabbableElements[tabbableElements.length-1])?null:_b;return{start,end}}function getSlottedChildrenOutsideRootElement(slotElement,root){var _a;return(null==(_a=slotElement.getRootNode({composed:!0}))?void 0:_a.host)!==root}function getTabbableElements(root){function walk(el){if(el instanceof Element){if(el.hasAttribute("inert")||el.closest("[inert]"))return;if(walkedEls.has(el))return;walkedEls.set(el,!0),!tabbableElements.includes(el)&&isTabbable(el)&&tabbableElements.push(el),el instanceof HTMLSlotElement&&getSlottedChildrenOutsideRootElement(el,root)&&el.assignedElements({flatten:!0}).forEach(assignedEl=>{walk(assignedEl)}),null!==el.shadowRoot&&"open"===el.shadowRoot.mode&&walk(el.shadowRoot)}for(const e of el.children)walk(e)}const walkedEls=new WeakMap,tabbableElements=[];return walk(root),tabbableElements.sort((a,b)=>{const aTabindex=+a.getAttribute("tabindex")||0,bTabindex=+b.getAttribute("tabindex")||0;return bTabindex-aTabindex})}var activeModals=[],Modal=class{constructor(element){this.tabDirection="forward",this.handleFocusIn=()=>{this.isActive()&&this.checkFocus()},this.handleKeyDown=event=>{var _a;if("Tab"!==event.key||this.isExternalActivated)return;if(!this.isActive())return;const currentActiveElement=getDeepestActiveElement();if(this.previousFocus=currentActiveElement,this.previousFocus&&this.possiblyHasTabbableChildren(this.previousFocus))return;this.tabDirection=event.shiftKey?"backward":"forward";const tabbableElements=getTabbableElements(this.element);let currentFocusIndex=tabbableElements.findIndex(el=>el===currentActiveElement);this.previousFocus=this.currentFocus;for(const addition="forward"===this.tabDirection?1:-1;;){currentFocusIndex+addition>=tabbableElements.length?currentFocusIndex=0:0>currentFocusIndex+addition?currentFocusIndex=tabbableElements.length-1:currentFocusIndex+=addition,this.previousFocus=this.currentFocus;const nextFocus=tabbableElements[currentFocusIndex];if("backward"===this.tabDirection&&this.previousFocus&&this.possiblyHasTabbableChildren(this.previousFocus))return;if(nextFocus&&this.possiblyHasTabbableChildren(nextFocus))return;event.preventDefault(),this.currentFocus=nextFocus,null==(_a=this.currentFocus)?void 0:_a.focus({preventScroll:!1});const allActiveElements=[...activeElements()];if(allActiveElements.includes(this.currentFocus)||!allActiveElements.includes(this.previousFocus))break}setTimeout(()=>this.checkFocus())},this.handleKeyUp=()=>{this.tabDirection="forward"},this.element=element,this.elementsWithTabbableControls=["iframe"]}activate(){activeModals.push(this.element),document.addEventListener("focusin",this.handleFocusIn),document.addEventListener("keydown",this.handleKeyDown),document.addEventListener("keyup",this.handleKeyUp)}deactivate(){activeModals=activeModals.filter(modal=>modal!==this.element),this.currentFocus=null,document.removeEventListener("focusin",this.handleFocusIn),document.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("keyup",this.handleKeyUp)}isActive(){return activeModals[activeModals.length-1]===this.element}activateExternal(){this.isExternalActivated=!0}deactivateExternal(){this.isExternalActivated=!1}checkFocus(){if(this.isActive()&&!this.isExternalActivated){const tabbableElements=getTabbableElements(this.element);if(!this.element.matches(":focus-within")){const start=tabbableElements[0],end=tabbableElements[tabbableElements.length-1],target="forward"===this.tabDirection?start:end;"function"==typeof(null==target?void 0:target.focus)&&(this.currentFocus=target,target.focus({preventScroll:!1}))}}}possiblyHasTabbableChildren(element){return this.elementsWithTabbableControls.includes(element.tagName.toLowerCase())||element.hasAttribute("controls")}};function getOffset(element,parent){var _Mathround=Math.round;return{top:_Mathround(element.getBoundingClientRect().top-parent.getBoundingClientRect().top),left:_Mathround(element.getBoundingClientRect().left-parent.getBoundingClientRect().left)}}var locks=new Set;function getScrollbarWidth(){const documentWidth=document.documentElement.clientWidth;return Math.abs(window.innerWidth-documentWidth)}function getExistingBodyPadding(){const padding=+getComputedStyle(document.body).paddingRight.replace(/px/,"");return isNaN(padding)||!padding?0:padding}function lockBodyScrolling(lockingEl){if(locks.add(lockingEl),!document.documentElement.classList.contains("sl-scroll-lock")){const scrollbarWidth=getScrollbarWidth()+getExistingBodyPadding();let scrollbarGutterProperty=getComputedStyle(document.documentElement).scrollbarGutter;scrollbarGutterProperty&&"auto"!==scrollbarGutterProperty||(scrollbarGutterProperty="stable"),2>scrollbarWidth&&(scrollbarGutterProperty=""),document.documentElement.style.setProperty("--sl-scroll-lock-gutter",scrollbarGutterProperty),document.documentElement.classList.add("sl-scroll-lock"),document.documentElement.style.setProperty("--sl-scroll-lock-size",`${scrollbarWidth}px`)}}function unlockBodyScrolling(lockingEl){locks.delete(lockingEl),0===locks.size&&(document.documentElement.classList.remove("sl-scroll-lock"),document.documentElement.style.removeProperty("--sl-scroll-lock-size"))}function scrollIntoView(element,container,direction="vertical",behavior="smooth"){const offset=getOffset(element,container),offsetTop=offset.top+container.scrollTop,offsetLeft=offset.left+container.scrollLeft,minX=container.scrollLeft,maxX=container.scrollLeft+container.offsetWidth,minY=container.scrollTop,maxY=container.scrollTop+container.offsetHeight;("horizontal"===direction||"both"===direction)&&(offsetLeft<minX?container.scrollTo({left:offsetLeft,behavior}):offsetLeft+element.clientWidth>maxX&&container.scrollTo({left:offsetLeft-container.offsetWidth+element.clientWidth,behavior})),("vertical"===direction||"both"===direction)&&(offsetTop<minY?container.scrollTo({top:offsetTop,behavior}):offsetTop+element.clientHeight>maxY&&container.scrollTo({top:offsetTop-container.offsetHeight+element.clientHeight,behavior}))}var dialog_styles_default=i$7` + :host { + --width: 31rem; + --header-spacing: var(--sl-spacing-large); + --body-spacing: var(--sl-spacing-large); + --footer-spacing: var(--sl-spacing-large); + + display: contents; + } + + .dialog { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: var(--sl-z-index-dialog); + } + + .dialog__panel { + display: flex; + flex-direction: column; + z-index: 2; + width: var(--width); + max-width: calc(100% - var(--sl-spacing-2x-large)); + max-height: calc(100% - var(--sl-spacing-2x-large)); + background-color: var(--sl-panel-background-color); + border-radius: var(--sl-border-radius-medium); + box-shadow: var(--sl-shadow-x-large); + } + + .dialog__panel:focus { + outline: none; + } + + /* Ensure there's enough vertical padding for phones that don't update vh when chrome appears (e.g. iPhone) */ + @media screen and (max-width: 420px) { + .dialog__panel { + max-height: 80vh; + } + } + + .dialog--open .dialog__panel { + display: flex; + opacity: 1; + } + + .dialog__header { + flex: 0 0 auto; + display: flex; + } + + .dialog__title { + flex: 1 1 auto; + font: inherit; + font-size: var(--sl-font-size-large); + line-height: var(--sl-line-height-dense); + padding: var(--header-spacing); + margin: 0; + } + + .dialog__header-actions { + flex-shrink: 0; + display: flex; + flex-wrap: wrap; + justify-content: end; + gap: var(--sl-spacing-2x-small); + padding: 0 var(--header-spacing); + } + + .dialog__header-actions sl-icon-button, + .dialog__header-actions ::slotted(sl-icon-button) { + flex: 0 0 auto; + display: flex; + align-items: center; + font-size: var(--sl-font-size-medium); + } + + .dialog__body { + flex: 1 1 auto; + display: block; + padding: var(--body-spacing); + overflow: auto; + -webkit-overflow-scrolling: touch; + } + + .dialog__footer { + flex: 0 0 auto; + text-align: right; + padding: var(--footer-spacing); + } + + .dialog__footer ::slotted(sl-button:not(:first-of-type)) { + margin-inline-start: var(--sl-spacing-x-small); + } + + .dialog:not(.dialog--has-footer) .dialog__footer { + display: none; + } + + .dialog__overlay { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: var(--sl-overlay-background-color); + } + + @media (forced-colors: active) { + .dialog__panel { + border: solid 1px var(--sl-color-neutral-0); + } + } +`,blurActiveElement=elm=>{var _a;const{activeElement}=document;activeElement&&elm.contains(activeElement)&&(null==(_a=document.activeElement)?void 0:_a.blur())},icon_button_styles_default=i$7` + :host { + display: inline-block; + color: var(--sl-color-neutral-600); + } + + .icon-button { + flex: 0 0 auto; + display: flex; + align-items: center; + background: none; + border: none; + border-radius: var(--sl-border-radius-medium); + font-size: inherit; + color: inherit; + padding: var(--sl-spacing-x-small); + cursor: pointer; + transition: var(--sl-transition-x-fast) color; + -webkit-appearance: none; + } + + .icon-button:hover:not(.icon-button--disabled), + .icon-button:focus-visible:not(.icon-button--disabled) { + color: var(--sl-color-primary-600); + } + + .icon-button:active:not(.icon-button--disabled) { + color: var(--sl-color-primary-700); + } + + .icon-button:focus { + outline: none; + } + + .icon-button--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .icon-button:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .icon-button__icon { + pointer-events: none; + } +`,SlIconButton=class extends ShoelaceElement{constructor(){super(...arguments),this.hasFocus=!1,this.label="",this.disabled=!1}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleClick(event){this.disabled&&(event.preventDefault(),event.stopPropagation())}click(){this.button.click()}focus(options){this.button.focus(options)}blur(){this.button.blur()}render(){const isLink=!!this.href,tag=isLink?i$2`a`:i$2`button`;return u$1` + <${tag} + part="base" + class=${e$2({"icon-button":!0,"icon-button--disabled":!isLink&&this.disabled,"icon-button--focused":this.hasFocus})} + ?disabled=${o$6(isLink?void 0:this.disabled)} + type=${o$6(isLink?void 0:"button")} + href=${o$6(isLink?this.href:void 0)} + target=${o$6(isLink?this.target:void 0)} + download=${o$6(isLink?this.download:void 0)} + rel=${o$6(isLink&&this.target?"noreferrer noopener":void 0)} + role=${o$6(isLink?void 0:"button")} + aria-disabled=${this.disabled?"true":"false"} + aria-label="${this.label}" + tabindex=${this.disabled?"-1":"0"} + @blur=${this.handleBlur} + @focus=${this.handleFocus} + @click=${this.handleClick} + > + <sl-icon + class="icon-button__icon" + name=${o$6(this.name)} + library=${o$6(this.library)} + src=${o$6(this.src)} + aria-hidden="true" + ></sl-icon> + </${tag}> + `}};SlIconButton.styles=[component_styles_default,icon_button_styles_default],SlIconButton.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".icon-button")],SlIconButton.prototype,"button",2),__decorateClass([r$6()],SlIconButton.prototype,"hasFocus",2),__decorateClass([n$5()],SlIconButton.prototype,"name",2),__decorateClass([n$5()],SlIconButton.prototype,"library",2),__decorateClass([n$5()],SlIconButton.prototype,"src",2),__decorateClass([n$5()],SlIconButton.prototype,"href",2),__decorateClass([n$5()],SlIconButton.prototype,"target",2),__decorateClass([n$5()],SlIconButton.prototype,"download",2),__decorateClass([n$5()],SlIconButton.prototype,"label",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlIconButton.prototype,"disabled",2);var defaultAnimationRegistry=new Map,customAnimationRegistry=new WeakMap;function ensureAnimation(animation){return null==animation?{keyframes:[],options:{duration:0}}:animation}function getLogicalAnimation(animation,dir){return"rtl"===dir.toLowerCase()?{keyframes:animation.rtlKeyframes||animation.keyframes,options:animation.options}:animation}function setDefaultAnimation(animationName,animation){defaultAnimationRegistry.set(animationName,ensureAnimation(animation))}function getAnimation(el,animationName,options){const customAnimation=customAnimationRegistry.get(el);if(null==customAnimation?void 0:customAnimation[animationName])return getLogicalAnimation(customAnimation[animationName],options.dir);const defaultAnimation=defaultAnimationRegistry.get(animationName);return defaultAnimation?getLogicalAnimation(defaultAnimation,options.dir):{keyframes:[],options:{duration:0}}}function waitForEvent(el,eventName){return new Promise(resolve=>{function done(event){event.target===el&&(el.removeEventListener(eventName,done),resolve())}el.addEventListener(eventName,done)})}function animateTo(el,keyframes,options){return new Promise(resolve=>{if((null==options?void 0:options.duration)===1/0)throw new Error("Promise-based animations must be finite.");const animation=el.animate(keyframes,__spreadProps(__spreadValues({},options),{duration:prefersReducedMotion()?0:options.duration}));animation.addEventListener("cancel",resolve,{once:!0}),animation.addEventListener("finish",resolve,{once:!0})})}function parseDuration(delay){return delay=delay.toString().toLowerCase(),-1<delay.indexOf("ms")?parseFloat(delay):-1<delay.indexOf("s")?1e3*parseFloat(delay):parseFloat(delay)}function prefersReducedMotion(){const query=window.matchMedia("(prefers-reduced-motion: reduce)");return query.matches}function stopAnimations(el){return Promise.all(el.getAnimations().map(animation=>new Promise(resolve=>{animation.cancel(),requestAnimationFrame(resolve)})))}function shimKeyframesHeightAuto(keyframes,calculatedHeight){return keyframes.map(keyframe=>__spreadProps(__spreadValues({},keyframe),{height:"auto"===keyframe.height?`${calculatedHeight}px`:keyframe.height}))}var SlDialog=class extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"footer"),this.localize=new LocalizeController(this),this.modal=new Modal(this),this.open=!1,this.label="",this.noHeader=!1,this.handleDocumentKeyDown=event=>{"Escape"===event.key&&this.modal.isActive()&&this.open&&(event.stopPropagation(),this.requestClose("keyboard"))}}firstUpdated(){this.dialog.hidden=!this.open,this.open&&(this.addOpenListeners(),this.modal.activate(),lockBodyScrolling(this))}disconnectedCallback(){super.disconnectedCallback(),this.modal.deactivate(),unlockBodyScrolling(this),this.removeOpenListeners()}requestClose(source){const slRequestClose=this.emit("sl-request-close",{cancelable:!0,detail:{source}});if(slRequestClose.defaultPrevented){const animation=getAnimation(this,"dialog.denyClose",{dir:this.localize.dir()});return void animateTo(this.panel,animation.keyframes,animation.options)}this.hide()}addOpenListeners(){var _a;"CloseWatcher"in window?(null==(_a=this.closeWatcher)?void 0:_a.destroy(),this.closeWatcher=new CloseWatcher,this.closeWatcher.onclose=()=>this.requestClose("keyboard")):document.addEventListener("keydown",this.handleDocumentKeyDown)}removeOpenListeners(){var _a;null==(_a=this.closeWatcher)?void 0:_a.destroy(),document.removeEventListener("keydown",this.handleDocumentKeyDown)}async handleOpenChange(){if(this.open){this.emit("sl-show"),this.addOpenListeners(),this.originalTrigger=document.activeElement,this.modal.activate(),lockBodyScrolling(this);const autoFocusTarget=this.querySelector("[autofocus]");autoFocusTarget&&autoFocusTarget.removeAttribute("autofocus"),await Promise.all([stopAnimations(this.dialog),stopAnimations(this.overlay)]),this.dialog.hidden=!1,requestAnimationFrame(()=>{const slInitialFocus=this.emit("sl-initial-focus",{cancelable:!0});slInitialFocus.defaultPrevented||(autoFocusTarget?autoFocusTarget.focus({preventScroll:!0}):this.panel.focus({preventScroll:!0})),autoFocusTarget&&autoFocusTarget.setAttribute("autofocus","")});const panelAnimation=getAnimation(this,"dialog.show",{dir:this.localize.dir()}),overlayAnimation=getAnimation(this,"dialog.overlay.show",{dir:this.localize.dir()});await Promise.all([animateTo(this.panel,panelAnimation.keyframes,panelAnimation.options),animateTo(this.overlay,overlayAnimation.keyframes,overlayAnimation.options)]),this.emit("sl-after-show")}else{blurActiveElement(this),this.emit("sl-hide"),this.removeOpenListeners(),this.modal.deactivate(),await Promise.all([stopAnimations(this.dialog),stopAnimations(this.overlay)]);const panelAnimation=getAnimation(this,"dialog.hide",{dir:this.localize.dir()}),overlayAnimation=getAnimation(this,"dialog.overlay.hide",{dir:this.localize.dir()});await Promise.all([animateTo(this.overlay,overlayAnimation.keyframes,overlayAnimation.options).then(()=>{this.overlay.hidden=!0}),animateTo(this.panel,panelAnimation.keyframes,panelAnimation.options).then(()=>{this.panel.hidden=!0})]),this.dialog.hidden=!0,this.overlay.hidden=!1,this.panel.hidden=!1,unlockBodyScrolling(this);const trigger=this.originalTrigger;"function"==typeof(null==trigger?void 0:trigger.focus)&&setTimeout(()=>trigger.focus()),this.emit("sl-after-hide")}}async show(){if(!this.open)return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open)return this.open=!1,waitForEvent(this,"sl-after-hide")}render(){return x$1` + <div + part="base" + class=${e$2({dialog:!0,"dialog--open":this.open,"dialog--has-footer":this.hasSlotController.test("footer")})} + > + <div part="overlay" class="dialog__overlay" @click=${()=>this.requestClose("overlay")} tabindex="-1"></div> + + <div + part="panel" + class="dialog__panel" + role="dialog" + aria-modal="true" + aria-hidden=${this.open?"false":"true"} + aria-label=${o$6(this.noHeader?this.label:void 0)} + aria-labelledby=${o$6(this.noHeader?void 0:"title")} + tabindex="-1" + > + ${this.noHeader?"":x$1` + <header part="header" class="dialog__header"> + <h2 part="title" class="dialog__title" id="title"> + <slot name="label"> ${0<this.label.length?this.label:String.fromCharCode(65279)} </slot> + </h2> + <div part="header-actions" class="dialog__header-actions"> + <slot name="header-actions"></slot> + <sl-icon-button + part="close-button" + exportparts="base:close-button__base" + class="dialog__close" + name="x-lg" + label=${this.localize.term("close")} + library="system" + @click="${()=>this.requestClose("close-button")}" + ></sl-icon-button> + </div> + </header> + `} + ${""} + <div part="body" class="dialog__body" tabindex="-1"><slot></slot></div> + + <footer part="footer" class="dialog__footer"> + <slot name="footer"></slot> + </footer> + </div> + </div> + `}};SlDialog.styles=[component_styles_default,dialog_styles_default],SlDialog.dependencies={"sl-icon-button":SlIconButton},__decorateClass([e$6(".dialog")],SlDialog.prototype,"dialog",2),__decorateClass([e$6(".dialog__panel")],SlDialog.prototype,"panel",2),__decorateClass([e$6(".dialog__overlay")],SlDialog.prototype,"overlay",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDialog.prototype,"open",2),__decorateClass([n$5({reflect:!0})],SlDialog.prototype,"label",2),__decorateClass([n$5({attribute:"no-header",type:Boolean,reflect:!0})],SlDialog.prototype,"noHeader",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlDialog.prototype,"handleOpenChange",1),setDefaultAnimation("dialog.show",{keyframes:[{opacity:0,scale:.8},{opacity:1,scale:1}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("dialog.hide",{keyframes:[{opacity:1,scale:1},{opacity:0,scale:.8}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("dialog.denyClose",{keyframes:[{scale:1},{scale:1.02},{scale:1}],options:{duration:250}}),setDefaultAnimation("dialog.overlay.show",{keyframes:[{opacity:0},{opacity:1}],options:{duration:250}}),setDefaultAnimation("dialog.overlay.hide",{keyframes:[{opacity:1},{opacity:0}],options:{duration:250}}),SlDialog.define("sl-dialog");var drawer_styles_default=i$7` + :host { + --size: 25rem; + --header-spacing: var(--sl-spacing-large); + --body-spacing: var(--sl-spacing-large); + --footer-spacing: var(--sl-spacing-large); + + display: contents; + } + + .drawer { + top: 0; + inset-inline-start: 0; + width: 100%; + height: 100%; + pointer-events: none; + overflow: hidden; + } + + .drawer--contained { + position: absolute; + z-index: initial; + } + + .drawer--fixed { + position: fixed; + z-index: var(--sl-z-index-drawer); + } + + .drawer__panel { + position: absolute; + display: flex; + flex-direction: column; + z-index: 2; + max-width: 100%; + max-height: 100%; + background-color: var(--sl-panel-background-color); + box-shadow: var(--sl-shadow-x-large); + overflow: auto; + pointer-events: all; + } + + .drawer__panel:focus { + outline: none; + } + + .drawer--top .drawer__panel { + top: 0; + inset-inline-end: auto; + bottom: auto; + inset-inline-start: 0; + width: 100%; + height: var(--size); + } + + .drawer--end .drawer__panel { + top: 0; + inset-inline-end: 0; + bottom: auto; + inset-inline-start: auto; + width: var(--size); + height: 100%; + } + + .drawer--bottom .drawer__panel { + top: auto; + inset-inline-end: auto; + bottom: 0; + inset-inline-start: 0; + width: 100%; + height: var(--size); + } + + .drawer--start .drawer__panel { + top: 0; + inset-inline-end: auto; + bottom: auto; + inset-inline-start: 0; + width: var(--size); + height: 100%; + } + + .drawer__header { + display: flex; + } + + .drawer__title { + flex: 1 1 auto; + font: inherit; + font-size: var(--sl-font-size-large); + line-height: var(--sl-line-height-dense); + padding: var(--header-spacing); + margin: 0; + } + + .drawer__header-actions { + flex-shrink: 0; + display: flex; + flex-wrap: wrap; + justify-content: end; + gap: var(--sl-spacing-2x-small); + padding: 0 var(--header-spacing); + } + + .drawer__header-actions sl-icon-button, + .drawer__header-actions ::slotted(sl-icon-button) { + flex: 0 0 auto; + display: flex; + align-items: center; + font-size: var(--sl-font-size-medium); + } + + .drawer__body { + flex: 1 1 auto; + display: block; + padding: var(--body-spacing); + overflow: auto; + -webkit-overflow-scrolling: touch; + } + + .drawer__footer { + text-align: right; + padding: var(--footer-spacing); + } + + .drawer__footer ::slotted(sl-button:not(:last-of-type)) { + margin-inline-end: var(--sl-spacing-x-small); + } + + .drawer:not(.drawer--has-footer) .drawer__footer { + display: none; + } + + .drawer__overlay { + display: block; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: var(--sl-overlay-background-color); + pointer-events: all; + } + + .drawer--contained .drawer__overlay { + display: none; + } + + @media (forced-colors: active) { + .drawer__panel { + border: solid 1px var(--sl-color-neutral-0); + } + } +`;function uppercaseFirstLetter(string){return string.charAt(0).toUpperCase()+string.slice(1)}var SlDrawer=class extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"footer"),this.localize=new LocalizeController(this),this.modal=new Modal(this),this.open=!1,this.label="",this.placement="end",this.contained=!1,this.noHeader=!1,this.handleDocumentKeyDown=event=>{this.contained||"Escape"===event.key&&this.modal.isActive()&&this.open&&(event.stopImmediatePropagation(),this.requestClose("keyboard"))}}firstUpdated(){this.drawer.hidden=!this.open,this.open&&(this.addOpenListeners(),!this.contained&&(this.modal.activate(),lockBodyScrolling(this)))}disconnectedCallback(){super.disconnectedCallback(),unlockBodyScrolling(this),this.removeOpenListeners()}requestClose(source){const slRequestClose=this.emit("sl-request-close",{cancelable:!0,detail:{source}});if(slRequestClose.defaultPrevented){const animation=getAnimation(this,"drawer.denyClose",{dir:this.localize.dir()});return void animateTo(this.panel,animation.keyframes,animation.options)}this.hide()}addOpenListeners(){var _a;"CloseWatcher"in window?(null==(_a=this.closeWatcher)?void 0:_a.destroy(),!this.contained&&(this.closeWatcher=new CloseWatcher,this.closeWatcher.onclose=()=>this.requestClose("keyboard"))):document.addEventListener("keydown",this.handleDocumentKeyDown)}removeOpenListeners(){var _a;document.removeEventListener("keydown",this.handleDocumentKeyDown),null==(_a=this.closeWatcher)?void 0:_a.destroy()}async handleOpenChange(){if(this.open){this.emit("sl-show"),this.addOpenListeners(),this.originalTrigger=document.activeElement,this.contained||(this.modal.activate(),lockBodyScrolling(this));const autoFocusTarget=this.querySelector("[autofocus]");autoFocusTarget&&autoFocusTarget.removeAttribute("autofocus"),await Promise.all([stopAnimations(this.drawer),stopAnimations(this.overlay)]),this.drawer.hidden=!1,requestAnimationFrame(()=>{const slInitialFocus=this.emit("sl-initial-focus",{cancelable:!0});slInitialFocus.defaultPrevented||(autoFocusTarget?autoFocusTarget.focus({preventScroll:!0}):this.panel.focus({preventScroll:!0})),autoFocusTarget&&autoFocusTarget.setAttribute("autofocus","")});const panelAnimation=getAnimation(this,`drawer.show${uppercaseFirstLetter(this.placement)}`,{dir:this.localize.dir()}),overlayAnimation=getAnimation(this,"drawer.overlay.show",{dir:this.localize.dir()});await Promise.all([animateTo(this.panel,panelAnimation.keyframes,panelAnimation.options),animateTo(this.overlay,overlayAnimation.keyframes,overlayAnimation.options)]),this.emit("sl-after-show")}else{blurActiveElement(this),this.emit("sl-hide"),this.removeOpenListeners(),this.contained||(this.modal.deactivate(),unlockBodyScrolling(this)),await Promise.all([stopAnimations(this.drawer),stopAnimations(this.overlay)]);const panelAnimation=getAnimation(this,`drawer.hide${uppercaseFirstLetter(this.placement)}`,{dir:this.localize.dir()}),overlayAnimation=getAnimation(this,"drawer.overlay.hide",{dir:this.localize.dir()});await Promise.all([animateTo(this.overlay,overlayAnimation.keyframes,overlayAnimation.options).then(()=>{this.overlay.hidden=!0}),animateTo(this.panel,panelAnimation.keyframes,panelAnimation.options).then(()=>{this.panel.hidden=!0})]),this.drawer.hidden=!0,this.overlay.hidden=!1,this.panel.hidden=!1;const trigger=this.originalTrigger;"function"==typeof(null==trigger?void 0:trigger.focus)&&setTimeout(()=>trigger.focus()),this.emit("sl-after-hide")}}handleNoModalChange(){this.open&&!this.contained&&(this.modal.activate(),lockBodyScrolling(this)),this.open&&this.contained&&(this.modal.deactivate(),unlockBodyScrolling(this))}async show(){if(!this.open)return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open)return this.open=!1,waitForEvent(this,"sl-after-hide")}render(){return x$1` + <div + part="base" + class=${e$2({drawer:!0,"drawer--open":this.open,"drawer--top":"top"===this.placement,"drawer--end":"end"===this.placement,"drawer--bottom":"bottom"===this.placement,"drawer--start":"start"===this.placement,"drawer--contained":this.contained,"drawer--fixed":!this.contained,"drawer--rtl":"rtl"===this.localize.dir(),"drawer--has-footer":this.hasSlotController.test("footer")})} + > + <div part="overlay" class="drawer__overlay" @click=${()=>this.requestClose("overlay")} tabindex="-1"></div> + + <div + part="panel" + class="drawer__panel" + role="dialog" + aria-modal="true" + aria-hidden=${this.open?"false":"true"} + aria-label=${o$6(this.noHeader?this.label:void 0)} + aria-labelledby=${o$6(this.noHeader?void 0:"title")} + tabindex="0" + > + ${this.noHeader?"":x$1` + <header part="header" class="drawer__header"> + <h2 part="title" class="drawer__title" id="title"> + <!-- If there's no label, use an invisible character to prevent the header from collapsing --> + <slot name="label"> ${0<this.label.length?this.label:String.fromCharCode(65279)} </slot> + </h2> + <div part="header-actions" class="drawer__header-actions"> + <slot name="header-actions"></slot> + <sl-icon-button + part="close-button" + exportparts="base:close-button__base" + class="drawer__close" + name="x-lg" + label=${this.localize.term("close")} + library="system" + @click=${()=>this.requestClose("close-button")} + ></sl-icon-button> + </div> + </header> + `} + + <slot part="body" class="drawer__body"></slot> + + <footer part="footer" class="drawer__footer"> + <slot name="footer"></slot> + </footer> + </div> + </div> + `}};SlDrawer.styles=[component_styles_default,drawer_styles_default],SlDrawer.dependencies={"sl-icon-button":SlIconButton},__decorateClass([e$6(".drawer")],SlDrawer.prototype,"drawer",2),__decorateClass([e$6(".drawer__panel")],SlDrawer.prototype,"panel",2),__decorateClass([e$6(".drawer__overlay")],SlDrawer.prototype,"overlay",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDrawer.prototype,"open",2),__decorateClass([n$5({reflect:!0})],SlDrawer.prototype,"label",2),__decorateClass([n$5({reflect:!0})],SlDrawer.prototype,"placement",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDrawer.prototype,"contained",2),__decorateClass([n$5({attribute:"no-header",type:Boolean,reflect:!0})],SlDrawer.prototype,"noHeader",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlDrawer.prototype,"handleOpenChange",1),__decorateClass([watch("contained",{waitUntilFirstUpdate:!0})],SlDrawer.prototype,"handleNoModalChange",1),setDefaultAnimation("drawer.showTop",{keyframes:[{opacity:0,translate:"0 -100%"},{opacity:1,translate:"0 0"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.hideTop",{keyframes:[{opacity:1,translate:"0 0"},{opacity:0,translate:"0 -100%"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.showEnd",{keyframes:[{opacity:0,translate:"100%"},{opacity:1,translate:"0"}],rtlKeyframes:[{opacity:0,translate:"-100%"},{opacity:1,translate:"0"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.hideEnd",{keyframes:[{opacity:1,translate:"0"},{opacity:0,translate:"100%"}],rtlKeyframes:[{opacity:1,translate:"0"},{opacity:0,translate:"-100%"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.showBottom",{keyframes:[{opacity:0,translate:"0 100%"},{opacity:1,translate:"0 0"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.hideBottom",{keyframes:[{opacity:1,translate:"0 0"},{opacity:0,translate:"0 100%"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.showStart",{keyframes:[{opacity:0,translate:"-100%"},{opacity:1,translate:"0"}],rtlKeyframes:[{opacity:0,translate:"100%"},{opacity:1,translate:"0"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.hideStart",{keyframes:[{opacity:1,translate:"0"},{opacity:0,translate:"-100%"}],rtlKeyframes:[{opacity:1,translate:"0"},{opacity:0,translate:"100%"}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("drawer.denyClose",{keyframes:[{scale:1},{scale:1.01},{scale:1}],options:{duration:250}}),setDefaultAnimation("drawer.overlay.show",{keyframes:[{opacity:0},{opacity:1}],options:{duration:250}}),setDefaultAnimation("drawer.overlay.hide",{keyframes:[{opacity:1},{opacity:0}],options:{duration:250}}),SlDrawer.define("sl-drawer");var details_styles_default=i$7` + :host { + display: block; + } + + .details { + border: solid 1px var(--sl-color-neutral-200); + border-radius: var(--sl-border-radius-medium); + background-color: var(--sl-color-neutral-0); + overflow-anchor: none; + } + + .details--disabled { + opacity: 0.5; + } + + .details__header { + display: flex; + align-items: center; + border-radius: inherit; + padding: var(--sl-spacing-medium); + user-select: none; + -webkit-user-select: none; + cursor: pointer; + } + + .details__header::-webkit-details-marker { + display: none; + } + + .details__header:focus { + outline: none; + } + + .details__header:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: calc(1px + var(--sl-focus-ring-offset)); + } + + .details--disabled .details__header { + cursor: not-allowed; + } + + .details--disabled .details__header:focus-visible { + outline: none; + box-shadow: none; + } + + .details__summary { + flex: 1 1 auto; + display: flex; + align-items: center; + } + + .details__summary-icon { + flex: 0 0 auto; + display: flex; + align-items: center; + transition: var(--sl-transition-medium) rotate ease; + } + + .details--open .details__summary-icon { + rotate: 90deg; + } + + .details--open.details--rtl .details__summary-icon { + rotate: -90deg; + } + + .details--open slot[name='expand-icon'], + .details:not(.details--open) slot[name='collapse-icon'] { + display: none; + } + + .details__body { + overflow: hidden; + } + + .details__content { + display: block; + padding: var(--sl-spacing-medium); + } +`,SlDetails=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.open=!1,this.disabled=!1}firstUpdated(){this.body.style.height=this.open?"auto":"0",this.open&&(this.details.open=!0),this.detailsObserver=new MutationObserver(changes=>{for(const change of changes)"attributes"===change.type&&"open"===change.attributeName&&(this.details.open?this.show():this.hide())}),this.detailsObserver.observe(this.details,{attributes:!0})}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.detailsObserver)?void 0:_a.disconnect()}handleSummaryClick(event){event.preventDefault(),this.disabled||(this.open?this.hide():this.show(),this.header.focus())}handleSummaryKeyDown(event){("Enter"===event.key||" "===event.key)&&(event.preventDefault(),this.open?this.hide():this.show()),("ArrowUp"===event.key||"ArrowLeft"===event.key)&&(event.preventDefault(),this.hide()),("ArrowDown"===event.key||"ArrowRight"===event.key)&&(event.preventDefault(),this.show())}async handleOpenChange(){if(this.open){this.details.open=!0;const slShow=this.emit("sl-show",{cancelable:!0});if(slShow.defaultPrevented)return this.open=!1,void(this.details.open=!1);await stopAnimations(this.body);const{keyframes,options}=getAnimation(this,"details.show",{dir:this.localize.dir()});await animateTo(this.body,shimKeyframesHeightAuto(keyframes,this.body.scrollHeight),options),this.body.style.height="auto",this.emit("sl-after-show")}else{const slHide=this.emit("sl-hide",{cancelable:!0});if(slHide.defaultPrevented)return this.details.open=!0,void(this.open=!0);await stopAnimations(this.body);const{keyframes,options}=getAnimation(this,"details.hide",{dir:this.localize.dir()});await animateTo(this.body,shimKeyframesHeightAuto(keyframes,this.body.scrollHeight),options),this.body.style.height="auto",this.details.open=!1,this.emit("sl-after-hide")}}async show(){if(!(this.open||this.disabled))return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open&&!this.disabled)return this.open=!1,waitForEvent(this,"sl-after-hide")}render(){const isRtl="rtl"===this.localize.dir();return x$1` + <details + part="base" + class=${e$2({details:!0,"details--open":this.open,"details--disabled":this.disabled,"details--rtl":isRtl})} + > + <summary + part="header" + id="header" + class="details__header" + role="button" + aria-expanded=${this.open?"true":"false"} + aria-controls="content" + aria-disabled=${this.disabled?"true":"false"} + tabindex=${this.disabled?"-1":"0"} + @click=${this.handleSummaryClick} + @keydown=${this.handleSummaryKeyDown} + > + <slot name="summary" part="summary" class="details__summary">${this.summary}</slot> + + <span part="summary-icon" class="details__summary-icon"> + <slot name="expand-icon"> + <sl-icon library="system" name=${isRtl?"chevron-left":"chevron-right"}></sl-icon> + </slot> + <slot name="collapse-icon"> + <sl-icon library="system" name=${isRtl?"chevron-left":"chevron-right"}></sl-icon> + </slot> + </span> + </summary> + + <div class="details__body" role="region" aria-labelledby="header"> + <slot part="content" id="content" class="details__content"></slot> + </div> + </details> + `}};SlDetails.styles=[component_styles_default,details_styles_default],SlDetails.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".details")],SlDetails.prototype,"details",2),__decorateClass([e$6(".details__header")],SlDetails.prototype,"header",2),__decorateClass([e$6(".details__body")],SlDetails.prototype,"body",2),__decorateClass([e$6(".details__expand-icon-slot")],SlDetails.prototype,"expandIconSlot",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDetails.prototype,"open",2),__decorateClass([n$5()],SlDetails.prototype,"summary",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDetails.prototype,"disabled",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlDetails.prototype,"handleOpenChange",1),setDefaultAnimation("details.show",{keyframes:[{height:"0",opacity:"0"},{height:"auto",opacity:"1"}],options:{duration:250,easing:"linear"}}),setDefaultAnimation("details.hide",{keyframes:[{height:"auto",opacity:"1"},{height:"0",opacity:"0"}],options:{duration:250,easing:"linear"}}),SlDetails.define("sl-details");var dropdown_styles_default=i$7` + :host { + display: inline-block; + } + + .dropdown::part(popup) { + z-index: var(--sl-z-index-dropdown); + } + + .dropdown[data-current-placement^='top']::part(popup) { + transform-origin: bottom; + } + + .dropdown[data-current-placement^='bottom']::part(popup) { + transform-origin: top; + } + + .dropdown[data-current-placement^='left']::part(popup) { + transform-origin: right; + } + + .dropdown[data-current-placement^='right']::part(popup) { + transform-origin: left; + } + + .dropdown__trigger { + display: block; + } + + .dropdown__panel { + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + box-shadow: var(--sl-shadow-large); + border-radius: var(--sl-border-radius-medium); + pointer-events: none; + } + + .dropdown--open .dropdown__panel { + display: block; + pointer-events: all; + } + + /* When users slot a menu, make sure it conforms to the popup's auto-size */ + ::slotted(sl-menu) { + max-width: var(--auto-size-available-width) !important; + max-height: var(--auto-size-available-height) !important; + } +`,popup_styles_default=i$7` + :host { + --arrow-color: var(--sl-color-neutral-1000); + --arrow-size: 6px; + + /* + * These properties are computed to account for the arrow's dimensions after being rotated 45º. The constant + * 0.7071 is derived from sin(45), which is the diagonal size of the arrow's container after rotating. + */ + --arrow-size-diagonal: calc(var(--arrow-size) * 0.7071); + --arrow-padding-offset: calc(var(--arrow-size-diagonal) - var(--arrow-size)); + + display: contents; + } + + .popup { + position: absolute; + isolation: isolate; + max-width: var(--auto-size-available-width, none); + max-height: var(--auto-size-available-height, none); + } + + .popup--fixed { + position: fixed; + } + + .popup:not(.popup--active) { + display: none; + } + + .popup__arrow { + position: absolute; + width: calc(var(--arrow-size-diagonal) * 2); + height: calc(var(--arrow-size-diagonal) * 2); + rotate: 45deg; + background: var(--arrow-color); + z-index: -1; + } + + /* Hover bridge */ + .popup-hover-bridge:not(.popup-hover-bridge--visible) { + display: none; + } + + .popup-hover-bridge { + position: fixed; + z-index: calc(var(--sl-z-index-dropdown) - 1); + top: 0; + right: 0; + bottom: 0; + left: 0; + clip-path: polygon( + var(--hover-bridge-top-left-x, 0) var(--hover-bridge-top-left-y, 0), + var(--hover-bridge-top-right-x, 0) var(--hover-bridge-top-right-y, 0), + var(--hover-bridge-bottom-right-x, 0) var(--hover-bridge-bottom-right-y, 0), + var(--hover-bridge-bottom-left-x, 0) var(--hover-bridge-bottom-left-y, 0) + ); + } +`;const min=Math.min,max=Math.max,round=Math.round,floor=Math.floor,createCoords=v=>({x:v,y:v}),oppositeSideMap={left:"right",right:"left",bottom:"top",top:"bottom"},oppositeAlignmentMap={start:"end",end:"start"};function clamp$1(start,value,end){return max(start,min(value,end))}function evaluate(value,param){return"function"==typeof value?value(param):value}function getSide(placement){return placement.split("-")[0]}function getAlignment(placement){return placement.split("-")[1]}function getOppositeAxis(axis){return"x"===axis?"y":"x"}function getAxisLength(axis){return"y"===axis?"height":"width"}const yAxisSides=new Set(["top","bottom"]);function getSideAxis(placement){return yAxisSides.has(getSide(placement))?"y":"x"}function getAlignmentAxis(placement){return getOppositeAxis(getSideAxis(placement))}function getAlignmentSides(placement,rects,rtl){void 0===rtl&&(rtl=!1);const alignment=getAlignment(placement),alignmentAxis=getAlignmentAxis(placement),length=getAxisLength(alignmentAxis);let mainAlignmentSide="x"===alignmentAxis?alignment===(rtl?"end":"start")?"right":"left":"start"===alignment?"bottom":"top";return rects.reference[length]>rects.floating[length]&&(mainAlignmentSide=getOppositePlacement(mainAlignmentSide)),[mainAlignmentSide,getOppositePlacement(mainAlignmentSide)]}function getExpandedPlacements(placement){const oppositePlacement=getOppositePlacement(placement);return[getOppositeAlignmentPlacement(placement),oppositePlacement,getOppositeAlignmentPlacement(oppositePlacement)]}function getOppositeAlignmentPlacement(placement){return placement.replace(/start|end/g,alignment=>oppositeAlignmentMap[alignment])}const lrPlacement=["left","right"],rlPlacement=["right","left"],tbPlacement=["top","bottom"],btPlacement=["bottom","top"];function getSideList(side,isStart,rtl){return"top"===side||"bottom"===side?rtl?isStart?rlPlacement:lrPlacement:isStart?lrPlacement:rlPlacement:"left"===side||"right"===side?isStart?tbPlacement:btPlacement:[]}function getOppositeAxisPlacements(placement,flipAlignment,direction,rtl){const alignment=getAlignment(placement);let list=getSideList(getSide(placement),"start"===direction,rtl);return alignment&&(list=list.map(side=>side+"-"+alignment),flipAlignment&&(list=list.concat(list.map(getOppositeAlignmentPlacement)))),list}function getOppositePlacement(placement){return placement.replace(/left|right|bottom|top/g,side=>oppositeSideMap[side])}function expandPaddingObject(padding){return{top:0,right:0,bottom:0,left:0,...padding}}function getPaddingObject(padding){return"number"==typeof padding?{top:padding,right:padding,bottom:padding,left:padding}:expandPaddingObject(padding)}function rectToClientRect(rect){const{x,y,width,height}=rect;return{width,height,top:y,left:x,right:x+width,bottom:y+height,x,y}}function computeCoordsFromPlacement(_ref,placement,rtl){let{reference,floating}=_ref;const sideAxis=getSideAxis(placement),alignmentAxis=getAlignmentAxis(placement),alignLength=getAxisLength(alignmentAxis),side=getSide(placement),isVertical="y"===sideAxis,commonX=reference.x+reference.width/2-floating.width/2,commonY=reference.y+reference.height/2-floating.height/2,commonAlign=reference[alignLength]/2-floating[alignLength]/2;let coords;switch(coords="top"===side?{x:commonX,y:reference.y-floating.height}:"bottom"===side?{x:commonX,y:reference.y+reference.height}:"right"===side?{x:reference.x+reference.width,y:commonY}:"left"===side?{x:reference.x-floating.width,y:commonY}:{x:reference.x,y:reference.y},getAlignment(placement)){case"start":coords[alignmentAxis]-=commonAlign*(rtl&&isVertical?-1:1);break;case"end":coords[alignmentAxis]+=commonAlign*(rtl&&isVertical?-1:1)}return coords}const computePosition$1=async(reference,floating,config)=>{const{placement="bottom",strategy="absolute",middleware=[],platform}=config,validMiddleware=middleware.filter(Boolean),rtl=await(null==platform.isRTL?void 0:platform.isRTL(floating));let rects=await platform.getElementRects({reference,floating,strategy}),{x,y}=computeCoordsFromPlacement(rects,placement,rtl),statefulPlacement=placement,middlewareData={},resetCount=0;for(let i=0;i<validMiddleware.length;i++){const{name,fn}=validMiddleware[i],{x:nextX,y:nextY,data,reset}=await fn({x,y,initialPlacement:placement,placement:statefulPlacement,strategy,middlewareData,rects,platform,elements:{reference,floating}});x=null==nextX?x:nextX,y=null==nextY?y:nextY,middlewareData={...middlewareData,[name]:{...middlewareData[name],...data}},reset&&50>=resetCount&&(resetCount++,"object"==typeof reset&&(reset.placement&&(statefulPlacement=reset.placement),reset.rects&&(rects=!0===reset.rects?await platform.getElementRects({reference,floating,strategy}):reset.rects),{x,y}=computeCoordsFromPlacement(rects,statefulPlacement,rtl)),i=-1)}return{x,y,placement:statefulPlacement,strategy,middlewareData}};async function detectOverflow(state,options){var _await$platform$isEle;void 0===options&&(options={});const{x,y,platform,rects,elements,strategy}=state,{boundary="clippingAncestors",rootBoundary="viewport",elementContext="floating",altBoundary=!1,padding=0}=evaluate(options,state),paddingObject=getPaddingObject(padding),altContext="floating"===elementContext?"reference":"floating",element=elements[altBoundary?altContext:elementContext],clippingClientRect=rectToClientRect(await platform.getClippingRect({element:!(null!=(_await$platform$isEle=await(null==platform.isElement?void 0:platform.isElement(element))))||_await$platform$isEle?element:element.contextElement||(await(null==platform.getDocumentElement?void 0:platform.getDocumentElement(elements.floating))),boundary,rootBoundary,strategy})),rect="floating"===elementContext?{x,y,width:rects.floating.width,height:rects.floating.height}:rects.reference,offsetParent=await(null==platform.getOffsetParent?void 0:platform.getOffsetParent(elements.floating)),offsetScale=(await(null==platform.isElement?void 0:platform.isElement(offsetParent)))?(await(null==platform.getScale?void 0:platform.getScale(offsetParent)))||{x:1,y:1}:{x:1,y:1},elementClientRect=rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect?await platform.convertOffsetParentRelativeRectToViewportRelativeRect({elements,rect,offsetParent,strategy}):rect);return{top:(clippingClientRect.top-elementClientRect.top+paddingObject.top)/offsetScale.y,bottom:(elementClientRect.bottom-clippingClientRect.bottom+paddingObject.bottom)/offsetScale.y,left:(clippingClientRect.left-elementClientRect.left+paddingObject.left)/offsetScale.x,right:(elementClientRect.right-clippingClientRect.right+paddingObject.right)/offsetScale.x}}const arrow$1=options=>({name:"arrow",options,async fn(state){const{x,y,placement,rects,platform,elements,middlewareData}=state,{element,padding=0}=evaluate(options,state)||{};if(null==element)return{};const paddingObject=getPaddingObject(padding),coords={x,y},axis=getAlignmentAxis(placement),length=getAxisLength(axis),arrowDimensions=await platform.getDimensions(element),isYAxis="y"===axis,minProp=isYAxis?"top":"left",maxProp=isYAxis?"bottom":"right",clientProp=isYAxis?"clientHeight":"clientWidth",endDiff=rects.reference[length]+rects.reference[axis]-coords[axis]-rects.floating[length],startDiff=coords[axis]-rects.reference[axis],arrowOffsetParent=await(null==platform.getOffsetParent?void 0:platform.getOffsetParent(element));let clientSize=arrowOffsetParent?arrowOffsetParent[clientProp]:0;clientSize&&(await(null==platform.isElement?void 0:platform.isElement(arrowOffsetParent)))||(clientSize=elements.floating[clientProp]||rects.floating[length]);const largestPossiblePadding=clientSize/2-arrowDimensions[length]/2-1,minPadding=min(paddingObject[minProp],largestPossiblePadding),maxPadding=min(paddingObject[maxProp],largestPossiblePadding),min$1=minPadding,max=clientSize-arrowDimensions[length]-maxPadding,center=clientSize/2-arrowDimensions[length]/2+(endDiff/2-startDiff/2),offset=clamp$1(min$1,center,max),shouldAddOffset=!middlewareData.arrow&&null!=getAlignment(placement)&¢er!==offset&&0>rects.reference[length]/2-(center<min$1?minPadding:maxPadding)-arrowDimensions[length]/2,alignmentOffset=shouldAddOffset?center<min$1?center-min$1:center-max:0;return{[axis]:coords[axis]+alignmentOffset,data:{[axis]:offset,centerOffset:center-offset-alignmentOffset,...(shouldAddOffset&&{alignmentOffset})},reset:shouldAddOffset}}}),flip$2=function(options){return void 0===options&&(options={}),{name:"flip",options,async fn(state){var _middlewareData$arrow,_middlewareData$flip;const{placement,middlewareData,rects,initialPlacement,platform,elements}=state,{mainAxis:checkMainAxis=!0,crossAxis:checkCrossAxis=!0,fallbackPlacements:specifiedFallbackPlacements,fallbackStrategy="bestFit",fallbackAxisSideDirection="none",flipAlignment=!0,...detectOverflowOptions}=evaluate(options,state);if(null!=(_middlewareData$arrow=middlewareData.arrow)&&_middlewareData$arrow.alignmentOffset)return{};const side=getSide(placement),initialSideAxis=getSideAxis(initialPlacement),isBasePlacement=getSide(initialPlacement)===initialPlacement,rtl=await(null==platform.isRTL?void 0:platform.isRTL(elements.floating)),fallbackPlacements=specifiedFallbackPlacements||(isBasePlacement||!flipAlignment?[getOppositePlacement(initialPlacement)]:getExpandedPlacements(initialPlacement)),hasFallbackAxisSideDirection="none"!==fallbackAxisSideDirection;!specifiedFallbackPlacements&&hasFallbackAxisSideDirection&&fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement,flipAlignment,fallbackAxisSideDirection,rtl));const placements=[initialPlacement,...fallbackPlacements],overflow=await detectOverflow(state,detectOverflowOptions),overflows=[];let overflowsData=(null==(_middlewareData$flip=middlewareData.flip)?void 0:_middlewareData$flip.overflows)||[];if(checkMainAxis&&overflows.push(overflow[side]),checkCrossAxis){const sides=getAlignmentSides(placement,rects,rtl);overflows.push(overflow[sides[0]],overflow[sides[1]])}if(overflowsData=[...overflowsData,{placement,overflows}],!overflows.every(side=>0>=side)){var _middlewareData$flip2,_overflowsData$filter;const nextIndex=((null==(_middlewareData$flip2=middlewareData.flip)?void 0:_middlewareData$flip2.index)||0)+1,nextPlacement=placements[nextIndex];if(nextPlacement){const ignoreCrossAxisOverflow="alignment"===checkCrossAxis&&initialSideAxis!==getSideAxis(nextPlacement);if(!ignoreCrossAxisOverflow||overflowsData.every(d=>getSideAxis(d.placement)!==initialSideAxis||0<d.overflows[0]))return{data:{index:nextIndex,overflows:overflowsData},reset:{placement:nextPlacement}}}let resetPlacement=null==(_overflowsData$filter=overflowsData.filter(d=>0>=d.overflows[0]).sort((a,b)=>a.overflows[1]-b.overflows[1])[0])?void 0:_overflowsData$filter.placement;if(!resetPlacement)switch(fallbackStrategy){case"bestFit":{var _overflowsData$filter2;const placement=null==(_overflowsData$filter2=overflowsData.filter(d=>{if(hasFallbackAxisSideDirection){const currentSideAxis=getSideAxis(d.placement);return currentSideAxis===initialSideAxis||"y"===currentSideAxis}return!0}).map(d=>[d.placement,d.overflows.filter(overflow=>0<overflow).reduce((acc,overflow)=>acc+overflow,0)]).sort((a,b)=>a[1]-b[1])[0])?void 0:_overflowsData$filter2[0];placement&&(resetPlacement=placement);break}case"initialPlacement":resetPlacement=initialPlacement}if(placement!==resetPlacement)return{reset:{placement:resetPlacement}}}return{}}}},originSides=new Set(["left","top"]);async function convertValueToCoords(state,options){const{placement,platform,elements}=state,rtl=await(null==platform.isRTL?void 0:platform.isRTL(elements.floating)),side=getSide(placement),alignment=getAlignment(placement),isVertical="y"===getSideAxis(placement),mainAxisMulti=originSides.has(side)?-1:1,crossAxisMulti=rtl&&isVertical?-1:1,rawValue=evaluate(options,state);let{mainAxis,crossAxis,alignmentAxis}="number"==typeof rawValue?{mainAxis:rawValue,crossAxis:0,alignmentAxis:null}:{mainAxis:rawValue.mainAxis||0,crossAxis:rawValue.crossAxis||0,alignmentAxis:rawValue.alignmentAxis};return alignment&&"number"==typeof alignmentAxis&&(crossAxis="end"===alignment?-1*alignmentAxis:alignmentAxis),isVertical?{x:crossAxis*crossAxisMulti,y:mainAxis*mainAxisMulti}:{x:mainAxis*mainAxisMulti,y:crossAxis*crossAxisMulti}}const offset$1=function(options){return void 0===options&&(options=0),{name:"offset",options,async fn(state){var _middlewareData$offse,_middlewareData$arrow;const{x,y,placement,middlewareData}=state,diffCoords=await convertValueToCoords(state,options);return placement===(null==(_middlewareData$offse=middlewareData.offset)?void 0:_middlewareData$offse.placement)&&null!=(_middlewareData$arrow=middlewareData.arrow)&&_middlewareData$arrow.alignmentOffset?{}:{x:x+diffCoords.x,y:y+diffCoords.y,data:{...diffCoords,placement}}}}},shift$1=function(options){return void 0===options&&(options={}),{name:"shift",options,async fn(state){const{x,y,placement}=state,{mainAxis:checkMainAxis=!0,crossAxis:checkCrossAxis=!1,limiter={fn:_ref=>{let{x,y}=_ref;return{x,y}}},...detectOverflowOptions}=evaluate(options,state),coords={x,y},overflow=await detectOverflow(state,detectOverflowOptions),crossAxis=getSideAxis(getSide(placement)),mainAxis=getOppositeAxis(crossAxis);let mainAxisCoord=coords[mainAxis],crossAxisCoord=coords[crossAxis];if(checkMainAxis){const minSide="y"===mainAxis?"top":"left",maxSide="y"===mainAxis?"bottom":"right",min=mainAxisCoord+overflow[minSide],max=mainAxisCoord-overflow[maxSide];mainAxisCoord=clamp$1(min,mainAxisCoord,max)}if(checkCrossAxis){const minSide="y"===crossAxis?"top":"left",maxSide="y"===crossAxis?"bottom":"right",min=crossAxisCoord+overflow[minSide],max=crossAxisCoord-overflow[maxSide];crossAxisCoord=clamp$1(min,crossAxisCoord,max)}const limitedCoords=limiter.fn({...state,[mainAxis]:mainAxisCoord,[crossAxis]:crossAxisCoord});return{...limitedCoords,data:{x:limitedCoords.x-x,y:limitedCoords.y-y,enabled:{[mainAxis]:checkMainAxis,[crossAxis]:checkCrossAxis}}}}}},size$1=function(options){return void 0===options&&(options={}),{name:"size",options,async fn(state){var _state$middlewareData,_state$middlewareData2;const{placement,rects,platform,elements}=state,{apply=()=>{},...detectOverflowOptions}=evaluate(options,state),overflow=await detectOverflow(state,detectOverflowOptions),side=getSide(placement),alignment=getAlignment(placement),isYAxis="y"===getSideAxis(placement),{width,height}=rects.floating;let heightSide,widthSide;"top"===side||"bottom"===side?(heightSide=side,widthSide=alignment===((await(null==platform.isRTL?void 0:platform.isRTL(elements.floating)))?"start":"end")?"left":"right"):(widthSide=side,heightSide="end"===alignment?"top":"bottom");const maximumClippingHeight=height-overflow.top-overflow.bottom,maximumClippingWidth=width-overflow.left-overflow.right,overflowAvailableHeight=min(height-overflow[heightSide],maximumClippingHeight),overflowAvailableWidth=min(width-overflow[widthSide],maximumClippingWidth),noShift=!state.middlewareData.shift;let availableHeight=overflowAvailableHeight,availableWidth=overflowAvailableWidth;if(null!=(_state$middlewareData=state.middlewareData.shift)&&_state$middlewareData.enabled.x&&(availableWidth=maximumClippingWidth),null!=(_state$middlewareData2=state.middlewareData.shift)&&_state$middlewareData2.enabled.y&&(availableHeight=maximumClippingHeight),noShift&&!alignment){const xMin=max(overflow.left,0),xMax=max(overflow.right,0),yMin=max(overflow.top,0),yMax=max(overflow.bottom,0);isYAxis?availableWidth=width-2*(0!==xMin||0!==xMax?xMin+xMax:max(overflow.left,overflow.right)):availableHeight=height-2*(0!==yMin||0!==yMax?yMin+yMax:max(overflow.top,overflow.bottom))}await apply({...state,availableWidth,availableHeight});const nextDimensions=await platform.getDimensions(elements.floating);return width!==nextDimensions.width||height!==nextDimensions.height?{reset:{rects:!0}}:{}}}};function hasWindow$1(){return"undefined"!=typeof window}function getNodeName(node){return isNode(node)?(node.nodeName||"").toLowerCase():"#document"}function getWindow(node){var _node$ownerDocument;return(null==node||null==(_node$ownerDocument=node.ownerDocument)?void 0:_node$ownerDocument.defaultView)||window}function getDocumentElement(node){var _ref;return null==(_ref=(isNode(node)?node.ownerDocument:node.document)||window.document)?void 0:_ref.documentElement}function isNode(value){return!!hasWindow$1()&&(value instanceof Node||value instanceof getWindow(value).Node)}function isElement(value){return!!hasWindow$1()&&(value instanceof Element||value instanceof getWindow(value).Element)}function isHTMLElement(value){return!!hasWindow$1()&&(value instanceof HTMLElement||value instanceof getWindow(value).HTMLElement)}function isShadowRoot(value){return!!(hasWindow$1()&&"undefined"!=typeof ShadowRoot)&&(value instanceof ShadowRoot||value instanceof getWindow(value).ShadowRoot)}const invalidOverflowDisplayValues=new Set(["inline","contents"]);function isOverflowElement(element){const{overflow,overflowX,overflowY,display}=getComputedStyle$1(element);return /auto|scroll|overlay|hidden|clip/.test(overflow+overflowY+overflowX)&&!invalidOverflowDisplayValues.has(display)}const tableElements=new Set(["table","td","th"]);function isTableElement(element){return tableElements.has(getNodeName(element))}const topLayerSelectors=[":popover-open",":modal"];function isTopLayer(element){return topLayerSelectors.some(selector=>{try{return element.matches(selector)}catch(_e){return!1}})}const transformProperties=["transform","translate","scale","rotate","perspective"],willChangeValues=["transform","translate","scale","rotate","perspective","filter"],containValues=["paint","layout","strict","content"];function isContainingBlock(elementOrCss){const webkit=isWebKit(),css=isElement(elementOrCss)?getComputedStyle$1(elementOrCss):elementOrCss;return transformProperties.some(value=>!!css[value]&&"none"!==css[value])||!!css.containerType&&"normal"!==css.containerType||!webkit&&!!css.backdropFilter&&"none"!==css.backdropFilter||!webkit&&!!css.filter&&"none"!==css.filter||willChangeValues.some(value=>(css.willChange||"").includes(value))||containValues.some(value=>(css.contain||"").includes(value))}function getContainingBlock(element){for(let currentNode=getParentNode(element);isHTMLElement(currentNode)&&!isLastTraversableNode(currentNode);){if(isContainingBlock(currentNode))return currentNode;if(isTopLayer(currentNode))return null;currentNode=getParentNode(currentNode)}return null}function isWebKit(){return!!("undefined"!=typeof CSS&&CSS.supports)&&CSS.supports("-webkit-backdrop-filter","none")}const lastTraversableNodeNames=new Set(["html","body","#document"]);function isLastTraversableNode(node){return lastTraversableNodeNames.has(getNodeName(node))}function getComputedStyle$1(element){return getWindow(element).getComputedStyle(element)}function getNodeScroll(element){return isElement(element)?{scrollLeft:element.scrollLeft,scrollTop:element.scrollTop}:{scrollLeft:element.scrollX,scrollTop:element.scrollY}}function getParentNode(node){if("html"===getNodeName(node))return node;const result=node.assignedSlot||node.parentNode||isShadowRoot(node)&&node.host||getDocumentElement(node);return isShadowRoot(result)?result.host:result}function getNearestOverflowAncestor(node){const parentNode=getParentNode(node);return isLastTraversableNode(parentNode)?node.ownerDocument?node.ownerDocument.body:node.body:isHTMLElement(parentNode)&&isOverflowElement(parentNode)?parentNode:getNearestOverflowAncestor(parentNode)}function getOverflowAncestors(node,list,traverseIframes){var _node$ownerDocument2;void 0===list&&(list=[]),void 0===traverseIframes&&(traverseIframes=!0);const scrollableAncestor=getNearestOverflowAncestor(node),isBody=scrollableAncestor===(null==(_node$ownerDocument2=node.ownerDocument)?void 0:_node$ownerDocument2.body),win=getWindow(scrollableAncestor);if(isBody){const frameElement=getFrameElement(win);return list.concat(win,win.visualViewport||[],isOverflowElement(scrollableAncestor)?scrollableAncestor:[],frameElement&&traverseIframes?getOverflowAncestors(frameElement):[])}return list.concat(scrollableAncestor,getOverflowAncestors(scrollableAncestor,[],traverseIframes))}function getFrameElement(win){return win.parent&&Object.getPrototypeOf(win.parent)?win.frameElement:null}function getCssDimensions(element){const css=getComputedStyle$1(element);let width=parseFloat(css.width)||0,height=parseFloat(css.height)||0;const hasOffset=isHTMLElement(element),offsetWidth=hasOffset?element.offsetWidth:width,offsetHeight=hasOffset?element.offsetHeight:height,shouldFallback=round(width)!==offsetWidth||round(height)!==offsetHeight;return shouldFallback&&(width=offsetWidth,height=offsetHeight),{width,height,$:shouldFallback}}function unwrapElement(element){return isElement(element)?element:element.contextElement}function getScale(element){var _NumberisFinite=Number.isFinite;const domElement=unwrapElement(element);if(!isHTMLElement(domElement))return createCoords(1);const rect=domElement.getBoundingClientRect(),{width,height,$}=getCssDimensions(domElement);let x=($?round(rect.width):rect.width)/width,y=($?round(rect.height):rect.height)/height;return x&&_NumberisFinite(x)||(x=1),y&&_NumberisFinite(y)||(y=1),{x,y}}const noOffsets=createCoords(0);function getVisualOffsets(element){const win=getWindow(element);return isWebKit()&&win.visualViewport?{x:win.visualViewport.offsetLeft,y:win.visualViewport.offsetTop}:noOffsets}function shouldAddVisualOffsets(element,isFixed,floatingOffsetParent){return void 0===isFixed&&(isFixed=!1),floatingOffsetParent&&(!isFixed||floatingOffsetParent===getWindow(element))&&isFixed}function getBoundingClientRect(element,includeScale,isFixedStrategy,offsetParent){void 0===includeScale&&(includeScale=!1),void 0===isFixedStrategy&&(isFixedStrategy=!1);const clientRect=element.getBoundingClientRect(),domElement=unwrapElement(element);let scale=createCoords(1);includeScale&&(offsetParent?isElement(offsetParent)&&(scale=getScale(offsetParent)):scale=getScale(element));const visualOffsets=shouldAddVisualOffsets(domElement,isFixedStrategy,offsetParent)?getVisualOffsets(domElement):createCoords(0);let x=(clientRect.left+visualOffsets.x)/scale.x,y=(clientRect.top+visualOffsets.y)/scale.y,width=clientRect.width/scale.x,height=clientRect.height/scale.y;if(domElement){const win=getWindow(domElement),offsetWin=offsetParent&&isElement(offsetParent)?getWindow(offsetParent):offsetParent;let currentWin=win,currentIFrame=getFrameElement(currentWin);for(;currentIFrame&&offsetParent&&offsetWin!==currentWin;){const iframeScale=getScale(currentIFrame),iframeRect=currentIFrame.getBoundingClientRect(),css=getComputedStyle$1(currentIFrame),left=iframeRect.left+(currentIFrame.clientLeft+parseFloat(css.paddingLeft))*iframeScale.x,top=iframeRect.top+(currentIFrame.clientTop+parseFloat(css.paddingTop))*iframeScale.y;x*=iframeScale.x,y*=iframeScale.y,width*=iframeScale.x,height*=iframeScale.y,x+=left,y+=top,currentWin=getWindow(currentIFrame),currentIFrame=getFrameElement(currentWin)}}return rectToClientRect({width,height,x,y})}function getWindowScrollBarX(element,rect){const leftScroll=getNodeScroll(element).scrollLeft;return rect?rect.left+leftScroll:getBoundingClientRect(getDocumentElement(element)).left+leftScroll}function getHTMLOffset(documentElement,scroll){const htmlRect=documentElement.getBoundingClientRect(),x=htmlRect.left+scroll.scrollLeft-getWindowScrollBarX(documentElement,htmlRect),y=htmlRect.top+scroll.scrollTop;return{x,y}}function convertOffsetParentRelativeRectToViewportRelativeRect(_ref){let{elements,rect,offsetParent,strategy}=_ref;const isFixed="fixed"===strategy,documentElement=getDocumentElement(offsetParent),topLayer=!!elements&&isTopLayer(elements.floating);if(offsetParent===documentElement||topLayer&&isFixed)return rect;let scroll={scrollLeft:0,scrollTop:0},scale=createCoords(1);const offsets=createCoords(0),isOffsetParentAnElement=isHTMLElement(offsetParent);if((isOffsetParentAnElement||!isOffsetParentAnElement&&!isFixed)&&(("body"!==getNodeName(offsetParent)||isOverflowElement(documentElement))&&(scroll=getNodeScroll(offsetParent)),isHTMLElement(offsetParent))){const offsetRect=getBoundingClientRect(offsetParent);scale=getScale(offsetParent),offsets.x=offsetRect.x+offsetParent.clientLeft,offsets.y=offsetRect.y+offsetParent.clientTop}const htmlOffset=!documentElement||isOffsetParentAnElement||isFixed?createCoords(0):getHTMLOffset(documentElement,scroll);return{width:rect.width*scale.x,height:rect.height*scale.y,x:rect.x*scale.x-scroll.scrollLeft*scale.x+offsets.x+htmlOffset.x,y:rect.y*scale.y-scroll.scrollTop*scale.y+offsets.y+htmlOffset.y}}function getClientRects(element){return Array.from(element.getClientRects())}function getDocumentRect(element){const html=getDocumentElement(element),scroll=getNodeScroll(element),body=element.ownerDocument.body,width=max(html.scrollWidth,html.clientWidth,body.scrollWidth,body.clientWidth),height=max(html.scrollHeight,html.clientHeight,body.scrollHeight,body.clientHeight);let x=-scroll.scrollLeft+getWindowScrollBarX(element);const y=-scroll.scrollTop;return"rtl"===getComputedStyle$1(body).direction&&(x+=max(html.clientWidth,body.clientWidth)-width),{width,height,x,y}}const SCROLLBAR_MAX=25;function getViewportRect(element,strategy){const win=getWindow(element),html=getDocumentElement(element),visualViewport=win.visualViewport;let width=html.clientWidth,height=html.clientHeight,x=0,y=0;if(visualViewport){width=visualViewport.width,height=visualViewport.height;const visualViewportBased=isWebKit();(!visualViewportBased||visualViewportBased&&"fixed"===strategy)&&(x=visualViewport.offsetLeft,y=visualViewport.offsetTop)}const windowScrollbarX=getWindowScrollBarX(html);if(0>=windowScrollbarX){const doc=html.ownerDocument,body=doc.body,bodyStyles=getComputedStyle(body),bodyMarginInline="CSS1Compat"===doc.compatMode?parseFloat(bodyStyles.marginLeft)+parseFloat(bodyStyles.marginRight)||0:0,clippingStableScrollbarWidth=Math.abs(html.clientWidth-body.clientWidth-bodyMarginInline);clippingStableScrollbarWidth<=SCROLLBAR_MAX&&(width-=clippingStableScrollbarWidth)}else windowScrollbarX<=SCROLLBAR_MAX&&(width+=windowScrollbarX);return{width,height,x,y}}const absoluteOrFixed=new Set(["absolute","fixed"]);function getInnerBoundingClientRect(element,strategy){const clientRect=getBoundingClientRect(element,!0,"fixed"===strategy),top=clientRect.top+element.clientTop,left=clientRect.left+element.clientLeft,scale=isHTMLElement(element)?getScale(element):createCoords(1),width=element.clientWidth*scale.x,height=element.clientHeight*scale.y,x=left*scale.x,y=top*scale.y;return{width,height,x,y}}function getClientRectFromClippingAncestor(element,clippingAncestor,strategy){let rect;if("viewport"===clippingAncestor)rect=getViewportRect(element,strategy);else if("document"===clippingAncestor)rect=getDocumentRect(getDocumentElement(element));else if(isElement(clippingAncestor))rect=getInnerBoundingClientRect(clippingAncestor,strategy);else{const visualOffsets=getVisualOffsets(element);rect={x:clippingAncestor.x-visualOffsets.x,y:clippingAncestor.y-visualOffsets.y,width:clippingAncestor.width,height:clippingAncestor.height}}return rectToClientRect(rect)}function hasFixedPositionAncestor(element,stopNode){const parentNode=getParentNode(element);return parentNode!==stopNode&&isElement(parentNode)&&!isLastTraversableNode(parentNode)&&("fixed"===getComputedStyle$1(parentNode).position||hasFixedPositionAncestor(parentNode,stopNode))}function getClippingElementAncestors(element,cache){const cachedResult=cache.get(element);if(cachedResult)return cachedResult;let result=getOverflowAncestors(element,[],!1).filter(el=>isElement(el)&&"body"!==getNodeName(el)),currentContainingBlockComputedStyle=null;const elementIsFixed="fixed"===getComputedStyle$1(element).position;for(let currentNode=elementIsFixed?getParentNode(element):element;isElement(currentNode)&&!isLastTraversableNode(currentNode);){const computedStyle=getComputedStyle$1(currentNode),currentNodeIsContaining=isContainingBlock(currentNode);currentNodeIsContaining||"fixed"!==computedStyle.position||(currentContainingBlockComputedStyle=null);const shouldDropCurrentNode=elementIsFixed?!currentNodeIsContaining&&!currentContainingBlockComputedStyle:!currentNodeIsContaining&&"static"===computedStyle.position&&!!currentContainingBlockComputedStyle&&absoluteOrFixed.has(currentContainingBlockComputedStyle.position)||isOverflowElement(currentNode)&&!currentNodeIsContaining&&hasFixedPositionAncestor(element,currentNode);shouldDropCurrentNode?result=result.filter(ancestor=>ancestor!==currentNode):currentContainingBlockComputedStyle=computedStyle,currentNode=getParentNode(currentNode)}return cache.set(element,result),result}function getClippingRect(_ref){let{element,boundary,rootBoundary,strategy}=_ref;const elementClippingAncestors="clippingAncestors"===boundary?isTopLayer(element)?[]:getClippingElementAncestors(element,this._c):[].concat(boundary),clippingAncestors=[...elementClippingAncestors,rootBoundary],firstClippingAncestor=clippingAncestors[0],clippingRect=clippingAncestors.reduce((accRect,clippingAncestor)=>{const rect=getClientRectFromClippingAncestor(element,clippingAncestor,strategy);return accRect.top=max(rect.top,accRect.top),accRect.right=min(rect.right,accRect.right),accRect.bottom=min(rect.bottom,accRect.bottom),accRect.left=max(rect.left,accRect.left),accRect},getClientRectFromClippingAncestor(element,firstClippingAncestor,strategy));return{width:clippingRect.right-clippingRect.left,height:clippingRect.bottom-clippingRect.top,x:clippingRect.left,y:clippingRect.top}}function getDimensions(element){const{width,height}=getCssDimensions(element);return{width,height}}function getRectRelativeToOffsetParent(element,offsetParent,strategy){function setLeftRTLScrollbarOffset(){offsets.x=getWindowScrollBarX(documentElement)}const isOffsetParentAnElement=isHTMLElement(offsetParent),documentElement=getDocumentElement(offsetParent),isFixed="fixed"===strategy,rect=getBoundingClientRect(element,!0,isFixed,offsetParent);let scroll={scrollLeft:0,scrollTop:0};const offsets=createCoords(0);if(isOffsetParentAnElement||!isOffsetParentAnElement&&!isFixed)if(("body"!==getNodeName(offsetParent)||isOverflowElement(documentElement))&&(scroll=getNodeScroll(offsetParent)),isOffsetParentAnElement){const offsetRect=getBoundingClientRect(offsetParent,!0,isFixed,offsetParent);offsets.x=offsetRect.x+offsetParent.clientLeft,offsets.y=offsetRect.y+offsetParent.clientTop}else documentElement&&setLeftRTLScrollbarOffset();isFixed&&!isOffsetParentAnElement&&documentElement&&setLeftRTLScrollbarOffset();const htmlOffset=!documentElement||isOffsetParentAnElement||isFixed?createCoords(0):getHTMLOffset(documentElement,scroll),x=rect.left+scroll.scrollLeft-offsets.x-htmlOffset.x,y=rect.top+scroll.scrollTop-offsets.y-htmlOffset.y;return{x,y,width:rect.width,height:rect.height}}function isStaticPositioned(element){return"static"===getComputedStyle$1(element).position}function getTrueOffsetParent(element,polyfill){if(!isHTMLElement(element)||"fixed"===getComputedStyle$1(element).position)return null;if(polyfill)return polyfill(element);let rawOffsetParent=element.offsetParent;return getDocumentElement(element)===rawOffsetParent&&(rawOffsetParent=rawOffsetParent.ownerDocument.body),rawOffsetParent}function getOffsetParent(element,polyfill){const win=getWindow(element);if(isTopLayer(element))return win;if(!isHTMLElement(element)){for(let svgOffsetParent=getParentNode(element);svgOffsetParent&&!isLastTraversableNode(svgOffsetParent);){if(isElement(svgOffsetParent)&&!isStaticPositioned(svgOffsetParent))return svgOffsetParent;svgOffsetParent=getParentNode(svgOffsetParent)}return win}let offsetParent=getTrueOffsetParent(element,polyfill);for(;offsetParent&&isTableElement(offsetParent)&&isStaticPositioned(offsetParent);)offsetParent=getTrueOffsetParent(offsetParent,polyfill);return offsetParent&&isLastTraversableNode(offsetParent)&&isStaticPositioned(offsetParent)&&!isContainingBlock(offsetParent)?win:offsetParent||getContainingBlock(element)||win}const getElementRects=async function(data){const getOffsetParentFn=this.getOffsetParent||getOffsetParent,getDimensionsFn=this.getDimensions,floatingDimensions=await getDimensionsFn(data.floating);return{reference:getRectRelativeToOffsetParent(data.reference,await getOffsetParentFn(data.floating),data.strategy),floating:{x:0,y:0,width:floatingDimensions.width,height:floatingDimensions.height}}};function isRTL(element){return"rtl"===getComputedStyle$1(element).direction}const platform={convertOffsetParentRelativeRectToViewportRelativeRect,getDocumentElement,getClippingRect,getOffsetParent,getElementRects,getClientRects,getDimensions,getScale,isElement,isRTL};function rectsAreEqual(a,b){return a.x===b.x&&a.y===b.y&&a.width===b.width&&a.height===b.height}function observeMove(element,onMove){function cleanup(){var _io;clearTimeout(timeoutId),null==(_io=io)||_io.disconnect(),io=null}function refresh(skip,threshold){function handleObserve(entries){const ratio=entries[0].intersectionRatio;if(ratio!==threshold){if(!isFirstUpdate)return refresh();ratio?refresh(!1,ratio):timeoutId=setTimeout(()=>{refresh(!1,1e-7)},1e3)}1!==ratio||rectsAreEqual(elementRectForRootMargin,element.getBoundingClientRect())||refresh(),isFirstUpdate=!1}void 0===skip&&(skip=!1),void 0===threshold&&(threshold=1),cleanup();const elementRectForRootMargin=element.getBoundingClientRect(),{left,top,width,height}=elementRectForRootMargin;if(skip||onMove(),!width||!height)return;const insetTop=floor(top),insetRight=floor(root.clientWidth-(left+width)),insetBottom=floor(root.clientHeight-(top+height)),insetLeft=floor(left),options={rootMargin:-insetTop+"px "+-insetRight+"px "+-insetBottom+"px "+-insetLeft+"px",threshold:max(0,min(1,threshold))||1};let isFirstUpdate=!0;try{io=new IntersectionObserver(handleObserve,{...options,root:root.ownerDocument})}catch(_e){io=new IntersectionObserver(handleObserve,options)}io.observe(element)}let io=null,timeoutId;const root=getDocumentElement(element);return refresh(!0),cleanup}function autoUpdate(reference,floating,update,options){function frameLoop(){const nextRefRect=getBoundingClientRect(reference);prevRefRect&&!rectsAreEqual(prevRefRect,nextRefRect)&&update(),prevRefRect=nextRefRect,frameId=requestAnimationFrame(frameLoop)}void 0===options&&(options={});const{ancestorScroll=!0,ancestorResize=!0,elementResize="function"==typeof ResizeObserver,layoutShift="function"==typeof IntersectionObserver,animationFrame=!1}=options,referenceEl=unwrapElement(reference),ancestors=ancestorScroll||ancestorResize?[...(referenceEl?getOverflowAncestors(referenceEl):[]),...getOverflowAncestors(floating)]:[];ancestors.forEach(ancestor=>{ancestorScroll&&ancestor.addEventListener("scroll",update,{passive:!0}),ancestorResize&&ancestor.addEventListener("resize",update)});const cleanupIo=referenceEl&&layoutShift?observeMove(referenceEl,update):null;let reobserveFrame=-1,resizeObserver=null;elementResize&&(resizeObserver=new ResizeObserver(_ref=>{let[firstEntry]=_ref;firstEntry&&firstEntry.target===referenceEl&&resizeObserver&&(resizeObserver.unobserve(floating),cancelAnimationFrame(reobserveFrame),reobserveFrame=requestAnimationFrame(()=>{var _resizeObserver;null==(_resizeObserver=resizeObserver)||_resizeObserver.observe(floating)})),update()}),referenceEl&&!animationFrame&&resizeObserver.observe(referenceEl),resizeObserver.observe(floating));let prevRefRect=animationFrame?getBoundingClientRect(reference):null,frameId;return animationFrame&&frameLoop(),update(),()=>{var _resizeObserver2;ancestors.forEach(ancestor=>{ancestorScroll&&ancestor.removeEventListener("scroll",update),ancestorResize&&ancestor.removeEventListener("resize",update)}),null==cleanupIo||cleanupIo(),null==(_resizeObserver2=resizeObserver)||_resizeObserver2.disconnect(),resizeObserver=null,animationFrame&&cancelAnimationFrame(frameId)}}const offset=offset$1,shift=shift$1,flip$1=flip$2,size=size$1,arrow=arrow$1,computePosition=(reference,floating,options)=>{const cache=new Map,mergedOptions={platform,...options},platformWithCache={...mergedOptions.platform,_c:cache};return computePosition$1(reference,floating,{...mergedOptions,platform:platformWithCache})};function offsetParent(element){return offsetParentPolyfill(element)}function flatTreeParent(element){return element.assignedSlot?element.assignedSlot:element.parentNode instanceof ShadowRoot?element.parentNode.host:element.parentNode}function offsetParentPolyfill(element){for(let ancestor=element;ancestor;ancestor=flatTreeParent(ancestor))if(ancestor instanceof Element&&"none"===getComputedStyle(ancestor).display)return null;for(let ancestor=flatTreeParent(element);ancestor;ancestor=flatTreeParent(ancestor)){if(!(ancestor instanceof Element))continue;const style=getComputedStyle(ancestor);if("contents"!==style.display){if("static"!==style.position||isContainingBlock(style))return ancestor;if("BODY"===ancestor.tagName)return ancestor}}return null}function isVirtualElement(e){return null!==e&&"object"==typeof e&&"getBoundingClientRect"in e&&(!("contextElement"in e)||e.contextElement instanceof Element)}var SlPopup=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.active=!1,this.placement="top",this.strategy="absolute",this.distance=0,this.skidding=0,this.arrow=!1,this.arrowPlacement="anchor",this.arrowPadding=10,this.flip=!1,this.flipFallbackPlacements="",this.flipFallbackStrategy="best-fit",this.flipPadding=0,this.shift=!1,this.shiftPadding=0,this.autoSizePadding=0,this.hoverBridge=!1,this.updateHoverBridge=()=>{if(this.hoverBridge&&this.anchorEl){const anchorRect=this.anchorEl.getBoundingClientRect(),popupRect=this.popup.getBoundingClientRect(),isVertical=this.placement.includes("top")||this.placement.includes("bottom");let topLeftX=0,topLeftY=0,topRightX=0,topRightY=0,bottomLeftX=0,bottomLeftY=0,bottomRightX=0,bottomRightY=0;isVertical?anchorRect.top<popupRect.top?(topLeftX=anchorRect.left,topLeftY=anchorRect.bottom,topRightX=anchorRect.right,topRightY=anchorRect.bottom,bottomLeftX=popupRect.left,bottomLeftY=popupRect.top,bottomRightX=popupRect.right,bottomRightY=popupRect.top):(topLeftX=popupRect.left,topLeftY=popupRect.bottom,topRightX=popupRect.right,topRightY=popupRect.bottom,bottomLeftX=anchorRect.left,bottomLeftY=anchorRect.top,bottomRightX=anchorRect.right,bottomRightY=anchorRect.top):anchorRect.left<popupRect.left?(topLeftX=anchorRect.right,topLeftY=anchorRect.top,topRightX=popupRect.left,topRightY=popupRect.top,bottomLeftX=anchorRect.right,bottomLeftY=anchorRect.bottom,bottomRightX=popupRect.left,bottomRightY=popupRect.bottom):(topLeftX=popupRect.right,topLeftY=popupRect.top,topRightX=anchorRect.left,topRightY=anchorRect.top,bottomLeftX=popupRect.right,bottomLeftY=popupRect.bottom,bottomRightX=anchorRect.left,bottomRightY=anchorRect.bottom),this.style.setProperty("--hover-bridge-top-left-x",`${topLeftX}px`),this.style.setProperty("--hover-bridge-top-left-y",`${topLeftY}px`),this.style.setProperty("--hover-bridge-top-right-x",`${topRightX}px`),this.style.setProperty("--hover-bridge-top-right-y",`${topRightY}px`),this.style.setProperty("--hover-bridge-bottom-left-x",`${bottomLeftX}px`),this.style.setProperty("--hover-bridge-bottom-left-y",`${bottomLeftY}px`),this.style.setProperty("--hover-bridge-bottom-right-x",`${bottomRightX}px`),this.style.setProperty("--hover-bridge-bottom-right-y",`${bottomRightY}px`)}}}async connectedCallback(){super.connectedCallback(),await this.updateComplete,this.start()}disconnectedCallback(){super.disconnectedCallback(),this.stop()}async updated(changedProps){super.updated(changedProps),changedProps.has("active")&&(this.active?this.start():this.stop()),changedProps.has("anchor")&&this.handleAnchorChange(),this.active&&(await this.updateComplete,this.reposition())}async handleAnchorChange(){if(await this.stop(),this.anchor&&"string"==typeof this.anchor){const root=this.getRootNode();this.anchorEl=root.getElementById(this.anchor)}else this.anchorEl=this.anchor instanceof Element||isVirtualElement(this.anchor)?this.anchor:this.querySelector("[slot=\"anchor\"]");this.anchorEl instanceof HTMLSlotElement&&(this.anchorEl=this.anchorEl.assignedElements({flatten:!0})[0]),this.anchorEl&&this.active&&this.start()}start(){this.anchorEl&&this.active&&(this.cleanup=autoUpdate(this.anchorEl,this.popup,()=>{this.reposition()}))}async stop(){return new Promise(resolve=>{this.cleanup?(this.cleanup(),this.cleanup=void 0,this.removeAttribute("data-current-placement"),this.style.removeProperty("--auto-size-available-width"),this.style.removeProperty("--auto-size-available-height"),requestAnimationFrame(()=>resolve())):resolve()})}reposition(){if(this.active&&this.anchorEl){const middleware=[offset({mainAxis:this.distance,crossAxis:this.skidding})];this.sync?middleware.push(size({apply:({rects})=>{const syncWidth="width"===this.sync||"both"===this.sync,syncHeight="height"===this.sync||"both"===this.sync;this.popup.style.width=syncWidth?`${rects.reference.width}px`:"",this.popup.style.height=syncHeight?`${rects.reference.height}px`:""}})):(this.popup.style.width="",this.popup.style.height=""),this.flip&&middleware.push(flip$1({boundary:this.flipBoundary,fallbackPlacements:this.flipFallbackPlacements,fallbackStrategy:"best-fit"===this.flipFallbackStrategy?"bestFit":"initialPlacement",padding:this.flipPadding})),this.shift&&middleware.push(shift({boundary:this.shiftBoundary,padding:this.shiftPadding})),this.autoSize?middleware.push(size({boundary:this.autoSizeBoundary,padding:this.autoSizePadding,apply:({availableWidth,availableHeight})=>{"vertical"===this.autoSize||"both"===this.autoSize?this.style.setProperty("--auto-size-available-height",`${availableHeight}px`):this.style.removeProperty("--auto-size-available-height"),"horizontal"===this.autoSize||"both"===this.autoSize?this.style.setProperty("--auto-size-available-width",`${availableWidth}px`):this.style.removeProperty("--auto-size-available-width")}})):(this.style.removeProperty("--auto-size-available-width"),this.style.removeProperty("--auto-size-available-height")),this.arrow&&middleware.push(arrow({element:this.arrowEl,padding:this.arrowPadding}));const getOffsetParent="absolute"===this.strategy?element=>platform.getOffsetParent(element,offsetParent):platform.getOffsetParent;computePosition(this.anchorEl,this.popup,{placement:this.placement,middleware,strategy:this.strategy,platform:__spreadProps(__spreadValues({},platform),{getOffsetParent})}).then(({x,y,middlewareData,placement})=>{const isRtl="rtl"===this.localize.dir(),staticSide={top:"bottom",right:"left",bottom:"top",left:"right"}[placement.split("-")[0]];if(this.setAttribute("data-current-placement",placement),Object.assign(this.popup.style,{left:`${x}px`,top:`${y}px`}),this.arrow){const arrowX=middlewareData.arrow.x,arrowY=middlewareData.arrow.y;let top="",right="",bottom="",left="";if("start"===this.arrowPlacement){const value="number"==typeof arrowX?`calc(${this.arrowPadding}px - var(--arrow-padding-offset))`:"";top="number"==typeof arrowY?`calc(${this.arrowPadding}px - var(--arrow-padding-offset))`:"",right=isRtl?value:"",left=isRtl?"":value}else if("end"===this.arrowPlacement){const value="number"==typeof arrowX?`calc(${this.arrowPadding}px - var(--arrow-padding-offset))`:"";right=isRtl?"":value,left=isRtl?value:"",bottom="number"==typeof arrowY?`calc(${this.arrowPadding}px - var(--arrow-padding-offset))`:""}else"center"===this.arrowPlacement?(left="number"==typeof arrowX?`calc(50% - var(--arrow-size-diagonal))`:"",top="number"==typeof arrowY?`calc(50% - var(--arrow-size-diagonal))`:""):(left="number"==typeof arrowX?`${arrowX}px`:"",top="number"==typeof arrowY?`${arrowY}px`:"");Object.assign(this.arrowEl.style,{top,right,bottom,left,[staticSide]:"calc(var(--arrow-size-diagonal) * -1)"})}}),requestAnimationFrame(()=>this.updateHoverBridge()),this.emit("sl-reposition")}}render(){return x$1` + <slot name="anchor" @slotchange=${this.handleAnchorChange}></slot> + + <span + part="hover-bridge" + class=${e$2({"popup-hover-bridge":!0,"popup-hover-bridge--visible":this.hoverBridge&&this.active})} + ></span> + + <div + part="popup" + class=${e$2({popup:!0,"popup--active":this.active,"popup--fixed":"fixed"===this.strategy,"popup--has-arrow":this.arrow})} + > + <slot></slot> + ${this.arrow?x$1`<div part="arrow" class="popup__arrow" role="presentation"></div>`:""} + </div> + `}};SlPopup.styles=[component_styles_default,popup_styles_default],__decorateClass([e$6(".popup")],SlPopup.prototype,"popup",2),__decorateClass([e$6(".popup__arrow")],SlPopup.prototype,"arrowEl",2),__decorateClass([n$5()],SlPopup.prototype,"anchor",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlPopup.prototype,"active",2),__decorateClass([n$5({reflect:!0})],SlPopup.prototype,"placement",2),__decorateClass([n$5({reflect:!0})],SlPopup.prototype,"strategy",2),__decorateClass([n$5({type:Number})],SlPopup.prototype,"distance",2),__decorateClass([n$5({type:Number})],SlPopup.prototype,"skidding",2),__decorateClass([n$5({type:Boolean})],SlPopup.prototype,"arrow",2),__decorateClass([n$5({attribute:"arrow-placement"})],SlPopup.prototype,"arrowPlacement",2),__decorateClass([n$5({attribute:"arrow-padding",type:Number})],SlPopup.prototype,"arrowPadding",2),__decorateClass([n$5({type:Boolean})],SlPopup.prototype,"flip",2),__decorateClass([n$5({attribute:"flip-fallback-placements",converter:{fromAttribute:value=>value.split(" ").map(p=>p.trim()).filter(p=>""!==p),toAttribute:value=>value.join(" ")}})],SlPopup.prototype,"flipFallbackPlacements",2),__decorateClass([n$5({attribute:"flip-fallback-strategy"})],SlPopup.prototype,"flipFallbackStrategy",2),__decorateClass([n$5({type:Object})],SlPopup.prototype,"flipBoundary",2),__decorateClass([n$5({attribute:"flip-padding",type:Number})],SlPopup.prototype,"flipPadding",2),__decorateClass([n$5({type:Boolean})],SlPopup.prototype,"shift",2),__decorateClass([n$5({type:Object})],SlPopup.prototype,"shiftBoundary",2),__decorateClass([n$5({attribute:"shift-padding",type:Number})],SlPopup.prototype,"shiftPadding",2),__decorateClass([n$5({attribute:"auto-size"})],SlPopup.prototype,"autoSize",2),__decorateClass([n$5()],SlPopup.prototype,"sync",2),__decorateClass([n$5({type:Object})],SlPopup.prototype,"autoSizeBoundary",2),__decorateClass([n$5({attribute:"auto-size-padding",type:Number})],SlPopup.prototype,"autoSizePadding",2),__decorateClass([n$5({attribute:"hover-bridge",type:Boolean})],SlPopup.prototype,"hoverBridge",2);var SlDropdown=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.open=!1,this.placement="bottom-start",this.disabled=!1,this.stayOpenOnSelect=!1,this.distance=0,this.skidding=0,this.hoist=!1,this.sync=void 0,this.handleKeyDown=event=>{this.open&&"Escape"===event.key&&(event.stopPropagation(),this.hide(),this.focusOnTrigger())},this.handleDocumentKeyDown=event=>{var _a;if("Escape"===event.key&&this.open&&!this.closeWatcher)return event.stopPropagation(),this.focusOnTrigger(),void this.hide();if("Tab"===event.key){if(this.open&&"sl-menu-item"===(null==(_a=document.activeElement)?void 0:_a.tagName.toLowerCase()))return event.preventDefault(),this.hide(),void this.focusOnTrigger();const computeClosestContaining=(element,tagName)=>{if(!element)return null;const closest=element.closest(tagName);if(closest)return closest;const rootNode=element.getRootNode();return rootNode instanceof ShadowRoot?computeClosestContaining(rootNode.host,tagName):null};setTimeout(()=>{var _a2;const activeElement=(null==(_a2=this.containingElement)?void 0:_a2.getRootNode())instanceof ShadowRoot?getDeepestActiveElement():document.activeElement;this.containingElement&&computeClosestContaining(activeElement,this.containingElement.tagName.toLowerCase())===this.containingElement||this.hide()})}},this.handleDocumentMouseDown=event=>{const path=event.composedPath();this.containingElement&&!path.includes(this.containingElement)&&this.hide()},this.handlePanelSelect=event=>{const target=event.target;this.stayOpenOnSelect||"sl-menu"!==target.tagName.toLowerCase()||(this.hide(),this.focusOnTrigger())}}connectedCallback(){super.connectedCallback(),this.containingElement||(this.containingElement=this)}firstUpdated(){this.panel.hidden=!this.open,this.open&&(this.addOpenListeners(),this.popup.active=!0)}disconnectedCallback(){super.disconnectedCallback(),this.removeOpenListeners(),this.hide()}focusOnTrigger(){const trigger=this.trigger.assignedElements({flatten:!0})[0];"function"==typeof(null==trigger?void 0:trigger.focus)&&trigger.focus()}getMenu(){return this.panel.assignedElements({flatten:!0}).find(el=>"sl-menu"===el.tagName.toLowerCase())}handleTriggerClick(){this.open?this.hide():(this.show(),this.focusOnTrigger())}async handleTriggerKeyDown(event){if([" ","Enter"].includes(event.key))return event.preventDefault(),void this.handleTriggerClick();const menu=this.getMenu();if(menu){const menuItems=menu.getAllItems(),firstMenuItem=menuItems[0],lastMenuItem=menuItems[menuItems.length-1];["ArrowDown","ArrowUp","Home","End"].includes(event.key)&&(event.preventDefault(),!this.open&&(this.show(),await this.updateComplete),0<menuItems.length&&this.updateComplete.then(()=>{("ArrowDown"===event.key||"Home"===event.key)&&(menu.setCurrentItem(firstMenuItem),firstMenuItem.focus()),("ArrowUp"===event.key||"End"===event.key)&&(menu.setCurrentItem(lastMenuItem),lastMenuItem.focus())}))}}handleTriggerKeyUp(event){" "===event.key&&event.preventDefault()}handleTriggerSlotChange(){this.updateAccessibleTrigger()}updateAccessibleTrigger(){const assignedElements=this.trigger.assignedElements({flatten:!0}),accessibleTrigger=assignedElements.find(el=>getTabbableBoundary(el).start);let target;if(accessibleTrigger){switch(accessibleTrigger.tagName.toLowerCase()){case"sl-button":case"sl-icon-button":target=accessibleTrigger.button;break;default:target=accessibleTrigger}target.setAttribute("aria-haspopup","true"),target.setAttribute("aria-expanded",this.open?"true":"false")}}async show(){if(!this.open)return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open)return this.open=!1,waitForEvent(this,"sl-after-hide")}reposition(){this.popup.reposition()}addOpenListeners(){var _a;this.panel.addEventListener("sl-select",this.handlePanelSelect),"CloseWatcher"in window?(null==(_a=this.closeWatcher)?void 0:_a.destroy(),this.closeWatcher=new CloseWatcher,this.closeWatcher.onclose=()=>{this.hide(),this.focusOnTrigger()}):this.panel.addEventListener("keydown",this.handleKeyDown),document.addEventListener("keydown",this.handleDocumentKeyDown),document.addEventListener("mousedown",this.handleDocumentMouseDown)}removeOpenListeners(){var _a;this.panel&&(this.panel.removeEventListener("sl-select",this.handlePanelSelect),this.panel.removeEventListener("keydown",this.handleKeyDown)),document.removeEventListener("keydown",this.handleDocumentKeyDown),document.removeEventListener("mousedown",this.handleDocumentMouseDown),null==(_a=this.closeWatcher)?void 0:_a.destroy()}async handleOpenChange(){if(this.disabled)return void(this.open=!1);if(this.updateAccessibleTrigger(),this.open){this.emit("sl-show"),this.addOpenListeners(),await stopAnimations(this),this.panel.hidden=!1,this.popup.active=!0;const{keyframes,options}=getAnimation(this,"dropdown.show",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.emit("sl-after-show")}else{this.emit("sl-hide"),this.removeOpenListeners(),await stopAnimations(this);const{keyframes,options}=getAnimation(this,"dropdown.hide",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.panel.hidden=!0,this.popup.active=!1,this.emit("sl-after-hide")}}render(){return x$1` + <sl-popup + part="base" + exportparts="popup:base__popup" + id="dropdown" + placement=${this.placement} + distance=${this.distance} + skidding=${this.skidding} + strategy=${this.hoist?"fixed":"absolute"} + flip + shift + auto-size="vertical" + auto-size-padding="10" + sync=${o$6(this.sync?this.sync:void 0)} + class=${e$2({dropdown:!0,"dropdown--open":this.open})} + > + <slot + name="trigger" + slot="anchor" + part="trigger" + class="dropdown__trigger" + @click=${this.handleTriggerClick} + @keydown=${this.handleTriggerKeyDown} + @keyup=${this.handleTriggerKeyUp} + @slotchange=${this.handleTriggerSlotChange} + ></slot> + + <div aria-hidden=${this.open?"false":"true"} aria-labelledby="dropdown"> + <slot part="panel" class="dropdown__panel"></slot> + </div> + </sl-popup> + `}};SlDropdown.styles=[component_styles_default,dropdown_styles_default],SlDropdown.dependencies={"sl-popup":SlPopup},__decorateClass([e$6(".dropdown")],SlDropdown.prototype,"popup",2),__decorateClass([e$6(".dropdown__trigger")],SlDropdown.prototype,"trigger",2),__decorateClass([e$6(".dropdown__panel")],SlDropdown.prototype,"panel",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDropdown.prototype,"open",2),__decorateClass([n$5({reflect:!0})],SlDropdown.prototype,"placement",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlDropdown.prototype,"disabled",2),__decorateClass([n$5({attribute:"stay-open-on-select",type:Boolean,reflect:!0})],SlDropdown.prototype,"stayOpenOnSelect",2),__decorateClass([n$5({attribute:!1})],SlDropdown.prototype,"containingElement",2),__decorateClass([n$5({type:Number})],SlDropdown.prototype,"distance",2),__decorateClass([n$5({type:Number})],SlDropdown.prototype,"skidding",2),__decorateClass([n$5({type:Boolean})],SlDropdown.prototype,"hoist",2),__decorateClass([n$5({reflect:!0})],SlDropdown.prototype,"sync",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlDropdown.prototype,"handleOpenChange",1),setDefaultAnimation("dropdown.show",{keyframes:[{opacity:0,scale:.9},{opacity:1,scale:1}],options:{duration:100,easing:"ease"}}),setDefaultAnimation("dropdown.hide",{keyframes:[{opacity:1,scale:1},{opacity:0,scale:.9}],options:{duration:100,easing:"ease"}});var dropdown_default=SlDropdown;SlDropdown.define("sl-dropdown"),SlIcon.define("sl-icon"),SlIconButton.define("sl-icon-button");var input_styles_default=i$7` + :host { + display: block; + } + + .input { + flex: 1 1 auto; + display: inline-flex; + align-items: stretch; + justify-content: start; + position: relative; + width: 100%; + font-family: var(--sl-input-font-family); + font-weight: var(--sl-input-font-weight); + letter-spacing: var(--sl-input-letter-spacing); + vertical-align: middle; + overflow: hidden; + cursor: text; + transition: + var(--sl-transition-fast) color, + var(--sl-transition-fast) border, + var(--sl-transition-fast) box-shadow, + var(--sl-transition-fast) background-color; + } + + /* Standard inputs */ + .input--standard { + background-color: var(--sl-input-background-color); + border: solid var(--sl-input-border-width) var(--sl-input-border-color); + } + + .input--standard:hover:not(.input--disabled) { + background-color: var(--sl-input-background-color-hover); + border-color: var(--sl-input-border-color-hover); + } + + .input--standard.input--focused:not(.input--disabled) { + background-color: var(--sl-input-background-color-focus); + border-color: var(--sl-input-border-color-focus); + box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color); + } + + .input--standard.input--focused:not(.input--disabled) .input__control { + color: var(--sl-input-color-focus); + } + + .input--standard.input--disabled { + background-color: var(--sl-input-background-color-disabled); + border-color: var(--sl-input-border-color-disabled); + opacity: 0.5; + cursor: not-allowed; + } + + .input--standard.input--disabled .input__control { + color: var(--sl-input-color-disabled); + } + + .input--standard.input--disabled .input__control::placeholder { + color: var(--sl-input-placeholder-color-disabled); + } + + /* Filled inputs */ + .input--filled { + border: none; + background-color: var(--sl-input-filled-background-color); + color: var(--sl-input-color); + } + + .input--filled:hover:not(.input--disabled) { + background-color: var(--sl-input-filled-background-color-hover); + } + + .input--filled.input--focused:not(.input--disabled) { + background-color: var(--sl-input-filled-background-color-focus); + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .input--filled.input--disabled { + background-color: var(--sl-input-filled-background-color-disabled); + opacity: 0.5; + cursor: not-allowed; + } + + .input__control { + flex: 1 1 auto; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + min-width: 0; + height: 100%; + color: var(--sl-input-color); + border: none; + background: inherit; + box-shadow: none; + padding: 0; + margin: 0; + cursor: inherit; + -webkit-appearance: none; + } + + .input__control::-webkit-search-decoration, + .input__control::-webkit-search-cancel-button, + .input__control::-webkit-search-results-button, + .input__control::-webkit-search-results-decoration { + -webkit-appearance: none; + } + + .input__control:-webkit-autofill, + .input__control:-webkit-autofill:hover, + .input__control:-webkit-autofill:focus, + .input__control:-webkit-autofill:active { + box-shadow: 0 0 0 var(--sl-input-height-large) var(--sl-input-background-color-hover) inset !important; + -webkit-text-fill-color: var(--sl-color-primary-500); + caret-color: var(--sl-input-color); + } + + .input--filled .input__control:-webkit-autofill, + .input--filled .input__control:-webkit-autofill:hover, + .input--filled .input__control:-webkit-autofill:focus, + .input--filled .input__control:-webkit-autofill:active { + box-shadow: 0 0 0 var(--sl-input-height-large) var(--sl-input-filled-background-color) inset !important; + } + + .input__control::placeholder { + color: var(--sl-input-placeholder-color); + user-select: none; + -webkit-user-select: none; + } + + .input:hover:not(.input--disabled) .input__control { + color: var(--sl-input-color-hover); + } + + .input__control:focus { + outline: none; + } + + .input__prefix, + .input__suffix { + display: inline-flex; + flex: 0 0 auto; + align-items: center; + cursor: default; + } + + .input__prefix ::slotted(sl-icon), + .input__suffix ::slotted(sl-icon) { + color: var(--sl-input-icon-color); + } + + /* + * Size modifiers + */ + + .input--small { + border-radius: var(--sl-input-border-radius-small); + font-size: var(--sl-input-font-size-small); + height: var(--sl-input-height-small); + } + + .input--small .input__control { + height: calc(var(--sl-input-height-small) - var(--sl-input-border-width) * 2); + padding: 0 var(--sl-input-spacing-small); + } + + .input--small .input__clear, + .input--small .input__password-toggle { + width: calc(1em + var(--sl-input-spacing-small) * 2); + } + + .input--small .input__prefix ::slotted(*) { + margin-inline-start: var(--sl-input-spacing-small); + } + + .input--small .input__suffix ::slotted(*) { + margin-inline-end: var(--sl-input-spacing-small); + } + + .input--medium { + border-radius: var(--sl-input-border-radius-medium); + font-size: var(--sl-input-font-size-medium); + height: var(--sl-input-height-medium); + } + + .input--medium .input__control { + height: calc(var(--sl-input-height-medium) - var(--sl-input-border-width) * 2); + padding: 0 var(--sl-input-spacing-medium); + } + + .input--medium .input__clear, + .input--medium .input__password-toggle { + width: calc(1em + var(--sl-input-spacing-medium) * 2); + } + + .input--medium .input__prefix ::slotted(*) { + margin-inline-start: var(--sl-input-spacing-medium); + } + + .input--medium .input__suffix ::slotted(*) { + margin-inline-end: var(--sl-input-spacing-medium); + } + + .input--large { + border-radius: var(--sl-input-border-radius-large); + font-size: var(--sl-input-font-size-large); + height: var(--sl-input-height-large); + } + + .input--large .input__control { + height: calc(var(--sl-input-height-large) - var(--sl-input-border-width) * 2); + padding: 0 var(--sl-input-spacing-large); + } + + .input--large .input__clear, + .input--large .input__password-toggle { + width: calc(1em + var(--sl-input-spacing-large) * 2); + } + + .input--large .input__prefix ::slotted(*) { + margin-inline-start: var(--sl-input-spacing-large); + } + + .input--large .input__suffix ::slotted(*) { + margin-inline-end: var(--sl-input-spacing-large); + } + + /* + * Pill modifier + */ + + .input--pill.input--small { + border-radius: var(--sl-input-height-small); + } + + .input--pill.input--medium { + border-radius: var(--sl-input-height-medium); + } + + .input--pill.input--large { + border-radius: var(--sl-input-height-large); + } + + /* + * Clearable + Password Toggle + */ + + .input__clear, + .input__password-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: inherit; + color: var(--sl-input-icon-color); + border: none; + background: none; + padding: 0; + transition: var(--sl-transition-fast) color; + cursor: pointer; + } + + .input__clear:hover, + .input__password-toggle:hover { + color: var(--sl-input-icon-color-hover); + } + + .input__clear:focus, + .input__password-toggle:focus { + outline: none; + } + + /* Don't show the browser's password toggle in Edge */ + ::-ms-reveal { + display: none; + } + + /* Hide the built-in number spinner */ + .input--no-spin-buttons input[type='number']::-webkit-outer-spin-button, + .input--no-spin-buttons input[type='number']::-webkit-inner-spin-button { + -webkit-appearance: none; + display: none; + } + + .input--no-spin-buttons input[type='number'] { + -moz-appearance: textfield; + } +`,SlInput=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this,{assumeInteractionOn:["sl-blur","sl-input"]}),this.hasSlotController=new HasSlotController(this,"help-text","label"),this.localize=new LocalizeController(this),this.hasFocus=!1,this.title="",this.__numberInput=Object.assign(document.createElement("input"),{type:"number"}),this.__dateInput=Object.assign(document.createElement("input"),{type:"date"}),this.type="text",this.name="",this.value="",this.defaultValue="",this.size="medium",this.filled=!1,this.pill=!1,this.label="",this.helpText="",this.clearable=!1,this.disabled=!1,this.placeholder="",this.readonly=!1,this.passwordToggle=!1,this.passwordVisible=!1,this.noSpinButtons=!1,this.form="",this.required=!1,this.spellcheck=!0}get valueAsDate(){var _a;return this.__dateInput.type=this.type,this.__dateInput.value=this.value,(null==(_a=this.input)?void 0:_a.valueAsDate)||this.__dateInput.valueAsDate}set valueAsDate(newValue){this.__dateInput.type=this.type,this.__dateInput.valueAsDate=newValue,this.value=this.__dateInput.value}get valueAsNumber(){var _a;return this.__numberInput.value=this.value,(null==(_a=this.input)?void 0:_a.valueAsNumber)||this.__numberInput.valueAsNumber}set valueAsNumber(newValue){this.__numberInput.valueAsNumber=newValue,this.value=this.__numberInput.value}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}firstUpdated(){this.formControlController.updateValidity()}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleChange(){this.value=this.input.value,this.emit("sl-change")}handleClearClick(event){event.preventDefault(),""!==this.value&&(this.value="",this.emit("sl-clear"),this.emit("sl-input"),this.emit("sl-change")),this.input.focus()}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleInput(){this.value=this.input.value,this.formControlController.updateValidity(),this.emit("sl-input")}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}handleKeyDown(event){const hasModifier=event.metaKey||event.ctrlKey||event.shiftKey||event.altKey;"Enter"!==event.key||hasModifier||setTimeout(()=>{event.defaultPrevented||event.isComposing||this.formControlController.submit()})}handlePasswordToggle(){this.passwordVisible=!this.passwordVisible}handleDisabledChange(){this.formControlController.setValidity(this.disabled)}handleStepChange(){this.input.step=this.step+"",this.formControlController.updateValidity()}async handleValueChange(){await this.updateComplete,this.formControlController.updateValidity()}focus(options){this.input.focus(options)}blur(){this.input.blur()}select(){this.input.select()}setSelectionRange(selectionStart,selectionEnd,selectionDirection="none"){this.input.setSelectionRange(selectionStart,selectionEnd,selectionDirection)}setRangeText(replacement,start,end,selectMode="preserve"){const selectionStart=null==start?this.input.selectionStart:start,selectionEnd=null==end?this.input.selectionEnd:end;this.input.setRangeText(replacement,selectionStart,selectionEnd,selectMode),this.value!==this.input.value&&(this.value=this.input.value)}showPicker(){"showPicker"in HTMLInputElement.prototype&&this.input.showPicker()}stepUp(){this.input.stepUp(),this.value!==this.input.value&&(this.value=this.input.value)}stepDown(){this.input.stepDown(),this.value!==this.input.value&&(this.value=this.input.value)}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.input.reportValidity()}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){const hasLabelSlot=this.hasSlotController.test("label"),hasHelpTextSlot=this.hasSlotController.test("help-text"),hasLabel=!!this.label||!!hasLabelSlot,hasHelpText=!!this.helpText||!!hasHelpTextSlot,hasClearIcon=this.clearable&&!this.disabled&&!this.readonly,isClearIconVisible=hasClearIcon&&("number"==typeof this.value||0<this.value.length);return x$1` + <div + part="form-control" + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--has-label":hasLabel,"form-control--has-help-text":hasHelpText})} + > + <label + part="form-control-label" + class="form-control__label" + for="input" + aria-hidden=${hasLabel?"false":"true"} + > + <slot name="label">${this.label}</slot> + </label> + + <div part="form-control-input" class="form-control-input"> + <div + part="base" + class=${e$2({input:!0,"input--small":"small"===this.size,"input--medium":"medium"===this.size,"input--large":"large"===this.size,"input--pill":this.pill,"input--standard":!this.filled,"input--filled":this.filled,"input--disabled":this.disabled,"input--focused":this.hasFocus,"input--empty":!this.value,"input--no-spin-buttons":this.noSpinButtons})} + > + <span part="prefix" class="input__prefix"> + <slot name="prefix"></slot> + </span> + + <input + part="input" + id="input" + class="input__control" + type=${"password"===this.type&&this.passwordVisible?"text":this.type} + title=${this.title} + name=${o$6(this.name)} + ?disabled=${this.disabled} + ?readonly=${this.readonly} + ?required=${this.required} + placeholder=${o$6(this.placeholder)} + minlength=${o$6(this.minlength)} + maxlength=${o$6(this.maxlength)} + min=${o$6(this.min)} + max=${o$6(this.max)} + step=${o$6(this.step)} + .value=${l(this.value)} + autocapitalize=${o$6(this.autocapitalize)} + autocomplete=${o$6(this.autocomplete)} + autocorrect=${o$6(this.autocorrect)} + ?autofocus=${this.autofocus} + spellcheck=${this.spellcheck} + pattern=${o$6(this.pattern)} + enterkeyhint=${o$6(this.enterkeyhint)} + inputmode=${o$6(this.inputmode)} + aria-describedby="help-text" + @change=${this.handleChange} + @input=${this.handleInput} + @invalid=${this.handleInvalid} + @keydown=${this.handleKeyDown} + @focus=${this.handleFocus} + @blur=${this.handleBlur} + /> + + ${isClearIconVisible?x$1` + <button + part="clear-button" + class="input__clear" + type="button" + aria-label=${this.localize.term("clearEntry")} + @click=${this.handleClearClick} + tabindex="-1" + > + <slot name="clear-icon"> + <sl-icon name="x-circle-fill" library="system"></sl-icon> + </slot> + </button> + `:""} + ${this.passwordToggle&&!this.disabled?x$1` + <button + part="password-toggle-button" + class="input__password-toggle" + type="button" + aria-label=${this.localize.term(this.passwordVisible?"hidePassword":"showPassword")} + @click=${this.handlePasswordToggle} + tabindex="-1" + > + ${this.passwordVisible?x$1` + <slot name="show-password-icon"> + <sl-icon name="eye-slash" library="system"></sl-icon> + </slot> + `:x$1` + <slot name="hide-password-icon"> + <sl-icon name="eye" library="system"></sl-icon> + </slot> + `} + </button> + `:""} + + <span part="suffix" class="input__suffix"> + <slot name="suffix"></slot> + </span> + </div> + </div> + + <div + part="form-control-help-text" + id="help-text" + class="form-control__help-text" + aria-hidden=${hasHelpText?"false":"true"} + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlInput.styles=[component_styles_default,form_control_styles_default,input_styles_default],SlInput.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".input__control")],SlInput.prototype,"input",2),__decorateClass([r$6()],SlInput.prototype,"hasFocus",2),__decorateClass([n$5()],SlInput.prototype,"title",2),__decorateClass([n$5({reflect:!0})],SlInput.prototype,"type",2),__decorateClass([n$5()],SlInput.prototype,"name",2),__decorateClass([n$5()],SlInput.prototype,"value",2),__decorateClass([defaultValue()],SlInput.prototype,"defaultValue",2),__decorateClass([n$5({reflect:!0})],SlInput.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlInput.prototype,"filled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlInput.prototype,"pill",2),__decorateClass([n$5()],SlInput.prototype,"label",2),__decorateClass([n$5({attribute:"help-text"})],SlInput.prototype,"helpText",2),__decorateClass([n$5({type:Boolean})],SlInput.prototype,"clearable",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlInput.prototype,"disabled",2),__decorateClass([n$5()],SlInput.prototype,"placeholder",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlInput.prototype,"readonly",2),__decorateClass([n$5({attribute:"password-toggle",type:Boolean})],SlInput.prototype,"passwordToggle",2),__decorateClass([n$5({attribute:"password-visible",type:Boolean})],SlInput.prototype,"passwordVisible",2),__decorateClass([n$5({attribute:"no-spin-buttons",type:Boolean})],SlInput.prototype,"noSpinButtons",2),__decorateClass([n$5({reflect:!0})],SlInput.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlInput.prototype,"required",2),__decorateClass([n$5()],SlInput.prototype,"pattern",2),__decorateClass([n$5({type:Number})],SlInput.prototype,"minlength",2),__decorateClass([n$5({type:Number})],SlInput.prototype,"maxlength",2),__decorateClass([n$5()],SlInput.prototype,"min",2),__decorateClass([n$5()],SlInput.prototype,"max",2),__decorateClass([n$5()],SlInput.prototype,"step",2),__decorateClass([n$5()],SlInput.prototype,"autocapitalize",2),__decorateClass([n$5()],SlInput.prototype,"autocorrect",2),__decorateClass([n$5()],SlInput.prototype,"autocomplete",2),__decorateClass([n$5({type:Boolean})],SlInput.prototype,"autofocus",2),__decorateClass([n$5()],SlInput.prototype,"enterkeyhint",2),__decorateClass([n$5({type:Boolean,converter:{fromAttribute:value=>!!(value&&"false"!==value),toAttribute:value=>value?"true":"false"}})],SlInput.prototype,"spellcheck",2),__decorateClass([n$5()],SlInput.prototype,"inputmode",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlInput.prototype,"handleDisabledChange",1),__decorateClass([watch("step",{waitUntilFirstUpdate:!0})],SlInput.prototype,"handleStepChange",1),__decorateClass([watch("value",{waitUntilFirstUpdate:!0})],SlInput.prototype,"handleValueChange",1),SlInput.define("sl-input");var menu_styles_default=i$7` + :host { + display: block; + position: relative; + background: var(--sl-panel-background-color); + border: solid var(--sl-panel-border-width) var(--sl-panel-border-color); + border-radius: var(--sl-border-radius-medium); + padding: var(--sl-spacing-x-small) 0; + overflow: auto; + overscroll-behavior: none; + } + + ::slotted(sl-divider) { + --spacing: var(--sl-spacing-x-small); + } +`,SlMenu=class extends ShoelaceElement{connectedCallback(){super.connectedCallback(),this.setAttribute("role","menu")}handleClick(event){const menuItemTypes=["menuitem","menuitemcheckbox"],composedPath=event.composedPath(),target=composedPath.find(el=>{var _a;return menuItemTypes.includes((null==(_a=null==el?void 0:el.getAttribute)?void 0:_a.call(el,"role"))||"")});if(!target)return;const closestMenu=composedPath.find(el=>{var _a;return"menu"===(null==(_a=null==el?void 0:el.getAttribute)?void 0:_a.call(el,"role"))}),clickHasSubmenu=closestMenu!==this;if(!clickHasSubmenu){const item=target;"checkbox"===item.type&&(item.checked=!item.checked),this.emit("sl-select",{detail:{item}})}}handleKeyDown(event){if("Enter"===event.key||" "===event.key){const item=this.getCurrentItem();event.preventDefault(),event.stopPropagation(),null==item?void 0:item.click()}else if(["ArrowDown","ArrowUp","Home","End"].includes(event.key)){const items=this.getAllItems(),activeItem=this.getCurrentItem();let index=activeItem?items.indexOf(activeItem):0;0<items.length&&(event.preventDefault(),event.stopPropagation(),"ArrowDown"===event.key?index++:"ArrowUp"===event.key?index--:"Home"===event.key?index=0:"End"===event.key&&(index=items.length-1),0>index&&(index=items.length-1),index>items.length-1&&(index=0),this.setCurrentItem(items[index]),items[index].focus())}}handleMouseDown(event){const target=event.target;this.isMenuItem(target)&&this.setCurrentItem(target)}handleSlotChange(){const items=this.getAllItems();0<items.length&&this.setCurrentItem(items[0])}isMenuItem(item){var _a;return"sl-menu-item"===item.tagName.toLowerCase()||["menuitem","menuitemcheckbox","menuitemradio"].includes(null==(_a=item.getAttribute("role"))?"":_a)}getAllItems(){return[...this.defaultSlot.assignedElements({flatten:!0})].filter(el=>!el.inert&&this.isMenuItem(el))}getCurrentItem(){return this.getAllItems().find(i=>"0"===i.getAttribute("tabindex"))}setCurrentItem(item){const items=this.getAllItems();items.forEach(i=>{i.setAttribute("tabindex",i===item?"0":"-1")})}render(){return x$1` + <slot + @slotchange=${this.handleSlotChange} + @click=${this.handleClick} + @keydown=${this.handleKeyDown} + @mousedown=${this.handleMouseDown} + ></slot> + `}};SlMenu.styles=[component_styles_default,menu_styles_default],__decorateClass([e$6("slot")],SlMenu.prototype,"defaultSlot",2),SlMenu.define("sl-menu");var menu_item_styles_default=i$7` + :host { + --submenu-offset: -2px; + + display: block; + } + + :host([inert]) { + display: none; + } + + .menu-item { + position: relative; + display: flex; + align-items: stretch; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + line-height: var(--sl-line-height-normal); + letter-spacing: var(--sl-letter-spacing-normal); + color: var(--sl-color-neutral-700); + padding: var(--sl-spacing-2x-small) var(--sl-spacing-2x-small); + transition: var(--sl-transition-fast) fill; + user-select: none; + -webkit-user-select: none; + white-space: nowrap; + cursor: pointer; + } + + .menu-item.menu-item--disabled { + outline: none; + opacity: 0.5; + cursor: not-allowed; + } + + .menu-item.menu-item--loading { + outline: none; + cursor: wait; + } + + .menu-item.menu-item--loading *:not(sl-spinner) { + opacity: 0.5; + } + + .menu-item--loading sl-spinner { + --indicator-color: currentColor; + --track-width: 1px; + position: absolute; + font-size: 0.75em; + top: calc(50% - 0.5em); + left: 0.65rem; + opacity: 1; + } + + .menu-item .menu-item__label { + flex: 1 1 auto; + display: inline-block; + text-overflow: ellipsis; + overflow: hidden; + } + + .menu-item .menu-item__prefix { + flex: 0 0 auto; + display: flex; + align-items: center; + } + + .menu-item .menu-item__prefix::slotted(*) { + margin-inline-end: var(--sl-spacing-x-small); + } + + .menu-item .menu-item__suffix { + flex: 0 0 auto; + display: flex; + align-items: center; + } + + .menu-item .menu-item__suffix::slotted(*) { + margin-inline-start: var(--sl-spacing-x-small); + } + + /* Safe triangle */ + .menu-item--submenu-expanded::after { + content: ''; + position: fixed; + z-index: calc(var(--sl-z-index-dropdown) - 1); + top: 0; + right: 0; + bottom: 0; + left: 0; + clip-path: polygon( + var(--safe-triangle-cursor-x, 0) var(--safe-triangle-cursor-y, 0), + var(--safe-triangle-submenu-start-x, 0) var(--safe-triangle-submenu-start-y, 0), + var(--safe-triangle-submenu-end-x, 0) var(--safe-triangle-submenu-end-y, 0) + ); + } + + :host(:focus-visible) { + outline: none; + } + + :host(:hover:not([aria-disabled='true'], :focus-visible)) .menu-item, + .menu-item--submenu-expanded { + background-color: var(--sl-color-neutral-100); + color: var(--sl-color-neutral-1000); + } + + :host(:focus-visible) .menu-item { + outline: none; + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + opacity: 1; + } + + .menu-item .menu-item__check, + .menu-item .menu-item__chevron { + flex: 0 0 auto; + display: flex; + align-items: center; + justify-content: center; + width: 1.5em; + visibility: hidden; + } + + .menu-item--checked .menu-item__check, + .menu-item--has-submenu .menu-item__chevron { + visibility: visible; + } + + /* Add elevation and z-index to submenus */ + sl-popup::part(popup) { + box-shadow: var(--sl-shadow-large); + z-index: var(--sl-z-index-dropdown); + margin-left: var(--submenu-offset); + } + + .menu-item--rtl sl-popup::part(popup) { + margin-left: calc(-1 * var(--submenu-offset)); + } + + @media (forced-colors: active) { + :host(:hover:not([aria-disabled='true'])) .menu-item, + :host(:focus-visible) .menu-item { + outline: dashed 1px SelectedItem; + outline-offset: -1px; + } + } + + ::slotted(sl-menu) { + max-width: var(--auto-size-available-width) !important; + max-height: var(--auto-size-available-height) !important; + } +`;const s=(i,t)=>{const e=i._$AN;if(void 0===e)return!1;for(const i of e)i._$AO?.(t,!1),s(i,t);return!0},o$5=i=>{let t,e;do{if(void 0===(t=i._$AM))break;e=t._$AN,e.delete(i),i=t}while(0===e?.size)},r$2=i=>{for(let t,e;t=i._$AM;i=t){if(e=t._$AN,void 0===e)t._$AN=e=new Set;else if(e.has(i))break;e.add(i),c$1(t)}};function h$2(i){void 0===this._$AN?this._$AM=i:(o$5(this),this._$AM=i,r$2(this))}function n$3(i,t=!1,e=0){const r=this._$AH,h=this._$AN;if(void 0!==h&&0!==h.size)if(!t)s(this,i);else if(Array.isArray(r))for(let i=e;i<r.length;i++)s(r[i],!1),o$5(r[i]);else null!=r&&(s(r,!1),o$5(r))}const c$1=i=>{i.type==t.CHILD&&(i._$AP??=n$3,i._$AQ??=h$2)};class f extends i$3{constructor(){super(...arguments),this._$AN=void 0}_$AT(i,t,e){super._$AT(i,t,e),r$2(this),this.isConnected=i._$AU}_$AO(i,t=!0){i!==this.isConnected&&(this.isConnected=i,i?this.reconnected?.():this.disconnected?.()),t&&(s(this,i),o$5(this))}setValue(t){if(f$1(this._$Ct))this._$Ct._$AI(t,this);else{const i=[...this._$Ct._$AH];i[this._$Ci]=t,this._$Ct._$AI(i,this,0)}}disconnected(){}reconnected(){}}const e$1=()=>new h$1;let h$1=class{};const o$4=new WeakMap,n$2=e$3(class extends f{render(){return E$1}update(i,[s]){const e=s!==this.G;return e&&void 0!==this.G&&this.rt(void 0),(e||this.lt!==this.ct)&&(this.G=s,this.ht=i.options?.host,this.rt(this.ct=i.element)),E$1}rt(t){if(this.isConnected||(t=void 0),"function"==typeof this.G){const i=this.ht??globalThis;let s=o$4.get(i);void 0===s&&(s=new WeakMap,o$4.set(i,s)),void 0!==s.get(this.G)&&this.G.call(this.ht,void 0),s.set(this.G,t),void 0!==t&&this.G.call(this.ht,t)}else this.G.value=t}get lt(){return"function"==typeof this.G?o$4.get(this.ht??globalThis)?.get(this.G):this.G?.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}});var SubmenuController=class{constructor(host,hasSlotController){this.popupRef=e$1(),this.enableSubmenuTimer=-1,this.isConnected=!1,this.isPopupConnected=!1,this.skidding=0,this.submenuOpenDelay=100,this.handleMouseMove=event=>{this.host.style.setProperty("--safe-triangle-cursor-x",`${event.clientX}px`),this.host.style.setProperty("--safe-triangle-cursor-y",`${event.clientY}px`)},this.handleMouseOver=()=>{this.hasSlotController.test("submenu")&&this.enableSubmenu()},this.handleKeyDown=event=>{switch(event.key){case"Escape":case"Tab":this.disableSubmenu();break;case"ArrowLeft":event.target!==this.host&&(event.preventDefault(),event.stopPropagation(),this.host.focus(),this.disableSubmenu());break;case"ArrowRight":case"Enter":case" ":this.handleSubmenuEntry(event)}},this.handleClick=event=>{var _a;event.target===this.host?(event.preventDefault(),event.stopPropagation()):event.target instanceof Element&&("sl-menu-item"===event.target.tagName||(null==(_a=event.target.role)?void 0:_a.startsWith("menuitem")))&&this.disableSubmenu()},this.handleFocusOut=event=>{event.relatedTarget&&event.relatedTarget instanceof Element&&this.host.contains(event.relatedTarget)||this.disableSubmenu()},this.handlePopupMouseover=event=>{event.stopPropagation()},this.handlePopupReposition=()=>{const submenuSlot=this.host.renderRoot.querySelector("slot[name='submenu']"),menu=null==submenuSlot?void 0:submenuSlot.assignedElements({flatten:!0}).filter(el=>"sl-menu"===el.localName)[0],isRtl="rtl"===getComputedStyle(this.host).direction;if(menu){const{left,top,width,height}=menu.getBoundingClientRect();this.host.style.setProperty("--safe-triangle-submenu-start-x",`${isRtl?left+width:left}px`),this.host.style.setProperty("--safe-triangle-submenu-start-y",`${top}px`),this.host.style.setProperty("--safe-triangle-submenu-end-x",`${isRtl?left+width:left}px`),this.host.style.setProperty("--safe-triangle-submenu-end-y",`${top+height}px`)}},(this.host=host).addController(this),this.hasSlotController=hasSlotController}hostConnected(){this.hasSlotController.test("submenu")&&!this.host.disabled&&this.addListeners()}hostDisconnected(){this.removeListeners()}hostUpdated(){this.hasSlotController.test("submenu")&&!this.host.disabled?(this.addListeners(),this.updateSkidding()):this.removeListeners()}addListeners(){this.isConnected||(this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseover",this.handleMouseOver),this.host.addEventListener("keydown",this.handleKeyDown),this.host.addEventListener("click",this.handleClick),this.host.addEventListener("focusout",this.handleFocusOut),this.isConnected=!0),!this.isPopupConnected&&this.popupRef.value&&(this.popupRef.value.addEventListener("mouseover",this.handlePopupMouseover),this.popupRef.value.addEventListener("sl-reposition",this.handlePopupReposition),this.isPopupConnected=!0)}removeListeners(){this.isConnected&&(this.host.removeEventListener("mousemove",this.handleMouseMove),this.host.removeEventListener("mouseover",this.handleMouseOver),this.host.removeEventListener("keydown",this.handleKeyDown),this.host.removeEventListener("click",this.handleClick),this.host.removeEventListener("focusout",this.handleFocusOut),this.isConnected=!1),this.isPopupConnected&&this.popupRef.value&&(this.popupRef.value.removeEventListener("mouseover",this.handlePopupMouseover),this.popupRef.value.removeEventListener("sl-reposition",this.handlePopupReposition),this.isPopupConnected=!1)}handleSubmenuEntry(event){const submenuSlot=this.host.renderRoot.querySelector("slot[name='submenu']");if(!submenuSlot)return void console.error("Cannot activate a submenu if no corresponding menuitem can be found.",this);let menuItems=null;for(const elt of submenuSlot.assignedElements())if(menuItems=elt.querySelectorAll("sl-menu-item, [role^='menuitem']"),0!==menuItems.length)break;if(menuItems&&0!==menuItems.length){menuItems[0].setAttribute("tabindex","0");for(let i=1;i!==menuItems.length;++i)menuItems[i].setAttribute("tabindex","-1");this.popupRef.value&&(event.preventDefault(),event.stopPropagation(),this.popupRef.value.active?menuItems[0]instanceof HTMLElement&&menuItems[0].focus():(this.enableSubmenu(!1),this.host.updateComplete.then(()=>{menuItems[0]instanceof HTMLElement&&menuItems[0].focus()}),this.host.requestUpdate()))}}setSubmenuState(state){this.popupRef.value&&this.popupRef.value.active!==state&&(this.popupRef.value.active=state,this.host.requestUpdate())}enableSubmenu(delay=!0){delay?(window.clearTimeout(this.enableSubmenuTimer),this.enableSubmenuTimer=window.setTimeout(()=>{this.setSubmenuState(!0)},this.submenuOpenDelay)):this.setSubmenuState(!0)}disableSubmenu(){window.clearTimeout(this.enableSubmenuTimer),this.setSubmenuState(!1)}updateSkidding(){var _a;if(null==(_a=this.host.parentElement)||!_a.computedStyleMap)return;const styleMap=this.host.parentElement.computedStyleMap(),skidding=["padding-top","border-top-width","margin-top"].reduce((accumulator,attr)=>{var _a2;const styleValue=null==(_a2=styleMap.get(attr))?new CSSUnitValue(0,"px"):_a2,unitValue=styleValue instanceof CSSUnitValue?styleValue:new CSSUnitValue(0,"px"),pxValue=unitValue.to("px");return accumulator-pxValue.value},0);this.skidding=skidding}isExpanded(){return!!this.popupRef.value&&this.popupRef.value.active}renderSubmenu(){const isRtl="rtl"===getComputedStyle(this.host).direction;return this.isConnected?x$1` + <sl-popup + ${n$2(this.popupRef)} + placement=${isRtl?"left-start":"right-start"} + anchor="anchor" + flip + flip-fallback-strategy="best-fit" + skidding="${this.skidding}" + strategy="fixed" + auto-size="vertical" + auto-size-padding="10" + > + <slot name="submenu"></slot> + </sl-popup> + `:x$1` <slot name="submenu" hidden></slot> `}},SlMenuItem=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.type="normal",this.checked=!1,this.value="",this.loading=!1,this.disabled=!1,this.hasSlotController=new HasSlotController(this,"submenu"),this.submenuController=new SubmenuController(this,this.hasSlotController),this.handleHostClick=event=>{this.disabled&&(event.preventDefault(),event.stopImmediatePropagation())},this.handleMouseOver=event=>{this.focus(),event.stopPropagation()}}connectedCallback(){super.connectedCallback(),this.addEventListener("click",this.handleHostClick),this.addEventListener("mouseover",this.handleMouseOver)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("click",this.handleHostClick),this.removeEventListener("mouseover",this.handleMouseOver)}handleDefaultSlotChange(){const textLabel=this.getTextLabel();return"undefined"==typeof this.cachedTextLabel?void(this.cachedTextLabel=textLabel):void(textLabel!==this.cachedTextLabel&&(this.cachedTextLabel=textLabel,this.emit("slotchange",{bubbles:!0,composed:!1,cancelable:!1})))}handleCheckedChange(){return this.checked&&"checkbox"!==this.type?(this.checked=!1,void console.error("The checked attribute can only be used on menu items with type=\"checkbox\"",this)):void("checkbox"===this.type?this.setAttribute("aria-checked",this.checked?"true":"false"):this.removeAttribute("aria-checked"))}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false")}handleTypeChange(){"checkbox"===this.type?(this.setAttribute("role","menuitemcheckbox"),this.setAttribute("aria-checked",this.checked?"true":"false")):(this.setAttribute("role","menuitem"),this.removeAttribute("aria-checked"))}getTextLabel(){return getTextContent(this.defaultSlot)}isSubmenu(){return this.hasSlotController.test("submenu")}render(){const isRtl="rtl"===this.localize.dir(),isSubmenuExpanded=this.submenuController.isExpanded();return x$1` + <div + id="anchor" + part="base" + class=${e$2({"menu-item":!0,"menu-item--rtl":isRtl,"menu-item--checked":this.checked,"menu-item--disabled":this.disabled,"menu-item--loading":this.loading,"menu-item--has-submenu":this.isSubmenu(),"menu-item--submenu-expanded":isSubmenuExpanded})} + ?aria-haspopup="${this.isSubmenu()}" + ?aria-expanded="${!!isSubmenuExpanded}" + > + <span part="checked-icon" class="menu-item__check"> + <sl-icon name="check" library="system" aria-hidden="true"></sl-icon> + </span> + + <slot name="prefix" part="prefix" class="menu-item__prefix"></slot> + + <slot part="label" class="menu-item__label" @slotchange=${this.handleDefaultSlotChange}></slot> + + <slot name="suffix" part="suffix" class="menu-item__suffix"></slot> + + <span part="submenu-icon" class="menu-item__chevron"> + <sl-icon name=${isRtl?"chevron-left":"chevron-right"} library="system" aria-hidden="true"></sl-icon> + </span> + + ${this.submenuController.renderSubmenu()} + ${this.loading?x$1` <sl-spinner part="spinner" exportparts="base:spinner__base"></sl-spinner> `:""} + </div> + `}};SlMenuItem.styles=[component_styles_default,menu_item_styles_default],SlMenuItem.dependencies={"sl-icon":SlIcon,"sl-popup":SlPopup,"sl-spinner":SlSpinner},__decorateClass([e$6("slot:not([name])")],SlMenuItem.prototype,"defaultSlot",2),__decorateClass([e$6(".menu-item")],SlMenuItem.prototype,"menuItem",2),__decorateClass([n$5()],SlMenuItem.prototype,"type",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlMenuItem.prototype,"checked",2),__decorateClass([n$5()],SlMenuItem.prototype,"value",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlMenuItem.prototype,"loading",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlMenuItem.prototype,"disabled",2),__decorateClass([watch("checked")],SlMenuItem.prototype,"handleCheckedChange",1),__decorateClass([watch("disabled")],SlMenuItem.prototype,"handleDisabledChange",1),__decorateClass([watch("type")],SlMenuItem.prototype,"handleTypeChange",1),SlMenuItem.define("sl-menu-item");var option_styles_default=i$7` + :host { + display: block; + user-select: none; + -webkit-user-select: none; + } + + :host(:focus) { + outline: none; + } + + .option { + position: relative; + display: flex; + align-items: center; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + line-height: var(--sl-line-height-normal); + letter-spacing: var(--sl-letter-spacing-normal); + color: var(--sl-color-neutral-700); + padding: var(--sl-spacing-x-small) var(--sl-spacing-medium) var(--sl-spacing-x-small) var(--sl-spacing-x-small); + transition: var(--sl-transition-fast) fill; + cursor: pointer; + } + + .option--hover:not(.option--current):not(.option--disabled) { + background-color: var(--sl-color-neutral-100); + color: var(--sl-color-neutral-1000); + } + + .option--current, + .option--current.option--disabled { + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + opacity: 1; + } + + .option--disabled { + outline: none; + opacity: 0.5; + cursor: not-allowed; + } + + .option__label { + flex: 1 1 auto; + display: inline-block; + line-height: var(--sl-line-height-dense); + } + + .option .option__check { + flex: 0 0 auto; + display: flex; + align-items: center; + justify-content: center; + visibility: hidden; + padding-inline-end: var(--sl-spacing-2x-small); + } + + .option--selected .option__check { + visibility: visible; + } + + .option__prefix, + .option__suffix { + flex: 0 0 auto; + display: flex; + align-items: center; + } + + .option__prefix::slotted(*) { + margin-inline-end: var(--sl-spacing-x-small); + } + + .option__suffix::slotted(*) { + margin-inline-start: var(--sl-spacing-x-small); + } + + @media (forced-colors: active) { + :host(:hover:not([aria-disabled='true'])) .option { + outline: dashed 1px SelectedItem; + outline-offset: -1px; + } + } +`,SlOption=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.isInitialized=!1,this.current=!1,this.selected=!1,this.hasHover=!1,this.value="",this.disabled=!1}connectedCallback(){super.connectedCallback(),this.setAttribute("role","option"),this.setAttribute("aria-selected","false")}handleDefaultSlotChange(){this.isInitialized?customElements.whenDefined("sl-select").then(()=>{const controller=this.closest("sl-select");controller&&controller.handleDefaultSlotChange()}):this.isInitialized=!0}handleMouseEnter(){this.hasHover=!0}handleMouseLeave(){this.hasHover=!1}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false")}handleSelectedChange(){this.setAttribute("aria-selected",this.selected?"true":"false")}handleValueChange(){"string"!=typeof this.value&&(this.value=this.value+""),this.value.includes(" ")&&(console.error(`Option values cannot include a space. All spaces have been replaced with underscores.`,this),this.value=this.value.replace(/ /g,"_"))}getTextLabel(){const nodes=this.childNodes;let label="";return[...nodes].forEach(node=>{node.nodeType!==Node.ELEMENT_NODE||node.hasAttribute("slot")||(label+=node.textContent),node.nodeType===Node.TEXT_NODE&&(label+=node.textContent)}),label.trim()}render(){return x$1` + <div + part="base" + class=${e$2({option:!0,"option--current":this.current,"option--disabled":this.disabled,"option--selected":this.selected,"option--hover":this.hasHover})} + @mouseenter=${this.handleMouseEnter} + @mouseleave=${this.handleMouseLeave} + > + <sl-icon part="checked-icon" class="option__check" name="check" library="system" aria-hidden="true"></sl-icon> + <slot part="prefix" name="prefix" class="option__prefix"></slot> + <slot part="label" class="option__label" @slotchange=${this.handleDefaultSlotChange}></slot> + <slot part="suffix" name="suffix" class="option__suffix"></slot> + </div> + `}};SlOption.styles=[component_styles_default,option_styles_default],SlOption.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".option__label")],SlOption.prototype,"defaultSlot",2),__decorateClass([r$6()],SlOption.prototype,"current",2),__decorateClass([r$6()],SlOption.prototype,"selected",2),__decorateClass([r$6()],SlOption.prototype,"hasHover",2),__decorateClass([n$5({reflect:!0})],SlOption.prototype,"value",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlOption.prototype,"disabled",2),__decorateClass([watch("disabled")],SlOption.prototype,"handleDisabledChange",1),__decorateClass([watch("selected")],SlOption.prototype,"handleSelectedChange",1),__decorateClass([watch("value")],SlOption.prototype,"handleValueChange",1),SlOption.define("sl-option"),SlPopup.define("sl-popup");var progress_bar_styles_default=i$7` + :host { + --height: 1rem; + --track-color: var(--sl-color-neutral-200); + --indicator-color: var(--sl-color-primary-600); + --label-color: var(--sl-color-neutral-0); + + display: block; + } + + .progress-bar { + position: relative; + background-color: var(--track-color); + height: var(--height); + border-radius: var(--sl-border-radius-pill); + box-shadow: inset var(--sl-shadow-small); + overflow: hidden; + } + + .progress-bar__indicator { + height: 100%; + font-family: var(--sl-font-sans); + font-size: 12px; + font-weight: var(--sl-font-weight-normal); + background-color: var(--indicator-color); + color: var(--label-color); + text-align: center; + line-height: var(--height); + white-space: nowrap; + overflow: hidden; + transition: + 400ms width, + 400ms background-color; + user-select: none; + -webkit-user-select: none; + } + + /* Indeterminate */ + .progress-bar--indeterminate .progress-bar__indicator { + position: absolute; + animation: indeterminate 2.5s infinite cubic-bezier(0.37, 0, 0.63, 1); + } + + .progress-bar--indeterminate.progress-bar--rtl .progress-bar__indicator { + animation-name: indeterminate-rtl; + } + + @media (forced-colors: active) { + .progress-bar { + outline: solid 1px SelectedItem; + background-color: var(--sl-color-neutral-0); + } + + .progress-bar__indicator { + outline: solid 1px SelectedItem; + background-color: SelectedItem; + } + } + + @keyframes indeterminate { + 0% { + left: -50%; + width: 50%; + } + 75%, + 100% { + left: 100%; + width: 50%; + } + } + + @keyframes indeterminate-rtl { + 0% { + right: -50%; + width: 50%; + } + 75%, + 100% { + right: 100%; + width: 50%; + } + } +`;const n$1="important",i$1=" !important",o$3=e$3(class extends i$3{constructor(t$1){if(super(t$1),t$1.type!==t.ATTRIBUTE||"style"!==t$1.name||2<t$1.strings?.length)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce((e,r)=>{const s=t[r];return null==s?e:e+`${r=r.includes("-")?r:r.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(e,[r]){const{style:s}=e.element;if(void 0===this.ft)return this.ft=new Set(Object.keys(r)),this.render(r);for(const t of this.ft)null==r[t]&&(this.ft.delete(t),t.includes("-")?s.removeProperty(t):s[t]=null);for(const t in r){const e=r[t];if(null!=e){this.ft.add(t);const r="string"==typeof e&&e.endsWith(i$1);t.includes("-")||r?s.setProperty(t,r?e.slice(0,-11):e,r?n$1:""):s[t]=e}}return T$1}});var SlProgressBar=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.value=0,this.indeterminate=!1,this.label=""}render(){return x$1` + <div + part="base" + class=${e$2({"progress-bar":!0,"progress-bar--indeterminate":this.indeterminate,"progress-bar--rtl":"rtl"===this.localize.dir()})} + role="progressbar" + title=${o$6(this.title)} + aria-label=${0<this.label.length?this.label:this.localize.term("progress")} + aria-valuemin="0" + aria-valuemax="100" + aria-valuenow=${this.indeterminate?0:this.value} + > + <div part="indicator" class="progress-bar__indicator" style=${o$3({width:`${this.value}%`})}> + ${this.indeterminate?"":x$1` <slot part="label" class="progress-bar__label"></slot> `} + </div> + </div> + `}};SlProgressBar.styles=[component_styles_default,progress_bar_styles_default],__decorateClass([n$5({type:Number,reflect:!0})],SlProgressBar.prototype,"value",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlProgressBar.prototype,"indeterminate",2),__decorateClass([n$5()],SlProgressBar.prototype,"label",2),SlProgressBar.define("sl-progress-bar");var radio_group_styles_default=i$7` + :host { + display: block; + } + + .form-control { + position: relative; + border: none; + padding: 0; + margin: 0; + } + + .form-control__label { + padding: 0; + } + + .radio-group--required .radio-group__label::after { + content: var(--sl-input-required-content); + margin-inline-start: var(--sl-input-required-content-offset); + } + + .visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + } +`,button_group_styles_default=i$7` + :host { + display: inline-block; + } + + .button-group { + display: flex; + flex-wrap: nowrap; + } +`,SlButtonGroup=class extends ShoelaceElement{constructor(){super(...arguments),this.disableRole=!1,this.label=""}handleFocus(event){const button=findButton(event.target);null==button?void 0:button.toggleAttribute("data-sl-button-group__button--focus",!0)}handleBlur(event){const button=findButton(event.target);null==button?void 0:button.toggleAttribute("data-sl-button-group__button--focus",!1)}handleMouseOver(event){const button=findButton(event.target);null==button?void 0:button.toggleAttribute("data-sl-button-group__button--hover",!0)}handleMouseOut(event){const button=findButton(event.target);null==button?void 0:button.toggleAttribute("data-sl-button-group__button--hover",!1)}handleSlotChange(){const slottedElements=[...this.defaultSlot.assignedElements({flatten:!0})];slottedElements.forEach(el=>{const index=slottedElements.indexOf(el),button=findButton(el);button&&(button.toggleAttribute("data-sl-button-group__button",!0),button.toggleAttribute("data-sl-button-group__button--first",0===index),button.toggleAttribute("data-sl-button-group__button--inner",0<index&&index<slottedElements.length-1),button.toggleAttribute("data-sl-button-group__button--last",index===slottedElements.length-1),button.toggleAttribute("data-sl-button-group__button--radio","sl-radio-button"===button.tagName.toLowerCase()))})}render(){return x$1` + <div + part="base" + class="button-group" + role="${this.disableRole?"presentation":"group"}" + aria-label=${this.label} + @focusout=${this.handleBlur} + @focusin=${this.handleFocus} + @mouseover=${this.handleMouseOver} + @mouseout=${this.handleMouseOut} + > + <slot @slotchange=${this.handleSlotChange}></slot> + </div> + `}};SlButtonGroup.styles=[component_styles_default,button_group_styles_default],__decorateClass([e$6("slot")],SlButtonGroup.prototype,"defaultSlot",2),__decorateClass([r$6()],SlButtonGroup.prototype,"disableRole",2),__decorateClass([n$5()],SlButtonGroup.prototype,"label",2);function findButton(el){var _a;return null==(_a=el.closest("sl-button, sl-radio-button"))?el.querySelector("sl-button, sl-radio-button"):_a}var SlRadioGroup=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this),this.hasSlotController=new HasSlotController(this,"help-text","label"),this.customValidityMessage="",this.hasButtonGroup=!1,this.errorMessage="",this.defaultValue="",this.label="",this.helpText="",this.name="option",this.value="",this.size="medium",this.form="",this.required=!1}get validity(){const isRequiredAndEmpty=this.required&&!this.value,hasCustomValidityMessage=""!==this.customValidityMessage;if(hasCustomValidityMessage)return customErrorValidityState;return isRequiredAndEmpty?valueMissingValidityState:validValidityState}get validationMessage(){const isRequiredAndEmpty=this.required&&!this.value,hasCustomValidityMessage=""!==this.customValidityMessage;if(hasCustomValidityMessage)return this.customValidityMessage;return isRequiredAndEmpty?this.validationInput.validationMessage:""}connectedCallback(){super.connectedCallback(),this.defaultValue=this.value}firstUpdated(){this.formControlController.updateValidity()}getAllRadios(){return[...this.querySelectorAll("sl-radio, sl-radio-button")]}handleRadioClick(event){const target=event.target.closest("sl-radio, sl-radio-button"),radios=this.getAllRadios(),oldValue=this.value;!target||target.disabled||(this.value=target.value,radios.forEach(radio=>radio.checked=radio===target),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input")))}handleKeyDown(event){var _a;if(!["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"," "].includes(event.key))return;const radios=this.getAllRadios().filter(radio=>!radio.disabled),checkedRadio=null==(_a=radios.find(radio=>radio.checked))?radios[0]:_a,incr=" "===event.key?0:["ArrowUp","ArrowLeft"].includes(event.key)?-1:1,oldValue=this.value;let index=radios.indexOf(checkedRadio)+incr;0>index&&(index=radios.length-1),index>radios.length-1&&(index=0),this.getAllRadios().forEach(radio=>{radio.checked=!1,this.hasButtonGroup||radio.setAttribute("tabindex","-1")}),this.value=radios[index].value,radios[index].checked=!0,this.hasButtonGroup?radios[index].shadowRoot.querySelector("button").focus():(radios[index].setAttribute("tabindex","0"),radios[index].focus()),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input")),event.preventDefault()}handleLabelClick(){this.focus()}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}async syncRadioElements(){var _a,_b;const radios=this.getAllRadios();if(await Promise.all(radios.map(async radio=>{await radio.updateComplete,radio.checked=radio.value===this.value,radio.size=this.size})),this.hasButtonGroup=radios.some(radio=>"sl-radio-button"===radio.tagName.toLowerCase()),0<radios.length&&!radios.some(radio=>radio.checked))if(this.hasButtonGroup){const buttonRadio=null==(_a=radios[0].shadowRoot)?void 0:_a.querySelector("button");buttonRadio&&buttonRadio.setAttribute("tabindex","0")}else radios[0].setAttribute("tabindex","0");if(this.hasButtonGroup){const buttonGroup=null==(_b=this.shadowRoot)?void 0:_b.querySelector("sl-button-group");buttonGroup&&(buttonGroup.disableRole=!0)}}syncRadios(){return customElements.get("sl-radio")&&customElements.get("sl-radio-button")?void this.syncRadioElements():void(customElements.get("sl-radio")?this.syncRadioElements():customElements.whenDefined("sl-radio").then(()=>this.syncRadios()),customElements.get("sl-radio-button")?this.syncRadioElements():customElements.whenDefined("sl-radio-button").then(()=>this.syncRadios()))}updateCheckedRadio(){const radios=this.getAllRadios();radios.forEach(radio=>radio.checked=radio.value===this.value),this.formControlController.setValidity(this.validity.valid)}handleSizeChange(){this.syncRadios()}handleValueChange(){this.hasUpdated&&this.updateCheckedRadio()}checkValidity(){const isRequiredAndEmpty=this.required&&!this.value,hasCustomValidityMessage=""!==this.customValidityMessage;return!(isRequiredAndEmpty||hasCustomValidityMessage)||(this.formControlController.emitInvalidEvent(),!1)}getForm(){return this.formControlController.getForm()}reportValidity(){const isValid=this.validity.valid;return this.errorMessage=this.customValidityMessage||isValid?"":this.validationInput.validationMessage,this.formControlController.setValidity(isValid),this.validationInput.hidden=!0,clearTimeout(this.validationTimeout),isValid||(this.validationInput.hidden=!1,this.validationInput.reportValidity(),this.validationTimeout=setTimeout(()=>this.validationInput.hidden=!0,1e4)),isValid}setCustomValidity(message=""){this.customValidityMessage=message,this.errorMessage=message,this.validationInput.setCustomValidity(message),this.formControlController.updateValidity()}focus(options){const radios=this.getAllRadios(),checked=radios.find(radio=>radio.checked),firstEnabledRadio=radios.find(radio=>!radio.disabled),radioToFocus=checked||firstEnabledRadio;radioToFocus&&radioToFocus.focus(options)}render(){const hasLabelSlot=this.hasSlotController.test("label"),hasHelpTextSlot=this.hasSlotController.test("help-text"),hasLabel=!!this.label||!!hasLabelSlot,hasHelpText=!!this.helpText||!!hasHelpTextSlot,defaultSlot=x$1` + <slot @slotchange=${this.syncRadios} @click=${this.handleRadioClick} @keydown=${this.handleKeyDown}></slot> + `;return x$1` + <fieldset + part="form-control" + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--radio-group":!0,"form-control--has-label":hasLabel,"form-control--has-help-text":hasHelpText})} + role="radiogroup" + aria-labelledby="label" + aria-describedby="help-text" + aria-errormessage="error-message" + > + <label + part="form-control-label" + id="label" + class="form-control__label" + aria-hidden=${hasLabel?"false":"true"} + @click=${this.handleLabelClick} + > + <slot name="label">${this.label}</slot> + </label> + + <div part="form-control-input" class="form-control-input"> + <div class="visually-hidden"> + <div id="error-message" aria-live="assertive">${this.errorMessage}</div> + <label class="radio-group__validation"> + <input + type="text" + class="radio-group__validation-input" + ?required=${this.required} + tabindex="-1" + hidden + @invalid=${this.handleInvalid} + /> + </label> + </div> + + ${this.hasButtonGroup?x$1` + <sl-button-group part="button-group" exportparts="base:button-group__base" role="presentation"> + ${defaultSlot} + </sl-button-group> + `:defaultSlot} + </div> + + <div + part="form-control-help-text" + id="help-text" + class="form-control__help-text" + aria-hidden=${hasHelpText?"false":"true"} + > + <slot name="help-text">${this.helpText}</slot> + </div> + </fieldset> + `}};SlRadioGroup.styles=[component_styles_default,form_control_styles_default,radio_group_styles_default],SlRadioGroup.dependencies={"sl-button-group":SlButtonGroup},__decorateClass([e$6("slot:not([name])")],SlRadioGroup.prototype,"defaultSlot",2),__decorateClass([e$6(".radio-group__validation-input")],SlRadioGroup.prototype,"validationInput",2),__decorateClass([r$6()],SlRadioGroup.prototype,"hasButtonGroup",2),__decorateClass([r$6()],SlRadioGroup.prototype,"errorMessage",2),__decorateClass([r$6()],SlRadioGroup.prototype,"defaultValue",2),__decorateClass([n$5()],SlRadioGroup.prototype,"label",2),__decorateClass([n$5({attribute:"help-text"})],SlRadioGroup.prototype,"helpText",2),__decorateClass([n$5()],SlRadioGroup.prototype,"name",2),__decorateClass([n$5({reflect:!0})],SlRadioGroup.prototype,"value",2),__decorateClass([n$5({reflect:!0})],SlRadioGroup.prototype,"size",2),__decorateClass([n$5({reflect:!0})],SlRadioGroup.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRadioGroup.prototype,"required",2),__decorateClass([watch("size",{waitUntilFirstUpdate:!0})],SlRadioGroup.prototype,"handleSizeChange",1),__decorateClass([watch("value")],SlRadioGroup.prototype,"handleValueChange",1),SlRadioGroup.define("sl-radio-group");var radio_styles_default=i$7` + :host { + display: block; + } + + :host(:focus-visible) { + outline: 0px; + } + + .radio { + display: inline-flex; + align-items: top; + font-family: var(--sl-input-font-family); + font-size: var(--sl-input-font-size-medium); + font-weight: var(--sl-input-font-weight); + color: var(--sl-input-label-color); + vertical-align: middle; + cursor: pointer; + } + + .radio--small { + --toggle-size: var(--sl-toggle-size-small); + font-size: var(--sl-input-font-size-small); + } + + .radio--medium { + --toggle-size: var(--sl-toggle-size-medium); + font-size: var(--sl-input-font-size-medium); + } + + .radio--large { + --toggle-size: var(--sl-toggle-size-large); + font-size: var(--sl-input-font-size-large); + } + + .radio__checked-icon { + display: inline-flex; + width: var(--toggle-size); + height: var(--toggle-size); + } + + .radio__control { + flex: 0 0 auto; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: var(--toggle-size); + height: var(--toggle-size); + border: solid var(--sl-input-border-width) var(--sl-input-border-color); + border-radius: 50%; + background-color: var(--sl-input-background-color); + color: transparent; + transition: + var(--sl-transition-fast) border-color, + var(--sl-transition-fast) background-color, + var(--sl-transition-fast) color, + var(--sl-transition-fast) box-shadow; + } + + .radio__input { + position: absolute; + opacity: 0; + padding: 0; + margin: 0; + pointer-events: none; + } + + /* Hover */ + .radio:not(.radio--checked):not(.radio--disabled) .radio__control:hover { + border-color: var(--sl-input-border-color-hover); + background-color: var(--sl-input-background-color-hover); + } + + /* Checked */ + .radio--checked .radio__control { + color: var(--sl-color-neutral-0); + border-color: var(--sl-color-primary-600); + background-color: var(--sl-color-primary-600); + } + + /* Checked + hover */ + .radio.radio--checked:not(.radio--disabled) .radio__control:hover { + border-color: var(--sl-color-primary-500); + background-color: var(--sl-color-primary-500); + } + + /* Checked + focus */ + :host(:focus-visible) .radio__control { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + /* Disabled */ + .radio--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + /* When the control isn't checked, hide the circle for Windows High Contrast mode a11y */ + .radio:not(.radio--checked) svg circle { + opacity: 0; + } + + .radio__label { + display: inline-block; + color: var(--sl-input-label-color); + line-height: var(--toggle-size); + margin-inline-start: 0.5em; + user-select: none; + -webkit-user-select: none; + } +`,SlRadio=class extends ShoelaceElement{constructor(){super(),this.checked=!1,this.hasFocus=!1,this.size="medium",this.disabled=!1,this.handleBlur=()=>{this.hasFocus=!1,this.emit("sl-blur")},this.handleClick=()=>{this.disabled||(this.checked=!0)},this.handleFocus=()=>{this.hasFocus=!0,this.emit("sl-focus")},this.addEventListener("blur",this.handleBlur),this.addEventListener("click",this.handleClick),this.addEventListener("focus",this.handleFocus)}connectedCallback(){super.connectedCallback(),this.setInitialAttributes()}setInitialAttributes(){this.setAttribute("role","radio"),this.setAttribute("tabindex","-1"),this.setAttribute("aria-disabled",this.disabled?"true":"false")}handleCheckedChange(){this.setAttribute("aria-checked",this.checked?"true":"false"),this.setAttribute("tabindex",this.checked?"0":"-1")}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false")}render(){return x$1` + <span + part="base" + class=${e$2({radio:!0,"radio--checked":this.checked,"radio--disabled":this.disabled,"radio--focused":this.hasFocus,"radio--small":"small"===this.size,"radio--medium":"medium"===this.size,"radio--large":"large"===this.size})} + > + <span part="${`control${this.checked?" control--checked":""}`}" class="radio__control"> + ${this.checked?x$1` <sl-icon part="checked-icon" class="radio__checked-icon" library="system" name="radio"></sl-icon> `:""} + </span> + + <slot part="label" class="radio__label"></slot> + </span> + `}};SlRadio.styles=[component_styles_default,radio_styles_default],SlRadio.dependencies={"sl-icon":SlIcon},__decorateClass([r$6()],SlRadio.prototype,"checked",2),__decorateClass([r$6()],SlRadio.prototype,"hasFocus",2),__decorateClass([n$5()],SlRadio.prototype,"value",2),__decorateClass([n$5({reflect:!0})],SlRadio.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRadio.prototype,"disabled",2),__decorateClass([watch("checked")],SlRadio.prototype,"handleCheckedChange",1),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlRadio.prototype,"handleDisabledChange",1),SlRadio.define("sl-radio");var availableUnits=[{max:276e4,value:6e4,unit:"minute"},{max:72e6,value:36e5,unit:"hour"},{max:5184e5,value:864e5,unit:"day"},{max:24192e5,value:6048e5,unit:"week"},{max:28512e6,value:2592e6,unit:"month"},{max:1/0,value:31536e6,unit:"year"}],SlRelativeTime=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.isoTime="",this.relativeTime="",this.date=new Date,this.format="long",this.numeric="auto",this.sync=!1}disconnectedCallback(){super.disconnectedCallback(),clearTimeout(this.updateTimeout)}render(){var _Mathabs=Math.abs,_Mathround2=Math.round;const now=new Date,then=new Date(this.date);if(isNaN(then.getMilliseconds()))return this.relativeTime="",this.isoTime="","";const diff=then.getTime()-now.getTime(),{unit,value}=availableUnits.find(singleUnit=>_Mathabs(diff)<singleUnit.max);if(this.isoTime=then.toISOString(),this.relativeTime=this.localize.relativeTime(_Mathround2(diff/value),unit,{numeric:this.numeric,style:this.format}),clearTimeout(this.updateTimeout),this.sync){let nextInterval;nextInterval="minute"===unit?getTimeUntilNextUnit("second"):"hour"===unit?getTimeUntilNextUnit("minute"):"day"===unit?getTimeUntilNextUnit("hour"):getTimeUntilNextUnit("day"),this.updateTimeout=window.setTimeout(()=>this.requestUpdate(),nextInterval)}return x$1` <time datetime=${this.isoTime}>${this.relativeTime}</time> `}};__decorateClass([r$6()],SlRelativeTime.prototype,"isoTime",2),__decorateClass([r$6()],SlRelativeTime.prototype,"relativeTime",2),__decorateClass([n$5()],SlRelativeTime.prototype,"date",2),__decorateClass([n$5()],SlRelativeTime.prototype,"format",2),__decorateClass([n$5()],SlRelativeTime.prototype,"numeric",2),__decorateClass([n$5({type:Boolean})],SlRelativeTime.prototype,"sync",2);function getTimeUntilNextUnit(unit){const value={second:1e3,minute:6e4,hour:36e5,day:864e5}[unit];return value-Date.now()%value}SlRelativeTime.define("sl-relative-time");var skeleton_styles_default=i$7` + :host { + --border-radius: var(--sl-border-radius-pill); + --color: var(--sl-color-neutral-200); + --sheen-color: var(--sl-color-neutral-300); + + display: block; + position: relative; + } + + .skeleton { + display: flex; + width: 100%; + height: 100%; + min-height: 1rem; + } + + .skeleton__indicator { + flex: 1 1 auto; + background: var(--color); + border-radius: var(--border-radius); + } + + .skeleton--sheen .skeleton__indicator { + background: linear-gradient(270deg, var(--sheen-color), var(--color), var(--color), var(--sheen-color)); + background-size: 400% 100%; + animation: sheen 8s ease-in-out infinite; + } + + .skeleton--pulse .skeleton__indicator { + animation: pulse 2s ease-in-out 0.5s infinite; + } + + /* Forced colors mode */ + @media (forced-colors: active) { + :host { + --color: GrayText; + } + } + + @keyframes sheen { + 0% { + background-position: 200% 0; + } + to { + background-position: -200% 0; + } + } + + @keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0.4; + } + 100% { + opacity: 1; + } + } +`,SlSkeleton=class extends ShoelaceElement{constructor(){super(...arguments),this.effect="none"}render(){return x$1` + <div + part="base" + class=${e$2({skeleton:!0,"skeleton--pulse":"pulse"===this.effect,"skeleton--sheen":"sheen"===this.effect})} + > + <div part="indicator" class="skeleton__indicator"></div> + </div> + `}};SlSkeleton.styles=[component_styles_default,skeleton_styles_default],__decorateClass([n$5()],SlSkeleton.prototype,"effect",2),SlSkeleton.define("sl-skeleton");var tag_styles_default=i$7` + :host { + display: inline-block; + } + + .tag { + display: flex; + align-items: center; + border: solid 1px; + line-height: 1; + white-space: nowrap; + user-select: none; + -webkit-user-select: none; + } + + .tag__remove::part(base) { + color: inherit; + padding: 0; + } + + /* + * Variant modifiers + */ + + .tag--primary { + background-color: var(--sl-color-primary-50); + border-color: var(--sl-color-primary-200); + color: var(--sl-color-primary-800); + } + + .tag--primary:active > sl-icon-button { + color: var(--sl-color-primary-600); + } + + .tag--success { + background-color: var(--sl-color-success-50); + border-color: var(--sl-color-success-200); + color: var(--sl-color-success-800); + } + + .tag--success:active > sl-icon-button { + color: var(--sl-color-success-600); + } + + .tag--neutral { + background-color: var(--sl-color-neutral-50); + border-color: var(--sl-color-neutral-200); + color: var(--sl-color-neutral-800); + } + + .tag--neutral:active > sl-icon-button { + color: var(--sl-color-neutral-600); + } + + .tag--warning { + background-color: var(--sl-color-warning-50); + border-color: var(--sl-color-warning-200); + color: var(--sl-color-warning-800); + } + + .tag--warning:active > sl-icon-button { + color: var(--sl-color-warning-600); + } + + .tag--danger { + background-color: var(--sl-color-danger-50); + border-color: var(--sl-color-danger-200); + color: var(--sl-color-danger-800); + } + + .tag--danger:active > sl-icon-button { + color: var(--sl-color-danger-600); + } + + /* + * Size modifiers + */ + + .tag--small { + font-size: var(--sl-button-font-size-small); + height: calc(var(--sl-input-height-small) * 0.8); + line-height: calc(var(--sl-input-height-small) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-small); + padding: 0 var(--sl-spacing-x-small); + } + + .tag--medium { + font-size: var(--sl-button-font-size-medium); + height: calc(var(--sl-input-height-medium) * 0.8); + line-height: calc(var(--sl-input-height-medium) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-medium); + padding: 0 var(--sl-spacing-small); + } + + .tag--large { + font-size: var(--sl-button-font-size-large); + height: calc(var(--sl-input-height-large) * 0.8); + line-height: calc(var(--sl-input-height-large) - var(--sl-input-border-width) * 2); + border-radius: var(--sl-input-border-radius-large); + padding: 0 var(--sl-spacing-medium); + } + + .tag__remove { + margin-inline-start: var(--sl-spacing-x-small); + } + + /* + * Pill modifier + */ + + .tag--pill { + border-radius: var(--sl-border-radius-pill); + } +`,SlTag=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.variant="neutral",this.size="medium",this.pill=!1,this.removable=!1}handleRemoveClick(){this.emit("sl-remove")}render(){return x$1` + <span + part="base" + class=${e$2({tag:!0,"tag--primary":"primary"===this.variant,"tag--success":"success"===this.variant,"tag--neutral":"neutral"===this.variant,"tag--warning":"warning"===this.variant,"tag--danger":"danger"===this.variant,"tag--text":"text"===this.variant,"tag--small":"small"===this.size,"tag--medium":"medium"===this.size,"tag--large":"large"===this.size,"tag--pill":this.pill,"tag--removable":this.removable})} + > + <slot part="content" class="tag__content"></slot> + + ${this.removable?x$1` + <sl-icon-button + part="remove-button" + exportparts="base:remove-button__base" + name="x-lg" + library="system" + label=${this.localize.term("remove")} + class="tag__remove" + @click=${this.handleRemoveClick} + tabindex="-1" + ></sl-icon-button> + `:""} + </span> + `}};SlTag.styles=[component_styles_default,tag_styles_default],SlTag.dependencies={"sl-icon-button":SlIconButton},__decorateClass([n$5({reflect:!0})],SlTag.prototype,"variant",2),__decorateClass([n$5({reflect:!0})],SlTag.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTag.prototype,"pill",2),__decorateClass([n$5({type:Boolean})],SlTag.prototype,"removable",2);var select_styles_default=i$7` + :host { + display: block; + } + + /** The popup */ + .select { + flex: 1 1 auto; + display: inline-flex; + width: 100%; + position: relative; + vertical-align: middle; + } + + .select::part(popup) { + z-index: var(--sl-z-index-dropdown); + } + + .select[data-current-placement^='top']::part(popup) { + transform-origin: bottom; + } + + .select[data-current-placement^='bottom']::part(popup) { + transform-origin: top; + } + + /* Combobox */ + .select__combobox { + flex: 1; + display: flex; + width: 100%; + min-width: 0; + position: relative; + align-items: center; + justify-content: start; + font-family: var(--sl-input-font-family); + font-weight: var(--sl-input-font-weight); + letter-spacing: var(--sl-input-letter-spacing); + vertical-align: middle; + overflow: hidden; + cursor: pointer; + transition: + var(--sl-transition-fast) color, + var(--sl-transition-fast) border, + var(--sl-transition-fast) box-shadow, + var(--sl-transition-fast) background-color; + } + + .select__display-input { + position: relative; + width: 100%; + font: inherit; + border: none; + background: none; + color: var(--sl-input-color); + cursor: inherit; + overflow: hidden; + padding: 0; + margin: 0; + -webkit-appearance: none; + } + + .select__display-input::placeholder { + color: var(--sl-input-placeholder-color); + } + + .select:not(.select--disabled):hover .select__display-input { + color: var(--sl-input-color-hover); + } + + .select__display-input:focus { + outline: none; + } + + /* Visually hide the display input when multiple is enabled */ + .select--multiple:not(.select--placeholder-visible) .select__display-input { + position: absolute; + z-index: -1; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; + } + + .select__value-input { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + padding: 0; + margin: 0; + opacity: 0; + z-index: -1; + } + + .select__tags { + display: flex; + flex: 1; + align-items: center; + flex-wrap: wrap; + margin-inline-start: var(--sl-spacing-2x-small); + } + + .select__tags::slotted(sl-tag) { + cursor: pointer !important; + } + + .select--disabled .select__tags, + .select--disabled .select__tags::slotted(sl-tag) { + cursor: not-allowed !important; + } + + /* Standard selects */ + .select--standard .select__combobox { + background-color: var(--sl-input-background-color); + border: solid var(--sl-input-border-width) var(--sl-input-border-color); + } + + .select--standard.select--disabled .select__combobox { + background-color: var(--sl-input-background-color-disabled); + border-color: var(--sl-input-border-color-disabled); + color: var(--sl-input-color-disabled); + opacity: 0.5; + cursor: not-allowed; + outline: none; + } + + .select--standard:not(.select--disabled).select--open .select__combobox, + .select--standard:not(.select--disabled).select--focused .select__combobox { + background-color: var(--sl-input-background-color-focus); + border-color: var(--sl-input-border-color-focus); + box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color); + } + + /* Filled selects */ + .select--filled .select__combobox { + border: none; + background-color: var(--sl-input-filled-background-color); + color: var(--sl-input-color); + } + + .select--filled:hover:not(.select--disabled) .select__combobox { + background-color: var(--sl-input-filled-background-color-hover); + } + + .select--filled.select--disabled .select__combobox { + background-color: var(--sl-input-filled-background-color-disabled); + opacity: 0.5; + cursor: not-allowed; + } + + .select--filled:not(.select--disabled).select--open .select__combobox, + .select--filled:not(.select--disabled).select--focused .select__combobox { + background-color: var(--sl-input-filled-background-color-focus); + outline: var(--sl-focus-ring); + } + + /* Sizes */ + .select--small .select__combobox { + border-radius: var(--sl-input-border-radius-small); + font-size: var(--sl-input-font-size-small); + min-height: var(--sl-input-height-small); + padding-block: 0; + padding-inline: var(--sl-input-spacing-small); + } + + .select--small .select__clear { + margin-inline-start: var(--sl-input-spacing-small); + } + + .select--small .select__prefix::slotted(*) { + margin-inline-end: var(--sl-input-spacing-small); + } + + .select--small.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { + margin-inline-start: var(--sl-input-spacing-small); + } + + .select--small.select--multiple:not(.select--placeholder-visible) .select__combobox { + padding-block: 2px; + padding-inline-start: 0; + } + + .select--small .select__tags { + gap: 2px; + } + + .select--medium .select__combobox { + border-radius: var(--sl-input-border-radius-medium); + font-size: var(--sl-input-font-size-medium); + min-height: var(--sl-input-height-medium); + padding-block: 0; + padding-inline: var(--sl-input-spacing-medium); + } + + .select--medium .select__clear { + margin-inline-start: var(--sl-input-spacing-medium); + } + + .select--medium .select__prefix::slotted(*) { + margin-inline-end: var(--sl-input-spacing-medium); + } + + .select--medium.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { + margin-inline-start: var(--sl-input-spacing-medium); + } + + .select--medium.select--multiple:not(.select--placeholder-visible) .select__combobox { + padding-inline-start: 0; + padding-block: 3px; + } + + .select--medium .select__tags { + gap: 3px; + } + + .select--large .select__combobox { + border-radius: var(--sl-input-border-radius-large); + font-size: var(--sl-input-font-size-large); + min-height: var(--sl-input-height-large); + padding-block: 0; + padding-inline: var(--sl-input-spacing-large); + } + + .select--large .select__clear { + margin-inline-start: var(--sl-input-spacing-large); + } + + .select--large .select__prefix::slotted(*) { + margin-inline-end: var(--sl-input-spacing-large); + } + + .select--large.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) { + margin-inline-start: var(--sl-input-spacing-large); + } + + .select--large.select--multiple:not(.select--placeholder-visible) .select__combobox { + padding-inline-start: 0; + padding-block: 4px; + } + + .select--large .select__tags { + gap: 4px; + } + + /* Pills */ + .select--pill.select--small .select__combobox { + border-radius: var(--sl-input-height-small); + } + + .select--pill.select--medium .select__combobox { + border-radius: var(--sl-input-height-medium); + } + + .select--pill.select--large .select__combobox { + border-radius: var(--sl-input-height-large); + } + + /* Prefix and Suffix */ + .select__prefix, + .select__suffix { + flex: 0; + display: inline-flex; + align-items: center; + color: var(--sl-input-placeholder-color); + } + + .select__suffix::slotted(*) { + margin-inline-start: var(--sl-spacing-small); + } + + /* Clear button */ + .select__clear { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: inherit; + color: var(--sl-input-icon-color); + border: none; + background: none; + padding: 0; + transition: var(--sl-transition-fast) color; + cursor: pointer; + } + + .select__clear:hover { + color: var(--sl-input-icon-color-hover); + } + + .select__clear:focus { + outline: none; + } + + /* Expand icon */ + .select__expand-icon { + flex: 0 0 auto; + display: flex; + align-items: center; + transition: var(--sl-transition-medium) rotate ease; + rotate: 0; + margin-inline-start: var(--sl-spacing-small); + } + + .select--open .select__expand-icon { + rotate: -180deg; + } + + /* Listbox */ + .select__listbox { + display: block; + position: relative; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + box-shadow: var(--sl-shadow-large); + background: var(--sl-panel-background-color); + border: solid var(--sl-panel-border-width) var(--sl-panel-border-color); + border-radius: var(--sl-border-radius-medium); + padding-block: var(--sl-spacing-x-small); + padding-inline: 0; + overflow: auto; + overscroll-behavior: none; + + /* Make sure it adheres to the popup's auto size */ + max-width: var(--auto-size-available-width); + max-height: var(--auto-size-available-height); + } + + .select__listbox ::slotted(sl-divider) { + --spacing: var(--sl-spacing-x-small); + } + + .select__listbox ::slotted(small) { + display: block; + font-size: var(--sl-font-size-small); + font-weight: var(--sl-font-weight-semibold); + color: var(--sl-color-neutral-500); + padding-block: var(--sl-spacing-2x-small); + padding-inline: var(--sl-spacing-x-large); + } +`;class e extends i$3{constructor(i){if(super(i),this.it=E$1,i.type!==t.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(r){if(r===E$1||null==r)return this._t=void 0,this.it=r;if(r===T$1)return r;if("string"!=typeof r)throw Error(this.constructor.directiveName+"() called with a non-string value");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}e.directiveName="unsafeHTML",e.resultType=1;const o$2=e$3(e);var SlSelect=class extends ShoelaceElement{constructor(){var _Mathmax=Math.max;super(...arguments),this.formControlController=new FormControlController(this,{assumeInteractionOn:["sl-blur","sl-input"]}),this.hasSlotController=new HasSlotController(this,"help-text","label"),this.localize=new LocalizeController(this),this.typeToSelectString="",this.hasFocus=!1,this.displayLabel="",this.selectedOptions=[],this.valueHasChanged=!1,this.name="",this._value="",this.defaultValue="",this.size="medium",this.placeholder="",this.multiple=!1,this.maxOptionsVisible=3,this.disabled=!1,this.clearable=!1,this.open=!1,this.hoist=!1,this.filled=!1,this.pill=!1,this.label="",this.placement="bottom",this.helpText="",this.form="",this.required=!1,this.getTag=option=>x$1` + <sl-tag + part="tag" + exportparts=" + base:tag__base, + content:tag__content, + remove-button:tag__remove-button, + remove-button__base:tag__remove-button__base + " + ?pill=${this.pill} + size=${this.size} + removable + @sl-remove=${event=>this.handleTagRemove(event,option)} + > + ${option.getTextLabel()} + </sl-tag> + `,this.handleDocumentFocusIn=event=>{const path=event.composedPath();this&&!path.includes(this)&&this.hide()},this.handleDocumentKeyDown=event=>{const target=event.target,isClearButton=null!==target.closest(".select__clear"),isIconButton=null!==target.closest("sl-icon-button");if(!(isClearButton||isIconButton)){if("Escape"===event.key&&this.open&&!this.closeWatcher&&(event.preventDefault(),event.stopPropagation(),this.hide(),this.displayInput.focus({preventScroll:!0})),"Enter"===event.key||" "===event.key&&""===this.typeToSelectString)return(event.preventDefault(),event.stopImmediatePropagation(),!this.open)?void this.show():void(this.currentOption&&!this.currentOption.disabled&&(this.valueHasChanged=!0,this.multiple?this.toggleOptionSelection(this.currentOption):this.setSelectedOptions(this.currentOption),this.updateComplete.then(()=>{this.emit("sl-input"),this.emit("sl-change")}),!this.multiple&&(this.hide(),this.displayInput.focus({preventScroll:!0}))));if(["ArrowUp","ArrowDown","Home","End"].includes(event.key)){const allOptions=this.getAllOptions(),currentIndex=allOptions.indexOf(this.currentOption);let newIndex=_Mathmax(0,currentIndex);if(event.preventDefault(),!this.open&&(this.show(),this.currentOption))return;"ArrowDown"===event.key?(newIndex=currentIndex+1,newIndex>allOptions.length-1&&(newIndex=0)):"ArrowUp"===event.key?(newIndex=currentIndex-1,0>newIndex&&(newIndex=allOptions.length-1)):"Home"===event.key?newIndex=0:"End"===event.key&&(newIndex=allOptions.length-1),this.setCurrentOption(allOptions[newIndex])}if(event.key&&1===event.key.length||"Backspace"===event.key){const allOptions=this.getAllOptions();if(event.metaKey||event.ctrlKey||event.altKey)return;if(!this.open){if("Backspace"===event.key)return;this.show()}event.stopPropagation(),event.preventDefault(),clearTimeout(this.typeToSelectTimeout),this.typeToSelectTimeout=window.setTimeout(()=>this.typeToSelectString="",1e3),"Backspace"===event.key?this.typeToSelectString=this.typeToSelectString.slice(0,-1):this.typeToSelectString+=event.key.toLowerCase();for(const option of allOptions){const label=option.getTextLabel().toLowerCase();if(label.startsWith(this.typeToSelectString)){this.setCurrentOption(option);break}}}}},this.handleDocumentMouseDown=event=>{const path=event.composedPath();this&&!path.includes(this)&&this.hide()}}get value(){return this._value}set value(val){val=this.multiple?Array.isArray(val)?val:val.split(" "):Array.isArray(val)?val.join(" "):val;this._value===val||(this.valueHasChanged=!0,this._value=val)}get validity(){return this.valueInput.validity}get validationMessage(){return this.valueInput.validationMessage}connectedCallback(){super.connectedCallback(),setTimeout(()=>{this.handleDefaultSlotChange()}),this.open=!1}addOpenListeners(){var _a;document.addEventListener("focusin",this.handleDocumentFocusIn),document.addEventListener("keydown",this.handleDocumentKeyDown),document.addEventListener("mousedown",this.handleDocumentMouseDown),this.getRootNode()!==document&&this.getRootNode().addEventListener("focusin",this.handleDocumentFocusIn),"CloseWatcher"in window&&(null==(_a=this.closeWatcher)?void 0:_a.destroy(),this.closeWatcher=new CloseWatcher,this.closeWatcher.onclose=()=>{this.open&&(this.hide(),this.displayInput.focus({preventScroll:!0}))})}removeOpenListeners(){var _a;document.removeEventListener("focusin",this.handleDocumentFocusIn),document.removeEventListener("keydown",this.handleDocumentKeyDown),document.removeEventListener("mousedown",this.handleDocumentMouseDown),this.getRootNode()!==document&&this.getRootNode().removeEventListener("focusin",this.handleDocumentFocusIn),null==(_a=this.closeWatcher)?void 0:_a.destroy()}handleFocus(){this.hasFocus=!0,this.displayInput.setSelectionRange(0,0),this.emit("sl-focus")}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleLabelClick(){this.displayInput.focus()}handleComboboxMouseDown(event){const path=event.composedPath(),isIconButton=path.some(el=>el instanceof Element&&"sl-icon-button"===el.tagName.toLowerCase());this.disabled||isIconButton||(event.preventDefault(),this.displayInput.focus({preventScroll:!0}),this.open=!this.open)}handleComboboxKeyDown(event){"Tab"===event.key||(event.stopPropagation(),this.handleDocumentKeyDown(event))}handleClearClick(event){event.stopPropagation(),this.valueHasChanged=!0,""!==this.value&&(this.setSelectedOptions([]),this.displayInput.focus({preventScroll:!0}),this.updateComplete.then(()=>{this.emit("sl-clear"),this.emit("sl-input"),this.emit("sl-change")}))}handleClearMouseDown(event){event.stopPropagation(),event.preventDefault()}handleOptionClick(event){const target=event.target,option=target.closest("sl-option"),oldValue=this.value;option&&!option.disabled&&(this.valueHasChanged=!0,this.multiple?this.toggleOptionSelection(option):this.setSelectedOptions(option),this.updateComplete.then(()=>this.displayInput.focus({preventScroll:!0})),this.value!==oldValue&&this.updateComplete.then(()=>{this.emit("sl-input"),this.emit("sl-change")}),!this.multiple&&(this.hide(),this.displayInput.focus({preventScroll:!0})))}handleDefaultSlotChange(){customElements.get("sl-option")||customElements.whenDefined("sl-option").then(()=>this.handleDefaultSlotChange());const allOptions=this.getAllOptions(),val=this.valueHasChanged?this.value:this.defaultValue,value=Array.isArray(val)?val:[val],values=[];allOptions.forEach(option=>values.push(option.value)),this.setSelectedOptions(allOptions.filter(el=>value.includes(el.value)))}handleTagRemove(event,option){event.stopPropagation(),this.valueHasChanged=!0,this.disabled||(this.toggleOptionSelection(option,!1),this.updateComplete.then(()=>{this.emit("sl-input"),this.emit("sl-change")}))}getAllOptions(){return[...this.querySelectorAll("sl-option")]}getFirstOption(){return this.querySelector("sl-option")}setCurrentOption(option){const allOptions=this.getAllOptions();allOptions.forEach(el=>{el.current=!1,el.tabIndex=-1}),option&&(this.currentOption=option,option.current=!0,option.tabIndex=0,option.focus())}setSelectedOptions(option){const allOptions=this.getAllOptions(),newSelectedOptions=Array.isArray(option)?option:[option];allOptions.forEach(el=>el.selected=!1),newSelectedOptions.length&&newSelectedOptions.forEach(el=>el.selected=!0),this.selectionChanged()}toggleOptionSelection(option,force){option.selected=!0===force||!1===force?force:!option.selected,this.selectionChanged()}selectionChanged(){var _a,_b,_c;const options=this.getAllOptions();this.selectedOptions=options.filter(el=>el.selected);const cachedValueHasChanged=this.valueHasChanged;if(this.multiple)this.value=this.selectedOptions.map(el=>el.value),this.displayLabel=this.placeholder&&0===this.value.length?"":this.localize.term("numOptionsSelected",this.selectedOptions.length);else{const selectedOption=this.selectedOptions[0];this.value=null==(_a=null==selectedOption?void 0:selectedOption.value)?"":_a,this.displayLabel=null==(_c=null==(_b=null==selectedOption?void 0:selectedOption.getTextLabel)?void 0:_b.call(selectedOption))?"":_c}this.valueHasChanged=cachedValueHasChanged,this.updateComplete.then(()=>{this.formControlController.updateValidity()})}get tags(){return this.selectedOptions.map((option,index)=>{if(index<this.maxOptionsVisible||0>=this.maxOptionsVisible){const tag=this.getTag(option,index);return x$1`<div @sl-remove=${e=>this.handleTagRemove(e,option)}> + ${"string"==typeof tag?o$2(tag):tag} + </div>`}return index===this.maxOptionsVisible?x$1`<sl-tag size=${this.size}>+${this.selectedOptions.length-index}</sl-tag>`:x$1``})}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}handleDisabledChange(){this.disabled&&(this.open=!1,this.handleOpenChange())}attributeChangedCallback(name,oldVal,newVal){if(super.attributeChangedCallback(name,oldVal,newVal),"value"===name){const cachedValueHasChanged=this.valueHasChanged;this.value=this.defaultValue,this.valueHasChanged=cachedValueHasChanged}}handleValueChange(){if(!this.valueHasChanged){const cachedValueHasChanged=this.valueHasChanged;this.value=this.defaultValue,this.valueHasChanged=cachedValueHasChanged}const allOptions=this.getAllOptions(),value=Array.isArray(this.value)?this.value:[this.value];this.setSelectedOptions(allOptions.filter(el=>value.includes(el.value)))}async handleOpenChange(){if(this.open&&!this.disabled){this.setCurrentOption(this.selectedOptions[0]||this.getFirstOption()),this.emit("sl-show"),this.addOpenListeners(),await stopAnimations(this),this.listbox.hidden=!1,this.popup.active=!0,requestAnimationFrame(()=>{this.setCurrentOption(this.currentOption)});const{keyframes,options}=getAnimation(this,"select.show",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.currentOption&&scrollIntoView(this.currentOption,this.listbox,"vertical","auto"),this.emit("sl-after-show")}else{this.emit("sl-hide"),this.removeOpenListeners(),await stopAnimations(this);const{keyframes,options}=getAnimation(this,"select.hide",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.listbox.hidden=!0,this.popup.active=!1,this.emit("sl-after-hide")}}async show(){return this.open||this.disabled?void(this.open=!1):(this.open=!0,waitForEvent(this,"sl-after-show"))}async hide(){return!this.open||this.disabled?void(this.open=!1):(this.open=!1,waitForEvent(this,"sl-after-hide"))}checkValidity(){return this.valueInput.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.valueInput.reportValidity()}setCustomValidity(message){this.valueInput.setCustomValidity(message),this.formControlController.updateValidity()}focus(options){this.displayInput.focus(options)}blur(){this.displayInput.blur()}render(){const hasLabelSlot=this.hasSlotController.test("label"),hasHelpTextSlot=this.hasSlotController.test("help-text"),hasLabel=!!this.label||!!hasLabelSlot,hasHelpText=!!this.helpText||!!hasHelpTextSlot,hasClearIcon=this.clearable&&!this.disabled&&0<this.value.length,isPlaceholderVisible=this.placeholder&&this.value&&0>=this.value.length;return x$1` + <div + part="form-control" + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--has-label":hasLabel,"form-control--has-help-text":hasHelpText})} + > + <label + id="label" + part="form-control-label" + class="form-control__label" + aria-hidden=${hasLabel?"false":"true"} + @click=${this.handleLabelClick} + > + <slot name="label">${this.label}</slot> + </label> + + <div part="form-control-input" class="form-control-input"> + <sl-popup + class=${e$2({select:!0,"select--standard":!0,"select--filled":this.filled,"select--pill":this.pill,"select--open":this.open,"select--disabled":this.disabled,"select--multiple":this.multiple,"select--focused":this.hasFocus,"select--placeholder-visible":isPlaceholderVisible,"select--top":"top"===this.placement,"select--bottom":"bottom"===this.placement,"select--small":"small"===this.size,"select--medium":"medium"===this.size,"select--large":"large"===this.size})} + placement=${this.placement} + strategy=${this.hoist?"fixed":"absolute"} + flip + shift + sync="width" + auto-size="vertical" + auto-size-padding="10" + > + <div + part="combobox" + class="select__combobox" + slot="anchor" + @keydown=${this.handleComboboxKeyDown} + @mousedown=${this.handleComboboxMouseDown} + > + <slot part="prefix" name="prefix" class="select__prefix"></slot> + + <input + part="display-input" + class="select__display-input" + type="text" + placeholder=${this.placeholder} + .disabled=${this.disabled} + .value=${this.displayLabel} + autocomplete="off" + spellcheck="false" + autocapitalize="off" + readonly + aria-controls="listbox" + aria-expanded=${this.open?"true":"false"} + aria-haspopup="listbox" + aria-labelledby="label" + aria-disabled=${this.disabled?"true":"false"} + aria-describedby="help-text" + role="combobox" + tabindex="0" + @focus=${this.handleFocus} + @blur=${this.handleBlur} + /> + + ${this.multiple?x$1`<div part="tags" class="select__tags">${this.tags}</div>`:""} + + <input + class="select__value-input" + type="text" + ?disabled=${this.disabled} + ?required=${this.required} + .value=${Array.isArray(this.value)?this.value.join(", "):this.value} + tabindex="-1" + aria-hidden="true" + @focus=${()=>this.focus()} + @invalid=${this.handleInvalid} + /> + + ${hasClearIcon?x$1` + <button + part="clear-button" + class="select__clear" + type="button" + aria-label=${this.localize.term("clearEntry")} + @mousedown=${this.handleClearMouseDown} + @click=${this.handleClearClick} + tabindex="-1" + > + <slot name="clear-icon"> + <sl-icon name="x-circle-fill" library="system"></sl-icon> + </slot> + </button> + `:""} + + <slot name="suffix" part="suffix" class="select__suffix"></slot> + + <slot name="expand-icon" part="expand-icon" class="select__expand-icon"> + <sl-icon library="system" name="chevron-down"></sl-icon> + </slot> + </div> + + <div + id="listbox" + role="listbox" + aria-expanded=${this.open?"true":"false"} + aria-multiselectable=${this.multiple?"true":"false"} + aria-labelledby="label" + part="listbox" + class="select__listbox" + tabindex="-1" + @mouseup=${this.handleOptionClick} + @slotchange=${this.handleDefaultSlotChange} + > + <slot></slot> + </div> + </sl-popup> + </div> + + <div + part="form-control-help-text" + id="help-text" + class="form-control__help-text" + aria-hidden=${hasHelpText?"false":"true"} + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlSelect.styles=[component_styles_default,form_control_styles_default,select_styles_default],SlSelect.dependencies={"sl-icon":SlIcon,"sl-popup":SlPopup,"sl-tag":SlTag},__decorateClass([e$6(".select")],SlSelect.prototype,"popup",2),__decorateClass([e$6(".select__combobox")],SlSelect.prototype,"combobox",2),__decorateClass([e$6(".select__display-input")],SlSelect.prototype,"displayInput",2),__decorateClass([e$6(".select__value-input")],SlSelect.prototype,"valueInput",2),__decorateClass([e$6(".select__listbox")],SlSelect.prototype,"listbox",2),__decorateClass([r$6()],SlSelect.prototype,"hasFocus",2),__decorateClass([r$6()],SlSelect.prototype,"displayLabel",2),__decorateClass([r$6()],SlSelect.prototype,"currentOption",2),__decorateClass([r$6()],SlSelect.prototype,"selectedOptions",2),__decorateClass([r$6()],SlSelect.prototype,"valueHasChanged",2),__decorateClass([n$5()],SlSelect.prototype,"name",2),__decorateClass([r$6()],SlSelect.prototype,"value",1),__decorateClass([n$5({attribute:"value"})],SlSelect.prototype,"defaultValue",2),__decorateClass([n$5({reflect:!0})],SlSelect.prototype,"size",2),__decorateClass([n$5()],SlSelect.prototype,"placeholder",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"multiple",2),__decorateClass([n$5({attribute:"max-options-visible",type:Number})],SlSelect.prototype,"maxOptionsVisible",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"disabled",2),__decorateClass([n$5({type:Boolean})],SlSelect.prototype,"clearable",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"open",2),__decorateClass([n$5({type:Boolean})],SlSelect.prototype,"hoist",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"filled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"pill",2),__decorateClass([n$5()],SlSelect.prototype,"label",2),__decorateClass([n$5({reflect:!0})],SlSelect.prototype,"placement",2),__decorateClass([n$5({attribute:"help-text"})],SlSelect.prototype,"helpText",2),__decorateClass([n$5({reflect:!0})],SlSelect.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSelect.prototype,"required",2),__decorateClass([n$5()],SlSelect.prototype,"getTag",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlSelect.prototype,"handleDisabledChange",1),__decorateClass([watch(["defaultValue","value"],{waitUntilFirstUpdate:!0})],SlSelect.prototype,"handleValueChange",1),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlSelect.prototype,"handleOpenChange",1),setDefaultAnimation("select.show",{keyframes:[{opacity:0,scale:.9},{opacity:1,scale:1}],options:{duration:100,easing:"ease"}}),setDefaultAnimation("select.hide",{keyframes:[{opacity:1,scale:1},{opacity:0,scale:.9}],options:{duration:100,easing:"ease"}}),SlSelect.define("sl-select");var textarea_styles_default=i$7` + :host { + display: block; + } + + .textarea { + display: grid; + align-items: center; + position: relative; + width: 100%; + font-family: var(--sl-input-font-family); + font-weight: var(--sl-input-font-weight); + line-height: var(--sl-line-height-normal); + letter-spacing: var(--sl-input-letter-spacing); + vertical-align: middle; + transition: + var(--sl-transition-fast) color, + var(--sl-transition-fast) border, + var(--sl-transition-fast) box-shadow, + var(--sl-transition-fast) background-color; + cursor: text; + } + + /* Standard textareas */ + .textarea--standard { + background-color: var(--sl-input-background-color); + border: solid var(--sl-input-border-width) var(--sl-input-border-color); + } + + .textarea--standard:hover:not(.textarea--disabled) { + background-color: var(--sl-input-background-color-hover); + border-color: var(--sl-input-border-color-hover); + } + .textarea--standard:hover:not(.textarea--disabled) .textarea__control { + color: var(--sl-input-color-hover); + } + + .textarea--standard.textarea--focused:not(.textarea--disabled) { + background-color: var(--sl-input-background-color-focus); + border-color: var(--sl-input-border-color-focus); + color: var(--sl-input-color-focus); + box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color); + } + + .textarea--standard.textarea--focused:not(.textarea--disabled) .textarea__control { + color: var(--sl-input-color-focus); + } + + .textarea--standard.textarea--disabled { + background-color: var(--sl-input-background-color-disabled); + border-color: var(--sl-input-border-color-disabled); + opacity: 0.5; + cursor: not-allowed; + } + + .textarea__control, + .textarea__size-adjuster { + grid-area: 1 / 1 / 2 / 2; + } + + .textarea__size-adjuster { + visibility: hidden; + pointer-events: none; + opacity: 0; + } + + .textarea--standard.textarea--disabled .textarea__control { + color: var(--sl-input-color-disabled); + } + + .textarea--standard.textarea--disabled .textarea__control::placeholder { + color: var(--sl-input-placeholder-color-disabled); + } + + /* Filled textareas */ + .textarea--filled { + border: none; + background-color: var(--sl-input-filled-background-color); + color: var(--sl-input-color); + } + + .textarea--filled:hover:not(.textarea--disabled) { + background-color: var(--sl-input-filled-background-color-hover); + } + + .textarea--filled.textarea--focused:not(.textarea--disabled) { + background-color: var(--sl-input-filled-background-color-focus); + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .textarea--filled.textarea--disabled { + background-color: var(--sl-input-filled-background-color-disabled); + opacity: 0.5; + cursor: not-allowed; + } + + .textarea__control { + font-family: inherit; + font-size: inherit; + font-weight: inherit; + line-height: 1.4; + color: var(--sl-input-color); + border: none; + background: none; + box-shadow: none; + cursor: inherit; + -webkit-appearance: none; + } + + .textarea__control::-webkit-search-decoration, + .textarea__control::-webkit-search-cancel-button, + .textarea__control::-webkit-search-results-button, + .textarea__control::-webkit-search-results-decoration { + -webkit-appearance: none; + } + + .textarea__control::placeholder { + color: var(--sl-input-placeholder-color); + user-select: none; + -webkit-user-select: none; + } + + .textarea__control:focus { + outline: none; + } + + /* + * Size modifiers + */ + + .textarea--small { + border-radius: var(--sl-input-border-radius-small); + font-size: var(--sl-input-font-size-small); + } + + .textarea--small .textarea__control { + padding: 0.5em var(--sl-input-spacing-small); + } + + .textarea--medium { + border-radius: var(--sl-input-border-radius-medium); + font-size: var(--sl-input-font-size-medium); + } + + .textarea--medium .textarea__control { + padding: 0.5em var(--sl-input-spacing-medium); + } + + .textarea--large { + border-radius: var(--sl-input-border-radius-large); + font-size: var(--sl-input-font-size-large); + } + + .textarea--large .textarea__control { + padding: 0.5em var(--sl-input-spacing-large); + } + + /* + * Resize types + */ + + .textarea--resize-none .textarea__control { + resize: none; + } + + .textarea--resize-vertical .textarea__control { + resize: vertical; + } + + .textarea--resize-auto .textarea__control { + height: auto; + resize: none; + overflow-y: hidden; + } +`,SlTextarea=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this,{assumeInteractionOn:["sl-blur","sl-input"]}),this.hasSlotController=new HasSlotController(this,"help-text","label"),this.hasFocus=!1,this.title="",this.name="",this.value="",this.size="medium",this.filled=!1,this.label="",this.helpText="",this.placeholder="",this.rows=4,this.resize="vertical",this.disabled=!1,this.readonly=!1,this.form="",this.required=!1,this.spellcheck=!0,this.defaultValue=""}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}connectedCallback(){super.connectedCallback(),this.resizeObserver=new ResizeObserver(()=>this.setTextareaHeight()),this.updateComplete.then(()=>{this.setTextareaHeight(),this.resizeObserver.observe(this.input)})}firstUpdated(){this.formControlController.updateValidity()}disconnectedCallback(){var _a;super.disconnectedCallback(),this.input&&(null==(_a=this.resizeObserver)?void 0:_a.unobserve(this.input))}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleChange(){this.value=this.input.value,this.setTextareaHeight(),this.emit("sl-change")}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleInput(){this.value=this.input.value,this.emit("sl-input")}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}setTextareaHeight(){"auto"===this.resize?(this.sizeAdjuster.style.height=`${this.input.clientHeight}px`,this.input.style.height="auto",this.input.style.height=`${this.input.scrollHeight}px`):this.input.style.height=""}handleDisabledChange(){this.formControlController.setValidity(this.disabled)}handleRowsChange(){this.setTextareaHeight()}async handleValueChange(){await this.updateComplete,this.formControlController.updateValidity(),this.setTextareaHeight()}focus(options){this.input.focus(options)}blur(){this.input.blur()}select(){this.input.select()}scrollPosition(position){return position?("number"==typeof position.top&&(this.input.scrollTop=position.top),void("number"==typeof position.left&&(this.input.scrollLeft=position.left))):{top:this.input.scrollTop,left:this.input.scrollTop}}setSelectionRange(selectionStart,selectionEnd,selectionDirection="none"){this.input.setSelectionRange(selectionStart,selectionEnd,selectionDirection)}setRangeText(replacement,start,end,selectMode="preserve"){const selectionStart=null==start?this.input.selectionStart:start,selectionEnd=null==end?this.input.selectionEnd:end;this.input.setRangeText(replacement,selectionStart,selectionEnd,selectMode),this.value!==this.input.value&&(this.value=this.input.value,this.setTextareaHeight())}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.input.reportValidity()}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){const hasLabelSlot=this.hasSlotController.test("label"),hasHelpTextSlot=this.hasSlotController.test("help-text"),hasLabel=!!this.label||!!hasLabelSlot,hasHelpText=!!this.helpText||!!hasHelpTextSlot;return x$1` + <div + part="form-control" + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--has-label":hasLabel,"form-control--has-help-text":hasHelpText})} + > + <label + part="form-control-label" + class="form-control__label" + for="input" + aria-hidden=${hasLabel?"false":"true"} + > + <slot name="label">${this.label}</slot> + </label> + + <div part="form-control-input" class="form-control-input"> + <div + part="base" + class=${e$2({textarea:!0,"textarea--small":"small"===this.size,"textarea--medium":"medium"===this.size,"textarea--large":"large"===this.size,"textarea--standard":!this.filled,"textarea--filled":this.filled,"textarea--disabled":this.disabled,"textarea--focused":this.hasFocus,"textarea--empty":!this.value,"textarea--resize-none":"none"===this.resize,"textarea--resize-vertical":"vertical"===this.resize,"textarea--resize-auto":"auto"===this.resize})} + > + <textarea + part="textarea" + id="input" + class="textarea__control" + title=${this.title} + name=${o$6(this.name)} + .value=${l(this.value)} + ?disabled=${this.disabled} + ?readonly=${this.readonly} + ?required=${this.required} + placeholder=${o$6(this.placeholder)} + rows=${o$6(this.rows)} + minlength=${o$6(this.minlength)} + maxlength=${o$6(this.maxlength)} + autocapitalize=${o$6(this.autocapitalize)} + autocorrect=${o$6(this.autocorrect)} + ?autofocus=${this.autofocus} + spellcheck=${o$6(this.spellcheck)} + enterkeyhint=${o$6(this.enterkeyhint)} + inputmode=${o$6(this.inputmode)} + aria-describedby="help-text" + @change=${this.handleChange} + @input=${this.handleInput} + @invalid=${this.handleInvalid} + @focus=${this.handleFocus} + @blur=${this.handleBlur} + ></textarea> + <!-- This "adjuster" exists to prevent layout shifting. https://github.com/shoelace-style/shoelace/issues/2180 --> + <div part="textarea-adjuster" class="textarea__size-adjuster" ?hidden=${"auto"!==this.resize}></div> + </div> + </div> + + <div + part="form-control-help-text" + id="help-text" + class="form-control__help-text" + aria-hidden=${hasHelpText?"false":"true"} + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlTextarea.styles=[component_styles_default,form_control_styles_default,textarea_styles_default],__decorateClass([e$6(".textarea__control")],SlTextarea.prototype,"input",2),__decorateClass([e$6(".textarea__size-adjuster")],SlTextarea.prototype,"sizeAdjuster",2),__decorateClass([r$6()],SlTextarea.prototype,"hasFocus",2),__decorateClass([n$5()],SlTextarea.prototype,"title",2),__decorateClass([n$5()],SlTextarea.prototype,"name",2),__decorateClass([n$5()],SlTextarea.prototype,"value",2),__decorateClass([n$5({reflect:!0})],SlTextarea.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTextarea.prototype,"filled",2),__decorateClass([n$5()],SlTextarea.prototype,"label",2),__decorateClass([n$5({attribute:"help-text"})],SlTextarea.prototype,"helpText",2),__decorateClass([n$5()],SlTextarea.prototype,"placeholder",2),__decorateClass([n$5({type:Number})],SlTextarea.prototype,"rows",2),__decorateClass([n$5()],SlTextarea.prototype,"resize",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTextarea.prototype,"disabled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTextarea.prototype,"readonly",2),__decorateClass([n$5({reflect:!0})],SlTextarea.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTextarea.prototype,"required",2),__decorateClass([n$5({type:Number})],SlTextarea.prototype,"minlength",2),__decorateClass([n$5({type:Number})],SlTextarea.prototype,"maxlength",2),__decorateClass([n$5()],SlTextarea.prototype,"autocapitalize",2),__decorateClass([n$5()],SlTextarea.prototype,"autocorrect",2),__decorateClass([n$5()],SlTextarea.prototype,"autocomplete",2),__decorateClass([n$5({type:Boolean})],SlTextarea.prototype,"autofocus",2),__decorateClass([n$5()],SlTextarea.prototype,"enterkeyhint",2),__decorateClass([n$5({type:Boolean,converter:{fromAttribute:value=>!!(value&&"false"!==value),toAttribute:value=>value?"true":"false"}})],SlTextarea.prototype,"spellcheck",2),__decorateClass([n$5()],SlTextarea.prototype,"inputmode",2),__decorateClass([defaultValue()],SlTextarea.prototype,"defaultValue",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlTextarea.prototype,"handleDisabledChange",1),__decorateClass([watch("rows",{waitUntilFirstUpdate:!0})],SlTextarea.prototype,"handleRowsChange",1),__decorateClass([watch("value",{waitUntilFirstUpdate:!0})],SlTextarea.prototype,"handleValueChange",1);var textarea_default=SlTextarea;SlTextarea.define("sl-textarea");var badge_styles_default=i$7` + :host { + display: inline-flex; + } + + .badge { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: max(12px, 0.75em); + font-weight: var(--sl-font-weight-semibold); + letter-spacing: var(--sl-letter-spacing-normal); + line-height: 1; + border-radius: var(--sl-border-radius-small); + border: solid 1px var(--sl-color-neutral-0); + white-space: nowrap; + padding: 0.35em 0.6em; + user-select: none; + -webkit-user-select: none; + cursor: inherit; + } + + /* Variant modifiers */ + .badge--primary { + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + .badge--success { + background-color: var(--sl-color-success-600); + color: var(--sl-color-neutral-0); + } + + .badge--neutral { + background-color: var(--sl-color-neutral-600); + color: var(--sl-color-neutral-0); + } + + .badge--warning { + background-color: var(--sl-color-warning-600); + color: var(--sl-color-neutral-0); + } + + .badge--danger { + background-color: var(--sl-color-danger-600); + color: var(--sl-color-neutral-0); + } + + /* Pill modifier */ + .badge--pill { + border-radius: var(--sl-border-radius-pill); + } + + /* Pulse modifier */ + .badge--pulse { + animation: pulse 1.5s infinite; + } + + .badge--pulse.badge--primary { + --pulse-color: var(--sl-color-primary-600); + } + + .badge--pulse.badge--success { + --pulse-color: var(--sl-color-success-600); + } + + .badge--pulse.badge--neutral { + --pulse-color: var(--sl-color-neutral-600); + } + + .badge--pulse.badge--warning { + --pulse-color: var(--sl-color-warning-600); + } + + .badge--pulse.badge--danger { + --pulse-color: var(--sl-color-danger-600); + } + + @keyframes pulse { + 0% { + box-shadow: 0 0 0 0 var(--pulse-color); + } + 70% { + box-shadow: 0 0 0 0.5rem transparent; + } + 100% { + box-shadow: 0 0 0 0 transparent; + } + } +`,SlBadge=class extends ShoelaceElement{constructor(){super(...arguments),this.variant="primary",this.pill=!1,this.pulse=!1}render(){return x$1` + <span + part="base" + class=${e$2({badge:!0,"badge--primary":"primary"===this.variant,"badge--success":"success"===this.variant,"badge--neutral":"neutral"===this.variant,"badge--warning":"warning"===this.variant,"badge--danger":"danger"===this.variant,"badge--pill":this.pill,"badge--pulse":this.pulse})} + role="status" + > + <slot></slot> + </span> + `}};SlBadge.styles=[component_styles_default,badge_styles_default],__decorateClass([n$5({reflect:!0})],SlBadge.prototype,"variant",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlBadge.prototype,"pill",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlBadge.prototype,"pulse",2),SlBadge.define("sl-badge"),SlTag.define("sl-tag");var tooltip_styles_default=i$7` + :host { + --max-width: 20rem; + --hide-delay: 0ms; + --show-delay: 150ms; + + display: contents; + } + + .tooltip { + --arrow-size: var(--sl-tooltip-arrow-size); + --arrow-color: var(--sl-tooltip-background-color); + } + + .tooltip::part(popup) { + z-index: var(--sl-z-index-tooltip); + } + + .tooltip[placement^='top']::part(popup) { + transform-origin: bottom; + } + + .tooltip[placement^='bottom']::part(popup) { + transform-origin: top; + } + + .tooltip[placement^='left']::part(popup) { + transform-origin: right; + } + + .tooltip[placement^='right']::part(popup) { + transform-origin: left; + } + + .tooltip__body { + display: block; + width: max-content; + max-width: var(--max-width); + border-radius: var(--sl-tooltip-border-radius); + background-color: var(--sl-tooltip-background-color); + font-family: var(--sl-tooltip-font-family); + font-size: var(--sl-tooltip-font-size); + font-weight: var(--sl-tooltip-font-weight); + line-height: var(--sl-tooltip-line-height); + text-align: start; + white-space: normal; + color: var(--sl-tooltip-color); + padding: var(--sl-tooltip-padding); + pointer-events: none; + user-select: none; + -webkit-user-select: none; + } +`,SlTooltip=class extends ShoelaceElement{constructor(){super(),this.localize=new LocalizeController(this),this.content="",this.placement="top",this.disabled=!1,this.distance=8,this.open=!1,this.skidding=0,this.trigger="hover focus",this.hoist=!1,this.handleBlur=()=>{this.hasTrigger("focus")&&this.hide()},this.handleClick=()=>{this.hasTrigger("click")&&(this.open?this.hide():this.show())},this.handleFocus=()=>{this.hasTrigger("focus")&&this.show()},this.handleDocumentKeyDown=event=>{"Escape"===event.key&&(event.stopPropagation(),this.hide())},this.handleMouseOver=()=>{if(this.hasTrigger("hover")){const delay=parseDuration(getComputedStyle(this).getPropertyValue("--show-delay"));clearTimeout(this.hoverTimeout),this.hoverTimeout=window.setTimeout(()=>this.show(),delay)}},this.handleMouseOut=()=>{if(this.hasTrigger("hover")){const delay=parseDuration(getComputedStyle(this).getPropertyValue("--hide-delay"));clearTimeout(this.hoverTimeout),this.hoverTimeout=window.setTimeout(()=>this.hide(),delay)}},this.addEventListener("blur",this.handleBlur,!0),this.addEventListener("focus",this.handleFocus,!0),this.addEventListener("click",this.handleClick),this.addEventListener("mouseover",this.handleMouseOver),this.addEventListener("mouseout",this.handleMouseOut)}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.closeWatcher)?void 0:_a.destroy(),document.removeEventListener("keydown",this.handleDocumentKeyDown)}firstUpdated(){this.body.hidden=!this.open,this.open&&(this.popup.active=!0,this.popup.reposition())}hasTrigger(triggerType){const triggers=this.trigger.split(" ");return triggers.includes(triggerType)}async handleOpenChange(){var _a,_b;if(this.open){if(this.disabled)return;this.emit("sl-show"),"CloseWatcher"in window?(null==(_a=this.closeWatcher)?void 0:_a.destroy(),this.closeWatcher=new CloseWatcher,this.closeWatcher.onclose=()=>{this.hide()}):document.addEventListener("keydown",this.handleDocumentKeyDown),await stopAnimations(this.body),this.body.hidden=!1,this.popup.active=!0;const{keyframes,options}=getAnimation(this,"tooltip.show",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.popup.reposition(),this.emit("sl-after-show")}else{this.emit("sl-hide"),null==(_b=this.closeWatcher)?void 0:_b.destroy(),document.removeEventListener("keydown",this.handleDocumentKeyDown),await stopAnimations(this.body);const{keyframes,options}=getAnimation(this,"tooltip.hide",{dir:this.localize.dir()});await animateTo(this.popup.popup,keyframes,options),this.popup.active=!1,this.body.hidden=!0,this.emit("sl-after-hide")}}async handleOptionsChange(){this.hasUpdated&&(await this.updateComplete,this.popup.reposition())}handleDisabledChange(){this.disabled&&this.open&&this.hide()}async show(){if(!this.open)return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open)return this.open=!1,waitForEvent(this,"sl-after-hide")}render(){return x$1` + <sl-popup + part="base" + exportparts=" + popup:base__popup, + arrow:base__arrow + " + class=${e$2({tooltip:!0,"tooltip--open":this.open})} + placement=${this.placement} + distance=${this.distance} + skidding=${this.skidding} + strategy=${this.hoist?"fixed":"absolute"} + flip + shift + arrow + hover-bridge + > + ${""} + <slot slot="anchor" aria-describedby="tooltip"></slot> + + ${""} + <div part="body" id="tooltip" class="tooltip__body" role="tooltip" aria-live=${this.open?"polite":"off"}> + <slot name="content">${this.content}</slot> + </div> + </sl-popup> + `}};SlTooltip.styles=[component_styles_default,tooltip_styles_default],SlTooltip.dependencies={"sl-popup":SlPopup},__decorateClass([e$6("slot:not([name])")],SlTooltip.prototype,"defaultSlot",2),__decorateClass([e$6(".tooltip__body")],SlTooltip.prototype,"body",2),__decorateClass([e$6("sl-popup")],SlTooltip.prototype,"popup",2),__decorateClass([n$5()],SlTooltip.prototype,"content",2),__decorateClass([n$5()],SlTooltip.prototype,"placement",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTooltip.prototype,"disabled",2),__decorateClass([n$5({type:Number})],SlTooltip.prototype,"distance",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTooltip.prototype,"open",2),__decorateClass([n$5({type:Number})],SlTooltip.prototype,"skidding",2),__decorateClass([n$5()],SlTooltip.prototype,"trigger",2),__decorateClass([n$5({type:Boolean})],SlTooltip.prototype,"hoist",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],SlTooltip.prototype,"handleOpenChange",1),__decorateClass([watch(["content","distance","hoist","placement","skidding"])],SlTooltip.prototype,"handleOptionsChange",1),__decorateClass([watch("disabled")],SlTooltip.prototype,"handleDisabledChange",1),setDefaultAnimation("tooltip.show",{keyframes:[{opacity:0,scale:.8},{opacity:1,scale:1}],options:{duration:150,easing:"ease"}}),setDefaultAnimation("tooltip.hide",{keyframes:[{opacity:1,scale:1},{opacity:0,scale:.8}],options:{duration:150,easing:"ease"}}),SlTooltip.define("sl-tooltip");const VARS=i$7` +:host { + --default-font-color: #222; + --page-background: #fafafa; + + --light-grey: #eee; + + --gray-1: #e6e6e6; + --gray-2: #a9a9a9; + --gray-3: #797979; + --gray-4: #515151; + + --nav-link-color: #444; + + --bar-shadow-color: rgba(0, 0, 0, .065); + --bar-border-color: #D4D4D4; + --error-border-color: #FF0000; + + --chromium-color-dark: #366597; + --chromium-color-medium: #85b4df; + --chromium-color-light: #bdd6ed; + --chromium-color-center: #4580c0; + + --material-primary-button: #58f; + + --card-background: white; + --card-border: 1px solid #ddd; + --card-box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; + + /* App specific */ + --invalid-color: rgba(255,0,0,0.75); + --content-padding: 16px; + --content-padding-half: 8px; + --content-padding-negative: -16px; + --content-padding-huge: 80px; + --default-border-radius: 3px; + + --max-content-width: 860px; +}`,RESET=i$7` +html, body { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, +pre, a, abbr, acronym, address, code, del, dfn, em, img, +dl, dt, dd, ol, ul, li, fieldset, form, label, legend, caption, tbody, tfoot, thead, tr { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +ol, ul { + padding: revert; +} + +blockquote, q { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; + quotes: "" ""; +} + +blockquote { + margin-left: 1em; + border-left: 2px solid #999; + padding-left: 1em; +} + +blockquote:before, q:before, +blockquote:after, q:after { + content: ""; +} + +th, td, caption { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; + text-align: left; + font-weight: normal; + vertical-align: middle; +} + +table { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; + border-collapse: separate; + border-spacing: 0; + vertical-align: middle; +} + +a img { + border: none; +} +`,FLEX_BOX=i$7` + .hbox, + .vbox { + display: flex; + align-items: center; + } + + .hbox { + flex-direction: row; + } + .hbox.align-top { + align-items: flex-start; + } + .vbox { + flex-direction: column; + } + + .hbox > .spacer, + .vbox > .spacer { + flex-grow: 1; + visibility: hidden; + } +`,SHARED_STYLES=[VARS,RESET,FLEX_BOX,i$7` + + * { + box-sizing: border-box; + /* font: inherit; */ + text-decoration: inherit; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + } + + .conditional-comma:last-child { + display: none; + } + + .data-table { + width: 100%; + border: var(--default-border); + border-radius: var(--border-radius); + } + .data-table th { + text-align: left; + background: var(--table-header-background); + padding: var(--content-padding-half) var(--content-padding); + } + .data-table td { + vertical-align: top; + border-top: var(--default-border); + padding: var(--content-padding-half) var(--content-padding); + } + + h1, + h2, + h3, + h4 { + font-weight: 300; + } + + h1 { + font-size: 30px; + } + + h2, + h3, + h4 { + background: var(--heading-background); + color: var(--heading-color); + } + + h2 { + font-size: 25px; + } + + h3 { + font-size: 20px; + } + + a { + text-decoration: none; + color: var(--link-color); + } + a:hover { + text-decoration: underline; + color: var(--link-hover-color); + cursor: pointer; + } + + input:not([type="submit"]), + textarea { + border: 1px solid var(--bar-border-color); + } + + input:not([type="submit"])[disabled], + textarea[disabled], + button[disabled] { + opacity: 0.5; + } + + button, + input[type="submit"], + .button { + display: inline-block; + padding: 4px 16px; + background: var(--button-background); + border: var(--button-border); + border-radius: var(--button-border-radius); + color: var(--button-color); + white-space: nowrap; + user-select: none; + cursor: pointer; + font-size: var(--button-font-size); + } + + button.primary, + input[type="submit"], + .button.primary { + background: var(--primary-button-background); + color: var(--primary-button-color); + font-weight: bold; + } + + button.primary:disabled, + input[type="submit"]:disabled, + .button.primary:disabled { + background: var(--gray-4); + } + + .button.secondary { + margin: var(--content-padding); + border: var(--default-border); + border-color: var(--primary-border-background); + border-radius: var(--border-radius); + } + + button:not(:disabled):hover { + border-color: var(--gray-4); + } + + #subheader { + display: flex; + align-items: center; + margin: var(--content-padding) 0; + max-width: var(--max-content-width); + width: 100%; + } + #subheader div.search { + min-width: 350px; + } + #subheader div input { + width: 280px; + padding: 10px 7px; + } + + code { + font-family: monospace; + } + + .description { + line-height: 1.4; + } + + .comma::after { + content: ","; + margin-right: 0.2em; + } + + details { + padding: var(--content-padding-quarter); + } + + details summary { + white-space: nowrap; + box-sizing: border-box; + contain: content; + overflow: hidden; + cursor: pointer; + transition: margin 250ms ease-out; + } + + details summary:hover { + color: var(--link-hover-color); + } + + details[open] #preview { + display: none; + } + + details[open] summary { + margin-bottom: var(--content-padding-quarter); + } + + details > div { + padding: var(--content-padding-quarter); + padding-left: var(--content-padding); + } + + .no-web-share { + display: none; + } + + .preformatted { + white-space: pre-wrap; + } + + .warning { + margin: var(--content-padding); + padding: var(--content-padding); + background: var(--warning-background); + color: var(--warning-color); + } + + #breadcrumbs { + display: flex; + align-items: center; + } + + #breadcrumbs a { + text-decoration: none; + color: inherit; + display: flex; + align-items: center; + } + + #breadcrumbs a sl-icon { + padding-right: var(--content-padding-half); + } + + sl-dialog::part(title) { + padding-top: calc(var(--header-spacing) / 2); + padding-bottom: calc(var(--header-spacing) / 2); + } + + sl-dialog::part(close-button) { + padding-right: 0; + } + + sl-dialog::part(body) { + padding-top: 0; + padding-bottom: calc(var(--body-spacing) / 2); + } + + sl-details::part(base) { + margin: var(--content-padding-half) 0 0 0; + color: var(--accordion-color); + border: none; + border-radius: 0; + background-color: transparent; + } + + sl-details::part(header) { + border-radius: var(--accordion-border-radius); + background: var(--accordion-background); + font-weight: 300; + font-size: 20px; + padding: var(--content-padding-quarter) var(--content-padding-half) + } + + sl-details::part(content) { + padding: 0; + } + + sl-skeleton { + --color: #eee; + --sheen-color: #ccc; + } + + sl-relative-time { + margin: 0 -3px; // Mitigate spacing from unknown cause. + } + + sl-relative-time.no-squeeze { + margin: 0 0; + } + + @media only screen and (max-width: 700px) { + h1 { + font-size: 24px; + } + h2 { + font-size: 20px; + } + h3 { + font-size: 15px; + } + + #subheader div:not(.search):not(.actionlinks):not(.tooltips) { + display: none; + } + + #subheader div.search { + text-align: center; + min-width: 0; + margin: 0; + } + #subheader div.search input { + width: auto; + } + } +`],LAYOUT_CSS=i$7` +.layout { + display: flex; +} +.layout.wrap { + flex-wrap: wrap; +} +.layout.center { + align-items: center; +} +.layout.center-center { + align-items: center; + justify-content: center; +} +.layout.vertical { + flex-direction: column; +}`;var __decorate$1a=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashAdminBlinkComponentListing=class extends i$4{constructor(){super(...arguments),this.editing=!1,this.component={},this.index=0,this.usersMap=new Map,this.componentId=0,this.name="",this.subscriberIds=[],this.ownerIds=[],this._client=window.csOpenApiClient}static get styles(){return[SHARED_STYLES,VARS,LAYOUT_CSS,i$7` + :host { + display: flex; + } + + :host([editing]) .owners_list_add_remove { + opacity: 1; + pointer-events: all; + } + + :host([editing]) .owners_list select[multiple] { + background-color: #fff; + border-color: rgba(0, 0, 0, 0); + } + + :host([editing]) .owners_list select[multiple] option { + padding-left: 4px; + } + + .component_name { + flex: 1 0 130px; + margin-right: var(--content-padding); + } + + .component_name h3 { + color: initial; + padding-top: 4px; + } + + .column_header { + margin-bottom: calc(var(--content-padding) / 2); + } + + .owners_list { + flex: 1 0 auto; + } + + .component_owner { + font-weight: 600; + } + + .owners_list_add_remove { + margin-left: calc(var(--content-padding) / 2); + opacity: 0; + transition: 200ms opacity cubic-bezier(0, 0, 0.2, 1); + pointer-events: none; + } + + .owners_list_add_remove button[disabled] { + pointer-events: none; + opacity: 0.5; + } + + .remove_owner_button { + color: darkred; + } + + select[multiple] { + min-width: 275px; + background-color: #eee; + border: none; + transition: 200ms background-color cubic-bezier(0, 0, 0.2, 1); + font-size: inherit; + } + + select[multiple]:disabled option { + color: initial; + padding: 4px 0; + } + `]}getOwnerListElement(){return this.shadowRoot?.querySelector(`#owner_list_${this.index}`)}_getOptionsElement(){return this._ownerCandidates}_findSelectedOptionElement(){return this._getOptionsElement().selectedOptions[0]}_isOwnerCheckboxChecked(){return this._isPrimaryCheckbox.checked}_isUserInOwnerList(userId){const ownersList=this.getOwnerListElement();return Array.from(ownersList.options).find(option=>parseInt(option.value)===userId)}_addUser(){const toggleAsOwner=this._isOwnerCheckboxChecked(),selectedCandidate=this._findSelectedOptionElement(),userId=parseInt(selectedCandidate.value);if(selectedCandidate.disabled)return void alert("Please select a user before trying to add");if(this._isUserInOwnerList(userId)&&!toggleAsOwner)return;let isError=!1;this._client.addUserToComponent({componentId:this.componentId,userId:userId,componentUsersRequest:{owner:toggleAsOwner}}).then(()=>{}).catch(()=>{isError=!0}).finally(()=>{this.dispatchEvent(new CustomEvent("adminAddComponentUser",{detail:{userId:userId,toggleAsOwner:toggleAsOwner,index:this.index,isError:isError},bubbles:!0,composed:!0}))})}_removeUser(){const toggleAsOwner=this._isOwnerCheckboxChecked(),selectedCandidate=this._findSelectedOptionElement(),userId=parseInt(selectedCandidate.value);if(selectedCandidate.disabled)return void alert("Please select a user before trying to remove");if(!this._isUserInOwnerList(userId))return;let isError=!1;this._client.removeUserFromComponent({componentId:this.componentId,userId:userId,componentUsersRequest:{owner:toggleAsOwner}}).then(()=>{}).catch(()=>{isError=!0}).finally(()=>{this.dispatchEvent(new CustomEvent("adminRemoveComponentUser",{detail:{userId:userId,toggleAsOwner:toggleAsOwner,index:this.index,isError:isError},bubbles:!0,composed:!0}))})}_printUserDetails(userId){return x$1`${this.usersMap.get(userId).name}: + ${this.usersMap.get(userId).email}`}render(){const userListTemplate=[];for(const user of this.usersMap.values())userListTemplate.push(x$1`<option + class="owner_name" + value="${user.id}" + data-email="${user.email}" + data-name="${user.name}" + > + ${user.name}: ${user.email} + </option>`);return x$1` + <div class="component_name"> + <div class="column_header">Component</div> + <h3>${this.name}</h3> + </div> + <div class="owners_list layout horizontal center"> + <div> + <div class="column_header">Receives email updates:</div> + <select + multiple + disabled + id="owner_list_${this.index}" + size="${this.subscriberIds.length}" + > + ${this.subscriberIds.map(subscriberId=>this.ownerIds.includes(subscriberId)?x$1`<option + class="owner_name component_owner" + value="${subscriberId}" + > + ${this._printUserDetails(subscriberId)} + </option>`:x$1`<option class="owner_name" value="${subscriberId}"> + ${this._printUserDetails(subscriberId)} + </option>`)}; + </select> + </div> + <div class="owners_list_add_remove"> + <div> + <select class="owner_candidates"> + <option selected disabled data-placeholder="true"> + Select owner to add/remove + </option> + ${userListTemplate}</select + ><br /> + <label + title="Toggles the user as an owner. If you click 'Remove' ans this is not checked, the user is removed from the component." + >Owner? <input type="checkbox" class="is_primary_checkbox" + /></label> + </div> + <button + @click="${this._addUser}" + class="add_owner_button" + data-component-name="${this.name}" + > + Add + </button> + <button + @click="${this._removeUser}" + class="remove_owner_button" + data-component-name="${this.name}" + > + Remove + </button> + </div> + </div> + `}};__decorate$1a([n$5({type:Boolean,reflect:!0})],ChromedashAdminBlinkComponentListing.prototype,"editing",void 0),__decorate$1a([n$5({type:Object})],ChromedashAdminBlinkComponentListing.prototype,"component",void 0),__decorate$1a([n$5({type:Number})],ChromedashAdminBlinkComponentListing.prototype,"index",void 0),__decorate$1a([n$5({type:Object})],ChromedashAdminBlinkComponentListing.prototype,"usersMap",void 0),__decorate$1a([n$5({type:Number})],ChromedashAdminBlinkComponentListing.prototype,"componentId",void 0),__decorate$1a([n$5({type:String})],ChromedashAdminBlinkComponentListing.prototype,"name",void 0),__decorate$1a([n$5({type:Array})],ChromedashAdminBlinkComponentListing.prototype,"subscriberIds",void 0),__decorate$1a([n$5({type:Array})],ChromedashAdminBlinkComponentListing.prototype,"ownerIds",void 0),__decorate$1a([e$6(".owner_candidates")],ChromedashAdminBlinkComponentListing.prototype,"_ownerCandidates",void 0),__decorate$1a([e$6(".is_primary_checkbox")],ChromedashAdminBlinkComponentListing.prototype,"_isPrimaryCheckbox",void 0),ChromedashAdminBlinkComponentListing=__decorate$1a([t$3("chromedash-admin-blink-component-listing")],ChromedashAdminBlinkComponentListing);const{entries,setPrototypeOf,isFrozen,getPrototypeOf,getOwnPropertyDescriptor}=Object;let{freeze,seal,create}=Object,{apply,construct}="undefined"!=typeof Reflect&&Reflect;freeze||(freeze=function(x){return x}),seal||(seal=function(x){return x}),apply||(apply=function(func,thisArg){for(var _len=arguments.length,args=Array(2<_len?_len-2:0),_key=2;_key<_len;_key++)args[_key-2]=arguments[_key];return func.apply(thisArg,args)}),construct||(construct=function(Func){for(var _len2=arguments.length,args=Array(1<_len2?_len2-1:0),_key2=1;_key2<_len2;_key2++)args[_key2-1]=arguments[_key2];return new Func(...args)});const arrayForEach=unapply(Array.prototype.forEach),arrayLastIndexOf=unapply(Array.prototype.lastIndexOf),arrayPop=unapply(Array.prototype.pop),arrayPush=unapply(Array.prototype.push),arraySplice=unapply(Array.prototype.splice),stringToLowerCase=unapply(String.prototype.toLowerCase),stringToString=unapply(String.prototype.toString),stringMatch=unapply(String.prototype.match),stringReplace=unapply(String.prototype.replace),stringIndexOf=unapply(String.prototype.indexOf),stringTrim=unapply(String.prototype.trim),objectHasOwnProperty=unapply(Object.prototype.hasOwnProperty),regExpTest=unapply(RegExp.prototype.test),typeErrorCreate=unconstruct(TypeError);function unapply(func){return function(thisArg){thisArg instanceof RegExp&&(thisArg.lastIndex=0);for(var _len3=arguments.length,args=Array(1<_len3?_len3-1:0),_key3=1;_key3<_len3;_key3++)args[_key3-1]=arguments[_key3];return apply(func,thisArg,args)}}function unconstruct(Func){return function(){for(var _len4=arguments.length,args=Array(_len4),_key4=0;_key4<_len4;_key4++)args[_key4]=arguments[_key4];return construct(Func,args)}}function addToSet(set,array){let transformCaseFunc=2<arguments.length&&arguments[2]!==void 0?arguments[2]:stringToLowerCase;setPrototypeOf&&setPrototypeOf(set,null);for(let l=array.length;l--;){let element=array[l];if("string"==typeof element){const lcElement=transformCaseFunc(element);lcElement!==element&&(!isFrozen(array)&&(array[l]=lcElement),element=lcElement)}set[element]=!0}return set}function cleanArray(array){for(let index=0;index<array.length;index++){const isPropertyExist=objectHasOwnProperty(array,index);isPropertyExist||(array[index]=null)}return array}function clone(object){const newObject=create(null);for(const[property,value]of entries(object)){const isPropertyExist=objectHasOwnProperty(object,property);isPropertyExist&&(Array.isArray(value)?newObject[property]=cleanArray(value):value&&"object"==typeof value&&value.constructor===Object?newObject[property]=clone(value):newObject[property]=value)}return newObject}function lookupGetter(object,prop){for(;null!==object;){const desc=getOwnPropertyDescriptor(object,prop);if(desc){if(desc.get)return unapply(desc.get);if("function"==typeof desc.value)return unapply(desc.value)}object=getPrototypeOf(object)}return function(){return null}}const html$1=freeze(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","search","section","select","shadow","slot","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),svg$1=freeze(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","enterkeyhint","exportparts","filter","font","g","glyph","glyphref","hkern","image","inputmode","line","lineargradient","marker","mask","metadata","mpath","part","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),svgFilters=freeze(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),svgDisallowed=freeze(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),mathMl$1=freeze(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),mathMlDisallowed=freeze(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),text=freeze(["#text"]),html=freeze(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","exportparts","face","for","headers","height","hidden","high","href","hreflang","id","inert","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","part","pattern","placeholder","playsinline","popover","popovertarget","popovertargetaction","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","slot","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","wrap","xmlns","slot"]),svg=freeze(["accent-height","accumulate","additive","alignment-baseline","amplitude","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","exponent","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","intercept","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","mask-type","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","slope","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","tablevalues","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),mathMl=freeze(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),xml=freeze(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),MUSTACHE_EXPR=seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm),ERB_EXPR=seal(/<%[\w\W]*|[\w\W]*%>/gm),TMPLIT_EXPR=seal(/\$\{[\w\W]*/gm),DATA_ATTR=seal(/^data-[\-\w.\u00B7-\uFFFF]+$/),ARIA_ATTR=seal(/^aria-[\-\w]+$/),IS_ALLOWED_URI=seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),IS_SCRIPT_OR_DATA=seal(/^(?:\w+script|data):/i),ATTR_WHITESPACE=seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),DOCTYPE_NAME=seal(/^html$/i),CUSTOM_ELEMENT=seal(/^[a-z][.\w]*(-[.\w]+)+$/i);var EXPRESSIONS=Object.freeze({__proto__:null,ARIA_ATTR:ARIA_ATTR,ATTR_WHITESPACE:ATTR_WHITESPACE,CUSTOM_ELEMENT:CUSTOM_ELEMENT,DATA_ATTR:DATA_ATTR,DOCTYPE_NAME:DOCTYPE_NAME,ERB_EXPR:ERB_EXPR,IS_ALLOWED_URI:IS_ALLOWED_URI,IS_SCRIPT_OR_DATA:IS_SCRIPT_OR_DATA,MUSTACHE_EXPR:MUSTACHE_EXPR,TMPLIT_EXPR:TMPLIT_EXPR});const NODE_TYPE={element:1,text:3,progressingInstruction:7,comment:8,document:9},getGlobal=function(){return"undefined"==typeof window?null:window},_createTrustedTypesPolicy=function(trustedTypes,purifyHostElement){if("object"!=typeof trustedTypes||"function"!=typeof trustedTypes.createPolicy)return null;let suffix=null;purifyHostElement&&purifyHostElement.hasAttribute("data-tt-policy-suffix")&&(suffix=purifyHostElement.getAttribute("data-tt-policy-suffix"));const policyName="dompurify"+(suffix?"#"+suffix:"");try{return trustedTypes.createPolicy(policyName,{createHTML(html){return html},createScriptURL(scriptUrl){return scriptUrl}})}catch(_){return console.warn("TrustedTypes policy "+policyName+" could not be created."),null}},_createHooksMap=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function createDOMPurify(){function _executeHooks(hooks,currentNode,data){arrayForEach(hooks,hook=>{hook.call(DOMPurify,currentNode,data,CONFIG)})}let window=0<arguments.length&&void 0!==arguments[0]?arguments[0]:getGlobal();const DOMPurify=root=>createDOMPurify(root);if(DOMPurify.version="3.3.1",DOMPurify.removed=[],!window||!window.document||window.document.nodeType!==NODE_TYPE.document||!window.Element)return DOMPurify.isSupported=!1,DOMPurify;let{document}=window;const originalDocument=document,currentScript=originalDocument.currentScript,{DocumentFragment,HTMLTemplateElement,Node,Element,NodeFilter,NamedNodeMap=window.NamedNodeMap||window.MozNamedAttrMap,HTMLFormElement,DOMParser,trustedTypes}=window,ElementPrototype=Element.prototype,cloneNode=lookupGetter(ElementPrototype,"cloneNode"),remove=lookupGetter(ElementPrototype,"remove"),getNextSibling=lookupGetter(ElementPrototype,"nextSibling"),getChildNodes=lookupGetter(ElementPrototype,"childNodes"),getParentNode=lookupGetter(ElementPrototype,"parentNode");if("function"==typeof HTMLTemplateElement){const template=document.createElement("template");template.content&&template.content.ownerDocument&&(document=template.content.ownerDocument)}let emptyHTML="",trustedTypesPolicy;const{implementation,createNodeIterator,createDocumentFragment,getElementsByTagName}=document,{importNode}=originalDocument;let hooks=_createHooksMap();DOMPurify.isSupported="function"==typeof entries&&"function"==typeof getParentNode&&implementation&&void 0!==implementation.createHTMLDocument;const{MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR,DATA_ATTR,ARIA_ATTR,IS_SCRIPT_OR_DATA,ATTR_WHITESPACE,CUSTOM_ELEMENT}=EXPRESSIONS;let{IS_ALLOWED_URI:IS_ALLOWED_URI$1}=EXPRESSIONS,ALLOWED_TAGS=null;const DEFAULT_ALLOWED_TAGS=addToSet({},[...html$1,...svg$1,...svgFilters,...mathMl$1,...text]);let ALLOWED_ATTR=null;const DEFAULT_ALLOWED_ATTR=addToSet({},[...html,...svg,...mathMl,...xml]);let CUSTOM_ELEMENT_HANDLING=Object.seal(create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),FORBID_TAGS=null,FORBID_ATTR=null;const EXTRA_ELEMENT_HANDLING=Object.seal(create(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let ALLOW_ARIA_ATTR=!0,ALLOW_DATA_ATTR=!0,ALLOW_UNKNOWN_PROTOCOLS=!1,ALLOW_SELF_CLOSE_IN_ATTR=!0,SAFE_FOR_TEMPLATES=!1,SAFE_FOR_XML=!0,WHOLE_DOCUMENT=!1,SET_CONFIG=!1,FORCE_BODY=!1,RETURN_DOM=!1,RETURN_DOM_FRAGMENT=!1,RETURN_TRUSTED_TYPE=!1,SANITIZE_DOM=!0,SANITIZE_NAMED_PROPS=!1;let KEEP_CONTENT=!0,IN_PLACE=!1,USE_PROFILES={},FORBID_CONTENTS=null;const DEFAULT_FORBID_CONTENTS=addToSet({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let DATA_URI_TAGS=null;const DEFAULT_DATA_URI_TAGS=addToSet({},["audio","video","img","source","image","track"]);let URI_SAFE_ATTRIBUTES=null;const DEFAULT_URI_SAFE_ATTRIBUTES=addToSet({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),MATHML_NAMESPACE="http://www.w3.org/1998/Math/MathML",SVG_NAMESPACE="http://www.w3.org/2000/svg",HTML_NAMESPACE="http://www.w3.org/1999/xhtml";let NAMESPACE=HTML_NAMESPACE,IS_EMPTY_INPUT=!1,ALLOWED_NAMESPACES=null;const DEFAULT_ALLOWED_NAMESPACES=addToSet({},[MATHML_NAMESPACE,SVG_NAMESPACE,HTML_NAMESPACE],stringToString);let MATHML_TEXT_INTEGRATION_POINTS=addToSet({},["mi","mo","mn","ms","mtext"]),HTML_INTEGRATION_POINTS=addToSet({},["annotation-xml"]);const COMMON_SVG_AND_HTML_ELEMENTS=addToSet({},["title","style","font","a","script"]);let PARSER_MEDIA_TYPE=null;const SUPPORTED_PARSER_MEDIA_TYPES=["application/xhtml+xml","text/html"];let transformCaseFunc=null,CONFIG=null;const formElement=document.createElement("form"),isRegexOrFunction=function isRegexOrFunction(testValue){return testValue instanceof RegExp||testValue instanceof Function},_parseConfig=function _parseConfig(){let cfg=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};if(!(CONFIG&&CONFIG===cfg)){if(cfg&&"object"==typeof cfg||(cfg={}),cfg=clone(cfg),PARSER_MEDIA_TYPE=-1===SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE)?"text/html":cfg.PARSER_MEDIA_TYPE,transformCaseFunc="application/xhtml+xml"===PARSER_MEDIA_TYPE?stringToString:stringToLowerCase,ALLOWED_TAGS=objectHasOwnProperty(cfg,"ALLOWED_TAGS")?addToSet({},cfg.ALLOWED_TAGS,transformCaseFunc):DEFAULT_ALLOWED_TAGS,ALLOWED_ATTR=objectHasOwnProperty(cfg,"ALLOWED_ATTR")?addToSet({},cfg.ALLOWED_ATTR,transformCaseFunc):DEFAULT_ALLOWED_ATTR,ALLOWED_NAMESPACES=objectHasOwnProperty(cfg,"ALLOWED_NAMESPACES")?addToSet({},cfg.ALLOWED_NAMESPACES,stringToString):DEFAULT_ALLOWED_NAMESPACES,URI_SAFE_ATTRIBUTES=objectHasOwnProperty(cfg,"ADD_URI_SAFE_ATTR")?addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),cfg.ADD_URI_SAFE_ATTR,transformCaseFunc):DEFAULT_URI_SAFE_ATTRIBUTES,DATA_URI_TAGS=objectHasOwnProperty(cfg,"ADD_DATA_URI_TAGS")?addToSet(clone(DEFAULT_DATA_URI_TAGS),cfg.ADD_DATA_URI_TAGS,transformCaseFunc):DEFAULT_DATA_URI_TAGS,FORBID_CONTENTS=objectHasOwnProperty(cfg,"FORBID_CONTENTS")?addToSet({},cfg.FORBID_CONTENTS,transformCaseFunc):DEFAULT_FORBID_CONTENTS,FORBID_TAGS=objectHasOwnProperty(cfg,"FORBID_TAGS")?addToSet({},cfg.FORBID_TAGS,transformCaseFunc):clone({}),FORBID_ATTR=objectHasOwnProperty(cfg,"FORBID_ATTR")?addToSet({},cfg.FORBID_ATTR,transformCaseFunc):clone({}),USE_PROFILES=!!objectHasOwnProperty(cfg,"USE_PROFILES")&&cfg.USE_PROFILES,ALLOW_ARIA_ATTR=!1!==cfg.ALLOW_ARIA_ATTR,ALLOW_DATA_ATTR=!1!==cfg.ALLOW_DATA_ATTR,ALLOW_UNKNOWN_PROTOCOLS=cfg.ALLOW_UNKNOWN_PROTOCOLS||!1,ALLOW_SELF_CLOSE_IN_ATTR=!1!==cfg.ALLOW_SELF_CLOSE_IN_ATTR,SAFE_FOR_TEMPLATES=cfg.SAFE_FOR_TEMPLATES||!1,SAFE_FOR_XML=!1!==cfg.SAFE_FOR_XML,WHOLE_DOCUMENT=cfg.WHOLE_DOCUMENT||!1,RETURN_DOM=cfg.RETURN_DOM||!1,RETURN_DOM_FRAGMENT=cfg.RETURN_DOM_FRAGMENT||!1,RETURN_TRUSTED_TYPE=cfg.RETURN_TRUSTED_TYPE||!1,FORCE_BODY=cfg.FORCE_BODY||!1,SANITIZE_DOM=!1!==cfg.SANITIZE_DOM,SANITIZE_NAMED_PROPS=cfg.SANITIZE_NAMED_PROPS||!1,KEEP_CONTENT=!1!==cfg.KEEP_CONTENT,IN_PLACE=cfg.IN_PLACE||!1,IS_ALLOWED_URI$1=cfg.ALLOWED_URI_REGEXP||IS_ALLOWED_URI,NAMESPACE=cfg.NAMESPACE||HTML_NAMESPACE,MATHML_TEXT_INTEGRATION_POINTS=cfg.MATHML_TEXT_INTEGRATION_POINTS||MATHML_TEXT_INTEGRATION_POINTS,HTML_INTEGRATION_POINTS=cfg.HTML_INTEGRATION_POINTS||HTML_INTEGRATION_POINTS,CUSTOM_ELEMENT_HANDLING=cfg.CUSTOM_ELEMENT_HANDLING||{},cfg.CUSTOM_ELEMENT_HANDLING&&isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(CUSTOM_ELEMENT_HANDLING.tagNameCheck=cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck),cfg.CUSTOM_ELEMENT_HANDLING&&isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(CUSTOM_ELEMENT_HANDLING.attributeNameCheck=cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),cfg.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),SAFE_FOR_TEMPLATES&&(ALLOW_DATA_ATTR=!1),RETURN_DOM_FRAGMENT&&(RETURN_DOM=!0),USE_PROFILES&&(ALLOWED_TAGS=addToSet({},text),ALLOWED_ATTR=[],!0===USE_PROFILES.html&&(addToSet(ALLOWED_TAGS,html$1),addToSet(ALLOWED_ATTR,html)),!0===USE_PROFILES.svg&&(addToSet(ALLOWED_TAGS,svg$1),addToSet(ALLOWED_ATTR,svg),addToSet(ALLOWED_ATTR,xml)),!0===USE_PROFILES.svgFilters&&(addToSet(ALLOWED_TAGS,svgFilters),addToSet(ALLOWED_ATTR,svg),addToSet(ALLOWED_ATTR,xml)),!0===USE_PROFILES.mathMl&&(addToSet(ALLOWED_TAGS,mathMl$1),addToSet(ALLOWED_ATTR,mathMl),addToSet(ALLOWED_ATTR,xml))),cfg.ADD_TAGS&&("function"==typeof cfg.ADD_TAGS?EXTRA_ELEMENT_HANDLING.tagCheck=cfg.ADD_TAGS:(ALLOWED_TAGS===DEFAULT_ALLOWED_TAGS&&(ALLOWED_TAGS=clone(ALLOWED_TAGS)),addToSet(ALLOWED_TAGS,cfg.ADD_TAGS,transformCaseFunc))),cfg.ADD_ATTR&&("function"==typeof cfg.ADD_ATTR?EXTRA_ELEMENT_HANDLING.attributeCheck=cfg.ADD_ATTR:(ALLOWED_ATTR===DEFAULT_ALLOWED_ATTR&&(ALLOWED_ATTR=clone(ALLOWED_ATTR)),addToSet(ALLOWED_ATTR,cfg.ADD_ATTR,transformCaseFunc))),cfg.ADD_URI_SAFE_ATTR&&addToSet(URI_SAFE_ATTRIBUTES,cfg.ADD_URI_SAFE_ATTR,transformCaseFunc),cfg.FORBID_CONTENTS&&(FORBID_CONTENTS===DEFAULT_FORBID_CONTENTS&&(FORBID_CONTENTS=clone(FORBID_CONTENTS)),addToSet(FORBID_CONTENTS,cfg.FORBID_CONTENTS,transformCaseFunc)),cfg.ADD_FORBID_CONTENTS&&(FORBID_CONTENTS===DEFAULT_FORBID_CONTENTS&&(FORBID_CONTENTS=clone(FORBID_CONTENTS)),addToSet(FORBID_CONTENTS,cfg.ADD_FORBID_CONTENTS,transformCaseFunc)),KEEP_CONTENT&&(ALLOWED_TAGS["#text"]=!0),WHOLE_DOCUMENT&&addToSet(ALLOWED_TAGS,["html","head","body"]),ALLOWED_TAGS.table&&(addToSet(ALLOWED_TAGS,["tbody"]),delete FORBID_TAGS.tbody),cfg.TRUSTED_TYPES_POLICY){if("function"!=typeof cfg.TRUSTED_TYPES_POLICY.createHTML)throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.");if("function"!=typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL)throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.");trustedTypesPolicy=cfg.TRUSTED_TYPES_POLICY,emptyHTML=trustedTypesPolicy.createHTML("")}else void 0===trustedTypesPolicy&&(trustedTypesPolicy=_createTrustedTypesPolicy(trustedTypes,currentScript)),null!==trustedTypesPolicy&&"string"==typeof emptyHTML&&(emptyHTML=trustedTypesPolicy.createHTML(""));freeze&&freeze(cfg),CONFIG=cfg}},ALL_SVG_TAGS=addToSet({},[...svg$1,...svgFilters,...svgDisallowed]),ALL_MATHML_TAGS=addToSet({},[...mathMl$1,...mathMlDisallowed]),_checkValidNamespace=function _checkValidNamespace(element){let parent=getParentNode(element);parent&&parent.tagName||(parent={namespaceURI:NAMESPACE,tagName:"template"});const tagName=stringToLowerCase(element.tagName),parentTagName=stringToLowerCase(parent.tagName);return!!ALLOWED_NAMESPACES[element.namespaceURI]&&(element.namespaceURI===SVG_NAMESPACE?parent.namespaceURI===HTML_NAMESPACE?"svg"===tagName:parent.namespaceURI===MATHML_NAMESPACE?"svg"===tagName&&("annotation-xml"===parentTagName||MATHML_TEXT_INTEGRATION_POINTS[parentTagName]):!!ALL_SVG_TAGS[tagName]:element.namespaceURI===MATHML_NAMESPACE?parent.namespaceURI===HTML_NAMESPACE?"math"===tagName:parent.namespaceURI===SVG_NAMESPACE?"math"===tagName&&HTML_INTEGRATION_POINTS[parentTagName]:!!ALL_MATHML_TAGS[tagName]:element.namespaceURI===HTML_NAMESPACE?!!(parent.namespaceURI!==SVG_NAMESPACE||HTML_INTEGRATION_POINTS[parentTagName])&&!!(parent.namespaceURI!==MATHML_NAMESPACE||MATHML_TEXT_INTEGRATION_POINTS[parentTagName])&&!ALL_MATHML_TAGS[tagName]&&(COMMON_SVG_AND_HTML_ELEMENTS[tagName]||!ALL_SVG_TAGS[tagName]):!!("application/xhtml+xml"===PARSER_MEDIA_TYPE&&ALLOWED_NAMESPACES[element.namespaceURI]))},_forceRemove=function _forceRemove(node){arrayPush(DOMPurify.removed,{element:node});try{getParentNode(node).removeChild(node)}catch(_){remove(node)}},_removeAttribute=function _removeAttribute(name,element){try{arrayPush(DOMPurify.removed,{attribute:element.getAttributeNode(name),from:element})}catch(_){arrayPush(DOMPurify.removed,{attribute:null,from:element})}if(element.removeAttribute(name),"is"===name)if(RETURN_DOM||RETURN_DOM_FRAGMENT)try{_forceRemove(element)}catch(_){}else try{element.setAttribute(name,"")}catch(_){}},_initDocument=function _initDocument(dirty){let doc=null,leadingWhitespace=null;if(FORCE_BODY)dirty="<remove></remove>"+dirty;else{const matches=stringMatch(dirty,/^[\r\n\t ]+/);leadingWhitespace=matches&&matches[0]}"application/xhtml+xml"===PARSER_MEDIA_TYPE&&NAMESPACE===HTML_NAMESPACE&&(dirty="<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>"+dirty+"</body></html>");const dirtyPayload=trustedTypesPolicy?trustedTypesPolicy.createHTML(dirty):dirty;if(NAMESPACE===HTML_NAMESPACE)try{doc=new DOMParser().parseFromString(dirtyPayload,PARSER_MEDIA_TYPE)}catch(_){}if(!doc||!doc.documentElement){doc=implementation.createDocument(NAMESPACE,"template",null);try{doc.documentElement.innerHTML=IS_EMPTY_INPUT?emptyHTML:dirtyPayload}catch(_){}}const body=doc.body||doc.documentElement;return dirty&&leadingWhitespace&&body.insertBefore(document.createTextNode(leadingWhitespace),body.childNodes[0]||null),NAMESPACE===HTML_NAMESPACE?getElementsByTagName.call(doc,WHOLE_DOCUMENT?"html":"body")[0]:WHOLE_DOCUMENT?doc.documentElement:body},_createNodeIterator=function _createNodeIterator(root){return createNodeIterator.call(root.ownerDocument||root,root,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT|NodeFilter.SHOW_PROCESSING_INSTRUCTION|NodeFilter.SHOW_CDATA_SECTION,null)},_isClobbered=function _isClobbered(element){return element instanceof HTMLFormElement&&("string"!=typeof element.nodeName||"string"!=typeof element.textContent||"function"!=typeof element.removeChild||!(element.attributes instanceof NamedNodeMap)||"function"!=typeof element.removeAttribute||"function"!=typeof element.setAttribute||"string"!=typeof element.namespaceURI||"function"!=typeof element.insertBefore||"function"!=typeof element.hasChildNodes)},_isNode=function _isNode(value){return"function"==typeof Node&&value instanceof Node},_sanitizeElements=function _sanitizeElements(currentNode){let content=null;if(_executeHooks(hooks.beforeSanitizeElements,currentNode,null),_isClobbered(currentNode))return _forceRemove(currentNode),!0;const tagName=transformCaseFunc(currentNode.nodeName);if(_executeHooks(hooks.uponSanitizeElement,currentNode,{tagName,allowedTags:ALLOWED_TAGS}),SAFE_FOR_XML&¤tNode.hasChildNodes()&&!_isNode(currentNode.firstElementChild)&®ExpTest(/<[/\w!]/g,currentNode.innerHTML)&®ExpTest(/<[/\w!]/g,currentNode.textContent))return _forceRemove(currentNode),!0;if(currentNode.nodeType===NODE_TYPE.progressingInstruction)return _forceRemove(currentNode),!0;if(SAFE_FOR_XML&¤tNode.nodeType===NODE_TYPE.comment&®ExpTest(/<[/\w]/g,currentNode.data))return _forceRemove(currentNode),!0;if(!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function&&EXTRA_ELEMENT_HANDLING.tagCheck(tagName))&&(!ALLOWED_TAGS[tagName]||FORBID_TAGS[tagName])){if(!FORBID_TAGS[tagName]&&_isBasicCustomElement(tagName)){if(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&®ExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,tagName))return!1;if(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))return!1}if(KEEP_CONTENT&&!FORBID_CONTENTS[tagName]){const parentNode=getParentNode(currentNode)||currentNode.parentNode,childNodes=getChildNodes(currentNode)||currentNode.childNodes;if(childNodes&&parentNode){const childCount=childNodes.length;for(let i=childCount-1;0<=i;--i){const childClone=cloneNode(childNodes[i],!0);childClone.__removalCount=(currentNode.__removalCount||0)+1,parentNode.insertBefore(childClone,getNextSibling(currentNode))}}}return _forceRemove(currentNode),!0}return currentNode instanceof Element&&!_checkValidNamespace(currentNode)?(_forceRemove(currentNode),!0):("noscript"===tagName||"noembed"===tagName||"noframes"===tagName)&®ExpTest(/<\/no(script|embed|frames)/i,currentNode.innerHTML)?(_forceRemove(currentNode),!0):(SAFE_FOR_TEMPLATES&¤tNode.nodeType===NODE_TYPE.text&&(content=currentNode.textContent,arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{content=stringReplace(content,expr," ")}),currentNode.textContent!==content&&(arrayPush(DOMPurify.removed,{element:currentNode.cloneNode()}),currentNode.textContent=content)),_executeHooks(hooks.afterSanitizeElements,currentNode,null),!1)},_isValidAttribute=function _isValidAttribute(lcTag,lcName,value){if(SANITIZE_DOM&&("id"===lcName||"name"===lcName)&&(value in document||value in formElement))return!1;if(ALLOW_DATA_ATTR&&!FORBID_ATTR[lcName]&®ExpTest(DATA_ATTR,lcName));else if(ALLOW_ARIA_ATTR&®ExpTest(ARIA_ATTR,lcName));else if(EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function&&EXTRA_ELEMENT_HANDLING.attributeCheck(lcName,lcTag));else if(!ALLOWED_ATTR[lcName]||FORBID_ATTR[lcName]){if(_isBasicCustomElement(lcTag)&&(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&®ExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,lcTag)||CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag))&&(CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp&®ExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck,lcName)||CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName,lcTag))||"is"===lcName&&CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp&®ExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck,value)||CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function&&CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));else return!1;}else if(URI_SAFE_ATTRIBUTES[lcName]);else if(regExpTest(IS_ALLOWED_URI$1,stringReplace(value,ATTR_WHITESPACE,"")));else if(("src"===lcName||"xlink:href"===lcName||"href"===lcName)&&"script"!==lcTag&&0===stringIndexOf(value,"data:")&&DATA_URI_TAGS[lcTag]);else if(ALLOW_UNKNOWN_PROTOCOLS&&!regExpTest(IS_SCRIPT_OR_DATA,stringReplace(value,ATTR_WHITESPACE,"")));else if(value)return!1;return!0},_isBasicCustomElement=function _isBasicCustomElement(tagName){return"annotation-xml"!==tagName&&stringMatch(tagName,CUSTOM_ELEMENT)},_sanitizeAttributes=function _sanitizeAttributes(currentNode){_executeHooks(hooks.beforeSanitizeAttributes,currentNode,null);const{attributes}=currentNode;if(attributes&&!_isClobbered(currentNode)){const hookEvent={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ALLOWED_ATTR,forceKeepAttr:void 0};for(let l=attributes.length;l--;){const attr=attributes[l],{name,namespaceURI,value:attrValue}=attr,lcName=transformCaseFunc(name),initValue=attrValue;let value="value"===name?initValue:stringTrim(initValue);if(hookEvent.attrName=lcName,hookEvent.attrValue=value,hookEvent.keepAttr=!0,hookEvent.forceKeepAttr=void 0,_executeHooks(hooks.uponSanitizeAttribute,currentNode,hookEvent),value=hookEvent.attrValue,SANITIZE_NAMED_PROPS&&("id"===lcName||"name"===lcName)&&(_removeAttribute(name,currentNode),value="user-content-"+value),SAFE_FOR_XML&®ExpTest(/((--!?|])>)|<\/(style|title|textarea)/i,value)){_removeAttribute(name,currentNode);continue}if("attributename"===lcName&&stringMatch(value,"href")){_removeAttribute(name,currentNode);continue}if(hookEvent.forceKeepAttr)continue;if(!hookEvent.keepAttr){_removeAttribute(name,currentNode);continue}if(!ALLOW_SELF_CLOSE_IN_ATTR&®ExpTest(/\/>/i,value)){_removeAttribute(name,currentNode);continue}SAFE_FOR_TEMPLATES&&arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{value=stringReplace(value,expr," ")});const lcTag=transformCaseFunc(currentNode.nodeName);if(!_isValidAttribute(lcTag,lcName,value)){_removeAttribute(name,currentNode);continue}if(trustedTypesPolicy&&"object"==typeof trustedTypes&&"function"==typeof trustedTypes.getAttributeType)if(namespaceURI);else switch(trustedTypes.getAttributeType(lcTag,lcName)){case"TrustedHTML":{value=trustedTypesPolicy.createHTML(value);break}case"TrustedScriptURL":{value=trustedTypesPolicy.createScriptURL(value);break}}if(value!==initValue)try{namespaceURI?currentNode.setAttributeNS(namespaceURI,name,value):currentNode.setAttribute(name,value),_isClobbered(currentNode)?_forceRemove(currentNode):arrayPop(DOMPurify.removed)}catch(_){_removeAttribute(name,currentNode)}}_executeHooks(hooks.afterSanitizeAttributes,currentNode,null)}},_sanitizeShadowDOM=function _sanitizeShadowDOM(fragment){let shadowNode=null;const shadowIterator=_createNodeIterator(fragment);for(_executeHooks(hooks.beforeSanitizeShadowDOM,fragment,null);shadowNode=shadowIterator.nextNode();)_executeHooks(hooks.uponSanitizeShadowNode,shadowNode,null),_sanitizeElements(shadowNode),_sanitizeAttributes(shadowNode),shadowNode.content instanceof DocumentFragment&&_sanitizeShadowDOM(shadowNode.content);_executeHooks(hooks.afterSanitizeShadowDOM,fragment,null)};return DOMPurify.sanitize=function(dirty){let cfg=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},body=null,importedNode=null,currentNode=null,returnNode=null;if(IS_EMPTY_INPUT=!dirty,IS_EMPTY_INPUT&&(dirty="<!-->"),"string"!=typeof dirty&&!_isNode(dirty))if("function"!=typeof dirty.toString)throw typeErrorCreate("toString is not a function");else if(dirty=dirty.toString(),"string"!=typeof dirty)throw typeErrorCreate("dirty is not a string, aborting");if(!DOMPurify.isSupported)return dirty;if(SET_CONFIG||_parseConfig(cfg),DOMPurify.removed=[],"string"==typeof dirty&&(IN_PLACE=!1),IN_PLACE){if(dirty.nodeName){const tagName=transformCaseFunc(dirty.nodeName);if(!ALLOWED_TAGS[tagName]||FORBID_TAGS[tagName])throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place")}}else if(dirty instanceof Node)body=_initDocument("<!---->"),importedNode=body.ownerDocument.importNode(dirty,!0),importedNode.nodeType===NODE_TYPE.element&&"BODY"===importedNode.nodeName?body=importedNode:"HTML"===importedNode.nodeName?body=importedNode:body.appendChild(importedNode);else{if(!RETURN_DOM&&!SAFE_FOR_TEMPLATES&&!WHOLE_DOCUMENT&&-1===dirty.indexOf("<"))return trustedTypesPolicy&&RETURN_TRUSTED_TYPE?trustedTypesPolicy.createHTML(dirty):dirty;if(body=_initDocument(dirty),!body)return RETURN_DOM?null:RETURN_TRUSTED_TYPE?emptyHTML:""}body&&FORCE_BODY&&_forceRemove(body.firstChild);for(const nodeIterator=_createNodeIterator(IN_PLACE?dirty:body);currentNode=nodeIterator.nextNode();)_sanitizeElements(currentNode),_sanitizeAttributes(currentNode),currentNode.content instanceof DocumentFragment&&_sanitizeShadowDOM(currentNode.content);if(IN_PLACE)return dirty;if(RETURN_DOM){if(RETURN_DOM_FRAGMENT)for(returnNode=createDocumentFragment.call(body.ownerDocument);body.firstChild;)returnNode.appendChild(body.firstChild);else returnNode=body;return(ALLOWED_ATTR.shadowroot||ALLOWED_ATTR.shadowrootmode)&&(returnNode=importNode.call(originalDocument,returnNode,!0)),returnNode}let serializedHTML=WHOLE_DOCUMENT?body.outerHTML:body.innerHTML;return WHOLE_DOCUMENT&&ALLOWED_TAGS["!doctype"]&&body.ownerDocument&&body.ownerDocument.doctype&&body.ownerDocument.doctype.name&®ExpTest(DOCTYPE_NAME,body.ownerDocument.doctype.name)&&(serializedHTML="<!DOCTYPE "+body.ownerDocument.doctype.name+">\n"+serializedHTML),SAFE_FOR_TEMPLATES&&arrayForEach([MUSTACHE_EXPR,ERB_EXPR,TMPLIT_EXPR],expr=>{serializedHTML=stringReplace(serializedHTML,expr," ")}),trustedTypesPolicy&&RETURN_TRUSTED_TYPE?trustedTypesPolicy.createHTML(serializedHTML):serializedHTML},DOMPurify.setConfig=function(){let cfg=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};_parseConfig(cfg),SET_CONFIG=!0},DOMPurify.clearConfig=function(){CONFIG=null,SET_CONFIG=!1},DOMPurify.isValidAttribute=function(tag,attr,value){CONFIG||_parseConfig({});const lcTag=transformCaseFunc(tag),lcName=transformCaseFunc(attr);return _isValidAttribute(lcTag,lcName,value)},DOMPurify.addHook=function(entryPoint,hookFunction){"function"!=typeof hookFunction||arrayPush(hooks[entryPoint],hookFunction)},DOMPurify.removeHook=function(entryPoint,hookFunction){if(void 0!==hookFunction){const index=arrayLastIndexOf(hooks[entryPoint],hookFunction);return-1===index?void 0:arraySplice(hooks[entryPoint],index,1)[0]}return arrayPop(hooks[entryPoint])},DOMPurify.removeHooks=function(entryPoint){hooks[entryPoint]=[]},DOMPurify.removeAllHooks=function(){hooks=_createHooksMap()},DOMPurify}var purify=createDOMPurify();function L(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=L();function Z(u){T=u}var C={exec:()=>null};function k(u,e=""){let t="string"==typeof u?u:u.source,n={replace:(r,i)=>{let s="string"==typeof i?i:i.source;return s=s.replace(m.caret,"$1"),t=t.replace(r,s),n},getRegex:()=>new RegExp(t,e)};return n}var me=(()=>{try{return!!/(?<=1)(?<!1)/}catch{return!1}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:u=>new RegExp(`^( {0,3}${u})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}#`),htmlBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}<(?:[a-z].*>|!--)`,"i")},xe=/^(?:[ \t]*(?:\n|$))+/,be=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,I=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Te=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,N=/(?:[*+-]|\d{1,9}[.)])/,re=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,se=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Oe=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),Q=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,we=/^[^\n]+/,F=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,ye=k(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",F).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Pe=k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,N).getRegex(),v="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",j=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,Se=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$))","i").replace("comment",j).replace("tag","address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul").replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ie=k(Q).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag","address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul").getRegex(),$e=k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",ie).getRegex(),U={blockquote:$e,code:be,def:ye,fences:Re,heading:Te,hr:I,html:Se,lheading:se,list:Pe,newline:xe,paragraph:ie,table:C,text:we},te=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3}\t)[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag","address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul").getRegex(),_e={...U,lheading:Oe,table:te,paragraph:k(Q).replace("hr",I).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",te).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag","address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul").getRegex()},Le={...U,html:k(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",j).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:C,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(Q).replace("hr",I).replace("heading",` *#{1,6} *[^ +]`).replace("lheading",se).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Me=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,ze=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,oe=/^( {2,}|\\)\n(?!\s*$)/,Ae=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,D=/[\p{P}\p{S}]/u,K=/[\s\p{P}\p{S}]/u,ae=/[^\s\p{P}\p{S}]/u,Ce=k(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,K).getRegex(),le=/(?!~)[\p{P}\p{S}]/u,Ie=/(?!~)[\s\p{P}\p{S}]/u,Ee=/(?:[^\s\p{P}\p{S}]|~)/u,Be=k(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",me?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),ue=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,qe=k(ue,"u").replace(/punct/g,D).getRegex(),ve=k(ue,"u").replace(/punct/g,le).getRegex(),pe="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",De=k("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)","gu").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),He=k("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)","gu").replace(/notPunctSpace/g,Ee).replace(/punctSpace/g,Ie).replace(/punct/g,le).getRegex(),Ze=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),Ge=k(/\\(punct)/,"gu").replace(/punct/g,D).getRegex(),Ne=k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Qe=k(j).replace("(?:-->|$)","-->").getRegex(),Fe=k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Qe).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),q=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/,je=k(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",q).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ce=k(/^!?\[(label)\]\[(ref)\]/).replace("label",q).replace("ref",F).getRegex(),he=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",F).getRegex(),Ue=k("reflink|nolink(?!\\()","g").replace("reflink",ce).replace("nolink",he).getRegex(),ne=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,W={_backpedal:C,anyPunctuation:Ge,autolink:Ne,blockSkip:Be,br:oe,code:ze,del:C,emStrongLDelim:qe,emStrongRDelimAst:De,emStrongRDelimUnd:Ze,escape:Me,link:je,nolink:he,punctuation:Ce,reflink:ce,reflinkSearch:Ue,tag:Fe,text:Ae,url:C},Ke={...W,link:k(/^!?\[(label)\]\((.*?)\)/).replace("label",q).getRegex(),reflink:k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",q).getRegex()},G$1={...W,emStrongRDelimAst:He,emStrongLDelim:ve,url:k(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ne).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:k(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",ne).getRegex()},We={...G$1,br:k(oe).replace("{2,}","*").getRegex(),text:k(G$1.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},E={normal:U,gfm:_e,pedantic:Le},M={normal:W,gfm:G$1,breaks:We,pedantic:Ke},Xe={"&":"&","<":"<",">":">",'"':""","'":"'"},ke=u=>Xe[u];function w(u,e){if(e){if(m.escapeTest.test(u))return u.replace(m.escapeReplace,ke);}else if(m.escapeTestNoEncode.test(u))return u.replace(m.escapeReplaceNoEncode,ke);return u}function X(u){try{u=encodeURI(u).replace(m.percentDecode,"%")}catch{return null}return u}function J(u,e){let t=u.replace(m.findPipe,(i,s,a)=>{let o=!1,l=s;for(;0<=--l&&"\\"===a[l];)o=!o;return o?"|":" |"}),n=t.split(m.splitPipe),r=0;if(n[0].trim()||n.shift(),0<n.length&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push("");for(;r<n.length;r++)n[r]=n[r].trim().replace(m.slashPipe,"|");return n}function z(u,e,t){let n=u.length;if(0===n)return"";let r=0;for(;r<n;){let i=u.charAt(n-r-1);if(i===e&&!0)r++;else break}return u.slice(0,n-r)}function de(u,e){if(-1===u.indexOf(e[1]))return-1;let t=0;for(let n=0;n<u.length;n++)if("\\"===u[n])n++;else if(u[n]===e[0])t++;else if(u[n]===e[1]&&(t--,0>t))return n;return 0<t?-2:-1}function ge(u,e,t,n,r){let i=e.href,s=e.title||null,a=u[1].replace(r.other.outputLinkReplace,"$1");n.state.inLink=!0;let o={type:"!"===u[0].charAt(0)?"image":"link",raw:t,href:i,title:s,text:a,tokens:n.inlineTokens(a)};return n.state.inLink=!1,o}function Je(u,e,t){let n=u.match(t.other.indentCodeCompensation);if(null===n)return e;let r=n[1];return e.split(` +`).map(i=>{let s=i.match(t.other.beginningSpace);if(null===s)return i;let[a]=s;return a.length>=r.length?i.slice(r.length):i}).join(` +`)}var y=class{options;rules;lexer;constructor(e){this.options=e||T}space(e){let t=this.rules.block.newline.exec(e);if(t&&0<t[0].length)return{type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:z(n,` +`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],r=Je(n,t[3]||"",this.rules);return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:r}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let r=z(n,"#");(this.options.pedantic||!r||this.rules.other.endingSpaceChar.test(r))&&(n=r.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:z(t[0],` +`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=z(t[0],` +`).split(` +`),r="",i="",s=[];for(;0<n.length;){let a=!1,o=[],l;for(l=0;l<n.length;l++)if(this.rules.other.blockquoteStart.test(n[l]))o.push(n[l]),a=!0;else if(!a)o.push(n[l]);else break;n=n.slice(l);let p=o.join(` +`),c=p.replace(this.rules.other.blockquoteSetextReplace,` + $1`).replace(this.rules.other.blockquoteSetextReplace2,"");r=r?`${r} +${p}`:p,i=i?`${i} +${c}`:c;let g=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(c,s,!0),this.lexer.state.top=g,0===n.length)break;let h=s.at(-1);if("code"===h?.type)break;if("blockquote"===h?.type){let R=h,f=R.raw+` +`+n.join(` +`),O=this.blockquote(f);s[s.length-1]=O,r=r.substring(0,r.length-R.raw.length)+O.raw,i=i.substring(0,i.length-R.text.length)+O.text;break}else if("list"===h?.type){let R=h,f=R.raw+` +`+n.join(` +`),O=this.list(f);s[s.length-1]=O,r=r.substring(0,r.length-h.raw.length)+O.raw,i=i.substring(0,i.length-R.raw.length)+O.raw,n=f.substring(s.at(-1).raw.length).split(` +`);continue}}return{type:"blockquote",raw:r,tokens:s,text:i}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),r=1<n.length,i={type:"list",raw:"",ordered:r,start:r?+n.slice(0,-1):"",loose:!1,items:[]};n=r?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=r?n:"[*+-]");for(let s=this.rules.other.listItemRegex(n),a=!1;e;){let l=!1,p="",c="";if(!(t=s.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let g=t[2].split(` +`,1)[0].replace(this.rules.other.listReplaceTabs,O=>" ".repeat(3*O.length)),h=e.split(` +`,1)[0],R=!g.trim(),f=0;if(this.options.pedantic?(f=2,c=g.trimStart()):R?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=4<f?1:f,c=g.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(p+=h+` +`,e=e.substring(h.length+1),l=!0),!l)for(let O=this.rules.other.nextBulletRegex(f),V=this.rules.other.hrRegex(f),Y=this.rules.other.fencesBeginRegex(f),ee=this.rules.other.headingBeginRegex(f),fe=this.rules.other.htmlBeginRegex(f);e;){let H=e.split(` +`,1)[0],A;if(h=H,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting," "),A=h):A=h.replace(this.rules.other.tabCharGlobal," "),Y.test(h)||ee.test(h)||fe.test(h)||O.test(h)||V.test(h))break;if(A.search(this.rules.other.nonSpaceChar)>=f||!h.trim())c+=` +`+A.slice(f);else{if(R||4<=g.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)||Y.test(g)||ee.test(g)||V.test(g))break;c+=` +`+h}R||h.trim()||(R=!0),p+=H+` +`,e=e.substring(H.length+1),g=A.slice(f)}i.loose||(a?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(a=!0)),i.items.push({type:"list_item",raw:p,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),i.raw+=p}let o=i.items.at(-1);if(o)o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,""),"text"===l.tokens[0]?.type||"paragraph"===l.tokens[0]?.type){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,""),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,"");for(let c=this.lexer.inlineQueue.length-1;0<=c;c--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)){this.lexer.inlineQueue[c].src=this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask,"");break}}let p=this.rules.other.listTaskCheckbox.exec(l.raw);if(p){let c={type:"checkbox",raw:p[0]+" ",checked:"[ ]"!==p[0]};l.checked=c.checked,i.loose?l.tokens[0]&&["paragraph","text"].includes(l.tokens[0].type)&&"tokens"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=c.raw+l.tokens[0].raw,l.tokens[0].text=c.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(c)):l.tokens.unshift({type:"paragraph",raw:c.raw,text:c.raw,tokens:[c]}):l.tokens.unshift(c)}}if(!i.loose){let p=l.tokens.filter(g=>"space"===g.type),c=0<p.length&&p.some(g=>this.rules.other.anyLine.test(g.raw));i.loose=c}}if(i.loose)for(let l of i.items){l.loose=!0;for(let p of l.tokens)"text"===p.type&&(p.type="paragraph")}return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:"html",block:!0,raw:t[0],pre:"pre"===t[1]||"script"===t[1]||"style"===t[1],text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),r=t[2]?t[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:n,raw:t[0],href:r,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=J(t[1]),r=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(` +`):[],s={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===r.length){for(let a of r)this.rules.other.tableAlignRight.test(a)?s.align.push("right"):this.rules.other.tableAlignCenter.test(a)?s.align.push("center"):this.rules.other.tableAlignLeft.test(a)?s.align.push("left"):s.align.push(null);for(let a=0;a<n.length;a++)s.header.push({text:n[a],tokens:this.lexer.inline(n[a]),header:!0,align:s.align[a]});for(let a of i)s.rows.push(J(a,s.header.length).map((o,l)=>({text:o,tokens:this.lexer.inline(o),header:!1,align:s.align[l]})));return s}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=` +`===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let s=z(n.slice(0,-1),"\\");if(0==(n.length-s.length)%2)return}else{let s=de(t[2],"()");if(-2===s)return;if(-1<s){let o=(0===t[0].indexOf("!")?5:4)+t[1].length+s;t[2]=t[2].substring(0,s),t[0]=t[0].substring(0,o).trim(),t[3]=""}}let r=t[2],i="";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(r);s&&(r=s[1],i=s[3])}else i=t[3]?t[3].slice(1,-1):"";return r=r.trim(),this.rules.other.startAngleBracket.test(r)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?r=r.slice(1):r=r.slice(1,-1)),ge(t,{href:r&&r.replace(this.rules.inline.anyPunctuation,"$1"),title:i&&i.replace(this.rules.inline.anyPunctuation,"$1")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let r=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),i=t[r.toLowerCase()];if(!i){let s=n[0].charAt(0);return{type:"text",raw:s,text:s}}return ge(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){var _Mathmin=Math.min;let r=this.rules.inline.emStrongLDelim.exec(e);if(!(!r||r[3]&&n.match(this.rules.other.unicodeAlphaNumeric))&&(!(r[1]||r[2]||"")||!n||this.rules.inline.punctuation.exec(n))){let s=[...r[0]].length-1,l=s,p=0,c="*"===r[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd,a,o;for(c.lastIndex=0,t=t.slice(-1*e.length+s);null!=(r=c.exec(t));){if(a=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!a)continue;if(o=[...a].length,r[3]||r[4]){l+=o;continue}else if((r[5]||r[6])&&s%3&&!((s+o)%3)){p+=o;continue}if(l-=o,0<l)continue;o=_Mathmin(o,o+l+p);let g=[...r[0]][0].length,h=e.slice(0,s+r.index+g+o);if(_Mathmin(s,o)%2){let f=h.slice(1,-1);return{type:"em",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return{type:"strong",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal," "),r=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return r&&i&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,r;return"@"===t[2]?(n=t[1],r="mailto:"+n):(n=t[1],r=n),{type:"link",raw:t[0],text:n,href:r,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,r;if("@"===t[2])n=t[0],r="mailto:"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(i!==t[0]);n=t[0],r="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:n,href:r,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:n}}}},x=class u{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new y,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:E.normal,inline:M.normal};this.options.pedantic?(t.block=E.pedantic,t.inline=M.pedantic):this.options.gfm&&(t.block=E.gfm,t.inline=this.options.breaks?M.breaks:M.gfm),this.tokenizer.rules=t}static get rules(){return{block:E,inline:M}}static lex(e,t){return new u(t).lex(e)}static lexInline(e,t){return new u(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,` +`),this.blockTokens(e,this.tokens);for(let t=0,n;t<this.inlineQueue.length;t++)n=this.inlineQueue[t],this.inlineTokens(n.src,n.tokens);return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=!1){for(this.options.pedantic&&(e=e.replace(m.tabCharGlobal," ").replace(m.spaceLine,""));e;){let r;if(this.options.extensions?.block?.some(s=>!!(r=s.call({lexer:this},e,t))&&(e=e.substring(r.raw.length),t.push(r),!0)))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let s=t.at(-1);1===r.raw.length&&void 0!==s?s.raw+=` +`:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let s=t.at(-1);"paragraph"===s?.type||"text"===s?.type?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(r=this.tokenizer.fences(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.heading(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.hr(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.blockquote(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.list(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.html(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.def(e)){e=e.substring(r.raw.length);let s=t.at(-1);"paragraph"===s?.type||"text"===s?.type?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.raw,this.inlineQueue.at(-1).src=s.text):this.tokens.links[r.tag]||(this.tokens.links[r.tag]={href:r.href,title:r.title},t.push(r));continue}if(r=this.tokenizer.table(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.lheading(e)){e=e.substring(r.raw.length),t.push(r);continue}let i=e;if(this.options.extensions?.startBlock){let s=1/0,a=e.slice(1),o;this.options.extensions.startBlock.forEach(l=>{o=l.call({lexer:this},a),"number"==typeof o&&0<=o&&(s=Math.min(s,o))}),s<1/0&&0<=s&&(i=e.substring(0,s+1))}if(this.state.top&&(r=this.tokenizer.paragraph(i))){let s=t.at(-1);n&&"paragraph"===s?.type?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let s=t.at(-1);"text"===s?.type?(s.raw+=(s.raw.endsWith(` +`)?"":` +`)+r.raw,s.text+=` +`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(e){let s="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(s);break}else throw new Error(s)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,r=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(0<o.length)for(;null!=(r=this.tokenizer.rules.inline.reflinkSearch.exec(n));)o.includes(r[0].slice(r[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(r=this.tokenizer.rules.inline.anyPunctuation.exec(n));)n=n.slice(0,r.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(let i;null!=(r=this.tokenizer.rules.inline.blockSkip.exec(n));)i=r[2]?r[2].length:0,n=n.slice(0,r.index+i)+"["+"a".repeat(r[0].length-i-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;for(let s=!1,a="";e;){s||(a=""),s=!1;let o;if(this.options.extensions?.inline?.some(p=>!!(o=p.call({lexer:this},e,t))&&(e=e.substring(o.raw.length),t.push(o),!0)))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let p=t.at(-1);"text"===o.type&&"text"===p?.type?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,a)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let l=e;if(this.options.extensions?.startInline){let p=1/0,c=e.slice(1),g;this.options.extensions.startInline.forEach(h=>{g=h.call({lexer:this},c),"number"==typeof g&&0<=g&&(p=Math.min(p,g))}),p<1/0&&0<=p&&(l=e.substring(0,p+1))}if(o=this.tokenizer.inlineText(l)){e=e.substring(o.raw.length),"_"!==o.raw.slice(-1)&&(a=o.raw.slice(-1)),s=!0;let p=t.at(-1);"text"===p?.type?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(e){let p="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(p);break}else throw new Error(p)}}return t}},P=class{options;parser;constructor(e){this.options=e||T}space(e){return""}code({text:e,lang:t,escaped:n}){let r=(t||"").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,"")+` +`;return r?"<pre><code class=\"language-"+w(r)+"\">"+(n?i:w(i,!0))+`</code></pre> +`:"<pre><code>"+(n?i:w(i,!0))+`</code></pre> +`}blockquote({tokens:e}){return`<blockquote> +${this.parser.parse(e)}</blockquote> +`}html({text:e}){return e}def(e){return""}heading({tokens:e,depth:t}){return`<h${t}>${this.parser.parseInline(e)}</h${t}> +`}hr(e){return`<hr> +`}list(e){let t=e.ordered,n=e.start,r="";for(let a=0,o;a<e.items.length;a++)o=e.items[a],r+=this.listitem(o);let i=t?"ol":"ul",s=t&&1!==n?" start=\""+n+"\"":"";return"<"+i+s+`> +`+r+"</"+i+`> +`}listitem(e){return`<li>${this.parser.parse(e.tokens)}</li> +`}checkbox({checked:e}){return"<input "+(e?"checked=\"\" ":"")+"disabled=\"\" type=\"checkbox\"> "}paragraph({tokens:e}){return`<p>${this.parser.parseInline(e)}</p> +`}table(e){let t="",n="";for(let i=0;i<e.header.length;i++)n+=this.tablecell(e.header[i]);t+=this.tablerow({text:n});let r="";for(let i=0,s;i<e.rows.length;i++){s=e.rows[i],n="";for(let a=0;a<s.length;a++)n+=this.tablecell(s[a]);r+=this.tablerow({text:n})}return r&&(r=`<tbody>${r}</tbody>`),`<table> +<thead> +`+t+`</thead> +`+r+`</table> +`}tablerow({text:e}){return`<tr> +${e}</tr> +`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}> +`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${w(e,!0)}</code>`}br(e){return"<br>"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let r=this.parser.parseInline(n),i=X(e);if(null===i)return r;e=i;let s="<a href=\""+e+"\"";return t&&(s+=" title=\""+w(t)+"\""),s+=">"+r+"</a>",s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=X(e);if(null===i)return w(n);e=i;let s=`<img src="${e}" alt="${n}"`;return t&&(s+=` title="${w(t)}"`),s+=">",s}text(e){return"tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:w(e.text)}},$=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return""+e}image({text:e}){return""+e}br(){return""}checkbox({raw:e}){return e}},b=class u{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new P,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new $}static parse(e,t){return new u(t).parse(e)}static parseInline(e,t){return new u(t).parseInline(e)}parse(e){let t="";for(let n=0,r;n<e.length;n++){if(r=e[n],this.options.extensions?.renderers?.[r.type]){let s=r,a=this.options.extensions.renderers[s.type].call({parser:this},s);if(!1!==a||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(s.type)){t+=a||"";continue}}let i=r;switch(i.type){case"space":{t+=this.renderer.space(i);break}case"hr":{t+=this.renderer.hr(i);break}case"heading":{t+=this.renderer.heading(i);break}case"code":{t+=this.renderer.code(i);break}case"table":{t+=this.renderer.table(i);break}case"blockquote":{t+=this.renderer.blockquote(i);break}case"list":{t+=this.renderer.list(i);break}case"checkbox":{t+=this.renderer.checkbox(i);break}case"html":{t+=this.renderer.html(i);break}case"def":{t+=this.renderer.def(i);break}case"paragraph":{t+=this.renderer.paragraph(i);break}case"text":{t+=this.renderer.text(i);break}default:{let s="Token with \""+i.type+"\" type was not found.";if(this.options.silent)return console.error(s),"";throw new Error(s)}}}return t}parseInline(e,t=this.renderer){let n="";for(let r=0,i;r<e.length;r++){if(i=e[r],this.options.extensions?.renderers?.[i.type]){let a=this.options.extensions.renderers[i.type].call({parser:this},i);if(!1!==a||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(i.type)){n+=a||"";continue}}let s=i;switch(s.type){case"escape":{n+=t.text(s);break}case"html":{n+=t.html(s);break}case"link":{n+=t.link(s);break}case"image":{n+=t.image(s);break}case"checkbox":{n+=t.checkbox(s);break}case"strong":{n+=t.strong(s);break}case"em":{n+=t.em(s);break}case"codespan":{n+=t.codespan(s);break}case"br":{n+=t.br(s);break}case"del":{n+=t.del(s);break}case"text":{n+=t.text(s);break}default:{let a="Token with \""+s.type+"\" type was not found.";if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return n}},S=class{options;block;constructor(e){this.options=e||T}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens","emStrongMask"]);static passThroughHooksRespectAsync=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?x.lex:x.lexInline}provideParser(){return this.block?b.parse:b.parseInline}},B=class{defaults=L();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=b;Renderer=P;TextRenderer=$;Lexer=x;Tokenizer=y;Hooks=S;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(let r of e)switch(n=n.concat(t.call(this,r)),r.type){case"table":{let i=r;for(let s of i.header)n=n.concat(this.walkTokens(s.tokens,t));for(let s of i.rows)for(let a of s)n=n.concat(this.walkTokens(a.tokens,t));break}case"list":{let i=r;n=n.concat(this.walkTokens(i.items,t));break}default:{let i=r;this.defaults.extensions?.childTokens?.[i.type]?this.defaults.extensions.childTokens[i.type].forEach(s=>{let a=i[s].flat(1/0);n=n.concat(this.walkTokens(a,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let s=t.renderers[i.name];t.renderers[i.name]=s?function(...a){let o=i.renderer.apply(this,a);return!1===o&&(o=s.apply(this,a)),o}:i.renderer}if("tokenizer"in i){if(!i.level||"block"!==i.level&&"inline"!==i.level)throw new Error("extension level must be 'block' or 'inline'");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&("block"===i.level?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:"inline"===i.level&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new P(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if(["options","parser"].includes(s))continue;let a=s,o=n.renderer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return!1===c&&(c=l.apply(i,p)),c||""}}r.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new y(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if(["options","rules","lexer"].includes(s))continue;let a=s,o=n.tokenizer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return!1===c&&(c=l.apply(i,p)),c}}r.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new S;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if(["options","block"].includes(s))continue;let a=s,o=n.hooks[a],l=i[a];i[a]=S.passThroughHooks.has(s)?p=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(s))return(async()=>{let g=await o.call(i,p);return l.call(i,g)})();let c=o.call(i,p);return l.call(i,c)}:(...p)=>{if(this.defaults.async)return(async()=>{let g=await o.apply(i,p);return!1===g&&(g=await l.apply(i,p)),g})();let c=o.apply(i,p);return!1===c&&(c=l.apply(i,p)),c}}r.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(a){let o=[];return o.push(s.call(this,a)),i&&(o=o.concat(i.call(this,a))),o}}this.defaults={...this.defaults,...r}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,r)=>{let i={...r},s={...this.defaults,...i},a=this.onError(!!s.silent,!!s.async);if(!0===this.defaults.async&&!1===i.async)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if("u"<typeof n||null===n)return a(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return(async()=>{let o=s.hooks?await s.hooks.preprocess(n):n,p=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(o,s),c=s.hooks?await s.hooks.processAllTokens(p):p;s.walkTokens&&(await Promise.all(this.walkTokens(c,s.walkTokens)));let h=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(c,s);return s.hooks?await s.hooks.postprocess(h):h})().catch(a);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let c=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(c=s.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=` +Please report this to https://github.com/markedjs/marked.`,e){let r="<p>An error occurred:</p><pre>"+w(n.message+"",!0)+"</pre>";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}},_=new B;function d(u,e){return _.parse(u,e)}d.options=d.setOptions=function(u){return _.setOptions(u),d.defaults=_.defaults,Z(d.defaults),d},d.getDefaults=L,d.defaults=T,d.use=function(...u){return _.use(...u),d.defaults=_.defaults,Z(d.defaults),d},d.walkTokens=function(u,e){return _.walkTokens(u,e)},d.parseInline=_.parseInline,d.Parser=b,d.parser=b.parse,d.Renderer=P,d.TextRenderer=$,d.Lexer=x,d.lexer=x.lex,d.Tokenizer=y,d.Hooks=S,d.parse=d,d.options,d.setOptions,d.use,d.walkTokens,d.parseInline,b.parse,x.lex;class ExternalReviewer{static get(repo){return"mozilla/standards-positions"===repo?new ExternalReviewer("https://avatars.githubusercontent.com/u/131524?s=48&v=4",{"position: defer":{description:"Defer",variant:"neutral"},"position: negative":{description:"Negative",variant:"danger"},"position: neutral":{description:"Neutral",variant:"neutral"},"position: positive":{description:"Positive",variant:"success"},"position: under consideration":{description:"Under Consideration",variant:"neutral"}}):"WebKit/standards-positions"===repo?new ExternalReviewer("https://avatars.githubusercontent.com/u/6458?s=48&v=4",{"position: oppose":{description:"Oppose",variant:"danger"},"position: neutral":{description:"Neutral",variant:"neutral"},"position: support":{description:"Support",variant:"success"}}):"w3ctag/design-reviews"===repo?new ExternalReviewer("https://avatars.githubusercontent.com/u/3874462?s=48&v=4",{"Resolution: ambivalent":{description:"Ambivalent",variant:"neutral"},"Resolution: decline":{description:"Decline",variant:"neutral"},"Resolution: lack of consensus":{description:"Lack of Consensus",variant:"neutral"},"Resolution: object":{description:"Object",variant:"danger"},"Resolution: out of scope":{description:"Out of Scope",variant:"neutral"},"Resolution: overtaken":{description:"Overtaken",variant:"warning"},"Resolution: satisfied with concerns":{description:"Satisfied with Concerns",variant:"warning"},"Resolution: satisfied":{description:"Satisfied",variant:"success"},"Resolution: timed out":{description:"Timed Out",variant:"warning"},"Resolution: too early":{description:"Too Early",variant:"warning"},"Resolution: unsatisfied":{description:"Unsatisfied",variant:"danger"},"Resolution: validated":{description:"Early Review Validated",variant:"warning"},"Resolution: withdrawn":{description:"Withdrawn",variant:"warning"}}):void 0}label(name){return this._labels[name]}constructor(icon,labels){this.icon=icon,this._labels=labels}}var __decorate$19=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const LINK_TYPE_CHROMIUM_BUG="chromium_bug",LINK_TYPE_GITHUB_ISSUE="github_issue",LINK_TYPE_GITHUB_PULL_REQUEST="github_pull_request",LINK_TYPE_GITHUB_MARKDOWN="github_markdown",LINK_TYPE_MDN_DOCS="mdn_docs",LINK_TYPE_GOOGLE_DOCS="google_docs",LINK_TYPE_MOZILLA_BUG="mozilla_bug",LINK_TYPE_WEBKIT_BUG="webkit_bug",LINK_TYPE_SPECS="specs";function _formatLongText(text,maxLength=50){return text.length>maxLength?text.substring(0,35)+"..."+text.substring(text.length-15,text.length):text}const _dateTimeFormat=new Intl.DateTimeFormat("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"numeric"});function enhanceChromeStatusLink(featureLink,text){function _formatTimestamp(timestamp){return _dateTimeFormat.format(new Date(1e3*timestamp))}function renderTooltipContent(){return x$1`<div class="tooltip"> + ${summary&&x$1` + <div> + <strong>Summary:</strong> + <span>${summary}</span> + </div> + `} + ${openedTimestamp&&x$1` + <div> + <strong>Opened:</strong> + <span>${_formatTimestamp(openedTimestamp)}</span> + </div> + `} + ${closedTimestamp&&x$1` + <div> + <strong>Closed:</strong> + <span>${_formatTimestamp(closedTimestamp)}</span> + </div> + `} + ${reporterRef&&x$1` + <div> + <strong>Reporter:</strong> + <span>${reporterRef.displayName}</span> + </div> + `} + ${ownerRef&&x$1` + <div> + <strong>Owner:</strong> + <span>${ownerRef.displayName}</span> + </div> + `} + </div>`}const information=featureLink.information,summary=information.summary,statusRef=information.statusRef,reporterRef=information.reporterRef,ownerRef=information.ownerRef,openedTimestamp=information.openedTimestamp,closedTimestamp=information.closedTimestamp;return text||(text=summary),x$1`<a + href="${featureLink.url}" + target="_blank" + rel="noopener noreferrer" + > + <sl-tooltip style="--sl-tooltip-arrow-size: 0;--max-width: 50vw;"> + <div slot="content">${renderTooltipContent()}</div> + <sl-tag> + <img + src="https://bugs.chromium.org/static/images/monorail.ico" + alt="icon" + class="icon" + /> + <sl-badge + size="small" + variant="${statusRef.meansOpen?"success":"neutral"}" + >${statusRef.status}</sl-badge + > + ${_formatLongText(text)} + </sl-tag> + </sl-tooltip> + </a>`}function enhanceGithubIssueLink(featureLink,text){function _formatISOTime(dateString){return _dateTimeFormat.format(new Date(dateString))}function renderTooltipContent(){return x$1`<div class="tooltip"> + ${title&&x$1` + <div> + <strong>Title:</strong> + <span>${title}</span> + </div> + `} + ${repo&&x$1` + <div> + <strong>Repo:</strong> + <span>${repo}</span> + </div> + `} + ${type&&x$1` + <div> + <strong>Type:</strong> + <span>${type}</span> + </div> + `} + ${createdAt&&x$1` + <div> + <strong>Opened:</strong> + <span>${_formatISOTime(createdAt)}</span> + </div> + `} + ${updatedAt&&x$1` + <div> + <strong>Updated:</strong> + <span>${_formatISOTime(updatedAt)}</span> + </div> + `} + ${closedAt&&x$1` + <div> + <strong>Closed:</strong> + <span>${_formatISOTime(closedAt)}</span> + </div> + `} + ${assignee&&x$1` + <div> + <strong>Assignee:</strong> + <span>${assignee}</span> + </div> + `} + ${owner&&x$1` + <div> + <strong>Owner:</strong> + <span>${owner}</span> + </div> + `} + </div>`}const information=featureLink.information,assignee=information.assignee_login,createdAt=new Date(information.created_at),closedAt=information.closed_at,updatedAt=information.updated_at,state=information.state,title=information.title,owner=information.user_login,number=information.number,repo=information.url.split("/").slice(4,6).join("/"),typePath=featureLink.url.split("/").slice(-2)[0],type="issues"===typePath?"Issue":"pull"===typePath?"Pull Request":typePath,externalReviewer=ExternalReviewer.get(repo);let stateDescription=x$1``,stateVariant;if(externalReviewer)for(const label of information.labels){const labelInfo=externalReviewer.label(label);if(labelInfo){({description:stateDescription,variant:stateVariant}=labelInfo);break}}if(void 0===stateVariant)if("open"===state){const age=Date.now()-createdAt.getTime();stateDescription=x$1`Opened + <sl-relative-time date=${createdAt.toISOString()} + >on ${_dateTimeFormat.format(createdAt)}</sl-relative-time + >`;const week=604800000;stateVariant="success",externalReviewer&&(2419200000>age?stateVariant="warning":stateVariant="neutral")}else console.assert("closed"===state),stateDescription="Closed",stateVariant="neutral";return text||(text=title),x$1`<a + href="${featureLink.url}" + target="_blank" + rel="noopener noreferrer" + > + <sl-tooltip style="--sl-tooltip-arrow-size: 0;--max-width: 50vw;"> + <div slot="content">${renderTooltipContent()}</div> + <sl-tag> + <img + src=${externalReviewer?.icon??"https://docs.github.com/assets/cb-600/images/site/favicon.png"} + alt="icon" + class="icon" + /> + <sl-badge size="small" variant=${stateVariant} + >${stateDescription}</sl-badge + > + ${_formatLongText(`#${number} `+text)} + </sl-tag> + </sl-tooltip> + </a>`}function enhanceGithubMarkdownLink(featureLink,text){function renderTooltipContent(){return x$1`<div class="tooltip"> + ${title&&x$1` + <div> + <strong>Title:</strong> + <span>${title}</span> + </div> + `} + ${path&&x$1` + <div> + <strong>File:</strong> + <span>${path}</span> + </div> + `} + ${size&&x$1` + <div> + <strong>Size:</strong> + <span>${readableSize}</span> + </div> + `} + </div>`}const information=featureLink.information,path=information.path,title=information._parsed_title,size=information.size,readableSize=(size/1024).toFixed(2)+" KB";return text||(text=title),x$1`<a + href="${featureLink.url}" + target="_blank" + rel="noopener noreferrer" + > + <sl-tooltip style="--sl-tooltip-arrow-size: 0;--max-width: 50vw;"> + <div slot="content">${renderTooltipContent()}</div> + <sl-tag> + <img + src="https://docs.github.com/assets/cb-600/images/site/favicon.png" + alt="icon" + class="icon" + /> + ${_formatLongText("Markdown: "+text)} + </sl-tag> + </sl-tooltip> + </a>`}function _enhanceLinkWithTitleAndDescription(featureLink,iconUrl){function renderTooltipContent(){return x$1`<div class="tooltip"> + ${title&&x$1` + <div> + <strong>Title:</strong> + <span>${title}</span> + </div> + `} + ${description&&x$1` + <div> + <strong>Description:</strong> + <span>${description}</span> + </div> + `} + </div>`}const information=featureLink.information,title=information.title,description=information.description;return x$1`<a + href="${featureLink.url}" + target="_blank" + rel="noopener noreferrer" + > + <sl-tooltip style="--sl-tooltip-arrow-size: 0;--max-width: 50vw;"> + <div slot="content">${renderTooltipContent()}</div> + <sl-tag> + <img src="${iconUrl}" alt="icon" class="icon" /> + ${_formatLongText(title)} + </sl-tag> + </sl-tooltip> + </a>`}function enhanceSpecsLink(featureLink){function renderTooltipContent(){return x$1`<div class="tooltip"> + ${title&&x$1` + <div> + <strong>Title:</strong> + <span>${title}</span> + </div> + `} + ${description&&x$1` + <div> + <strong>Description:</strong> + <span>${description}</span> + </div> + `} + ${hashtag&&x$1` + <div> + <strong>Hashtag:</strong> + <span>#${hashtag}</span> + </div> + `} + </div>`}const url=featureLink.url,iconUrl=`https://www.google.com/s2/favicons?domain_url=${url}`,hashtag=url.split("#")[1],information=featureLink.information,title=information.title,description=information.description;return x$1`<a + href="${featureLink.url}" + target="_blank" + rel="noopener noreferrer" + > + <sl-tooltip style="--sl-tooltip-arrow-size: 0;--max-width: 50vw;"> + <div slot="content">${renderTooltipContent()}</div> + <sl-tag> + <img src="${iconUrl}" alt="icon" class="icon" /> + Spec: ${_formatLongText(title)} + </sl-tag> + </sl-tooltip> + </a>`}function enhanceMDNDocsLink(featureLink){return _enhanceLinkWithTitleAndDescription(featureLink,"https://developer.mozilla.org/favicon-48x48.png")}function enhanceMozillaBugLink(featureLink){return _enhanceLinkWithTitleAndDescription(featureLink,"https://bugzilla.mozilla.org/favicon.ico")}function enhanceWebKitBugLink(featureLink){return _enhanceLinkWithTitleAndDescription(featureLink,"https://bugs.webkit.org/images/favicon.ico")}function enhanceGoogleDocsLink(featureLink){const url=featureLink.url,type=url.split("/")[3];let iconUrl="https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico";return"spreadsheets"===type?iconUrl="https://ssl.gstatic.com/docs/spreadsheets/favicon3.ico":"presentation"===type?iconUrl="https://ssl.gstatic.com/docs/presentations/images/favicon5.ico":"forms"===type&&(iconUrl="https://ssl.gstatic.com/docs/spreadsheets/forms/favicon_qp2.png"),_enhanceLinkWithTitleAndDescription(featureLink,iconUrl)}let ChromedashLink=class ChromedashLink extends i$4{constructor(){super(...arguments),this.showContentAsLabel=!1,this.class="",this.featureLinks=[],this.ignoreHttpErrorCodes=[],this.alwaysInTag=!1}static{this.styles=[...SHARED_STYLES,i$7` + :host { + display: inline; + white-space: normal; + line-break: anywhere; + color: var(--default-font-color); + } + + a:hover { + text-decoration: none; + } + + sl-badge::part(base) { + display: inline; + padding: 0 4px; + border-width: 0; + text-transform: capitalize; + font-weight: 400; + } + + sl-tag::part(base) { + vertical-align: middle; + height: 18px; + background-color: rgb(232, 234, 237); + color: var(--default-font-color); + border: none; + border-radius: 500px; + display: inline-flex; + align-items: center; + column-gap: 0.3em; + padding: 1px 5px; + margin: 1px 0; + } + + sl-tag::part(base):hover { + background-color: rgb(209, 211, 213); + } + + sl-relative-time { + margin: 0; + } + + .icon { + display: block; + width: 12px; + height: 12px; + } + + .tooltip { + display: flex; + flex-direction: column; + row-gap: 0.5em; + } + `]}willUpdate(changedProperties){(changedProperties.has("href")||changedProperties.has("featureLinks"))&&(this._featureLink=this.featureLinks.find(fe=>fe.url===this.href))}fallback(){const slot=x$1`<slot>${this.href}</slot>`;return x$1`<a + href=${o$6(this.href)} + target="_blank" + rel="noopener noreferrer" + class=${this.class} + >${this.alwaysInTag?x$1`<sl-tag>${slot}</sl-tag>`:slot}</a + >`}withLabel(link){return this.showContentAsLabel?x$1`<slot></slot>: ${link}`:link}render(){if(!this.href)return console.error("Missing [href] attribute in",this),x$1`<slot></slot>`;const featureLink=this._featureLink;if(!featureLink)return this.fallback();if(!featureLink.information)return featureLink.http_error_code&&!this.ignoreHttpErrorCodes.includes(featureLink.http_error_code)?x$1`<sl-tag> + <sl-icon library="material" name="link"></sl-icon> + <sl-badge + size="small" + variant="${500<=featureLink.http_error_code?"danger":"warning"}" + > + ${featureLink.http_error_code} + </sl-badge> + ${this.fallback()} + </sl-tag>`:this.fallback();try{switch(featureLink.type){case LINK_TYPE_CHROMIUM_BUG:return this.withLabel(enhanceChromeStatusLink(featureLink));case LINK_TYPE_GITHUB_ISSUE:return this.withLabel(enhanceGithubIssueLink(featureLink));case LINK_TYPE_GITHUB_PULL_REQUEST:return this.withLabel(enhanceGithubIssueLink(featureLink));case LINK_TYPE_GITHUB_MARKDOWN:return this.withLabel(enhanceGithubMarkdownLink(featureLink));case LINK_TYPE_MDN_DOCS:return this.withLabel(enhanceMDNDocsLink(featureLink));case LINK_TYPE_GOOGLE_DOCS:return this.withLabel(enhanceGoogleDocsLink(featureLink));case LINK_TYPE_MOZILLA_BUG:return this.withLabel(enhanceMozillaBugLink(featureLink));case LINK_TYPE_WEBKIT_BUG:return this.withLabel(enhanceWebKitBugLink(featureLink));case LINK_TYPE_SPECS:return this.withLabel(enhanceSpecsLink(featureLink));default:return this.fallback()}}catch(e){return console.log("feature link render error:",this,e),this.fallback()}}};__decorate$19([n$5({type:String})],ChromedashLink.prototype,"href",void 0),__decorate$19([n$5({type:Boolean})],ChromedashLink.prototype,"showContentAsLabel",void 0),__decorate$19([n$5({type:String})],ChromedashLink.prototype,"class",void 0),__decorate$19([n$5({type:Array})],ChromedashLink.prototype,"featureLinks",void 0),__decorate$19([n$5({type:Array})],ChromedashLink.prototype,"ignoreHttpErrorCodes",void 0),__decorate$19([n$5({type:Boolean})],ChromedashLink.prototype,"alwaysInTag",void 0),__decorate$19([r$6()],ChromedashLink.prototype,"_featureLink",void 0),ChromedashLink=__decorate$19([t$3("chromedash-link")],ChromedashLink);function enhanceUrl(url,featureLinks=[],text){return x$1`<chromedash-link href=${url} .featureLinks=${featureLinks} + >${url}</chromedash-link + >`}function enhanceAutolink(part,featureLinks){return x$1`<chromedash-link href=${part.href} .featureLinks=${featureLinks} .ignoreHttpErrorCodes=${[404]}>${part.content}</chromedash-link>`}const CRBUG_DEFAULT_PROJECT="chromium",CRBUG_URL="https://bugs.chromium.org",ISSUE_TRACKER_RE=/(\b(issues?|bugs?)[ \t]*(:|=|\b)|\bfixed[ \t]*:)([ \t]*((\b[-a-z0-9]+)[:\#])?(\#?)(\d+)\b(,?[ \t]*(and|or)?)?)+/gi,PROJECT_LOCALID_RE=/((\b(issue|bug)[ \t]*(:|=)?[ \t]*|\bfixed[ \t]*:[ \t]*)?((\b[-a-z0-9]+)[:\#])?(\#?)(\d+))/gi,PROJECT_COMMENT_BUG_RE=/(((\b(issue|bug)[ \t]*(:|=)?[ \t]*)(\#?)(\d+)[ \t*])?((\b((comment)[ \t]*(:|=)?[ \t]*(\#?))|(\B((\#))(c)))(\d+)))/gi,PROJECT_LOCALID_RE_PROJECT_GROUP=6,PROJECT_LOCALID_RE_ID_GROUP=8,SHORT_LINK_RE=/(^|[^-\/._])\b(https?:\/\/|ftp:\/\/|mailto:)?(go|g|shortn|who|teams)\/([^\s<]+)/gi,NUMERIC_SHORT_LINK_RE=/(^|[^-\/._])\b(https?:\/\/|ftp:\/\/)?(b|t|o|omg|cl|cr|fxr|fxrev|fxb|tqr)\/([0-9]+)/gi,IMPLIED_LINK_RE=/(?!@)(^|[^-\/._])\b[a-z]((-|\.)?[a-z0-9])+\.(com|net|org|edu|dev)\b(\/[^\s<]*)?/gi,IS_LINK_RE=/()\b(https?:\/\/|ftp:\/\/|mailto:)([^\s<]+)/gi,LINK_TRAILING_CHARS=[[null,":"],[null,"."],[null,","],[null,">"],["(",")"],["[","]"],["{","}"],["'","'"],["\"","\""]],GOOG_SHORT_LINK_RE=/^(b|t|o|omg|cl|cr|go|g|shortn|who|teams|fxr|fxrev|fxb|tqr)\/.*/gi,Components=new Map;Components.set("00-commentbug",{refRegs:[PROJECT_COMMENT_BUG_RE],replacer:replaceCommentBugRef}),Components.set("02-full-urls",{refRegs:[IS_LINK_RE],replacer:replaceLinkRef}),Components.set("04-tracker-regular",{refRegs:[ISSUE_TRACKER_RE],replacer:replaceTrackerIssueRef}),Components.set("05-linkify-shorthand",{refRegs:[SHORT_LINK_RE,NUMERIC_SHORT_LINK_RE,IMPLIED_LINK_RE],replacer:replaceLinkRef});function replaceIssueRef(stringMatch,projectName,localId,commentId){return createIssueRefRun(projectName,localId,stringMatch,commentId)}function replaceTrackerIssueRef(match,currentProjectName=CRBUG_DEFAULT_PROJECT){const issueRefRE=PROJECT_LOCALID_RE,commentId="",textRuns=[];let pos=0,refMatch;for(;null!==(refMatch=issueRefRE.exec(match[0]));)refMatch.index>pos&&textRuns.push({content:match[0].slice(pos,refMatch.index)}),refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP]&&(currentProjectName=refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP]),textRuns.push(replaceIssueRef(refMatch[0],currentProjectName,refMatch[PROJECT_LOCALID_RE_ID_GROUP],commentId)),pos=refMatch.index+refMatch[0].length;return""!==match[0].slice(pos)&&textRuns.push({content:match[0].slice(pos)}),textRuns}function replaceCommentBugRef(match){let textRun;const issueNum=match[7],commentNum=match[18];if(issueNum&&commentNum){const href=`${CRBUG_URL}/p/${CRBUG_DEFAULT_PROJECT}/issues/detail?id=${issueNum}#c${commentNum}`;textRun={content:match[0],tag:"a",href}}else if(commentNum){const href=`${CRBUG_URL}/p/${CRBUG_DEFAULT_PROJECT}/issues/detail#c${commentNum}`;textRun={content:match[0],tag:"a",href}}else textRun={content:match[0]};return[textRun]}function replaceLinkRef(match){const textRuns=[];let content=match[0],trailing="";match[1]&&(textRuns.push({content:match[1]}),content=content.slice(match[1].length)),LINK_TRAILING_CHARS.forEach(([begin,end])=>{!content.endsWith(end)||begin&&content.slice(0,-end.length).includes(begin)||(trailing=end+trailing,content=content.slice(0,-end.length))});let href=content;const lowerHref=href.toLowerCase();return lowerHref.startsWith("http")||lowerHref.startsWith("ftp")||lowerHref.startsWith("mailto")||(href=GOOG_SHORT_LINK_RE.test(lowerHref)?"http://"+href:"https://"+href,GOOG_SHORT_LINK_RE.lastIndex=0),textRuns.push({content:content,tag:"a",href:href}),trailing.length&&textRuns.push({content:trailing}),textRuns}function createIssueRefRun(projectName,localId,content,commentId){return{tag:"a",content:content,href:`${CRBUG_URL}/p/${projectName}/issues/detail?id=${localId}${commentId}`}}function markupAutolinks(plainString,featureLinks=[]){plainString=plainString||"";const chunks=[plainString.trim()],textRuns=[];chunks.filter(Boolean).forEach(chunk=>{textRuns.push(...autolinkChunk(chunk))});const result=textRuns.map(part=>"a"===part.tag?enhanceAutolink(part,featureLinks):x$1`${part.content}`);return result}function autolinkChunk(chunk){let textRuns=[{content:chunk}];return Components.forEach(({refRegs,replacer})=>{refRegs.forEach(re=>{textRuns=applyLinks(textRuns,replacer,re)})}),textRuns}function applyLinks(textRuns,replacer,re){const resultRuns=[];return textRuns.forEach(textRun=>{if(textRun.tag)resultRuns.push(textRun);else{const content=textRun.content;let pos=0,match;for(;null!==(match=re.exec(content));)match.index>pos&&resultRuns.push({content:content.slice(pos,match.index)}),resultRuns.push(...replacer(match)),pos=match.index+match[0].length;""!==content.slice(pos)&&resultRuns.push({content:content.slice(pos)})}}),resultRuns}const FEATURE_CATEGORIES={WEBCOMPONENTS:[1,"Web Components"],MISC:[2,"Miscellaneous"],SECURITY:[3,"Security"],MULTIMEDIA:[4,"Multimedia"],DOM:[5,"DOM"],FILE:[6,"File APIs"],OFFLINE:[7,"Offline / Storage"],DEVICE:[8,"Device"],COMMUNICATION:[9,"Realtime / Communication"],JAVASCRIPT:[10,"JavaScript"],NETWORKING:[11,"Network / Connectivity"],INPUT:[12,"User input"],PERFORMANCE:[13,"Performance"],GRAPHICS:[14,"Graphics"],CSS:[15,"CSS"],HOUDINI:[16,"Houdini"],SERVICEWORKER:[17,"Service Worker"],WEBRTC:[18,"WebRTC"],LAYERED:[19,"Layered APIs"],WEBASSEMBLY:[20,"WebAssembly"],CAPABILITIES:[21,"Capabilities (Fugu)"],IWA:[22,"Isolated Web Apps-specific API"]},ENTERPRISE_FEATURE_CATEGORIES={SECURITYANDPRIVACY:[1,"Security / Privacy"],USERPRODUCTIVITYANDAPPS:[2,"User Productivity / Apps"],MANAGEMENT:[3,"Management"]},ENTERPRISE_FEATURE_CATEGORIES_DISPLAYNAME={1:"Security/Privacy",2:"User Productivity/Apps",3:"Management"},PLATFORM_CATEGORIES={PLATFORM_ANDROID:[1,"Android"],PLATFORM_IOS:[2,"iOS"],PLATFORM_CHROMEOS:[3,"ChromeOS"],PLATFORM_LACROS:[4,"LaCrOS",!0],PLATFORM_LINUX:[5,"Linux"],PLATFORM_MAC:[6,"MacOS"],PLATFORM_WINDOWS:[7,"Windows"],PLATFORM_FUCHSIA:[8,"Fuchsia"]},PLATFORMS_DISPLAYNAME={1:"Android",2:"iOS",3:"ChromeOS",4:"LaCrOS",5:"Linux",6:"MacOS",7:"Windows",8:"Fuchsia"},ROLLOUT_STAGE_PLAN_CATEGORIES={ROLLOUT_STAGE_PLAN_SLOW:[0,"Feature rolls out gradually"],ROLLOUT_STAGE_PLAN_TRUSTED_TESTERS:[1,"Early preview available to Chrome Enterprise Truster Testers"],ROLLOUT_STAGE_PLAN_CUSTOM:[2,"Custom rollout (explain in Rollout details field)"]},ROLLOUT_STAGE_PLAN_DISPLAYNAME={0:"Feature rolls out gradually",1:"Early preview available to Chrome Enterprise Truster Testers",2:"Custom rollout (explain in Rollout details field)"},ENTERPRISE_IMPACT_DISPLAYNAME={1:"None",2:"Low",3:"Medium",4:"High"},ENTERPRISE_IMPACT={IMPACT_NONE:[1,"None"],IMPACT_LOW:[2,"Low"],IMPACT_MEDIUM:[3,"Medium"],IMPACT_HIGH:[4,"High"]},ROLLOUT_PLAN={ROLLOUT_100:[0,"Will ship enabled for all users"],ROLLOUT_0_THEN_100:[1,"(RARE) Ships disabled, then flips on for all users"],ROLLOUT_GRADUAL:[2,"(RARE) Experiment users ramp up over time"],ROLLOUT_OTHER:[3,"(RARE) It's complicated or unusual"]},ROLLOUT_PLAN_DISPLAYNAME={0:ROLLOUT_PLAN.ROLLOUT_100[1],1:ROLLOUT_PLAN.ROLLOUT_0_THEN_100[1],2:ROLLOUT_PLAN.ROLLOUT_GRADUAL[1],3:ROLLOUT_PLAN.ROLLOUT_OTHER[1]},USE_COUNTER_TYPE_WEBFEATURE=0,USE_COUNTER_TYPE_WEBDXFEATURE=1,USE_COUNTER_TYPE_CSS_PROPERTY_ID=2,WEBFEATURE_USE_COUNTER_TYPES={WEBFEATURE:[USE_COUNTER_TYPE_WEBFEATURE,"WebFeature",x$1`The feature's use counter has been added to + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom" + >web_feature.mojom</a + >.`],WEBDXFEATURE:[USE_COUNTER_TYPE_WEBDXFEATURE,"WebDXFeature",x$1`The feature's use counter has been added to + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom" + >webdx_feature.mojom</a + >.`],CSS:[USE_COUNTER_TYPE_CSS_PROPERTY_ID,"CSSSampleID",x$1`The feature's use counter has been added to + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom" + >css_property_id.mojom</a + >.`]};var FeatureType;(function(FeatureType){FeatureType[FeatureType.Incubate=0]="Incubate",FeatureType[FeatureType.Existing=1]="Existing",FeatureType[FeatureType.CodeChange=2]="CodeChange",FeatureType[FeatureType.Deprecation=3]="Deprecation",FeatureType[FeatureType.Enterprise=4]="Enterprise"})(FeatureType||(FeatureType={}));var AITestEvaluationStatus;(function(AITestEvaluationStatus){AITestEvaluationStatus[AITestEvaluationStatus.COMPLETE=1]="COMPLETE",AITestEvaluationStatus[AITestEvaluationStatus.IN_PROGRESS=2]="IN_PROGRESS",AITestEvaluationStatus[AITestEvaluationStatus.FAILED=3]="FAILED"})(AITestEvaluationStatus||(AITestEvaluationStatus={}));const FEATURE_TYPES_WITHOUT_ENTERPRISE={FEATURE_TYPE_INCUBATE_ID:[0,"New or changed feature",x$1`Choose this if you're still working on the design of a feature and + might need to send an Intent to Prototype or request a TAG review. Note + that backward-incompatible changes sometimes need to be implemented as a + pair of adding the new behavior and a separate entry to remove the old + behavior. This feature type follows the + <a + href="https://www.chromium.org/blink/launching-features/#new-feature-process" + target="_blank" + >New Feature Incubation</a + > + process.`],FEATURE_TYPE_EXISTING_ID:[1,"Chromium catches up",x$1`Choose this if a standards body already has consensus for a feature, or + it's already shipped in another implementation. This feature type omits + some options that the "New feature" type includes. It follows the + <a + href="https://www.chromium.org/blink/launching-features/#process-existing-standard" + target="_blank" + >Implementations of already-defined consensus-based standards</a + > + process.`],FEATURE_TYPE_CODE_CHANGE_ID:[2,"No developer-visible change",x$1`Choose this if you're hoping that nobody notices the change you're + going to make, but there's a chance that a bug will make it visible. This + feature type follows the + <a + href="https://www.chromium.org/blink/launching-features/#behavior-changes" + target="_blank" + >Web-developer-facing change to existing behavior</a + > + process.`],FEATURE_TYPE_DEPRECATION_ID:[3,"Feature removal",x$1`Choose this if you are deprecating and then removing an existing + feature. This feature type follows the + <a + href="https://www.chromium.org/blink/launching-features/#feature-deprecations" + target="_blank" + >Feature deprecations</a + > + process.`]},FEATURE_TYPES={...FEATURE_TYPES_WITHOUT_ENTERPRISE,FEATURE_TYPE_ENTERPRISE_ID:[4,"New Feature or removal affecting enterprises","For features or changes that need to be communicated to enterprises or schools."]},ENTERPRISE_PRODUCT_CATEGORY={CHROME_BROWSER_UPDATE:[0,"Chrome Browser update","New features, performance improvements, security fixes and minor updates addressing security vulnerabilities and bugs. These features apply to both consumers and enterprises."],CHROME_ENTERPRISE_CORE:[1,"Chrome Enterprise Core (CEC)","These features allow IT administrators to manage Chrome browser settings, policies, apps and extensions across an organization from a central location (Admin Console)."],CHROME_ENTERPRISE_PREMIUM:[2,"Chrome Enterprise Premium (CEP, paid SKU)","These features add advanced security and enhanced controls for organizations with more custom needs e.g. data masking functionality."]},ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME={0:"Chrome Browser update",1:"Chrome Enterprise Core (CEC)",2:"Chrome Enterprise Premium (CEP, paid SKU)"},STAGE_BLINK_INCUBATE=110,STAGE_BLINK_PROTOTYPE=120,STAGE_BLINK_DEV_TRIAL=130,STAGE_BLINK_EVAL_READINESS=140,STAGE_BLINK_ORIGIN_TRIAL=150,STAGE_BLINK_EXTEND_ORIGIN_TRIAL=151,STAGE_BLINK_SHIPPING=160,STAGE_FAST_PROTOTYPE=220,STAGE_FAST_DEV_TRIAL=230,STAGE_FAST_ORIGIN_TRIAL=250,STAGE_FAST_EXTEND_ORIGIN_TRIAL=251,STAGE_FAST_SHIPPING=260,STAGE_PSA_IMPLEMENT_FIELDS=320,STAGE_PSA_DEV_TRIAL=330,STAGE_PSA_SHIPPING=360,STAGE_DEP_PLAN=410,STAGE_DEP_DEV_TRIAL=430,STAGE_DEP_DEPRECATION_TRIAL=450,STAGE_DEP_EXTEND_DEPRECATION_TRIAL=451,STAGE_DEP_SHIPPING=460,STAGE_ENT_ROLLOUT=1061,STAGE_ENT_SHIPPED=1070,STAGE_TYPES_DEV_TRIAL=new Set([STAGE_BLINK_DEV_TRIAL,STAGE_FAST_DEV_TRIAL,STAGE_PSA_DEV_TRIAL,STAGE_DEP_DEV_TRIAL]),STAGE_TYPES_ORIGIN_TRIAL=new Set([STAGE_BLINK_ORIGIN_TRIAL,STAGE_FAST_ORIGIN_TRIAL,STAGE_DEP_DEPRECATION_TRIAL]),STAGE_TYPES_SHIPPING=new Set([STAGE_BLINK_SHIPPING,STAGE_FAST_SHIPPING,STAGE_PSA_SHIPPING,STAGE_DEP_SHIPPING]),OT_EXTENSION_STAGE_MAPPING={[STAGE_BLINK_ORIGIN_TRIAL]:STAGE_BLINK_EXTEND_ORIGIN_TRIAL,[STAGE_FAST_ORIGIN_TRIAL]:STAGE_FAST_EXTEND_ORIGIN_TRIAL,[STAGE_DEP_DEPRECATION_TRIAL]:STAGE_DEP_EXTEND_DEPRECATION_TRIAL},STAGE_SHORT_NAMES={[STAGE_BLINK_INCUBATE]:"Incubate",[STAGE_BLINK_PROTOTYPE]:"Prototype",[STAGE_BLINK_DEV_TRIAL]:"DevTrial",[STAGE_BLINK_EVAL_READINESS]:"Eval readiness",[STAGE_BLINK_ORIGIN_TRIAL]:"OT",[STAGE_BLINK_EXTEND_ORIGIN_TRIAL]:"Extend OT",[STAGE_BLINK_SHIPPING]:"Ship",[STAGE_FAST_PROTOTYPE]:"Prototype",[STAGE_FAST_DEV_TRIAL]:"DevTrial",[STAGE_FAST_ORIGIN_TRIAL]:"OT",[STAGE_FAST_EXTEND_ORIGIN_TRIAL]:"Extend OT",[STAGE_FAST_SHIPPING]:"Ship",[STAGE_PSA_IMPLEMENT_FIELDS]:"Implement",[STAGE_PSA_DEV_TRIAL]:"DevTrial",[STAGE_PSA_SHIPPING]:"Ship",[STAGE_DEP_PLAN]:"Plan",[STAGE_DEP_DEV_TRIAL]:"DevTrial",[STAGE_DEP_DEPRECATION_TRIAL]:"Dep Trial",[STAGE_DEP_EXTEND_DEPRECATION_TRIAL]:"Extend Dep Trial",[STAGE_DEP_SHIPPING]:"Ship",[STAGE_ENT_ROLLOUT]:"Rollout",[STAGE_ENT_SHIPPED]:"Ship"},INTENT_STAGES={INTENT_NONE:[0,"None"],INTENT_INCUBATE:[7,"Start incubating"],INTENT_IMPLEMENT:[1,"Start prototyping"],INTENT_EXPERIMENT:[2,"Dev trials"],INTENT_IMPLEMENT_SHIP:[4,"Evaluate readiness to ship"],INTENT_ORIGIN_TRIAL:[3,"Origin Trial"],INTENT_EXTEND_ORIGIN_TRIAL:[11,"Extend Trial"],INTENT_SHIP:[5,"Prepare to ship"],INTENT_REMOVED:[6,"Removed"],INTENT_SHIPPED:[8,"Shipped"],INTENT_PARKED:[9,"Parked"],INTENT_ROLLOUT:[10,"Rollout"]},DT_MILESTONE_FIELDS=new Set(["dt_milestone_desktop_start","dt_milestone_android_start","dt_milestone_ios_start","dt_milestone_webview_start"]),OT_MILESTONE_START_FIELDS=new Set(["ot_milestone_desktop_start","ot_milestone_android_start","ot_milestone_webview_start"]),SHIPPED_MILESTONE_FIELDS=new Set(["shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone"]);var UsageType;(function(UsageType){UsageType[UsageType.Prototype=0]="Prototype",UsageType[UsageType.DeveloperTesting=1]="DeveloperTesting",UsageType[UsageType.Experiment=2]="Experiment",UsageType[UsageType.Ship=3]="Ship",UsageType[UsageType.PSA=4]="PSA",UsageType[UsageType.DeprecateAndRemove=5]="DeprecateAndRemove",UsageType[UsageType.CrossFunctionReview=6]="CrossFunctionReview",UsageType[UsageType.ReleaseNotes=7]="ReleaseNotes"})(UsageType||(UsageType={}));const ALL_FEATURE_TYPE_INCUBATE_INTENTS=new Set([UsageType.Prototype,UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),ALL_FEATURE_TYPE_EXISTING_INTENTS=new Set([UsageType.Prototype,UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),ALL_FEATURE_TYPE_CODE_CHANGE_INTENTS=new Set([UsageType.DeveloperTesting,UsageType.PSA]),ALL_FEATURE_TYPE_DEPRECATION_INTENTS=new Set([UsageType.DeprecateAndRemove,UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),ALL_INTENT_USAGE_BY_FEATURE_TYPE={[FeatureType.Incubate]:ALL_FEATURE_TYPE_INCUBATE_INTENTS,[FeatureType.Existing]:ALL_FEATURE_TYPE_EXISTING_INTENTS,[FeatureType.CodeChange]:ALL_FEATURE_TYPE_CODE_CHANGE_INTENTS,[FeatureType.Deprecation]:ALL_FEATURE_TYPE_DEPRECATION_INTENTS},STAGE_SPECIFIC_FIELDS=new Set(["shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone","ot_milestone_desktop_start","ot_milestone_desktop_end","ot_milestone_android_start","ot_milestone_android_end","ot_milestone_webview_start","ot_milestone_webview_end","dt_milestone_desktop_start","dt_milestone_android_start","dt_milestone_ios_start","dt_milestone_webview_start","extension_desktop_last","extension_android_last","extension_webview_last","intent_to_implement_url","intent_to_ship_url","intent_to_experiment_url","intent_to_extend_experiment_url","intent_thread_url","ot_creation__intent_to_experiment_url","ot_extension__intent_to_extend_experiment_url","r4dt_url","display_name","ot_display_name","ot_owner_email","origin_trial_feedback_url","ot_chromium_trial_name","ot_description","ot_emails","ot_feedback_submission_url","ot_request_note","ot_webfeature_use_counter","ot_documentation_url","ot_creation__bypass_file_checks","ot_creation__ot_documentation_url","ot_is_deprecation_trial","ot_has_third_party_support","ot_is_critical_trial","ot_creation__milestone_desktop_first","ot_creation__milestone_desktop_last","ot_extension__milestone_desktop_last","ot_require_approvals","ot_approval_buganizer_component","ot_approval_buganizer_custom_field_id","ot_approval_group_email","ot_approval_criteria_url","finch_url","experiment_goals","experiment_risks","experiment_extension_reason","rollout_milestone","rollout_platforms","rollout_details","rollout_stage_plan","enterprise_policies","announcement_url"]),STAGE_FIELD_NAME_MAPPING={shipped_milestone:"desktop_first",shipped_android_milestone:"android_first",shipped_ios_milestone:"ios_first",shipped_webview_milestone:"webview_first",ot_milestone_desktop_start:"desktop_first",ot_milestone_desktop_end:"desktop_last",ot_milestone_android_start:"android_first",ot_milestone_android_end:"android_last",ot_milestone_webview_start:"webview_first",ot_milestone_webview_end:"webview_last",ot_creation__milestone_desktop_first:"desktop_first",ot_creation__milestone_desktop_last:"desktop_last",ot_creation__ot_documentation_url:"ot_documentation_url",ot_extension__milestone_desktop_last:"desktop_last",dt_milestone_desktop_start:"desktop_first",dt_milestone_android_start:"android_first",dt_milestone_ios_start:"ios_first",dt_milestone_webview_start:"webview_first",extension_desktop_last:"desktop_last",extension_android_last:"android_last",extension_webview_last:"webview_last",rollout_milestone:"desktop_first",intent_to_implement_url:"intent_thread_url",intent_to_ship_url:"intent_thread_url",intent_to_experiment_url:"intent_thread_url",intent_to_extend_experiment_url:"intent_thread_url",ot_creation__intent_to_experiment_url:"intent_thread_url",ot_extension__intent_to_extend_experiment_url:"intent_thread_url",r4dt_url:"intent_thread_url"},GATE_TYPES={API_PROTOTYPE:1,API_ORIGIN_TRIAL:2,API_EXTEND_ORIGIN_TRIAL:3,API_SHIP:4,API_PLAN:5,PRIVACY_ORIGIN_TRIAL:32,PRIVACY_SHIP:34,SECURITY_ORIGIN_TRIAL:42,SECURITY_SHIP:44,ENTERPRISE_SHIP:54,ENTERPRISE_PLAN:55,DEBUGGABILITY_ORIGIN_TRIAL:62,DEBUGGABILITY_SHIP:64,DEBUGGABILITY_PLAN:65,TESTING_SHIP:74,TESTING_PLAN:75},GATE_PREPARING=0,GATE_REVIEW_REQUESTED=2,GATE_NA_REQUESTED=9,VOTE_OPTIONS={NO_RESPONSE:[7,"No response"],NA:[1,"N/a or Ack"],REVIEW_STARTED:[3,"Review started"],NEEDS_WORK:[4,"Needs work"],INTERNAL_REVIEW:[8,"Internal review"],APPROVED:[5,"Approved"],DENIED:[6,"Denied"]},VOTE_NA_SELF=10,VOTE_NA_VERIFIED=11,GATE_ACTIVE_REVIEW_STATES=[GATE_REVIEW_REQUESTED,VOTE_OPTIONS.REVIEW_STARTED[0],VOTE_OPTIONS.NEEDS_WORK[0],VOTE_OPTIONS.INTERNAL_REVIEW[0],GATE_NA_REQUESTED],GATE_FINISHED_REVIEW_STATES=[VOTE_OPTIONS.NA[0],VOTE_OPTIONS.APPROVED[0],VOTE_OPTIONS.DENIED[0],VOTE_NA_SELF,VOTE_NA_VERIFIED],GATE_APPROVED_REVIEW_STATES=[VOTE_OPTIONS.APPROVED[0],VOTE_OPTIONS.NA[0],VOTE_NA_SELF,VOTE_NA_VERIFIED],GATE_TEAM_ORDER=["Privacy","WP Security","Enterprise","Debuggability","Testing","API Owners"],OT_MILESTONE_END_FIELDS={ot_milestone_desktop_end:"desktop_last",ot_milestone_android_end:"android_last",ot_milestone_webview_end:"webview_last"},OT_SETUP_STATUS_OPTIONS={OT_NOT_CREATED:1,OT_READY_FOR_CREATION:2,OT_CREATION_FAILED:3,OT_ACTIVATION_FAILED:4},IMPLEMENTATION_STATUS={NO_ACTIVE_DEV:[1,"No active development"],PROPOSED:[2,"Proposed"],IN_DEVELOPMENT:[3,"In development"],BEHIND_A_FLAG:[4,"In developer trial (Behind a flag)"],ENABLED_BY_DEFAULT:[5,"Enabled by default"],DEPRECATED:[6,"Deprecated"],REMOVED:[7,"Removed"],ORIGIN_TRIAL:[8,"Origin trial"],ON_HOLD:[10,"On hold"],NO_LONGER_PURSUING:[1e3,"No longer pursuing"]},STANDARD_MATURITY_CHOICES={UNKNOWN_STD:[1,"Unknown standards status - check spec link for status"],PROPOSAL_STD:[2,"Proposal in a personal repository, no adoption from community"],INCUBATION_STD:[3,"Specification being incubated in a Community Group"],WORKINGDRAFT_STD:[4,"Specification currently under development in a Working Group"],STANDARD_STD:[5,"Final published standard: Recommendation, Living Standard, Candidate Recommendation, or similar final form"]},REVIEW_STATUS_CHOICES={REVIEW_PENDING:[1,"Pending"],REVIEW_ISSUES_OPEN:[2,"Issues open"],REVIEW_ISSUES_ADDRESSED:[3,"Issues addressed"],REVIEW_NA:[4,"Not applicable"]},VENDOR_VIEWS_COMMON={SHIPPED:[1,"Shipped/Shipping"],IN_DEV:[2,"In development"],PUBLIC_SUPPORT:[3,"Positive"],NO_PUBLIC_SIGNALS:[5,"No signal"],OPPOSED:[7,"Negative"],NEUTRAL:[8,"Neutral"],SIGNALS_NA:[9,"N/A"]},VENDOR_VIEWS_GECKO={NO_PUBLIC_SIGNALS:[5,"No signal"],SIGNALS_NA:[9,"N/A"],GECKO_UNDER_CONSIDERATION:[10,"Under consideration"],GECKO_DEFER:[14,"Defer"],PUBLIC_SUPPORT:[3,"Positive"],OPPOSED:[7,"Negative"],NEUTRAL:[8,"Neutral"],SHIPPED:[1,"Shipped/Shipping"]},WEB_DEV_VIEWS={DEV_STRONG_POSITIVE:[1,"Strongly positive"],DEV_POSITIVE:[2,"Positive"],DEV_MIXED_SIGNALS:[3,"Mixed signals"],DEV_NO_SIGNALS:[4,"No signals"],DEV_NEGATIVE:[5,"Negative"],DEV_STRONG_NEGATIVE:[6,"Strongly negative"]},COMMA_SEPARATED_FIELDS=["owner","editors","cc_recipients","spec_mentors","search_tags","devrel","i2e_lgtms","i2s_lgtms"],LINE_SEPARATED_FIELDS=["explainer_links","doc_links","sample_links","screenshot_links"];function formatFeatureForEdit(feature){const formattedFeature={...feature,category:feature.category_int,enterprise_feature_categories:Array.from(new Set(feature.enterprise_feature_categories||[])).map(x=>parseInt(x).toString()),enterprise_product_category:feature.enterprise_product_category,feature_type:feature.feature_type_int,intent_stage:feature.intent_stage_int,accurate_as_of:!0,spec_link:feature.standards.spec,standard_maturity:feature.standards.maturity.val,tag_review_status:feature.tag_review_status_int,security_review_status:feature.security_review_status_int,privacy_review_status:feature.privacy_review_status_int,sample_links:feature.resources.samples,doc_links:feature.resources.docs,search_tags:feature.tags,blink_components:feature.browsers.chrome.blink_components?.[0],bug_url:feature.browsers.chrome.bug,devrel:feature.browsers.chrome.devrel,owner:feature.browsers.chrome.owners,prefixed:feature.browsers.chrome.prefixed,impl_status_chrome:feature.browsers.chrome.status.val,shipped_milestone:feature.browsers.chrome.desktop,shipped_android_milestone:feature.browsers.chrome.android,shipped_webview_milestone:feature.browsers.chrome.webview,shipped_ios_milestone:feature.browsers.chrome.ios,ff_views:feature.browsers.ff.view?.val,ff_views_link:feature.browsers.ff.view?.url,ff_views_notes:feature.browsers.ff.view?.notes,safari_views:feature.browsers.safari.view?.val,safari_views_link:feature.browsers.safari.view?.url,safari_views_notes:feature.browsers.safari.view?.notes,web_dev_views:feature.browsers.webdev.view?.val,web_dev_views_link:feature.browsers.webdev.view?.url,web_dev_views_notes:feature.browsers.webdev.view?.notes,other_views_notes:feature.browsers.other.view?.notes};return COMMA_SEPARATED_FIELDS.map(field=>{formattedFeature[field]&&(formattedFeature[field]=formattedFeature[field].join(", "))}),LINE_SEPARATED_FIELDS.map(field=>{formattedFeature[field]&&(formattedFeature[field]=formattedFeature[field].join("\r\n"))}),formattedFeature}const NEW_FEATURE_FORM_FIELDS=["name","summary","unlisted","enterprise_impact","enterprise_feature_categories","shipping_year","owner","editors","cc_recipients","blink_components","category","web_feature"],ENTERPRISE_NEW_FEATURE_FORM_FIELDS=["name","summary","owner","editors","enterprise_feature_categories","enterprise_product_category","first_enterprise_notification_milestone","enterprise_impact","confidential"],FLAT_METADATA_FIELDS={name:"Feature metadata",sections:[{name:"Feature metadata",fields:["name","summary","unlisted","enterprise_impact","enterprise_feature_categories","shipping_year","owner","editors","cc_recipients","devrel","category","feature_type","active_stage_id","search_tags","web_feature"]},{name:"Implementation in Chromium",fields:["blink_components","bug_url","launch_bug_url","comments"]}]},FLAT_ENTERPRISE_METADATA_FIELDS={sections:[{name:"Feature metadata",fields:["name","summary","owner","editors","enterprise_feature_categories","enterprise_product_category","enterprise_impact","confidential","first_enterprise_notification_milestone","screenshot_links"]}]},FLAT_INCUBATE_FIELDS={name:"Identify the need",sections:[{name:"Identify the need",fields:["motivation","initial_public_proposal_url","explainer_links"]},{name:"Implementation in Chromium",fields:["requires_embedder_support"]}]},FLAT_PROTOTYPE_FIELDS={name:"Prototype a solution",sections:[{name:"Prototype a solution",fields:["motivation","spec_link","standard_maturity","api_spec","automation_spec","spec_mentors","intent_to_implement_url"]}]},FLAT_DEV_TRIAL_FIELDS={name:"Dev trials and iterate on design",sections:[{name:"Dev trial",fields:["devtrial_instructions","doc_links","interop_compat_risks","safari_views","safari_views_link","safari_views_notes","ff_views","ff_views_link","ff_views_notes","web_dev_views","web_dev_views_link","web_dev_views_notes","other_views_notes","security_review_status","privacy_review_status","ergonomics_risks","activation_risks","security_risks","debuggability","measurement","all_platforms","all_platforms_descr","wpt","wpt_descr","sample_links"]},{name:"Implementation in Chromium",fields:["flag_name","finch_name","non_finch_justification","dt_milestone_desktop_start","dt_milestone_android_start","dt_milestone_ios_start","announcement_url"]}]},FLAT_ORIGIN_TRIAL_FIELDS={name:"Origin trial",sections:[{name:"Origin trial",fields:["display_name","experiment_goals","experiment_risks","ongoing_constraints","i2e_lgtms","ot_documentation_url","intent_to_experiment_url","origin_trial_feedback_url"]},{name:"Implementation in Chromium",fields:["ot_milestone_desktop_start","ot_milestone_desktop_end","ot_milestone_android_start","ot_milestone_android_end","ot_milestone_webview_start","ot_milestone_webview_end","experiment_timeline"]}]},FLAT_TRIAL_EXTENSION_FIELDS={name:"Trial extension",sections:[{name:"Trial extension",fields:["experiment_extension_reason","intent_to_extend_experiment_url","extension_desktop_last"]}]},FLAT_EVAL_READINESS_TO_SHIP_FIELDS={name:"Evaluate readiness to ship",sections:[{name:"Evaluate readiness to ship",fields:["prefixed","tag_review"]}]},FLAT_PREPARE_TO_SHIP_FIELDS={name:"Prepare to ship",sections:[{name:"Prepare to ship",fields:["display_name","tag_review_status","webview_risks","anticipated_spec_changes","i2s_lgtms","availability_expectation","adoption_expectation","adoption_plan","non_oss_deps","finch_url","intent_to_ship_url"]},{name:"Implementation in Chromium",fields:["rollout_plan","shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone"]}]},FLAT_ENTERPRISE_PREPARE_TO_SHIP_FIELDS={name:"Rollout step",sections:[{name:"Rollout step",fields:["rollout_milestone","rollout_platforms","rollout_details","rollout_stage_plan","enterprise_policies"]}]},PSA_IMPLEMENT_FIELDS={name:"Start prototyping",sections:[{name:"Start prototyping",fields:["motivation","spec_link","standard_maturity"]}]},PSA_PREPARE_TO_SHIP_FIELDS={name:"Prepare to ship",sections:[{name:"Prepare to ship",fields:["intent_to_ship_url"]},{name:"Implementation in Chromium",fields:["rollout_plan","shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone"]}]},DEPRECATION_PLAN_FIELDS={name:"Write up deprecation plan",sections:[{name:"Write up deprecation plan",fields:["deprecation_motivation","spec_link"]}]},DEPRECATION_DEV_TRIAL_FIELDS={name:"Dev trial of deprecation",sections:[{name:"Dev trial of deprecation",fields:["devtrial_instructions","doc_links","interop_compat_risks","safari_views","safari_views_link","safari_views_notes","ff_views","ff_views_link","ff_views_notes","web_dev_views","web_dev_views_link","web_dev_views_notes","other_views_notes","security_review_status","privacy_review_status","ergonomics_risks","activation_risks","security_risks","webview_risks","debuggability","measurement","all_platforms","all_platforms_descr","wpt","wpt_descr","sample_links"]},{name:"Implementation in Chromium",fields:["flag_name","finch_name","non_finch_justification","dt_milestone_desktop_start","dt_milestone_android_start","dt_milestone_ios_start","announcement_url"]}]},ORIGIN_TRIAL_CREATION_FIELDS={sections:[{fields:["ot_display_name","ot_description","ot_owner_email","ot_emails","ot_creation__milestone_desktop_first","ot_creation__milestone_desktop_last","ot_creation__intent_to_experiment_url","ot_creation__ot_documentation_url","ot_feedback_submission_url","ot_chromium_trial_name","ot_is_deprecation_trial","ot_webfeature_use_counter","ot_has_third_party_support","ot_is_critical_trial","ot_require_approvals"]}]},ORIGIN_TRIAL_EXTENSION_FIELDS={sections:[{fields:["ot_extension__milestone_desktop_last","experiment_extension_reason"]}]},DEPRECATION_ORIGIN_TRIAL_FIELDS={name:"Prepare for Deprecation Trial",sections:[{name:"Prepare for Deprecation Trial",fields:["display_name","experiment_goals","experiment_risks","ongoing_constraints","r4dt_url","r4dt_lgtms","origin_trial_feedback_url"]},{name:"Implementation in Chromium",fields:["ot_milestone_desktop_start","ot_milestone_desktop_end","ot_milestone_android_start","ot_milestone_android_end","ot_milestone_webview_start","ot_milestone_webview_end","experiment_timeline"]}]},DEPRECATION_PREPARE_TO_SHIP_FIELDS={name:"Prepare to ship",sections:[{name:"Prepare to ship",fields:["display_name","intent_to_ship_url","i2s_lgtms"]},{name:"Implementation in Chromium",fields:["rollout_plan","shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone"]}]},VERIFY_ACCURACY_METADATA_FIELDS={name:"Important fields",sections:[{name:"Feature Metadata",fields:["summary","owner","finch_name","non_finch_justification","bug_url"]}]},VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS={name:"Prepare to ship",sections:[{name:"Shipping milestones",fields:["shipped_milestone","shipped_android_milestone","shipped_ios_milestone","shipped_webview_milestone"]}]},VERIFY_ACCURACY_ENTERPRISE_PREPARE_TO_SHIP_FIELDS={name:"Rollout step",sections:[{name:"Rollout milestones",fields:["rollout_milestone","rollout_platforms","rollout_details","rollout_stage_plan","enterprise_policies"]}]},VERIFY_ACCURACY_CONFIRMATION_FIELD={name:"Verify Accuracy",sections:[{name:"Verify Accuracy",fields:["accurate_as_of"]}]},FORMS_BY_STAGE_TYPE={[STAGE_BLINK_INCUBATE]:FLAT_INCUBATE_FIELDS,[STAGE_BLINK_PROTOTYPE]:FLAT_PROTOTYPE_FIELDS,[STAGE_BLINK_DEV_TRIAL]:FLAT_DEV_TRIAL_FIELDS,[STAGE_BLINK_EVAL_READINESS]:FLAT_EVAL_READINESS_TO_SHIP_FIELDS,[STAGE_BLINK_ORIGIN_TRIAL]:FLAT_ORIGIN_TRIAL_FIELDS,[STAGE_BLINK_EXTEND_ORIGIN_TRIAL]:FLAT_TRIAL_EXTENSION_FIELDS,[STAGE_BLINK_SHIPPING]:FLAT_PREPARE_TO_SHIP_FIELDS,[STAGE_FAST_PROTOTYPE]:FLAT_PROTOTYPE_FIELDS,[STAGE_FAST_DEV_TRIAL]:FLAT_DEV_TRIAL_FIELDS,[STAGE_FAST_ORIGIN_TRIAL]:FLAT_ORIGIN_TRIAL_FIELDS,[STAGE_FAST_EXTEND_ORIGIN_TRIAL]:FLAT_TRIAL_EXTENSION_FIELDS,[STAGE_FAST_SHIPPING]:FLAT_PREPARE_TO_SHIP_FIELDS,[STAGE_PSA_IMPLEMENT_FIELDS]:PSA_IMPLEMENT_FIELDS,[STAGE_PSA_DEV_TRIAL]:FLAT_DEV_TRIAL_FIELDS,[STAGE_PSA_SHIPPING]:PSA_PREPARE_TO_SHIP_FIELDS,[STAGE_DEP_PLAN]:DEPRECATION_PLAN_FIELDS,[STAGE_DEP_DEV_TRIAL]:DEPRECATION_DEV_TRIAL_FIELDS,[STAGE_DEP_DEPRECATION_TRIAL]:DEPRECATION_ORIGIN_TRIAL_FIELDS,[STAGE_DEP_EXTEND_DEPRECATION_TRIAL]:FLAT_TRIAL_EXTENSION_FIELDS,[STAGE_DEP_SHIPPING]:DEPRECATION_PREPARE_TO_SHIP_FIELDS,[STAGE_ENT_ROLLOUT]:FLAT_ENTERPRISE_PREPARE_TO_SHIP_FIELDS,[STAGE_ENT_SHIPPED]:FLAT_PREPARE_TO_SHIP_FIELDS},CREATEABLE_STAGES={[FEATURE_TYPES.FEATURE_TYPE_INCUBATE_ID[0]]:[STAGE_BLINK_ORIGIN_TRIAL,STAGE_BLINK_SHIPPING,STAGE_ENT_ROLLOUT],[FEATURE_TYPES.FEATURE_TYPE_EXISTING_ID[0]]:[STAGE_FAST_ORIGIN_TRIAL,STAGE_FAST_SHIPPING,STAGE_ENT_ROLLOUT],[FEATURE_TYPES.FEATURE_TYPE_CODE_CHANGE_ID[0]]:[STAGE_PSA_SHIPPING,STAGE_ENT_ROLLOUT],[FEATURE_TYPES.FEATURE_TYPE_DEPRECATION_ID[0]]:[STAGE_DEP_DEPRECATION_TRIAL,STAGE_DEP_SHIPPING,STAGE_ENT_ROLLOUT],[FEATURE_TYPES.FEATURE_TYPE_ENTERPRISE_ID[0]]:[STAGE_ENT_ROLLOUT]},VERIFY_ACCURACY_FORMS_BY_STAGE_TYPE={[STAGE_BLINK_SHIPPING]:VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS,[STAGE_FAST_SHIPPING]:VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS,[STAGE_PSA_SHIPPING]:VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS,[STAGE_DEP_SHIPPING]:VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS,[STAGE_ENT_ROLLOUT]:VERIFY_ACCURACY_ENTERPRISE_PREPARE_TO_SHIP_FIELDS,[STAGE_ENT_SHIPPED]:VERIFY_ACCURACY_PREPARE_TO_SHIP_FIELDS};let toastEl;const NARROW_WINDOW_MAX_WIDTH=700,ACCURACY_GRACE_PERIOD=2419200000,SHIPPED_FEATURE_OUTDATED_GRACE_PERIOD=5443200000,IS_MOBILE=(()=>{const width=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;return width<=NARROW_WINDOW_MAX_WIDTH})();function autolink(s,featureLinks=[],isMarkdown=!1){if(s=s??"",isMarkdown){const rendered=d.parse(s),sanitized=purify.sanitize(rendered),markup=x$1`${o$2(sanitized)}`;return[markup]}else{const withLinks=markupAutolinks(s,featureLinks);return withLinks}}function showToastMessage(msg){toastEl||(toastEl=document.querySelector("chromedash-toast")),toastEl?.showMessage&&toastEl.showMessage(msg)}function findProcessStage(feStage,process){for(const processStage of process.stages)if(feStage.stage_type==processStage.stage_type)return processStage;return null}function shouldShowDisplayNameField(feStages,stageType){let matchingStageCount=0;for(let i=0;i<feStages.length;i++)if(feStages[i].stage_type===stageType&&(matchingStageCount++,1<matchingStageCount))return!0;return!1}function findFirstFeatureStage(intentStage,currentStage,fe){if(intentStage==currentStage.intent_stage)return currentStage;for(const feStage of fe.stages)if(intentStage==feStage.intent_stage)return feStage;return null}function unambiguousStageName(stage,feature){const processStageName=FORMS_BY_STAGE_TYPE[stage.stage_type]?.name;if(!processStageName)return void console.error(`Unexpected stage type ${stage.stage_type} in stage ${stage.id}.`);if(stage.display_name)return`${processStageName}: ${stage.display_name}`;const index=feature.stages.filter(s=>s.stage_type===stage.stage_type).findIndex(s=>s.id===stage.id);return 0<index?`${processStageName} ${index+1}`:processStageName}function getStageValue(stage,fieldName){return stage?fieldName in STAGE_FIELD_NAME_MAPPING?stage[STAGE_FIELD_NAME_MAPPING[fieldName]]:stage[fieldName]:void 0}function calcMaxMilestone(feStage,fieldName){if(!feStage)return;if(feStage[`max_${fieldName}`]||!feStage.extensions)return;let maxMilestone=getStageValue(feStage,fieldName)||0;for(const extension of feStage.extensions)for(const otMilestoneField of Object.values(OT_MILESTONE_END_FIELDS)){const extensionValue=getStageValue(extension,otMilestoneField);extensionValue&&(maxMilestone=Math.max(maxMilestone,extensionValue))}feStage[`max_${fieldName}`]=maxMilestone}function _getMilestoneExtensionValue(feStage,fieldName){if(feStage){const milestoneValue=getStageValue(feStage,fieldName);calcMaxMilestone(feStage,fieldName);const maxMilestoneFieldName=`max_${fieldName}`;return feStage[maxMilestoneFieldName]&&!milestoneValue?`Extended to ${feStage[maxMilestoneFieldName]}`:feStage[maxMilestoneFieldName]&&feStage[maxMilestoneFieldName]>milestoneValue?`${feStage[maxMilestoneFieldName]} (extended from ${milestoneValue})`:milestoneValue}}function isDefinedValue(value){return value!==void 0&&null!==value&&0!=value.length}function hasFieldValue(fieldName,feStage,feature){const value=getFieldValueFromFeature(fieldName,feStage,feature);return isDefinedValue(value)}function getFieldValueFromFeature(fieldName,feStage,feature){if(STAGE_SPECIFIC_FIELDS.has(fieldName)){const value=getStageValue(feStage,fieldName);return"rollout_platforms"===fieldName&&value?value.map(platformId=>PLATFORMS_DISPLAYNAME[platformId]):"rollout_stage_plan"===fieldName?ROLLOUT_STAGE_PLAN_DISPLAYNAME[value]:fieldName in OT_MILESTONE_END_FIELDS?_getMilestoneExtensionValue(feStage,fieldName):value}if(!feature)return null;const fieldNameMapping={owner:"browsers.chrome.owners",editors:"editors",search_tags:"tags",spec_link:"standards.spec",standard_maturity:"standards.maturity.text",sample_links:"resources.samples",docs_links:"resources.docs",bug_url:"browsers.chrome.bug",blink_components:"browsers.chrome.blink_components",devrel:"browsers.chrome.devrel",prefixed:"browsers.chrome.prefixed",impl_status_chrome:"browsers.chrome.status.text",shipped_milestone:"browsers.chrome.desktop",shipped_android_milestone:"browsers.chrome.android",shipped_webview_milestone:"browsers.chrome.webview",shipped_ios_milestone:"browsers.chrome.ios",ff_views:"browsers.ff.view.text",ff_views_link:"browsers.ff.view.url",ff_views_notes:"browsers.ff.view.notes",safari_views:"browsers.safari.view.text",safari_views_link:"browsers.safari.view.url",safari_views_notes:"browsers.safari.view.notes",web_dev_views:"browsers.webdev.view.text",web_dev_views_link:"browsers.webdev.view.url",web_dev_views_notes:"browsers.webdev.view.notes",other_views_notes:"browsers.other.view.notes"};let value;if(fieldNameMapping[fieldName]){let propertyValue=feature;for(const step of fieldNameMapping[fieldName].split("."))propertyValue&&(propertyValue=propertyValue[step]);value=propertyValue}else value=feature[fieldName];if("enterprise_product_category"===fieldName&&void 0!==value)return ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME[value];if("enterprise_feature_categories"===fieldName&&value)return value.map(categoryId=>ENTERPRISE_FEATURE_CATEGORIES_DISPLAYNAME[categoryId]);if("enterprise_impact"===fieldName&&value)return ENTERPRISE_IMPACT_DISPLAYNAME[value];if("rollout_plan"===fieldName&&void 0!==value)return ROLLOUT_PLAN_DISPLAYNAME[value];if("active_stage_id"===fieldName&&value){for(const stage of feature.stages)if(stage.id===value)return unambiguousStageName(stage,feature);return}return value}function flattenSections(stage){return stage.sections.reduce((combined,section)=>[...combined,...section.fields],[])}function setupScrollToHash(pageElement){const scrollToElement=hash=>{if(hash){const el=pageElement.shadowRoot.querySelector(hash);if(el){el.input?el.focus():setTimeout(()=>{el.focus()},100);const fieldRowSelector=`chromedash-form-field[name="${el.name}"] tr + tr`,fieldRow=pageElement.shadowRoot.querySelector(fieldRowSelector);fieldRow?fieldRow.scrollIntoView({block:"center",behavior:"smooth"}):el.scrollIntoView({behavior:"smooth"})}}};if(window.scrollToElement=hash=>{scrollToElement(hash)},location.hash){const hash=decodeURIComponent(location.hash);scrollToElement(hash)}}function redirectToCurrentPage(){const url=window.location.href.split("?")[0];window.location.href=url}function renderHTMLIf(condition,originalHTML){return condition?originalHTML:E$1}function _parseDateStr(dateStr){dateStr=dateStr||"",dateStr=dateStr.replace(" ","T");const dateObj=new Date(`${dateStr}Z`);return isNaN(+dateObj)?null:dateObj}function renderAbsoluteDate(dateStr,includeTime=!1){return dateStr?includeTime?dateStr.split(".")[0]:dateStr.split(" ")[0]:""}function renderRelativeDate(dateStr){const dateObj=_parseDateStr(dateStr);return dateObj?x$1` <span class="relative_date"> + (<sl-relative-time date="${dateObj.toISOString()}"> </sl-relative-time>) + </span>`:E$1}function isoDateString(date){return date.toISOString().slice(0,10)}function parseRawQuery(rawQuery){const params=new URLSearchParams(rawQuery),result={};for(const param of params.keys()){const values=params.getAll(param);values.length&&(result[param]=values[0])}return result}function getNewLocation(params,location){const url=new URL(location);if(url.search="",params)for(const[k,v]of Object.entries(params))v&&url.searchParams.append(k,v.toString());return url}function getDisabledHelpText(field,feStage){return("ot_milestone_desktop_start"===field||"ot_milestone_desktop_end"===field)&&(feStage?.ot_setup_status===OT_SETUP_STATUS_OPTIONS.OT_READY_FOR_CREATION||feStage?.ot_setup_status===OT_SETUP_STATUS_OPTIONS.OT_CREATION_FAILED||feStage?.ot_setup_status===OT_SETUP_STATUS_OPTIONS.OT_ACTIVATION_FAILED)?"Origin trial milestone cannot be edited while a creation request is in progress":""}function updateURLParams(key,val){const newURL=formatURLParams(key,val);newURL.toString()===window.location.toString()||window.history.pushState({path:newURL.toString()},"",newURL)}function formatURLParams(key,val){const rawQuery=parseRawQuery(window.location.search);rawQuery[key]=encodeURIComponent(val);const newURL=getNewLocation(rawQuery,window.location);return newURL.hash="",newURL}function formatUrlForRelativeOffset(start,delta,pageSize,totalCount){const offset=start+delta;return void 0===totalCount||offset<=-pageSize||offset>=totalCount?void 0:formatUrlForOffset(Math.max(0,offset))}function formatUrlForOffset(offset){return formatURLParams("start",offset).toString()}function clearURLParams(key){const rawQuery=parseRawQuery(window.location.search);delete rawQuery[key];const newURL=getNewLocation(rawQuery,window.location);newURL.hash="";newURL.toString()===window.location.toString()||window.history.pushState({path:newURL.toString()},"",newURL)}function formatFeatureChanges(fieldValues,featureId,formStageId){let hasChanges=!1;const featureChanges={id:featureId},stages={};formStageId&&(stages[formStageId]={id:formStageId});for(const{name,touched,value,stageId,implicitValue,isMarkdown}of fieldValues){if(!touched)continue;let formattedValue=value;if(Array.isArray(formattedValue)&&(formattedValue=formattedValue.join(",")),void 0!==implicitValue){if(!formattedValue)continue;featureChanges[name]=implicitValue}else stageId?(stageId in stages||(stages[stageId]={id:stageId}),stages[stageId][STAGE_FIELD_NAME_MAPPING[name]||name]={form_field_name:name,value:formattedValue}):(featureChanges[name]=formattedValue,void 0!==isMarkdown&&(featureChanges[name+"_is_markdown"]=isMarkdown));hasChanges=!0}return{feature_changes:featureChanges,stages:Object.values(stages),has_changes:hasChanges}}function handleSaveChangesResponse(response){const app=document.querySelector("chromedash-app");app.setUnsavedChanges(""!==response)}function extensionMilestoneIsValid(value,currentMilestone){if(isNaN(value))return!1;for(let i=0;i<value.length;i++)if("0">value[i]||"9"<value[i])return!1;const intValue=parseInt(value);return!(1e3<=intValue)&&parseInt(currentMilestone)<=intValue}function userCanEdit(user,featureId){return!!(user&&(user.can_edit_all||user.editable_features.includes(featureId)))}function isVerifiedWithinGracePeriod(accurateAsOf,currentDate,gracePeriod=ACCURACY_GRACE_PERIOD){if(!accurateAsOf)return!1;const accurateDate=Date.parse(accurateAsOf);return!(accurateDate+gracePeriod<currentDate)}const METRICS_TYPE_AND_VIEW_TO_SUBTITLE={csspopularity:"CSS usage metrics > all properties",cssanimated:"CSS usage metrics > animated properties",featurepopularity:"HTML & JavaScript usage metrics > all features",webfeaturepopularity:"Web features usage metrics > all features"};function isShippedFeatureOutdated(feature,hasShipped,closestShippingDate){return!!hasShipped&&!!(feature.accurate_as_of&&closestShippingDate)&&Date.parse(feature.accurate_as_of)<Date.parse(closestShippingDate)}function isShippedFeatureOutdatedForAuthor(feature,userCanEdit,hasShipped,closestShippingDate){return userCanEdit&&isShippedFeatureOutdated(feature,hasShipped,closestShippingDate)}function isShippedFeatureOutdatedForAll(feature,hasShipped,currentDate,closestShippingDate){if(!isShippedFeatureOutdated(feature,hasShipped,closestShippingDate))return!1;const isVerified=isVerifiedWithinGracePeriod(feature.accurate_as_of,currentDate,SHIPPED_FEATURE_OUTDATED_GRACE_PERIOD);return!isVerified}async function fetchClosestShippingDate(milestone){if(0===milestone)return"";try{const newMilestonesInfo=await window.csClient.getSpecifiedChannels(milestone,milestone);return newMilestonesInfo[milestone]?.final_beta}catch{return showToastMessage("Some errors occurred. Please refresh the page or try again later."),""}}async function findClosestShippingDate(channels,stages){var _Mathmax2=Math.max;const latestStableVersion=channels?.stable?.version;if(!latestStableVersion||!stages)return{closestShippingDate:"",isUpcoming:!1,hasShipped:!1};let closestShippingDate="",isUpcoming=!1,hasShipped=!1;const shippingTypeMilestones=new Set;for(const stage of stages)(STAGE_TYPES_SHIPPING.has(stage.stage_type)||stage.stage_type===STAGE_ENT_ROLLOUT)&&(shippingTypeMilestones.add(stage.desktop_first),shippingTypeMilestones.add(stage.android_first),shippingTypeMilestones.add(stage.ios_first),shippingTypeMilestones.add(stage.webview_first));const upcomingMilestonesTarget=new Set([...shippingTypeMilestones]);let foundMilestone=0;if(upcomingMilestonesTarget.has(latestStableVersion+1)?(foundMilestone=latestStableVersion+1,isUpcoming=!0):upcomingMilestonesTarget.has(latestStableVersion+2)&&(foundMilestone=latestStableVersion+2,isUpcoming=!0),isUpcoming)Object.keys(channels).forEach(key=>{channels[key].version===foundMilestone&&(closestShippingDate=channels[key].final_beta||"")});else{const shippedMilestonesTarget=shippingTypeMilestones;let latestMilestone=0;for(const ms of shippedMilestonesTarget)ms&&ms<=latestStableVersion&&(latestMilestone=_Mathmax2(latestMilestone,ms));latestMilestone===latestStableVersion?(closestShippingDate=channels.stable?.final_beta||"",hasShipped=!0):(closestShippingDate=await fetchClosestShippingDate(latestMilestone),hasShipped=!0)}return{closestShippingDate,isUpcoming,hasShipped}}function isUpcomingFeatureOutdated(feature,isUpcoming,currentDate){return isUpcoming&&!isVerifiedWithinGracePeriod(feature.accurate_as_of,currentDate)}function getFeatureOutdatedBanner(feature,shippingInfo,currentDate,userCanEdit){currentDate||(currentDate=Date.now());const{closestShippingDate,hasShipped,isUpcoming}=shippingInfo;if(isUpcomingFeatureOutdated(feature,isUpcoming,currentDate))return userCanEdit?x$1` + <div class="warning layout horizontal center"> + <span class="tooltip" id="outdated-icon" title="Feature outdated "> + <sl-icon name="exclamation-circle-fill" data-tooltip></sl-icon> + </span> + <span> + Your feature hasn't been verified as accurate since  + <sl-relative-time + date=${feature.accurate_as_of??""} + ></sl-relative-time + >, but it is scheduled to ship  + <sl-relative-time date=${closestShippingDate}></sl-relative-time>. + Please + <a href="/guide/verify_accuracy/${feature.id}" + >verify that your feature is accurate</a + >. + </span> + </div> + `:x$1` + <div class="warning layout horizontal center"> + <span class="tooltip" id="outdated-icon" title="Feature outdated "> + <sl-icon name="exclamation-circle-fill" data-tooltip></sl-icon> + </span> + <span> + This feature hasn't been verified as accurate since  + <sl-relative-time + date=${feature.accurate_as_of??""} + ></sl-relative-time + >, but it is scheduled to ship  + <sl-relative-time date=${closestShippingDate}></sl-relative-time>. + </span> + </div> + `;if(isShippedFeatureOutdated(feature,hasShipped,closestShippingDate)){if(isShippedFeatureOutdatedForAuthor(feature,userCanEdit,hasShipped,closestShippingDate))return x$1` + <div class="warning layout horizontal center"> + <span + class="tooltip" + id="shipped-outdated-author" + title="Feature outdated " + > + <sl-icon name="exclamation-circle-fill" data-tooltip></sl-icon> + </span> + <span> + Your feature hasn't been verified as accurate since  + <sl-relative-time + date=${feature.accurate_as_of??""} + ></sl-relative-time + >, but it claims to have shipped  + <sl-relative-time date=${closestShippingDate}></sl-relative-time>. + Please + <a href="/guide/verify_accuracy/${feature.id}" + >verify that your feature is accurate</a + >. + </span> + </div> + `;if(isShippedFeatureOutdatedForAll(feature,hasShipped,currentDate,closestShippingDate))return x$1` + <div class="warning layout horizontal center"> + <span + class="tooltip" + id="shipped-outdated-all" + title="Feature outdated " + > + <sl-icon name="exclamation-circle-fill" data-tooltip></sl-icon> + </span> + <span> + This feature hasn't been verified as accurate since  + <sl-relative-time + date=${feature.accurate_as_of??""} + ></sl-relative-time + >, but it claims to have shipped  + <sl-relative-time date=${closestShippingDate}></sl-relative-time>. + </span> + </div> + `}return null}var __decorate$18=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashAdminBlinkPage=class ChromedashAdminBlinkPage extends i$4{constructor(){super(...arguments),this.loading=!0,this.user=null,this._editMode=!1,this._client=window.csOpenApiClient}static get styles(){return[SHARED_STYLES,VARS,LAYOUT_CSS,i$7` + body { + scroll-behavior: smooth; + } + + #spinner { + display: none !important; + } + + #subheader .subheader_toggles { + display: flex !important; + justify-content: flex-end; + flex: 1 0 auto; + } + + #subheader ul { + list-style-type: none; + margin-left: var(--content-padding); + } + + #subheader ul li { + text-align: center; + border-radius: var(--default-border-radius); + box-shadow: 1px 1px 4px var(--bar-shadow-color); + padding: 0.5em; + background: var(--chromium-color-dark); + color: #fff; + font-weight: 500; + text-transform: uppercase; + } + + #subheader ul li a { + color: inherit; + text-decoration: none; + } + + #subheader .view_owners_linke { + margin-left: var(--content-padding); + } + + #components_list { + list-style: none; + margin-bottom: calc(var(--content-padding) * 4); + } + + #components_list li { + padding: var(--content-padding) 0; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){this.loading=!0,this._client.listComponentUsers().then(response=>{this.usersMap=new Map(response.users.map(user=>[user.id,user])),this.components=response.components,this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}_onEditModeToggle(){this._editMode=!this._editMode}_addComponentUserListener(e){const component=Object.assign({},this.components[e.detail.index]);return e.detail.isError?void showToastMessage(`"Unable to add ${this.usersMap.get(e.detail.userId).name} to ${component.name}".`):void(!component.subscriber_ids?.includes(e.detail.userId)&&(component.subscriber_ids=[...(component.subscriber_ids??[]),e.detail.userId]),e.detail.toggleAsOwner&&(component.owner_ids=[...(component.owner_ids??[]),e.detail.userId]),showToastMessage(`"${this.usersMap.get(e.detail.userId).name} added to ${component.name}".`),this.components[e.detail.index]=component,this.requestUpdate())}_removeComponentUserListener(e){const component=Object.assign({},this.components[e.detail.index]);return e.detail.isError?void showToastMessage(`"Unable to remove ${this.usersMap.get(e.detail.userId).name} from ${component.name}".`):void(component.subscriber_ids=component.subscriber_ids.filter(currentUserId=>e.detail.userId!==currentUserId),e.detail.toggleAsOwner&&(component.owner_ids=component.owner_ids.filter(currentUserId=>e.detail.userId!==currentUserId)),showToastMessage(`"${this.usersMap.get(e.detail.userId).name} removed from ${component.name}".`),this.components[e.detail.index]=component,this.requestUpdate())}renderSubheader(){return x$1` + <div id="subheader"> + <div class="layout horizontal center"> + <div> + <h2>Blink components</h2> + ${this.loading?x$1`<div>loading components</div>`:x$1`<div id="component-count"> + listing ${this.components.length} components + </div>`} + </div> + </div> + <div class="layout horizontal subheader_toggles"> + <label + ><input + type="checkbox" + ?checked="${this._editMode}" + @change="${this._onEditModeToggle}" + />Edit mode</label + > + </div> + </div> + `}scrollToPosition(){if(location.hash){const hash=decodeURIComponent(location.hash);if(hash){const el=this.shadowRoot.querySelector(hash);el.scrollIntoView({behavior:"smooth"})}}}renderComponents(){return x$1` + <ul id="components_list"> + ${this.components.map((component,index)=>x$1` + <li class="layout horizontal" id="${component.name}"> + <chromedash-admin-blink-component-listing + .componentId=${component.id} + .name=${component.name} + .subscriberIds=${component.subscriber_ids??[]} + .ownerIds=${component.owner_ids??[]} + .index=${index} + .usersMap=${this.usersMap} + ?editing=${this._editMode} + @adminRemoveComponentUser=${this._removeComponentUserListener} + @adminAddComponentUser=${this._addComponentUserListener} + ></chromedash-admin-blink-component-listing> + </li> + `)} + </ul> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?x$1``:this.renderComponents()} + `}};__decorate$18([n$5({type:Boolean})],ChromedashAdminBlinkPage.prototype,"loading",void 0),__decorate$18([n$5({type:Object})],ChromedashAdminBlinkPage.prototype,"user",void 0),__decorate$18([n$5({type:Boolean})],ChromedashAdminBlinkPage.prototype,"_editMode",void 0),__decorate$18([r$6()],ChromedashAdminBlinkPage.prototype,"components",void 0),__decorate$18([r$6()],ChromedashAdminBlinkPage.prototype,"usersMap",void 0),ChromedashAdminBlinkPage=__decorate$18([t$3("chromedash-admin-blink-page")],ChromedashAdminBlinkPage);var __decorate$17=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashAdminFeatureLinksPage=class ChromedashAdminFeatureLinksPage extends i$4{constructor(){super(...arguments),this.sampleId="",this.samplesLoading=!1,this.loading=!0,this.featureLinksSamples=[]}static get styles(){return[SHARED_STYLES,VARS,LAYOUT_CSS,i$7` + .feature-links-summary .line { + padding: var(--content-padding-half); + display: flex; + align-items: center; + justify-content: space-between; + font-size: 16px; + } + .feature-links-samples .line { + background: rgb(232, 234, 237); + } + sl-icon-button::part(base) { + padding: 0; + margin-left: 8px; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}async fetchData(){try{this.loading=!0,this.featureLinksSummary=await window.csClient.getFeatureLinksSummary()}catch{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}finally{this.loading=!1}}calcSampleId(domain,type,isError){return`domain=${domain}&type=${type}&isError=${isError}`}async fetchLinkSamples(domain,type,isError){this.sampleId=this.calcSampleId(domain,type,isError),this.featureLinksSamples=[],this.samplesLoading=!0;try{this.featureLinksSamples=await window.csClient.getFeatureLinksSamples(domain,type,isError)}catch{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}finally{this.samplesLoading=!1}}renderSamples(){return this.samplesLoading?x$1`<sl-spinner></sl-spinner>`:x$1` + <div class="feature-links-samples"> + ${this.featureLinksSamples.map(sample=>x$1` + <div class="line"> + <div> + <a href=${sample.url}><i>${sample.url}</i></a> + ${sample.http_error_code?x$1`<i>(${sample.http_error_code})</i>`:E$1} + </div> + <a + href=${`/feature/${sample.feature_ids}`} + target="_blank" + rel="noopener" + > + <sl-icon + library="material" + name="link" + slot="prefix" + title="linked feature" + ></sl-icon> + </a> + </div> + `)} + </div> + `}renderComponents(){return x$1` + <div class="feature-links-summary"> + <sl-details summary="Link Summary" open> + <div class="line"> + All Links <b>${this.featureLinksSummary.total_count}</b> + </div> + <div class="line"> + Covered Links <b>${this.featureLinksSummary.covered_count}</b> + </div> + <div class="line"> + Uncovered (aka "web") Links + <b>${this.featureLinksSummary.uncovered_count}</b> + </div> + <div class="line"> + All Error Links<b>${this.featureLinksSummary.error_count}</b> + </div> + <div class="line"> + HTTP Error Links<b>${this.featureLinksSummary.http_error_count}</b> + </div> + </sl-details> + <sl-details summary="Link Types" open> + ${this.featureLinksSummary.link_types.map(linkType=>x$1` + <div class="line"> + ${linkType.key.toUpperCase()} <b>${linkType.count}</b> + </div> + `)} + </sl-details> + <sl-details summary="Uncovered Link Domains" open> + ${this.featureLinksSummary.uncovered_link_domains.map(domain=>x$1` + <div class="line"> + <div> + <a href=${domain.key}>${domain.key}</a> + <sl-icon-button + library="material" + name="search" + slot="prefix" + title="Samples" + @click=${()=>this.fetchLinkSamples(domain.key,"web",void 0)} + > + ></sl-icon-button + > + </div> + <b>${domain.count}</b> + </div> + ${this.sampleId===this.calcSampleId(domain.key,"web",void 0)?this.renderSamples():E$1} + `)} + </sl-details> + <sl-details summary="Error Link Domains" open> + ${this.featureLinksSummary.error_link_domains.map(domain=>x$1` + <div class="line"> + <div> + <a href=${domain.key}>${domain.key}</a> + <sl-icon-button + library="material" + name="search" + slot="prefix" + title="Samples" + @click=${()=>this.fetchLinkSamples(domain.key,void 0,!0)} + > + ></sl-icon-button + > + </div> + <b>${domain.count}</b> + </div> + ${this.sampleId===this.calcSampleId(domain.key,void 0,!0)?this.renderSamples():E$1} + `)} + </sl-details> + </div> + `}render(){return x$1` ${this.loading?x$1``:this.renderComponents()} `}};__decorate$17([r$6()],ChromedashAdminFeatureLinksPage.prototype,"sampleId",void 0),__decorate$17([r$6()],ChromedashAdminFeatureLinksPage.prototype,"samplesLoading",void 0),__decorate$17([r$6()],ChromedashAdminFeatureLinksPage.prototype,"loading",void 0),__decorate$17([r$6()],ChromedashAdminFeatureLinksPage.prototype,"featureLinksSamples",void 0),__decorate$17([r$6()],ChromedashAdminFeatureLinksPage.prototype,"featureLinksSummary",void 0),ChromedashAdminFeatureLinksPage=__decorate$17([t$3("chromedash-admin-feature-links-page")],ChromedashAdminFeatureLinksPage);const TEXT_KIND="text",NUM_KIND="number",MILESTONE_KIND="milestone",DATE_KIND="YYYY-MM-DD",EMAIL_KIND="user@example.com",ENUM_KIND="enum",QUERIABLE_FIELDS=[{name:"created.when",kind:DATE_KIND,doc:"Date that the feature entry was created"},{name:"updated.when",kind:DATE_KIND,doc:"Date that the feature was most recently edited"},{name:"name",kind:"text",doc:"The name of the feature"},{name:"tag",kind:"text",doc:"Search tags for finding feature entries"},{name:"web_feature_id",kind:"text",doc:"String ID of a related WebDX feature"},{name:"owner",kind:EMAIL_KIND,doc:"One of the feature owners"},{name:"shipping_year",kind:NUM_KIND,doc:"Estimated shipping year"},{name:"browsers.chrome.devrel",kind:EMAIL_KIND,doc:"Developer relations contact"},{name:"browsers.chrome.desktop",kind:MILESTONE_KIND,doc:"Desktop shipping milestone"},{name:"browsers.chrome.android",kind:MILESTONE_KIND,doc:"Android shipping milestone"},{name:"browsers.chrome.ios",kind:MILESTONE_KIND,doc:"iOS shipping milestone"},{name:"browsers.chrome.webview",kind:MILESTONE_KIND,doc:"Webview shipping milestone"},{name:"browsers.chrome.flag_name",kind:"text",doc:"Flag name that allows developers to enable the feature"},{name:"browsers.chrome.finch_name",kind:"text",doc:"Finch name"},{name:"browsers.chrome.devtrial.desktop.start",kind:MILESTONE_KIND,doc:"Desktop DevTrial start"},{name:"browsers.chrome.devtrial.android.start",kind:MILESTONE_KIND,doc:"Android DevTrial start"},{name:"browsers.chrome.devtrial.ios.start",kind:MILESTONE_KIND,doc:"iOS DevTrial start"},{name:"browsers.chrome.devtrial.webview.start",kind:MILESTONE_KIND,doc:"WebView DevTrial start"},{name:"browsers.chrome.ot.desktop.start",kind:MILESTONE_KIND,doc:"Desktop Origin Trial start"},{name:"browsers.chrome.ot.desktop.end",kind:MILESTONE_KIND,doc:"Desktop Origin Trial end"},{name:"browsers.chrome.ot.android.start",kind:MILESTONE_KIND,doc:"Android Origin Trial start"},{name:"browsers.chrome.ot.android.end",kind:MILESTONE_KIND,doc:"Android Origin Trial end"},{name:"browsers.chrome.ot.webview.start",kind:MILESTONE_KIND,doc:"WebView Origin Trial start"},{name:"browsers.chrome.ot.webview.end",kind:MILESTONE_KIND,doc:"WebView Origin Trial end"},{name:"rollout_milestone",kind:MILESTONE_KIND,doc:"Stable rollout milestone"},{name:"rollout_stage_plan",kind:ENUM_KIND,doc:"Stage rollout plan"},{name:"any_start_milestone",kind:MILESTONE_KIND,doc:"A milestone in which the feature is scheduled to ship or start an origin trial or dev trial, on any platform"},{name:"category",kind:ENUM_KIND,doc:"Feature category",choices:FEATURE_CATEGORIES},{name:"enterprise_product_category",kind:ENUM_KIND,doc:"Enterprise product category",choices:ENTERPRISE_PRODUCT_CATEGORY},{name:"feature_type",kind:ENUM_KIND,doc:"Feature type",choices:FEATURE_TYPES},{name:"impl_status_chrome",kind:ENUM_KIND,doc:"Implementation status",choices:IMPLEMENTATION_STATUS},{name:"intent_stage",kind:ENUM_KIND,doc:"Spec process stage",choices:INTENT_STAGES},{name:"security_review_status",kind:ENUM_KIND,doc:"Security review status",choices:REVIEW_STATUS_CHOICES},{name:"privacy_review_status",kind:ENUM_KIND,doc:"Privacy review status",choices:REVIEW_STATUS_CHOICES},{name:"tag_review_status",kind:ENUM_KIND,doc:"TAG Specification Review Status",choices:REVIEW_STATUS_CHOICES},{name:"browsers.webkit.view",kind:ENUM_KIND,doc:"WebKit views",choices:VENDOR_VIEWS_COMMON},{name:"browsers.ff.view",kind:ENUM_KIND,doc:"Firefox views",choices:VENDOR_VIEWS_GECKO},{name:"browsers.webdev.view",kind:ENUM_KIND,doc:"Web / Framework developer views",choices:WEB_DEV_VIEWS},{name:"accurate_as_of",kind:DATE_KIND,doc:"When the feature's fields were last verified"}];var __decorate$16=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let searchHelpDialogEl;async function openSearchHelpDialog(){searchHelpDialogEl||(searchHelpDialogEl=document.createElement("chromedash-search-help-dialog"),document.body.appendChild(searchHelpDialogEl),await searchHelpDialogEl.updateComplete),searchHelpDialogEl.show()}let ChromedashSearchHelpDialog=class ChromedashSearchHelpDialog extends i$4{static get styles(){return[...SHARED_STYLES,i$7` + h3 { + margin: var(--content-padding-large) 0; + } + section { + margin-left: var(--content-padding); + } + p { + margin: var(--content-padding-half) 0; + } + #dialog-content { + max-width: 60rem; + } + li { + margin-left: var(--content-padding); + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}renderExampleRow(terms,explanation){return x$1` + <tr> + <td>${terms.map(term=>x$1`<div><code>${term}</code></div>`)}</td> + <td>${explanation}</td> + </tr> + `}renderCommonSearchExamples(){return x$1` + <h3>Common search examples</h3> + <section> + <table class="data-table"> + ${this.renderExampleRow(["memory","memory pool","memory -pool"],"Features that include or exclude words in any field.")} + ${this.renderExampleRow(["browsers.chrome.desktop:123","browsers.chrome.desktop:current_stable+1"],"Features shipping in the specified milestone.")} + ${this.renderExampleRow(["browsers.chrome.desktop:120..122","browsers.chrome.desktop:current_stable-1..current_stable+1"],"Features shipping in a milestone range.")} + ${this.renderExampleRow(["owner:user@example.com"],"Features with the specified owner.")} + ${this.renderExampleRow(["created.when>2024-01-01","created.when<now-8w","updated.when:2023-01-01..2023-12-31"],"Features created or modified before or after a date.")} + ${this.renderExampleRow(["feature_type:\"Feature deprecation\"","feature_type!=\"Feature deprecation\"","-feature_type:\"Feature deprecation\""],"Features of a specific type or excluding a type.")} + ${this.renderExampleRow(["category:CSS,DOM"],"Features that have a value in a comma-separated list.")} + ${this.renderExampleRow(["category:CSS OR category:DOM"],"Combine two query clauses with a logical-OR.")} + </table> + </section> + `}renderSearchSyntax(){return x$1` + <h3>Search syntax</h3> + <section> + <p> + A search query consists of a series of terms that are separated by + spaces. Terms can be single words or conditions. + </p> + + <p> + When searching for words, the results will include features that + include those words in any field of the feature entry. We do not + support searching for wildcards, partial words, punctuation, or quoted + phrases. + </p> + + <p> + When searching using conditions, each condition consists of three + parts: FIELD OPERATOR VALUE(S) + </p> + + <ul> + <li>FIELD: One of the fields listed below.</li> + <li> + OPERATOR: Usually a colon, but it can be an inequality for numeric, + date, or enum fields. The colon operator does case-insensitive + matching of words within a text field, while an equals-sign does + exact matching of an entire string value. + </li> + <li> + VALUE(S): A single word, number, date, or enum value listed below. + If the value contains spaces, it must be inside double quotes. + <ul> + <li> + Use the equals operator with a comma-separated list to match any + value in that list. + </li> + <li> + Use the equals operator with two number or date values separated + by "<code>..</code>" to find any value between or including + those endpoints. The left value must be less than the right + value. + </li> + <li> + For dates, you can compute a date a certain number of days or + weeks before or after now. "<code>now-3d</code>" is 3 days ago, + and "<code>now+2w</code>" is 2 weeks from now. + </li> + <li> + For milestones, you can compute a milestone relative to the + current stable version of Chrome. + "<code>current_stable+1</code>" is 1 version after the current + stable version. + </li> + </ul> + </li> + </ul> + + <p> + You may negate any search term by prefixing it with a minus sign. + Search terms are implicitly joined together by a logical-AND. However, + you may type the keyword <code>OR</code> between terms as a logical-OR + operator. We do not support parenthesis in queries. + </p> + </section> + `}renderFieldRow(queryField){if(queryField.choices){const choiceItems=Object.values(queryField.choices).map(c=>x$1` <div>${queryField.name}:"${c[1]}"</div> `);return x$1` + <tr> + <td> + <code>${choiceItems}</code> + </td> + <td>${queryField.doc}</td> + </tr> + `}return x$1` + <tr> + <td> + <code>${queryField.name}:<i>${queryField.kind}</i></code> + </td> + <td>${queryField.doc}</td> + </tr> + `}renderFieldList(){return x$1` + <h3>Available search fields</h3> + <section> + <table class="data-table"> + ${QUERIABLE_FIELDS.map(qf=>this.renderFieldRow(qf))} + </table> + </section> + `}renderDialogContent(){return x$1` + <div id="dialog-content"> + ${this.renderCommonSearchExamples()} ${this.renderSearchSyntax()} + ${this.renderFieldList()} + </div> + `}render(){return x$1` + <sl-dialog + class="missing-prereqs" + label="Feature Search Help" + style="--width:fit-content" + > + ${this.renderDialogContent()} + </sl-dialog> + `}};ChromedashSearchHelpDialog=__decorate$16([t$3("chromedash-search-help-dialog")],ChromedashSearchHelpDialog);var __decorate$15=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};function convertQueriableFieldToVocabularyItems(qf){if(qf.choices===void 0)return[{group:qf.name,name:qf.name+":",doc:qf.doc}];const result=[];for(const ch in qf.choices){const label=qf.choices[ch][1];result.push({group:qf.name,name:qf.name+":\""+label+"\"",doc:qf.doc})}return result}const VOCABULARY=QUERIABLE_FIELDS.map(convertQueriableFieldToVocabularyItems).flat();let ChromedashFeatureFilter=class ChromedashFeatureFilter extends i$4{constructor(){super(...arguments),this.typeaheadRef=e$1(),this.query="",this.handleDocumentKeyUp=e=>{const inInputContext=e.composedPath().some(el=>["INPUT","TEXTAREA","SL-POPUP","SL-DIALOG"].includes(el.tagName));"/"!==e.key||inInputContext||(e.preventDefault(),e.stopPropagation(),(this.typeaheadRef?.value).focus())}}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}connectedCallback(){super.connectedCallback(),document.addEventListener("keyup",this.handleDocumentKeyUp)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("keyup",this.handleDocumentKeyUp)}handleSearchClick(){const typeahead=this.typeaheadRef.value;if(typeahead){typeahead.hide();const newQuery=typeahead.value.trim();this._fireEvent("search",{query:newQuery})}}static get styles(){return[...SHARED_STYLES,i$7` + sl-icon-button { + font-size: 1.6rem; + margin: 0 !important; + } + `]}showHelp(event){event.stopPropagation();const typeahead=this.typeaheadRef.value;typeahead&&(typeahead.hide(),openSearchHelpDialog())}render(){return x$1` + <chromedash-typeahead + ${n$2(this.typeaheadRef)} + value=${this.query} + placeholder="Search" + .vocabulary=${VOCABULARY} + @sl-change=${this.handleSearchClick} + > + <sl-icon-button + library="material" + name="search" + slot="prefix" + @click="${this.handleSearchClick}" + > + </sl-icon-button> + <sl-icon-button + library="material" + name="help_20px" + slot="suffix" + @click="${this.showHelp}" + > + </sl-icon-button> + </chromedash-typeahead> + `}};__decorate$15([n$5({type:String})],ChromedashFeatureFilter.prototype,"query",void 0),ChromedashFeatureFilter=__decorate$15([t$3("chromedash-feature-filter")],ChromedashFeatureFilter);function*o$1(o,t,e=1){const i=void 0===t?0:o;t??=o;for(let o=i;0<e?o<t:t<o;o+=e)yield o}function*o(o,f){if(void 0!==o){let i=0;for(const t of o)yield f(t,i++)}}var __decorate$14=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFeaturePagination=class ChromedashFeaturePagination extends i$4{constructor(){super(...arguments),this.totalCount=0,this.start=0,this.pageSize=100}static get styles(){return[SHARED_STYLES,i$7` + .active { + background: var(--light-grey); + } + .stepper { + width: 7em; + } + .pagination { + padding: var(--content-padding-half) 0; + min-height: 50px; + } + .pagination span { + color: var(--unimportant-text-color); + margin-right: var(--content-padding); + } + sl-button::part(base):hover { + background: var(--sl-color-blue-100); + } + .pagination sl-icon-button { + font-size: 1.6rem; + } + .pagination sl-icon-button::part(base) { + padding: 0; + } + #items-per-page { + align-self: center; + color: var(--unimportant-text-color); + font-size: var(--sl-input-font-size-small); + } + sl-select { + align-self: center; + display: inline-block; + margin: 0 var(--content-padding-quarter) 0 var(--content-padding); + width: 7em; + } + `]}renderPageButtons(){var _Mathceil=Math.ceil,_Mathfloor=Math.floor;if(void 0===this.totalCount||0===this.totalCount)return x$1``;const currentPage=_Mathfloor(this.start/this.pageSize),numPages=_Mathceil(this.totalCount/this.pageSize);let missingFront=!1,missingBack=!1,hasLastPage=1<numPages,displayPages=[];const displaySet=new Set;for(const digit of o$1(numPages))if(0!==digit&&digit!==numPages-1){if(10>=numPages){displaySet.add(digit);continue}if(digit<currentPage-4){missingFront=!0;continue}if(digit>currentPage+4){missingBack=!0;continue}displaySet.add(digit)}return displayPages=Array.from(displaySet),x$1` + <sl-button + variant="text" + id="jump_1" + class="page-button ${0===currentPage?"active":""}" + href=${formatUrlForOffset(0)} + > + ${1} + </sl-button> + ${missingFront?x$1`<div>...</div>`:E$1} + ${o(displayPages,i=>x$1` + <sl-button + variant="text" + id="jump_${i+1}" + class="page-button ${i===currentPage?"active":""}" + href=${formatUrlForOffset(i*this.pageSize)} + > + ${i+1} + </sl-button> + `)} + ${missingBack?x$1`<div>...</div>`:E$1} + ${hasLastPage?x$1`<sl-button + variant="text" + id="jump_${numPages}" + class="page-button ${numPages-1===currentPage?"active":""}" + href=${formatUrlForOffset((numPages-1)*this.pageSize)} + > + ${numPages} + </sl-button>`:E$1} + `}setItemsPerPage(event){const target=event.target,newSize=parseInt(target.value),newURL=formatURLParams("num",newSize).toString();window.location.href=newURL}renderItemsPerPage(){const options=[25,50,100];return options.includes(this.pageSize)||(options.push(this.pageSize),options.sort((a,b)=>a-b)),x$1` + <sl-select + value="${this.pageSize}" + size="small" + @sl-change=${this.setItemsPerPage} + > + ${options.map(opt=>x$1` + <sl-option id="opt_${opt}" value=${opt}>${opt}</sl-option> + `)} + </sl-select> + <span id="items-per-page"> items per page </span> + `}render(){if(this.totalCount===void 0||0===this.totalCount)return x$1``;const prevUrl=formatUrlForRelativeOffset(this.start,-this.pageSize,this.pageSize,this.totalCount),nextUrl=formatUrlForRelativeOffset(this.start,this.pageSize,this.pageSize,this.totalCount);return x$1` + <div id="main" class="pagination hbox halign-items-space-between"> + <div class="spacer"></div> + <sl-button + variant="text" + id="previous" + class="stepper" + href=${o$6(prevUrl)} + ?disabled=${prevUrl===void 0} + >Previous</sl-button + > + + ${this.renderPageButtons()} + + <sl-button + variant="text" + id="next" + class="stepper" + href=${o$6(nextUrl)} + ?disabled=${nextUrl===void 0} + >Next</sl-button + > + + ${this.renderItemsPerPage()} + + <div class="spacer"></div> + </div> + `}};__decorate$14([n$5({type:Number})],ChromedashFeaturePagination.prototype,"totalCount",void 0),__decorate$14([n$5({type:Number})],ChromedashFeaturePagination.prototype,"start",void 0),__decorate$14([n$5({type:Number})],ChromedashFeaturePagination.prototype,"pageSize",void 0),ChromedashFeaturePagination=__decorate$14([t$3("chromedash-feature-pagination")],ChromedashFeaturePagination);var __decorate$13=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFeatureRow=class ChromedashFeatureRow extends i$4{constructor(){super(...arguments),this.columns=void 0,this.canEdit=!1,this.signedIn=!1,this.starredFeatures=new Set,this.gates={},this.selectedGateId=0}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: table-row; + background: var(--table-row-background); + } + td { + padding: var(--content-padding-half); + border-bottom: var(--table-divider); + } + td.name_col { + width: 100%; + } + td.icon_col { + white-space: nowrap; + vertical-align: top; + } + td.icon_col a { + padding: 2px 4px; + } + td.icon_col a:hover { + text-decoration: none; + } + .quick_actions { + white-space: nowrap; + float: right; + } + .highlights { + padding-left: var(--content-padding); + } + .highlights div { + color: var(--unimportant-text-color); + padding: var(--content-padding-quarter); + } + sl-icon-button { + font-size: 1.3rem; + } + sl-icon-button::part(base) { + color: var(--link-color); + } + `]}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}toggleStar(e){e.preventDefault(),e.stopPropagation();const iconEl=e.target,featureId=+iconEl.dataset.featureId,newStarred=!this.starredFeatures.has(featureId);this._fireEvent("star-toggle-event",{featureId:featureId,doStar:newStarred})}renderStarIcon(feature){return x$1` + <sl-icon-button + @click=${this.toggleStar} + title="Receive an email notification when there are updates" + library="material" + name="${this.starredFeatures.has(+feature.id)?"star":"star_border"}" + data-feature-id="${feature.id}" + ></sl-icon-button> + `}renderIcons(feature){return this.signedIn?x$1` ${this.renderStarIcon(feature)} `:E$1}renderQuickActions(feature){if("approvals"==this.columns){const threadLinks=feature?[]:[];return x$1` <span class="quick_actions"> ${threadLinks} </span> `}return E$1}isActiveGate(gate){return GATE_ACTIVE_REVIEW_STATES.includes(gate.state)}getActiveStages(feature){const featureGates=this.gates[feature.id]||[],activeGates=featureGates.filter(g=>this.isActiveGate(g)),activeStageIds=new Set(activeGates.map(g=>g.stage_id)),activeStagesAndTheirGates=[];for(const stage of feature.stages){activeStageIds.has(stage.id)&&activeStagesAndTheirGates.push({stage:stage,gates:featureGates.filter(g=>g.stage_id==stage.id)});for(const extension of stage.extensions||[])activeStageIds.has(extension.id)&&activeStagesAndTheirGates.push({stage:extension,gates:featureGates.filter(g=>g.stage_id==extension.id)})}return activeStagesAndTheirGates}getStageShortName(stage){return STAGE_SHORT_NAMES[stage.stage_type]?`${STAGE_SHORT_NAMES[stage.stage_type]}: `:E$1}renderActiveStageAndGates(stageAndGates){const sortedGates=stageAndGates.gates;return sortedGates.sort((g1,g2)=>GATE_TEAM_ORDER.indexOf(g1.team_name)-GATE_TEAM_ORDER.indexOf(g2.team_name)),x$1` + <div> + ${this.getStageShortName(stageAndGates.stage)} + ${sortedGates.map(gate=>x$1` + <chromedash-gate-chip + .feature=${this.feature} + .stage=${stageAndGates.stage} + .gate=${gate} + selectedGateId=${this.selectedGateId} + ></chromedash-gate-chip> + `)} + </div> + `}renderHighlights(feature){if("approvals"==this.columns){const activeStages=this.getActiveStages(feature);return x$1` + <div class="highlights"> + ${0<activeStages.length?x$1` + <div> + ${activeStages.map(stageAndGates=>this.renderActiveStageAndGates(stageAndGates))} + </div> + `:E$1} + ${this.renderQuickActions(feature)} + </div> + `}return E$1}render(){const feature=this.feature;return x$1` + <td class="name_col"> + <a href="/feature/${feature.id}">${feature.name}</a> + ${this.renderHighlights(feature)} + </td> + <td class="icon_col">${this.renderIcons(feature)}</td> + `}};__decorate$13([n$5({attribute:!1})],ChromedashFeatureRow.prototype,"feature",void 0),__decorate$13([n$5({type:String})],ChromedashFeatureRow.prototype,"columns",void 0),__decorate$13([n$5({type:Boolean})],ChromedashFeatureRow.prototype,"canEdit",void 0),__decorate$13([n$5({type:Boolean})],ChromedashFeatureRow.prototype,"signedIn",void 0),__decorate$13([n$5({attribute:!1})],ChromedashFeatureRow.prototype,"starredFeatures",void 0),__decorate$13([n$5({attribute:!1})],ChromedashFeatureRow.prototype,"gates",void 0),__decorate$13([n$5({type:Number})],ChromedashFeatureRow.prototype,"selectedGateId",void 0),ChromedashFeatureRow=__decorate$13([t$3("chromedash-feature-row")],ChromedashFeatureRow);var __decorate$12=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFeatureTable=class ChromedashFeatureTable extends i$4{constructor(){super(...arguments),this.loading=!0,this.reloading=!1,this.features=[],this.totalCount=0,this.start=0,this.query="",this.showEnterprise=!1,this.sortSpec="",this.showQuery=!1,this.starredFeatures=new Set,this.num=100,this.alwaysOfferPagination=!1,this.noResultsMessage="No results",this.noPaginatedResultsMessage="No results on this pagination page",this.canEdit=!1,this.gates={},this.selectedGateId=0,this.nameOnly=!1}connectedCallback(){super.connectedCallback(),this.fetchFeatures(!0)}fetchFeatures(isInitialLoad=!1){this.loading=isInitialLoad,this.reloading=!isInitialLoad,window.csClient.searchFeatures(this.query,this.showEnterprise,this.sortSpec,this.start,this.num,this.nameOnly).then(resp=>{this.features=resp.features,this.totalCount=resp.total_count,this.loading=!1,this.reloading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}),"approvals"==this.columns&&this.loadGateData()}refetch(){this.fetchFeatures()}loadGateData(){window.csClient.getPendingGates().then(res=>{const gatesByFID={};for(const g of res.gates)gatesByFID.hasOwnProperty(g.feature_id)||(gatesByFID[g.feature_id]=[]),gatesByFID[g.feature_id].push(g);this.gates=gatesByFID}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}updated(changedProperties){"starred-by:me"==this.query&&!this.loading&&changedProperties.has("starredFeatures")&&this.fetchFeatures()}handleSearch(event){this.loading=!0,this.query=event.detail.query,this.start=0,this.fetchFeatures()}static get styles(){return[...SHARED_STYLES,i$7` + .status-and-count { + padding: var(--content-padding-half) 0; + min-height: 50px; + } + .status-and-count span { + color: var(--unimportant-text-color); + margin-right: var(--content-padding); + } + .status-and-count sl-icon-button { + font-size: 1.6rem; + } + .status-and-count sl-icon-button::part(base) { + padding: 0; + } + table { + width: 100%; + } + .skel td { + background: white; + padding: 14px; + border-bottom: var(--table-divider); + } + sl-skeleton { + height: 24px; + } + .message { + padding: var(--content-padding); + } + `]}renderMessages(){return this.loading?x$1` + <tr class="skel"> + <td> + <sl-skeleton effect="sheen" style="width: 50%"></sl-skeleton> + </td> + </tr> + <tr class="skel"> + <td> + <sl-skeleton effect="sheen" style="width: 65%"></sl-skeleton> + </td> + </tr> + <tr class="skel"> + <td> + <sl-skeleton effect="sheen" style="width: 40%"></sl-skeleton> + </td> + </tr> + <tr class="skel"> + <td> + <sl-skeleton effect="sheen" style="width: 50%"></sl-skeleton> + </td> + </tr> + `:0==this.totalCount?x$1` + <tr> + <td class="message">${this.noResultsMessage}</td> + </tr> + `:!!(0==this.features.length&&0<this.start)&&x$1` + <tr> + <td class="message">${this.noPaginatedResultsMessage}</td> + </tr> + `}renderSearch(){return this.showQuery?x$1` + <chromedash-feature-filter + .query=${this.query} + @search="${this.handleSearch}" + ></chromedash-feature-filter> + `:E$1}renderLoadingStatusAndCount(){const firstShown=this.start+1,lastShown=this.start+this.features.length,prevUrl=formatUrlForRelativeOffset(this.start,-this.num,this.num,this.totalCount),nextUrl=formatUrlForRelativeOffset(this.start,this.num,this.num,this.totalCount);if(this.alwaysOfferPagination){if(this.loading)return x$1` <div class="status-and-count"> + <sl-skeleton effect="sheen" style="float: right; width: 12em"> + </sl-skeleton> + </div>`;}else if(this.loading||1==firstShown&&lastShown==this.totalCount)return E$1;return 0===this.features.length?E$1:x$1` + <div class="status-and-count hbox"> + <span>${this.reloading?"Reloading...":E$1}</span> + <div class="spacer"></div> + <span>${firstShown} - ${lastShown} of ${this.totalCount}</span> + <sl-icon-button + library="material" + name="navigate_before" + title="Previous page" + href=${o$6(prevUrl)} + ?disabled=${void 0===prevUrl} + ></sl-icon-button> + <sl-icon-button + library="material" + name="navigate_next" + title="Next page" + href=${o$6(nextUrl)} + ?disabled=${void 0===nextUrl} + ></sl-icon-button> + </div> + `}renderPagination(features){const firstShown=this.start+1,lastShown=this.start+features.length;if(this.alwaysOfferPagination){if(this.loading)return x$1` <div class="pagination"> + <sl-skeleton effect="sheen" style="float: right; width: 12em"> + </sl-skeleton> + </div>`;}else if(this.loading||1==firstShown&&lastShown==this.totalCount)return E$1;return 0===features.length?E$1:x$1` + <chromedash-feature-pagination + pageSize=${this.num} + start=${this.start} + totalCount=${this.totalCount} + > + </chromedash-feature-pagination> + `}renderFeature(feature){return x$1` + <chromedash-feature-row + .feature=${feature} + columns=${this.columns} + ?signedIn=${this.signedIn} + ?canEdit=${this.canEdit} + .starredFeatures=${this.starredFeatures} + .gates=${this.gates} + selectedGateId=${this.selectedGateId} + ></chromedash-feature-row> + `}render(){return x$1` + ${this.renderSearch()} ${this.renderLoadingStatusAndCount()} + <table> + ${this.renderMessages()||this.features.map(feature=>this.renderFeature(feature))} + </table> + ${this.renderPagination(this.features)} + `}};__decorate$12([r$6()],ChromedashFeatureTable.prototype,"loading",void 0),__decorate$12([r$6()],ChromedashFeatureTable.prototype,"reloading",void 0),__decorate$12([r$6()],ChromedashFeatureTable.prototype,"features",void 0),__decorate$12([r$6()],ChromedashFeatureTable.prototype,"totalCount",void 0),__decorate$12([n$5({type:Number,attribute:!1})],ChromedashFeatureTable.prototype,"start",void 0),__decorate$12([n$5({type:String})],ChromedashFeatureTable.prototype,"query",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"showEnterprise",void 0),__decorate$12([n$5({type:String,attribute:!1})],ChromedashFeatureTable.prototype,"sortSpec",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"showQuery",void 0),__decorate$12([n$5({type:Object,attribute:!1})],ChromedashFeatureTable.prototype,"starredFeatures",void 0),__decorate$12([n$5({type:Number,attribute:!1})],ChromedashFeatureTable.prototype,"num",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"alwaysOfferPagination",void 0),__decorate$12([n$5({type:String})],ChromedashFeatureTable.prototype,"noResultsMessage",void 0),__decorate$12([n$5({type:String})],ChromedashFeatureTable.prototype,"noPaginatedResultsMessage",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"canEdit",void 0),__decorate$12([n$5({type:Object})],ChromedashFeatureTable.prototype,"gates",void 0),__decorate$12([n$5({type:Number})],ChromedashFeatureTable.prototype,"selectedGateId",void 0),__decorate$12([n$5({type:String})],ChromedashFeatureTable.prototype,"columns",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"signedIn",void 0),__decorate$12([n$5({type:Boolean})],ChromedashFeatureTable.prototype,"nameOnly",void 0),ChromedashFeatureTable=__decorate$12([t$3("chromedash-feature-table")],ChromedashFeatureTable);var __decorate$11=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashAllFeaturesPage=class ChromedashAllFeaturesPage extends i$4{constructor(){super(...arguments),this.title="Features",this.showQuery=!0,this.selectedGateId=0,this.rawQuery={},this.query="",this.columns="normal",this.showEnterprise=!1,this.sortSpec="",this.start=0,this.num=100,this.starredFeatures=new Set,this.isNewfeaturesPage=!1,this.nameOnly=!1}static get styles(){return[SHARED_STYLES,i$7` + #content-title { + padding-top: var(--content-padding); + } + `]}connectedCallback(){super.connectedCallback(),this.initializeParams(),this.fetchData()}initializeParams(){var _NumberisNaN=Number.isNaN;this.rawQuery&&(null!=this.rawQuery.q&&(this.query=this.rawQuery.q),null!=this.rawQuery.columns&&(this.columns=this.rawQuery.columns),null!=this.rawQuery.enterprise&&(this.showEnterprise=!0),null!=this.rawQuery.sort&&(this.sortSpec=this.rawQuery.sort),null!=this.rawQuery.start&&!_NumberisNaN(parseInt(this.rawQuery.start))&&(this.start=parseInt(this.rawQuery.start)),null!=this.rawQuery.num&&!_NumberisNaN(parseInt(this.rawQuery.num))&&(this.num=parseInt(this.rawQuery.num),this.num=Math.max(1,Math.min(this.num,1e3))),this.isNewfeaturesPage&&(this.nameOnly=!0))}fetchData(){window.csClient.getStars().then(starredFeatures=>{this.starredFeatures=new Set(starredFeatures)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}refetch(){const tables=this.chromedashFeatureTables;for(const table of tables)table.refetch()}handleStarToggle(e){const newStarredFeatures=new Set(this.starredFeatures);window.csClient.setStar(e.detail.featureId,e.detail.doStar).then(()=>{e.detail.doStar?newStarredFeatures.add(e.detail.featureId):newStarredFeatures.delete(e.detail.featureId),this.starredFeatures=newStarredFeatures}).catch(()=>{alert("Unable to star the Feature. Please Try Again.")})}renderFeatureList(){return x$1` + <chromedash-feature-table + .query=${this.query} + ?showEnterprise=${this.showEnterprise} + .sortSpec=${this.sortSpec} + .start=${this.start} + .num=${this.num} + .nameOnly=${this.nameOnly} + ?showQuery=${this.showQuery} + ?signedIn=${!!this.user} + ?canEdit=${this.user&&this.user.can_edit_all} + .starredFeatures=${this.starredFeatures} + @star-toggle-event=${this.handleStarToggle} + selectedGateId=${this.selectedGateId} + alwaysOfferPagination + columns=${this.columns} + > + </chromedash-feature-table> + `}render(){const adminNotice=this.user?.is_admin&&"approvals"===this.columns?x$1`<p> + You see all pending approvals because you're a site admin. + </p>`:E$1;return x$1` + <div id="content-title"> + <h2>${this.title}</h2> + </div> + ${adminNotice} ${this.renderFeatureList()} + `}};__decorate$11([n$5({type:String})],ChromedashAllFeaturesPage.prototype,"title",void 0),__decorate$11([n$5({type:Boolean})],ChromedashAllFeaturesPage.prototype,"showQuery",void 0),__decorate$11([n$5({type:Object})],ChromedashAllFeaturesPage.prototype,"user",void 0),__decorate$11([n$5({type:Number})],ChromedashAllFeaturesPage.prototype,"selectedGateId",void 0),__decorate$11([n$5({type:Object})],ChromedashAllFeaturesPage.prototype,"rawQuery",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"query",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"columns",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"showEnterprise",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"sortSpec",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"start",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"num",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"starredFeatures",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"isNewfeaturesPage",void 0),__decorate$11([r$6()],ChromedashAllFeaturesPage.prototype,"nameOnly",void 0),__decorate$11([r$5("chromedash-feature-table")],ChromedashAllFeaturesPage.prototype,"chromedashFeatureTables",void 0),ChromedashAllFeaturesPage=__decorate$11([t$3("chromedash-all-features-page")],ChromedashAllFeaturesPage);var __decorate$10=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashAmendment extends i$4{constructor(){super(...arguments),this.amendment={field_name:"",old_value:"",new_value:""}}static get styles(){return[...SHARED_STYLES,i$7` + details { + color: var(--unimportant-text-color); + } + `]}render(){return x$1` + <details> + <summary> + <b>${this.amendment.field_name}</b>: + <span id="preview">${this.amendment.new_value}</span> + </summary> + + <div> + <b>Old</b>: + <div>${this.amendment.old_value}</div> + </div> + + <div> + <b>New</b>: + <div>${this.amendment.new_value}</div> + </div> + </details> + `}}__decorate$10([n$5({type:Object})],ChromedashAmendment.prototype,"amendment",void 0),customElements.define("chromedash-amendment",ChromedashAmendment);class ChromedashActivity extends i$4{constructor(){super(...arguments),this.user=null,this.featureId=0,this.activity=null,this.narrow=!1}static get styles(){return[...SHARED_STYLES,i$7` + .comment_header { + min-height: 24px; + } + + .comment_header.narrow .author { + font-weight: 500; + } + .comment_header.narrow .preposition { + display: none; + } + .comment_header.narrow .date { + display: block; + padding-bottom: var(--content-padding); + } + + .comment { + background: var(--accordion-background); + border-radius: var(--large-border-radius); + padding: var(--content-padding-half); + margin-bottom: var(--content-padding); + margin-right: var(--content-padding); + } + + .comment-menu-icon { + float: right; + margin-right: 8px; + cursor: pointer; + } + + .comment_body { + padding: var(--content-padding-half); + white-space: pre-wrap; + } + + p { + padding: 1em; + } + `]}isEditable(){return!!this.user&&(this.activity.deleted_by?this.user.is_admin||this.activity.deleted_by===this.user.email:this.user.email===this.activity.author||this.user.is_admin)}renderDeletedPreface(){return this.isEditable()&&this.activity.deleted_by?x$1`<div style="color: darkred"> + [Deleted] (comment hidden for other users) + </div>`:E$1}formatEditMenu(){if(!this.isEditable())return E$1;let menuItem=x$1` <sl-menu-item + @click="${()=>this.handleDelete(!1)}" + >Delete Comment</sl-menu-item + >`;return this.activity.deleted_by&&(menuItem=x$1` <sl-menu-item @click="${()=>this.handleDelete(!0)}" + >Undelete Comment</sl-menu-item + >`),x$1` <sl-dropdown class="comment-menu-icon"> + <sl-icon-button + library="material" + name="more_vert_24px" + label="Comment menu" + slot="trigger" + ></sl-icon-button> + <sl-menu>${menuItem}</sl-menu> + </sl-dropdown>`}render(){if(!this.activity)return E$1;const preface=this.renderDeletedPreface();return x$1` + <div class="comment"> + <div class="comment_header ${this.narrow?"narrow":""}"> + ${this.formatEditMenu()} + <span class="author">${this.activity.author}</span> + <span class="preposition">on</span> + <span class="date"> + ${renderAbsoluteDate(this.activity.created,!0)} + ${renderRelativeDate(this.activity.created)} + </span> + </div> + <div id="amendments"> + ${this.activity.amendments.map(a=>x$1` + <chromedash-amendment .amendment=${a}></chromedash-amendment> + `)} + </div> + <!-- prettier-ignore --> + <div class="comment_body">${preface}${autolink(this.activity.content)}</div> + </div> + `}async handleDelete(isUndelete){let resp;resp=isUndelete?await window.csClient.undeleteComment(this.featureId,this.activity.comment_id):await window.csClient.deleteComment(this.featureId,this.activity.comment_id),resp&&"Done"===resp.message&&(this.activity.deleted_by=isUndelete?null:this.user.email,this.requestUpdate())}}__decorate$10([n$5({type:Object})],ChromedashActivity.prototype,"user",void 0),__decorate$10([n$5({type:Number})],ChromedashActivity.prototype,"featureId",void 0),__decorate$10([n$5({type:Object})],ChromedashActivity.prototype,"activity",void 0),__decorate$10([n$5({type:Boolean})],ChromedashActivity.prototype,"narrow",void 0),customElements.define("chromedash-activity",ChromedashActivity);class ChromedashActivityLog extends i$4{constructor(){super(...arguments),this.user=null,this.featureId=0,this.comments=[],this.narrow=!1,this.reverse=!1,this.loading=!1}static get styles(){return[...SHARED_STYLES,i$7` + p { + padding: var(--content-padding); + } + `]}render(){if(this.loading)return x$1`<p>Loading...</p>`;if(void 0===this.comments||0===this.comments.length)return x$1`<p>No comments yet.</p>`;const orderedComments=this.reverse?this.comments.slice(0).reverse():this.comments;return orderedComments.map(activity=>x$1` + <chromedash-activity + .user=${this.user} + .featureId=${this.featureId} + .narrow=${this.narrow} + .activity=${activity} + > + </chromedash-activity> + `)}}__decorate$10([n$5({type:Object})],ChromedashActivityLog.prototype,"user",void 0),__decorate$10([n$5({type:Number})],ChromedashActivityLog.prototype,"featureId",void 0),__decorate$10([n$5({type:Array})],ChromedashActivityLog.prototype,"comments",void 0),__decorate$10([n$5({type:Boolean})],ChromedashActivityLog.prototype,"narrow",void 0),__decorate$10([r$6()],ChromedashActivityLog.prototype,"reverse",void 0),__decorate$10([r$6()],ChromedashActivityLog.prototype,"loading",void 0),customElements.define("chromedash-activity-log",ChromedashActivityLog);var __decorate$$=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashActivityPage=class ChromedashActivityPage extends i$4{constructor(){super(...arguments),this.commentAreaRef=e$1(),this.featureId=0,this.comments=[],this.loading=!0,this.needsPost=!1,this.contextLink=""}static get styles(){return[...SHARED_STYLES,i$7` + .instructions { + padding: var(--content-padding-half); + margin-bottom: var(--content-padding-large); + margin-left: 10px; + } + + #comment_area { + margin: 0 var(--content-padding); + } + #header { + margin-bottom: 10px; + margin-left: 15px; + } + #controls { + padding: var(--content-padding); + text-align: right; + display: flex; + justify-content: space-between; + align-items: center; + } + #controls * + * { + padding-left: var(--content-padding); + } + `]}connectedCallback(){super.connectedCallback(),this.fetchComments()}fetchComments(){this.loading=!0,Promise.all([window.csClient.getComments(this.featureId,null)]).then(([commentRes])=>{this.comments=commentRes.comments,this.needsPost=!1,this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}reloadComments(){const commentArea=this.commentAreaRef.value;commentArea.value="",this.needsPost=!1,Promise.all([window.csClient.getComments(this.featureId,null)]).then(([commentRes])=>{this.comments=commentRes.comments}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}checkNeedsPost(){let newNeedsPost=!1;const commentArea=this.commentAreaRef.value,newVal=commentArea&&commentArea.value.trim()||"";""!=newVal&&(newNeedsPost=!0),this.needsPost=newNeedsPost}handlePost(){const commentArea=this.commentAreaRef.value,commentText=commentArea.value.trim();""!=commentText&&window.csClient.postComment(this.featureId,null,commentText,0).then(()=>{this.reloadComments()}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}renderCommentsSkeleton(){return x$1` + <h2>Comments</h2> + <sl-skeleton effect="sheen"></sl-skeleton> + `}renderControls(){if(!this.user||!this.user.can_comment)return E$1;const postButton=x$1` + <sl-button + variant="primary" + @click=${this.handlePost} + ?disabled=${!this.needsPost} + size="small" + >Post</sl-button + > + `;return x$1` + <sl-textarea + id="comment_area" + rows="2" + cols="40" + resize="auto" + ${n$2(this.commentAreaRef)} + @sl-change=${this.checkNeedsPost} + @keypress=${this.checkNeedsPost} + placeholder="Add a comment" + ></sl-textarea> + <div class="instructions"> + Comments will be visible publicly. Only reviewers will be notified when + a comment is posted. + </div> + <div id="controls">${postButton}</div> + `}renderComments(){return x$1` + <div id="header"> + <h2 id="breadcrumbs"> + <a href="/feature/${this.featureId}"> + <sl-icon name="arrow-left"></sl-icon> + Comments & Activity + </a> + </h2> + </div> + ${this.renderControls()} + <chromedash-activity-log + .user=${this.user} + .featureId=${this.featureId} + .narrow=${!0} + .reverse=${!0} + .comments=${this.comments} + > + </chromedash-activity-log> + `}render(){return x$1` + ${this.loading?this.renderCommentsSkeleton():this.renderComments()} + `}};__decorate$$([n$5({type:Object})],ChromedashActivityPage.prototype,"user",void 0),__decorate$$([n$5({type:Number})],ChromedashActivityPage.prototype,"featureId",void 0),__decorate$$([n$5({type:Array})],ChromedashActivityPage.prototype,"comments",void 0),__decorate$$([r$6()],ChromedashActivityPage.prototype,"loading",void 0),__decorate$$([n$5({type:Boolean})],ChromedashActivityPage.prototype,"needsPost",void 0),__decorate$$([n$5({type:String})],ChromedashActivityPage.prototype,"contextLink",void 0),ChromedashActivityPage=__decorate$$([t$3("chromedash-activity-page")],ChromedashActivityPage);var isarray=Array.isArray||function(arr){return"[object Array]"==Object.prototype.toString.call(arr)},pathToRegexp_1=pathToRegexp,parse_1=parse$1,compile_1=compile,tokensToFunction_1=tokensToFunction,tokensToRegExp_1=tokensToRegExp,PATH_REGEXP=new RegExp("(\\\\.)|([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^()])+)\\))?|\\(((?:\\\\.|[^()])+)\\))([+*?])?|(\\*))","g");function parse$1(str){for(var tokens=[],key=0,index=0,path="",res;null!=(res=PATH_REGEXP.exec(str));){var m=res[0],escaped=res[1],offset=res.index;if(path+=str.slice(index,offset),index=offset+m.length,escaped){path+=escaped[1];continue}path&&(tokens.push(path),path="");var prefix=res[2],name=res[3],capture=res[4],group=res[5],suffix=res[6],asterisk=res[7],repeat="+"===suffix||"*"===suffix,optional="?"===suffix||"*"===suffix,delimiter=prefix||"/",pattern=capture||group||(asterisk?".*":"[^"+delimiter+"]+?");tokens.push({name:name||key++,prefix:prefix||"",delimiter:delimiter,optional:optional,repeat:repeat,pattern:escapeGroup(pattern)})}return index<str.length&&(path+=str.substr(index)),path&&tokens.push(path),tokens}function compile(str){return tokensToFunction(parse$1(str))}function tokensToFunction(tokens){for(var matches=Array(tokens.length),i=0;i<tokens.length;i++)"object"==typeof tokens[i]&&(matches[i]=new RegExp("^"+tokens[i].pattern+"$"));return function(obj){for(var path="",data=obj||{},i=0,token;i<tokens.length;i++){if(token=tokens[i],"string"==typeof token){path+=token;continue}var value=data[token.name],segment;if(null==value)if(token.optional)continue;else throw new TypeError("Expected \""+token.name+"\" to be defined");if(isarray(value)){if(!token.repeat)throw new TypeError("Expected \""+token.name+"\" to not repeat, but received \""+value+"\"");if(0===value.length)if(token.optional)continue;else throw new TypeError("Expected \""+token.name+"\" to not be empty");for(var j=0;j<value.length;j++){if(segment=encodeURIComponent(value[j]),!matches[i].test(segment))throw new TypeError("Expected all \""+token.name+"\" to match \""+token.pattern+"\", but received \""+segment+"\"");path+=(0==j?token.prefix:token.delimiter)+segment}continue}if(segment=encodeURIComponent(value),!matches[i].test(segment))throw new TypeError("Expected \""+token.name+"\" to match \""+token.pattern+"\", but received \""+segment+"\"");path+=token.prefix+segment}return path}}function escapeString(str){return str.replace(/([.+*?=^!:${}()[\]|\/])/g,"\\$1")}function escapeGroup(group){return group.replace(/([=!:$\/()])/g,"\\$1")}function attachKeys(re,keys){return re.keys=keys,re}function flags(options){return options.sensitive?"":"i"}function regexpToRegexp(path,keys){var groups=path.source.match(/\((?!\?)/g);if(groups)for(var i=0;i<groups.length;i++)keys.push({name:i,prefix:null,delimiter:null,optional:!1,repeat:!1,pattern:null});return attachKeys(path,keys)}function arrayToRegexp(path,keys,options){for(var parts=[],i=0;i<path.length;i++)parts.push(pathToRegexp(path[i],keys,options).source);var regexp=new RegExp("(?:"+parts.join("|")+")",flags(options));return attachKeys(regexp,keys)}function stringToRegexp(path,keys,options){for(var tokens=parse$1(path),re=tokensToRegExp(tokens,options),i=0;i<tokens.length;i++)"string"!=typeof tokens[i]&&keys.push(tokens[i]);return attachKeys(re,keys)}function tokensToRegExp(tokens,options){options=options||{};for(var strict=options.strict,end=!1!==options.end,route="",lastToken=tokens[tokens.length-1],endsWithSlash="string"==typeof lastToken&&/\/$/.test(lastToken),i=0,token;i<tokens.length;i++)if(token=tokens[i],"string"==typeof token)route+=escapeString(token);else{var prefix=escapeString(token.prefix),capture=token.pattern;token.repeat&&(capture+="(?:"+prefix+capture+")*"),capture=token.optional?prefix?"(?:"+prefix+"("+capture+"))?":"("+capture+")?":prefix+"("+capture+")",route+=capture}return strict||(route=(endsWithSlash?route.slice(0,-2):route)+"(?:\\/(?=$))?"),route+=end?"$":strict&&endsWithSlash?"":"(?=\\/|$)",new RegExp("^"+route,flags(options))}function pathToRegexp(path,keys,options){return keys=keys||[],isarray(keys)?!options&&(options={}):(options=keys,keys=[]),path instanceof RegExp?regexpToRegexp(path,keys):isarray(path)?arrayToRegexp(path,keys,options):stringToRegexp(path,keys,options)}pathToRegexp_1.parse=parse_1,pathToRegexp_1.compile=compile_1,pathToRegexp_1.tokensToFunction=tokensToFunction_1,pathToRegexp_1.tokensToRegExp=tokensToRegExp_1;var hasDocument="undefined"!=typeof document,hasWindow="undefined"!=typeof window,hasHistory="undefined"!=typeof history,hasProcess="undefined"!=typeof process,clickEvent=hasDocument&&document.ontouchstart?"touchstart":"click",isLocation=hasWindow&&!!(window.history.location||window.location);function Page(){this.callbacks=[],this.exits=[],this.current="",this.len=0,this._decodeURLComponents=!0,this._base="",this._strict=!1,this._running=!1,this._hashbang=!1,this.clickHandler=this.clickHandler.bind(this),this._onpopstate=this._onpopstate.bind(this)}Page.prototype.configure=function(options){var opts=options||{};this._window=opts.window||hasWindow&&window,this._decodeURLComponents=!1!==opts.decodeURLComponents,this._popstate=!1!==opts.popstate&&hasWindow,this._click=!1!==opts.click&&hasDocument,this._hashbang=!!opts.hashbang;var _window=this._window;this._popstate?_window.addEventListener("popstate",this._onpopstate,!1):hasWindow&&_window.removeEventListener("popstate",this._onpopstate,!1),this._click?_window.document.addEventListener(clickEvent,this.clickHandler,!1):hasDocument&&_window.document.removeEventListener(clickEvent,this.clickHandler,!1),this._hashbang&&hasWindow&&!hasHistory?_window.addEventListener("hashchange",this._onpopstate,!1):hasWindow&&_window.removeEventListener("hashchange",this._onpopstate,!1)},Page.prototype.base=function(path){return 0===arguments.length?this._base:void(this._base=path)},Page.prototype._getBase=function(){var base=this._base;if(!!base)return base;var loc=hasWindow&&this._window&&this._window.location;return hasWindow&&this._hashbang&&loc&&"file:"===loc.protocol&&(base=loc.pathname),base},Page.prototype.strict=function(enable){return 0===arguments.length?this._strict:void(this._strict=enable)},Page.prototype.start=function(options){var opts=options||{};if(this.configure(opts),!1!==opts.dispatch){this._running=!0;var url;if(isLocation){var window=this._window,loc=window.location;url=this._hashbang&&~loc.hash.indexOf("#!")?loc.hash.substr(2)+loc.search:this._hashbang?loc.search+loc.hash:loc.pathname+loc.search+loc.hash}this.replace(url,null,!0,opts.dispatch)}},Page.prototype.stop=function(){if(this._running){this.current="",this.len=0,this._running=!1;var window=this._window;this._click&&window.document.removeEventListener(clickEvent,this.clickHandler,!1),hasWindow&&window.removeEventListener("popstate",this._onpopstate,!1),hasWindow&&window.removeEventListener("hashchange",this._onpopstate,!1)}},Page.prototype.show=function(path,state,dispatch,push){var ctx=new Context(path,state,this),prev=this.prevContext;return this.prevContext=ctx,this.current=ctx.path,!1!==dispatch&&this.dispatch(ctx,prev),!1!==ctx.handled&&!1!==push&&ctx.pushState(),ctx},Page.prototype.back=function(path,state){var page=this;if(0<this.len){var window=this._window;hasHistory&&window.history.back(),this.len--}else path?setTimeout(function(){page.show(path,state)}):setTimeout(function(){page.show(page._getBase(),state)})},Page.prototype.redirect=function(from,to){var inst=this;"string"==typeof from&&"string"==typeof to&&page.call(this,from,function(e){setTimeout(function(){inst.replace(to)},0)}),"string"==typeof from&&"undefined"==typeof to&&setTimeout(function(){inst.replace(from)},0)},Page.prototype.replace=function(path,state,init,dispatch){var ctx=new Context(path,state,this),prev=this.prevContext;return this.prevContext=ctx,this.current=ctx.path,ctx.init=init,ctx.save(),!1!==dispatch&&this.dispatch(ctx,prev),ctx},Page.prototype.dispatch=function(ctx,prev){function nextExit(){var fn=page.exits[j++];return fn?void fn(prev,nextExit):nextEnter()}function nextEnter(){var fn=page.callbacks[i++];return ctx.path===page.current?fn?void fn(ctx,nextEnter):unhandled.call(page,ctx):void(ctx.handled=!1)}var i=0,j=0,page=this;prev?nextExit():nextEnter()},Page.prototype.exit=function(path,fn){if("function"==typeof path)return this.exit("*",path);for(var route=new Route(path,null,this),i=1;i<arguments.length;++i)this.exits.push(route.middleware(arguments[i]))},Page.prototype.clickHandler=function(e){if(1===this._which(e)&&!(e.metaKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented){var el=e.target,eventPath=e.path||(e.composedPath?e.composedPath():null);if(eventPath)for(var i=0;i<eventPath.length;i++)if(eventPath[i].nodeName&&"A"===eventPath[i].nodeName.toUpperCase()&&eventPath[i].href){el=eventPath[i];break}for(;el&&"A"!==el.nodeName.toUpperCase();)el=el.parentNode;if(el&&"A"===el.nodeName.toUpperCase()){var svg="object"==typeof el.href&&"SVGAnimatedString"===el.href.constructor.name;if(!(el.hasAttribute("download")||"external"===el.getAttribute("rel"))){var link=el.getAttribute("href");if(!(!this._hashbang&&this._samePath(el)&&(el.hash||"#"===link))&&!(link&&-1<link.indexOf("mailto:"))&&(svg?!el.target.baseVal:!el.target)&&(svg||this.sameOrigin(el.href))){var path=svg?el.href.baseVal:el.pathname+el.search+(el.hash||"");path="/"===path[0]?path:"/"+path,hasProcess&&path.match(/^\/[a-zA-Z]:\//)&&(path=path.replace(/^\/[a-zA-Z]:\//,"/"));var orig=path,pageBase=this._getBase();0===path.indexOf(pageBase)&&(path=path.substr(pageBase.length)),this._hashbang&&(path=path.replace("#!","")),pageBase&&orig===path&&(!isLocation||"file:"!==this._window.location.protocol)||(e.preventDefault(),this.show(orig))}}}}},Page.prototype._onpopstate=function(){var loaded=!1;return hasWindow?(hasDocument&&"complete"===document.readyState?loaded=!0:window.addEventListener("load",function(){setTimeout(function(){loaded=!0},0)}),function onpopstate(e){if(loaded){var page=this;if(e.state){var path=e.state.path;page.replace(path,e.state)}else if(isLocation){var loc=page._window.location;page.show(loc.pathname+loc.search+loc.hash,void 0,void 0,!1)}}}):function(){}}(),Page.prototype._which=function(e){return e=e||hasWindow&&this._window.event,null==e.which?e.button:e.which},Page.prototype._toURL=function(href){var window=this._window;if("function"==typeof URL&&isLocation)return new URL(href,window.location.toString());if(hasDocument){var anc=window.document.createElement("a");return anc.href=href,anc}},Page.prototype.sameOrigin=function(href){if(!href||!isLocation)return!1;var url=this._toURL(href),window=this._window,loc=window.location;return loc.protocol===url.protocol&&loc.hostname===url.hostname&&(loc.port===url.port||""===loc.port&&(80==url.port||443==url.port))},Page.prototype._samePath=function(url){if(!isLocation)return!1;var window=this._window,loc=window.location;return url.pathname===loc.pathname&&url.search===loc.search},Page.prototype._decodeURLEncodedURIComponent=function(val){return"string"==typeof val?this._decodeURLComponents?decodeURIComponent(val.replace(/\+/g," ")):val:val};function createPage(){function pageFn(){return page.apply(pageInstance,arguments)}var pageInstance=new Page;return pageFn.callbacks=pageInstance.callbacks,pageFn.exits=pageInstance.exits,pageFn.base=pageInstance.base.bind(pageInstance),pageFn.strict=pageInstance.strict.bind(pageInstance),pageFn.start=pageInstance.start.bind(pageInstance),pageFn.stop=pageInstance.stop.bind(pageInstance),pageFn.show=pageInstance.show.bind(pageInstance),pageFn.back=pageInstance.back.bind(pageInstance),pageFn.redirect=pageInstance.redirect.bind(pageInstance),pageFn.replace=pageInstance.replace.bind(pageInstance),pageFn.dispatch=pageInstance.dispatch.bind(pageInstance),pageFn.exit=pageInstance.exit.bind(pageInstance),pageFn.configure=pageInstance.configure.bind(pageInstance),pageFn.sameOrigin=pageInstance.sameOrigin.bind(pageInstance),pageFn.clickHandler=pageInstance.clickHandler.bind(pageInstance),pageFn.create=createPage,Object.defineProperty(pageFn,"len",{get:function(){return pageInstance.len},set:function(val){pageInstance.len=val}}),Object.defineProperty(pageFn,"current",{get:function(){return pageInstance.current},set:function(val){pageInstance.current=val}}),pageFn.Context=Context,pageFn.Route=Route,pageFn}function page(path,fn){if("function"==typeof path)return page.call(this,"*",path);if("function"==typeof fn)for(var route=new Route(path,null,this),i=1;i<arguments.length;++i)this.callbacks.push(route.middleware(arguments[i]));else"string"==typeof path?this["string"==typeof fn?"redirect":"show"](path,fn):this.start(path)}function unhandled(ctx){if(!ctx.handled){var page=this,window=page._window,current;current=page._hashbang?isLocation&&this._getBase()+window.location.hash.replace("#!",""):isLocation&&window.location.pathname+window.location.search,current===ctx.canonicalPath||(page.stop(),ctx.handled=!1,isLocation&&(window.location.href=ctx.canonicalPath))}}function escapeRegExp(s){return s.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function Context(path,state,pageInstance){var _page=this.page=pageInstance||page,window=_page._window,hashbang=_page._hashbang,pageBase=_page._getBase();"/"===path[0]&&0!==path.indexOf(pageBase)&&(path=pageBase+(hashbang?"#!":"")+path);var i=path.indexOf("?");this.canonicalPath=path;var re=new RegExp("^"+escapeRegExp(pageBase));if(this.path=path.replace(re,"")||"/",hashbang&&(this.path=this.path.replace("#!","")||"/"),this.title=hasDocument&&window.document.title,this.state=state||{},this.state.path=path,this.querystring=~i?_page._decodeURLEncodedURIComponent(path.slice(i+1)):"",this.pathname=_page._decodeURLEncodedURIComponent(~i?path.slice(0,i):path),this.params={},this.hash="",!hashbang){if(!~this.path.indexOf("#"))return;var parts=this.path.split("#");this.path=this.pathname=parts[0],this.hash=_page._decodeURLEncodedURIComponent(parts[1])||"",this.querystring=this.querystring.split("#")[0]}}Context.prototype.pushState=function(){var page=this.page,window=page._window,hashbang=page._hashbang;page.len++,hasHistory&&window.history.pushState(this.state,this.title,hashbang&&"/"!==this.path?"#!"+this.path:this.canonicalPath)},Context.prototype.save=function(){var page=this.page;hasHistory&&page._window.history.replaceState(this.state,this.title,page._hashbang&&"/"!==this.path?"#!"+this.path:this.canonicalPath)};function Route(path,options,page){var _page=this.page=page||globalPage,opts=options||{};opts.strict=opts.strict||_page._strict,this.path="*"===path?"(.*)":path,this.method="GET",this.regexp=pathToRegexp_1(this.path,this.keys=[],opts)}Route.prototype.middleware=function(fn){var self=this;return function(ctx,next){return self.match(ctx.path,ctx.params)?(ctx.routePath=self.path,fn(ctx,next)):void next()}},Route.prototype.match=function(path,params){var keys=this.keys,qsIndex=path.indexOf("?"),pathname=~qsIndex?path.slice(0,qsIndex):path,m=this.regexp.exec(decodeURIComponent(pathname));if(!m)return!1;delete params[0];for(var i=1,len=m.length;i<len;++i){var key=keys[i-1],val=this.page._decodeURLEncodedURIComponent(m[i]);val===void 0&&hasOwnProperty.call(params,key.name)||(params[key.name]=val)}return!0};var globalPage=createPage(),page_js=globalPage,default_1=globalPage;page_js.default=default_1;var __decorate$_=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const DRAWER_WIDTH_PX=200;let ChromedashDrawer=class ChromedashDrawer extends i$4{constructor(){super(...arguments),this.currentPage="",this.devMode="False",this.googleSignInClientId="",this.defaultOpen=!1,this.loading=!1}static get styles(){return[...SHARED_STYLES,i$7` + :host { + --nav-link-color: var(--sl-color-neutral-700); + --nav-link-font-size: 16px; + --nav-link-hover-background: var(--sl-color-neutral-100); + --nav-link-active-color: var(--sl-color-primary-900); + --nav-link-active-background: var(--light-accent-color); + } + nav { + display: flex; + flex: 1; + align-items: baseline; + user-select: none; + background: var(--card-background); + border: none; + align-items: center; + margin: 0 var(--content-padding-half); + -webkit-font-smoothing: initial; + } + nav a { + text-decoration: none !important; + cursor: pointer; + font-size: var(--nav-link-font-size); + text-align: left; + padding: var(--content-padding-half); + color: var(--nav-link-color); + white-space: nowrap; + border-radius: var(--pill-border-radius); + } + nav a:hover { + color: black; + background: var(--nav-link-hover-background); + } + nav a.disabled { + opacity: 0.5; + pointer-events: none; + } + nav [active] { + color: var(--nav-link-active-color); + background: var(--nav-link-active-background); + } + nav [active]:hover { + background: var(--sl-color-neutral-100); + } + hr { + margin: 15px var(--content-padding-half); + } + + .section-header { + margin: 0px var(--content-padding-half) 10px; + font-weight: bold; + } + sl-drawer a { + display: block; + } + sl-drawer::part(header) { + display: none; + } + sl-button { + margin-left: 10px; + } + @media only screen and (max-width: 700px) { + header { + --logoSize: 24px; + + margin: 0; + display: block; + } + sl-drawer a { + display: block; + } + sl-drawer::part(header) { + display: none; + } + } + `]}connectedCallback(){super.connectedCallback();this.user&&this.user.email||(this.loading=!0,window.csClient.getPermissions().then(user=>{this.user=user,!this.user&&IS_MOBILE&&(!window.isPlaywright&&this.initializeGoogleSignIn(),"True"==this.devMode&&this.initializeTestingSignIn())}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}).finally(()=>{this.loading=!1}))}initializeGoogleSignIn(){google.accounts.id.initialize({client_id:this.googleSignInClientId,callback:this.handleCredentialResponse}),google.accounts.id.prompt();const signInButton=document.createElement("div");google.accounts.id.renderButton(signInButton,{type:"standard"}),this.insertAdjacentElement("afterbegin",signInButton)}initializeTestingSignIn(){const signInTestingButton=document.createElement("button");signInTestingButton.innerText="Sign in as example@chromium.org",signInTestingButton.setAttribute("type","button"),signInTestingButton.setAttribute("data-testid","dev-mode-sign-in-button"),signInTestingButton.setAttribute("style","position:fixed; right:0; z-index:1000; background: lightblue; border: 1px solid blue;"),signInTestingButton.addEventListener("click",()=>{fetch("/dev/mock_login",{method:"POST"}).then(response=>{if(!response.ok)throw new Error(`Sign in failed! Response: ${response.status}`)}).then(()=>{setTimeout(()=>{const url=window.location.href.split("?")[0];window.location.href=url},1e3)}).catch(error=>{console.error("Sign in failed.",error)})});const signInButtonContainer=document.querySelector("body");signInButtonContainer&&signInButtonContainer.insertAdjacentElement("afterbegin",signInTestingButton)}handleCredentialResponse(credentialResponse){window.csClient.signIn(credentialResponse).then(()=>{setTimeout(()=>{const url=window.location.href.split("?")[0];window.location.href=url},1e3)}).catch(()=>{console.error("Sign in failed, so signing out to allow retry"),this.signOut()})}handleSignOutClick(e){e.preventDefault(),this.signOut()}signOut(){window.csClient.signOut().then(()=>{window.location.reload()})}userCanApprove(){return this.user&&(this.user.is_admin||0<this.user.approvable_gate_types?.length)}isCurrentPage(href){return this.currentPage===href}toggleDrawerActions(){const drawer=this.shadowRoot.querySelector(".drawer-placement-start");return drawer.open?drawer.hide():drawer.show(),drawer.open}renderNavItem(url,label){return x$1`<a href="${url}" ?active=${this.isCurrentPage(url)} + >${label}</a + >`}renderDrawer(){let accountMenu=E$1;IS_MOBILE&&!this.loading&&(accountMenu=this.renderAccountMenu());const myFeaturesMenu=this.renderMyFeaturesMenu(),adminMenu=this.renderAdminMenu(),now=new Date,year=now.getFullYear(),shippingThisYear=this.renderNavItem("/features?q=shipping_year:"+year,"Shipping "+year),nextYear=year+1;let shippingNextYear=this.renderNavItem("/features?q=shipping_year:"+nextYear,"Shipping "+nextYear);return 8>now.getMonth()&&(shippingNextYear=x$1``),x$1` + <sl-drawer + label="Menu" + placement="start" + class="drawer-placement-start" + style="--size: ${DRAWER_WIDTH_PX}px;" + contained + noHeader + ?open=${!IS_MOBILE&&this.defaultOpen} + > + ${accountMenu} ${this.renderNavItem("/roadmap","Roadmap")} + ${this.renderNavItem("/features","All features")} ${shippingThisYear} + ${shippingNextYear} ${myFeaturesMenu} + <hr /> + <div class="section-header">Stats</div> + ${this.renderNavItem("/metrics/css/popularity","CSS")} + ${this.renderNavItem("/metrics/css/animated","CSS Animation")} + ${this.renderNavItem("/metrics/feature/popularity","JS/HTML")} + ${this.renderNavItem("/metrics/webfeature/popularity","Web Features")} + <hr /> + <div class="section-header">Reports</div> + ${this.renderNavItem("/reports/spec_mentors","Spec Mentors")} + ${this.renderNavItem("/reports/external_reviews","External Reviews")} + ${adminMenu} + </sl-drawer> + `}renderAccountMenu(){return this.user?x$1` + <div class="section-header">${this.user.email}</div> + <a href="/settings">Settings</a> + <a + href="#" + id="sign-out-link" + data-testid="sign-out-link" + @click=${this.handleSignOutClick} + >Sign out</a + > + ${this.user.can_create_feature&&!this.isCurrentPage("/guide/new")?x$1` + <sl-button + data-testid="create-feature-button" + href="/guide/new" + variant="primary" + size="small" + > + Create feature + </sl-button> + `:E$1} + <hr /> + `:E$1}renderMyFeaturesMenu(){return this.user?.email?x$1` + <hr /> + <div class="section-header">My features</div> + ${this.userCanApprove()?this.renderNavItem("/myfeatures/review","Pending review"):E$1} + ${this.renderNavItem("/myfeatures/starred","Starred")} + ${this.renderNavItem("/myfeatures/editable","Owner / editor")} + `:E$1}renderAdminMenu(){return this.user?.is_admin?x$1` + <hr /> + <div class="section-header">Admin</div> + ${this.renderNavItem("/admin/users/new","Users")} + ${this.renderNavItem("/admin/ot_requests","OT requests")} + ${this.renderNavItem("/admin/bulk_edit","Bulk edit")} + ${this.renderNavItem("/admin/feature_links","Feature links")} + ${this.renderNavItem("/reports/feature-latency","Feature latency")} + ${this.renderNavItem("/reports/review-latency","Review latency")} + ${this.renderNavItem("/admin/blink","Subscriptions")} + ${this.renderNavItem("/admin/find_stop_words","Find stop words JSON")} + ${this.renderNavItem("/features/stale","Stale features")} + `:E$1}render(){return x$1` <nav>${this.renderDrawer()}</nav> `}};__decorate$_([n$5({type:String})],ChromedashDrawer.prototype,"currentPage",void 0),__decorate$_([n$5({type:String})],ChromedashDrawer.prototype,"devMode",void 0),__decorate$_([n$5({type:String})],ChromedashDrawer.prototype,"googleSignInClientId",void 0),__decorate$_([n$5({type:Boolean})],ChromedashDrawer.prototype,"defaultOpen",void 0),__decorate$_([r$6()],ChromedashDrawer.prototype,"user",void 0),__decorate$_([r$6()],ChromedashDrawer.prototype,"loading",void 0),ChromedashDrawer=__decorate$_([t$3("chromedash-drawer")],ChromedashDrawer);var __decorate$Z=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashApp=class ChromedashApp extends i$4{constructor(){super(...arguments),this.gateColumnRef=e$1(),this.paired_user=void 0,this.appTitle="",this.googleSignInClientId="",this.devMode="",this.bannerMessage="",this.bannerTime=null,this.loading=!0,this.currentPage="",this.pageComponent=null,this.contextLink="/features",this.sidebarHidden=!0,this.selectedGateId=0,this.beforeUnloadHandler=null,this.drawerOpen=!IS_MOBILE}static get styles(){return[...SHARED_STYLES,i$7` + .main-toolbar { + display: flex; + position: relative; + padding: 0; + } + .main-toolbar .toolbar-content { + width: 100%; + } + + #rollout { + width: 100%; + text-align: center; + padding: 1em; + color: black; + background: lightgrey; + } + + #app-content-container { + display: flex; + flex-direction: column; + height: 100%; + } + + #content { + margin: 0; + position: relative; + flex: 1; + } + + #content-flex-wrapper { + display: flex; + justify-content: center; + width: 100%; + } + + #content-component-wrapper { + width: var(--max-content-width); + max-width: 95%; + } + #content-component-wrapper[wide] { + width: 100%; + } + + #content-sidebar-space { + position: sticky; + flex-shrink: 100; + width: var(--sidebar-space); + } + + #sidebar { + position: absolute; + top: 0; + right: 0; + width: var(--sidebar-width); + max-width: var(--sidebar-max-width); + bottom: 0; + } + #sidebar[hidden] { + display: none; + } + #sidebar-content { + position: sticky; + top: 10px; + height: 85vh; + overflow-y: auto; + border: var(--sidebar-border); + border-radius: var(--sidebar-radius); + background: var(--sidebar-bg); + padding: var(--content-padding); + } + + @media only screen and (max-width: 700px) { + #content { + margin-left: 0; + margin-right: 0; + } + } + `]}firstUpdated(){const toastEl=document.createElement("chromedash-toast");document.body.appendChild(toastEl)}connectedCallback(){super.connectedCallback(),this.loading=!0,window.csClient.getPermissions().then(user=>{this.user=user}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}).finally(()=>{this.setUpRoutes(),this.loading=!1})}fetchPairedUser(){return void 0!==this.paired_user&&this.pageComponent?void(this.pageComponent.paired_user=this.paired_user):void window.csClient.getPermissions(!0).then(pu=>{this.paired_user=pu,this.pageComponent&&(this.pageComponent.paired_user=pu)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}removeBeforeUnloadHandler(){this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null)}addBeforeUnloadHandler(){this.removeBeforeUnloadHandler(),this.beforeUnloadHandler=event=>{this.getUnsavedChanges()&&(event.preventDefault(),event.returnValue=`You made changes that have not been saved. + Are you sure you want to leave?`)},window.addEventListener("beforeunload",this.beforeUnloadHandler)}getUnsavedChanges(){return this.pageComponent?this.pageComponent.unsavedChanges:void 0}setUnsavedChanges(flag){this.pageComponent&&(this.pageComponent.unsavedChanges=flag)}handleFormSubmit(){const currentPageComponent=this.pageComponent,currentUnsavedChanges=this.pageComponent.unsavedChanges;this.setUnsavedChanges(!1),this.removeBeforeUnloadHandler(),window.setTimeout(()=>{this.pageComponent==currentPageComponent&&this.getUnsavedChanges()&&(this.setUnsavedChanges(currentUnsavedChanges),this.addBeforeUnloadHandler())},1e3)}setupNewPage(ctx,componentName,shouldSetContext=!1,shouldHideSidebar=!0){if(this.currentPage==ctx.path&&ctx.hash)return window.scrollToElement&&window.scrollToElement(`#${ctx.hash}`),!1;if(this.pageComponent&&this.getUnsavedChanges()&&!confirm("You will lose unsaved changes. Proceed anyway?"))return ctx.handled=!1,!1;const signinRequired=-1<ctx.querystring.search("loginStatus=False");return this.pageComponent=document.createElement(signinRequired?"chromedash-login-required-page":componentName),this.setUnsavedChanges(!1),this.removeBeforeUnloadHandler(),this.pageComponent.allFormFieldComponentsList=[],window.setTimeout(()=>{const form=this.pageComponent.shadowRoot?.querySelector("form");form&&(this.addBeforeUnloadHandler(),this.pageComponent.addEventListener("sl-change",()=>{this.setUnsavedChanges(!0)}),form.addEventListener("submit",()=>{this.handleFormSubmit()}))},1e3),this.pageComponent.contextLink=this.contextLink,shouldSetContext&&(this.contextLink=ctx.path),this.currentPage=ctx.path,shouldHideSidebar&&this.hideSidebar(),!0}setUpRoutes(){page_js.strict(!0),page_js("/",()=>page_js.redirect("/roadmap")),page_js("/roadmap",ctx=>{this.setupNewPage(ctx,"chromedash-roadmap-page",!0)&&(this.pageComponent.user=this.user)}),page_js("/myfeatures",ctx=>{this.setupNewPage(ctx,"chromedash-myfeatures-page",!0)&&(this.pageComponent.user=this.user,this.pageComponent.selectedGateId=this.selectedGateId)}),page_js("/myfeatures/review",ctx=>{this.setupNewPage(ctx,"chromedash-all-features-page",!0)&&(this.pageComponent.user=this.user,this.pageComponent.title="Features pending my review",this.pageComponent.query="pending-approval-by:me",this.pageComponent.columns="approvals",this.pageComponent.sortSpec="gate.requested_on",this.pageComponent.showEnterprise=!0,this.pageComponent.showQuery=!1,this.pageComponent.rawQuery=parseRawQuery(ctx.querystring))}),page_js("/myfeatures/starred",ctx=>{this.setupNewPage(ctx,"chromedash-all-features-page",!0)&&(this.pageComponent.user=this.user,this.pageComponent.title="Features I starred",this.pageComponent.query="starred-by:me",this.pageComponent.showEnterprise=!0,this.pageComponent.showQuery=!1,this.pageComponent.rawQuery=parseRawQuery(ctx.querystring))}),page_js("/myfeatures/editable",ctx=>{this.setupNewPage(ctx,"chromedash-all-features-page",!0)&&(this.pageComponent.user=this.user,this.pageComponent.title="Features I can edit",this.pageComponent.query="can_edit:me",this.pageComponent.showEnterprise=!0,this.pageComponent.showQuery=!1,this.pageComponent.rawQuery=parseRawQuery(ctx.querystring))}),page_js("/features",ctx=>{this.setupNewPage(ctx,"chromedash-all-features-page",!0)&&(this.pageComponent.user=this.user,this.pageComponent.rawQuery=parseRawQuery(ctx.querystring),this.pageComponent.isNewfeaturesPage=!0,this.pageComponent.addEventListener("search",this.handleSearchQuery.bind(this)))}),page_js("/feature/:featureId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-feature-page",!0,!1)&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.user=this.user,this.fetchPairedUser(),this.pageComponent.selectedGateId=this.selectedGateId,this.pageComponent.appTitle=this.appTitle,this.pageComponent.featureId!=this.gateColumnRef.value?.feature?.id&&this.hideSidebar())}),page_js("/feature/:featureId(\\d+)/activity",ctx=>{this.setupNewPage(ctx,"chromedash-activity-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.user=this.user)}),page_js("/feature/:featureId(\\d+)/ai-coverage-evaluation",ctx=>{this.setupNewPage(ctx,"chromedash-wpt-eval-page",!0,!1)&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.user=this.user,this.pageComponent.appTitle=this.appTitle)}),page_js("/guide/new",ctx=>{this.setupNewPage(ctx,"chromedash-guide-new-page")&&(-1!=ctx.querystring.search("loginStatus=False")||(this.pageComponent.userEmail=this.user.email))}),page_js("/guide/enterprise/new",ctx=>{this.setupNewPage(ctx,"chromedash-guide-new-page")&&(-1==ctx.querystring.search("loginStatus=False")&&(this.pageComponent.userEmail=this.user.email),this.pageComponent.isEnterpriseFeature=!0)}),page_js("/guide/editall/:featureId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-guide-editall-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.user=this.user,this.pageComponent.appTitle=this.appTitle)}),page_js("/guide/verify_accuracy/:featureId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-guide-verify-accuracy-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.appTitle=this.appTitle)}),page_js("/guide/stage/:featureId(\\d+)/:stageId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-guide-stage-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.stageId=parseInt(ctx.params.stageId),this.pageComponent.appTitle=this.appTitle)}),page_js("/guide/stage/:featureId(\\d+)/:intentStage(\\d+)/:stageId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-guide-stage-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.stageId=parseInt(ctx.params.stageId),this.pageComponent.appTitle=this.appTitle)}),page_js("/feature/:featureId(\\d+)/gate/:gateId(\\d+/intent)",ctx=>{this.setupNewPage(ctx,"chromedash-intent-preview-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.gateId=parseInt(ctx.params.gateId),this.pageComponent.appTitle=this.appTitle,this.hideSidebar())}),page_js("/feature/:featureId(\\d+)/stage/:stageId(\\d+/intent)",ctx=>{this.setupNewPage(ctx,"chromedash-intent-preview-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.stageId=parseInt(ctx.params.stageId),this.pageComponent.appTitle=this.appTitle,this.hideSidebar())}),page_js("/ot_creation_request/:featureId(\\d+)/:stageId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-ot-creation-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.stageId=parseInt(ctx.params.stageId),this.pageComponent.appTitle=this.appTitle,this.pageComponent.userEmail=this.user.email)}),page_js("/ot_extension_request/:featureId(\\d+)/:stageId(\\d+)",ctx=>{this.setupNewPage(ctx,"chromedash-ot-extension-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.stageId=parseInt(ctx.params.stageId),this.pageComponent.appTitle=this.appTitle,this.pageComponent.userEmail=this.user.email)}),page_js("/guide/stage/:featureId(\\d+)/metadata",ctx=>{this.setupNewPage(ctx,"chromedash-guide-metadata-page")&&(this.pageComponent.featureId=parseInt(ctx.params.featureId),this.pageComponent.appTitle=this.appTitle)}),page_js("/settings",ctx=>{!this.setupNewPage(ctx,"chromedash-settings-page")}),page_js("/metrics/:type/:view",ctx=>{this.setupNewPage(ctx,"chromedash-stack-rank-page")&&(this.pageComponent.type=ctx.params.type,this.pageComponent.view=ctx.params.view)}),page_js("/metrics/:type/timeline/:view/:bucketId",ctx=>{this.setupNewPage(ctx,"chromedash-timeline-page")&&(this.pageComponent.type=ctx.params.type,this.pageComponent.view=ctx.params.view,this.pageComponent.selectedBucketId=ctx.params.bucketId)}),page_js("/features/stale",ctx=>{!this.setupNewPage(ctx,"chromedash-stale-features-page")}),page_js("/metrics",()=>page_js.redirect("/metrics/css/popularity")),page_js("/metrics/css",()=>page_js.redirect("/metrics/css/popularity")),page_js("/metrics/css/timeline/popularity",()=>page_js.redirect("/metrics/css/popularity")),page_js("/metrics/css/timeline/animated",()=>page_js.redirect("/metrics/css/animated")),page_js("/metrics/feature/timeline/popularity",()=>page_js.redirect("/metrics/feature/popularity")),page_js("/metrics/webfeature/timeline/popularity",()=>page_js.redirect("/metrics/webfeature/popularity")),page_js("/reports/external_reviews",ctx=>{!this.setupNewPage(ctx,"chromedash-report-external-reviews-dispatch-page")}),page_js("/reports/external_reviews/:reviewer",ctx=>["tag","gecko","webkit"].includes(ctx.params.reviewer)?void(!this.setupNewPage(ctx,"chromedash-report-external-reviews-page")||(this.pageComponent.reviewer=ctx.params.reviewer)):void page_js.redirect("/reports/external_reviews")),page_js("/reports/spec_mentors",ctx=>{this.setupNewPage(ctx,"chromedash-report-spec-mentors-page")&&(this.pageComponent.rawQuery=parseRawQuery(ctx.querystring),this.pageComponent.addEventListener("afterchanged",e=>updateURLParams("after",isoDateString(e.detail.after))))}),page_js("/reports/feature-latency",ctx=>{this.setupNewPage(ctx,"chromedash-report-feature-latency-page")&&(this.pageComponent.rawQuery=parseRawQuery(ctx.querystring),this.pageComponent.addEventListener("afterchanged",e=>updateURLParams("after",isoDateString(e.detail.after))))}),page_js("/reports/review-latency",ctx=>{!this.setupNewPage(ctx,"chromedash-report-review-latency-page")}),page_js("/enterprise",ctx=>{this.setupNewPage(ctx,"chromedash-enterprise-page",!0)&&(this.pageComponent.user=this.user)}),page_js("/admin/blink",ctx=>{this.pageComponent=document.createElement("chromedash-admin-blink-page"),this.pageComponent.user=this.user,this.currentPage=ctx.path,this.hideSidebar()}),page_js("/admin/feature_links",ctx=>{this.setupNewPage(ctx,"chromedash-admin-feature-links-page")&&(this.pageComponent.user=this.user)}),page_js("/admin/bulk_edit",ctx=>{this.pageComponent=document.createElement("chromedash-bulk-edit-page"),this.pageComponent.user=this.user,this.currentPage=ctx.path}),page_js("/enterprise/releasenotes",ctx=>{this.setupNewPage(ctx,"chromedash-enterprise-release-notes-page",!0)&&(this.pageComponent.user=this.user)}),page_js.start()}handleSearchQuery(e){updateURLParams("q",e.detail.query),clearURLParams("start")}showSidebar(){this.sidebarHidden=!1}hideSidebar(){this.sidebarHidden=!0,this.selectedGateId=0,this.pageComponent.selectedGateId=0}showGateColumn(feature,stageId,gate){this.gateColumnRef.value?.setContext(feature,stageId,gate),this.selectedGateId=gate.id,this.pageComponent.selectedGateId=gate.id,this.showSidebar()}handleShowGateColumn(e){this.showGateColumn(e.detail.feature,e.detail.stage.id,e.detail.gate)}handleShowDrawer(){const drawer=this.renderRoot.querySelector("chromedash-drawer");this.drawerOpen=drawer.toggleDrawerActions()}refetch(){this.pageComponent?.refetch&&this.pageComponent.refetch(),this.gateColumnRef.value?.refetch&&this.gateColumnRef.value.refetch()}renderContentAndSidebar(){const wide=this.pageComponent&&"CHROMEDASH-ROADMAP-PAGE"==this.pageComponent.tagName;return wide?x$1` + <div id="content-component-wrapper" wide>${this.pageComponent}</div> + `:x$1` + <div + id="content-component-wrapper" + @show-gate-column=${this.handleShowGateColumn} + @refetch-needed=${this.refetch} + > + ${this.pageComponent} + </div> + <div id="content-sidebar-space"> + <div id="sidebar" ?hidden=${this.sidebarHidden}> + <div id="sidebar-content"> + <chromedash-gate-column + .user=${this.user} + ${n$2(this.gateColumnRef)} + @close=${this.hideSidebar} + @refetch-needed=${this.refetch} + > + </chromedash-gate-column> + </div> + </div> + </div> + `}renderRolloutBanner(currentPage){return E$1}render(){let styleMargin={"margin-left":"20px"};return!IS_MOBILE&&this.drawerOpen&&(styleMargin={"margin-left":"210px"}),this.loading?E$1:x$1` + <div id="app-content-container"> + <div class="main-toolbar"> + <div class="toolbar-content"> + <chromedash-header + .user=${this.user} + .appTitle=${this.appTitle} + .devMode=${this.devMode} + .googleSignInClientId=${this.googleSignInClientId} + .currentPage=${this.currentPage} + @drawer-clicked=${this.handleShowDrawer} + > + <slot></slot> + </chromedash-header> + </div> + </div> + + <div id="content"> + <div> + <chromedash-drawer + .user=${this.user} + .currentPage=${this.currentPage} + ?defaultOpen=${!0} + .devMode=${this.devMode} + .googleSignInClientId=${this.googleSignInClientId} + > + </chromedash-drawer> + </div> + <div style=${o$3(styleMargin)}> + <chromedash-banner + .message=${this.bannerMessage} + .timestamp=${this.bannerTime} + > + </chromedash-banner> + <div id="content-flex-wrapper"> + ${this.renderContentAndSidebar()} + </div> + ${this.renderRolloutBanner(this.currentPage)} + </div> + </div> + <chromedash-footer></chromedash-footer> + </div> + `}};__decorate$Z([n$5({attribute:!1})],ChromedashApp.prototype,"user",void 0),__decorate$Z([n$5({attribute:!1})],ChromedashApp.prototype,"paired_user",void 0),__decorate$Z([n$5({type:String})],ChromedashApp.prototype,"appTitle",void 0),__decorate$Z([n$5({type:String})],ChromedashApp.prototype,"googleSignInClientId",void 0),__decorate$Z([n$5({type:String})],ChromedashApp.prototype,"devMode",void 0),__decorate$Z([n$5({type:String})],ChromedashApp.prototype,"bannerMessage",void 0),__decorate$Z([n$5({type:Number})],ChromedashApp.prototype,"bannerTime",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"loading",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"currentPage",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"pageComponent",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"contextLink",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"sidebarHidden",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"selectedGateId",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"beforeUnloadHandler",void 0),__decorate$Z([r$6()],ChromedashApp.prototype,"drawerOpen",void 0),ChromedashApp=__decorate$Z([t$3("chromedash-app")],ChromedashApp);var __decorate$Y=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashBanner=class ChromedashBanner extends i$4{constructor(){super(...arguments),this.timestamp=null,this.message=""}static get styles(){return[...SHARED_STYLES,i$7` + div { + display: inline-block; + background: var(--warning-background); + color: var(--warning-color); + border-radius: var(--border-radius); + padding: var(--content-padding); + width: 100%; + } + `]}computeLocalDateString(){if(!this.timestamp)return E$1;const date=new Date(1e3*this.timestamp),formatOptions={weekday:"long",year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"numeric"};return date.toLocaleString(void 0,formatOptions)}render(){return this.message?x$1` <div>${this.message} ${this.computeLocalDateString()}</div> `:E$1}};__decorate$Y([n$5({type:Number})],ChromedashBanner.prototype,"timestamp",void 0),__decorate$Y([n$5({type:String})],ChromedashBanner.prototype,"message",void 0),ChromedashBanner=__decorate$Y([t$3("chromedash-banner")],ChromedashBanner);const FORM_STYLES=[VARS,i$7` + table tr[hidden] th, table tr[hidden] td { + padding: 0; + } + + table th { + padding: 12px 10px 5px 0; + vertical-align: top; + } + + table td { + padding: 6px 10px; + vertical-align: top; + } + + table td:first-of-type { + width: 60%; + } + + table .helptext { + display: block; + font-size: small; + margin-top: 2px; + } + + table input[type="text"], table input[type="url"], + table input[type="email"], table textarea { + width: 100%; + font: var(--form-element-font); + } + + table select { + max-width: 350px; + } + + table:required { + border: 1px solid $chromium-color-dark; + } + + table .interacted:valid { + border: 1px solid green; + } + + table .interacted:invalid { + border: 1px solid $invalid-color; + } + + table input:not([type="submit"]):not([type="search"]) { + outline: 1px dotted var(--error-border-color); + background-color: #FFEDF5; + } + + input, textarea { + padding: 7px; + } + + form[name="feature_form"] h3 { + margin: var(--content-padding-half) 0; + } + form[name="feature_form"] input[type="submit"] { + margin-top: var(--content-padding); + } + + form[name="feature_form"] .stage_form { + margin-bottom: 2em; + } + + form section.flat_form + h3, .final_buttons { + margin-top: 2em; + } + + .fade-in { + animation:fadeIn 0.5s linear; + } + + @keyframes fadeIn { + 0% { + opacity:0 + } + 100% { + opacity:1; + } + } + + #metadata, .stage_form, .flat_form, .final_buttons { + max-width: 67em; + padding: 1em; + } + + #metadata, .stage_form, .flat_form { + color: #444; + background: white; + border: 1px solid #ccc; + box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; + } + + #metadata-readonly div + div { + margin-top: 4px; + } + + sl-input::part(base) { + overflow: visible; + } + + sl-input[invalid]::part(input), + sl-checkbox[invalid]::part(input), + chromedash-textarea[invalid]::part(textarea) + { + outline: 1px dotted red; + background-color: #FFEDF5; + } + + sl-select[size="small"] sl-menu-item::part(base) { + font-size: var(--sl-font-size-x-small); + padding: 0px; + } + + /* Hide select until loading is done and the component is defined. */ + :not(:defined) { + visibility: hidden; + } + + /* menu items for selects should not be displayed at all, until defined */ + sl-select sl-menu-item:not(:defined) { + display: none; + } + + chromedash-form-field { + display: table-row-group; + } + + chromedash-form-field tr[hidden] th, + chromedash-form-field tr[hidden] td { + padding: 0; + } + + chromedash-form-field th, + chromedash-form-field td { + text-align: left; + vertical-align: top; + } + + chromedash-form-field th { + padding: 12px 10px 5px 0; + } + + chromedash-form-field td { + padding: 6px 10px; + } + + chromedash-form-field td:first-of-type { + width: 60%; + max-width: 35em; + } + + chromedash-form-field .check-warning { + color: orange; + } + + chromedash-form-field .check-error { + color: red; + } + + chromedash-form-field .helptext { + display: block; + font-size: small; + margin-top: 2px; + } + + chromedash-form-field .helptext > *:first-child { + margin-top: 0; + } + chromedash-form-field .helptext > *:last-child { + margin-bottom: 0; + } + + chromedash-form-field .helptext p { + margin: 1em 0; + } + + chromedash-form-field .helptext ul { + margin: 1em 0; + } + + chromedash-form-field .helptext blockquote { + margin: 1em; + border: 1px solid lightgrey; + padding: 0.5em; + } + + chromedash-form-field .errorlist { + color: red; + } + + chromedash-form-field sl-input[data-user-invalid]::part(base), + chromedash-form-field chromedash-textarea[data-user-invalid]::part(base) { + border-color: red; + } + + chromedash-form-field sl-details::part(base) { + border-width: 0; + } + + chromedash-form-field sl-details::part(header) { + padding: 0; + display: none; + } + + chromedash-form-field sl-details::part(content) { + padding-top: 0; + } + + chromedash-form-field sl-icon-button::part(base) { + font-size: 16px; + color: var(--link-color); + padding: 0; + margin: 4px; + } + + chromedash-form-field td.extrahelp { + padding-left: 2em; + } + chromedash-form-field .extrahelp > span, chromedash-form-field .webdx > span { + margin: 0; + } + + chromedash-form-field .datalist-input { + width: 100%; + height: 30px; + border-radius: 4px; + padding-left: 12px; + font-family: inherit; + font-size: inherit; + color: #27272a; + } + chromedash-form-field .datalist-input:hover { + border-color: #aaa; + } + chromedash-form-field .datalist-input:focus { + outline: none; + border-color: #0ea5e9; + } + + chromedash-form-field .datalist-input-wrapper { + border-radius: 4px; + } + chromedash-form-field .datalist-input-wrapper:focus-within { + box-shadow: 0 0 0 3px #0ea5e966; + } + + chromedash-form-field .form-field-header { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + } + chromedash-form-field .usage-tag { + padding: 2px 6px; + margin-inline-start: 4px; + border-radius: 12px; + font-size: 0.85em; + font-weight: 700; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: help; + color: #424242; + background-color: #f5f5f5; + border: 1px solid #bdbdbd; + } + + sl-skeleton { + margin-bottom: 1em; + width: 60%; + } + sl-skeleton:nth-of-type(even) { + width: 50%; + } + + h3 sl-skeleton { + margin-top: 1em; + width: 30%; + height: 1.5em; + } + + .choices label { + font-weight: bold; + } + .choices div { + margin-top: 1em; + } + .choices p { + margin: 0.5em 1.5em 1em; + } + `];var global$1="undefined"==typeof global?"undefined"==typeof self?"undefined"==typeof window?{}:window:self:global,lookup=[],revLookup=[],Arr="undefined"==typeof Uint8Array?Array:Uint8Array,inited=!1;function init(){inited=!0;for(var code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,len=code.length;i<len;++i)lookup[i]=code[i],revLookup[code.charCodeAt(i)]=i;revLookup[45]=62,revLookup[95]=63}function toByteArray(b64){inited||init();var len=b64.length,i,j,l,tmp,placeHolders,arr;if(0<len%4)throw new Error("Invalid string. Length must be a multiple of 4");placeHolders="="===b64[len-2]?2:"="===b64[len-1]?1:0,arr=new Arr(3*len/4-placeHolders),l=0<placeHolders?len-4:len;var L=0;for(i=0,j=0;i<l;i+=4,j+=3)tmp=revLookup[b64.charCodeAt(i)]<<18|revLookup[b64.charCodeAt(i+1)]<<12|revLookup[b64.charCodeAt(i+2)]<<6|revLookup[b64.charCodeAt(i+3)],arr[L++]=255&tmp>>16,arr[L++]=255&tmp>>8,arr[L++]=255&tmp;return 2===placeHolders?(tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4,arr[L++]=255&tmp):1==placeHolders&&(tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2,arr[L++]=255&tmp>>8,arr[L++]=255&tmp),arr}function tripletToBase64(num){return lookup[63&num>>18]+lookup[63&num>>12]+lookup[63&num>>6]+lookup[63&num]}function encodeChunk(uint8,start,end){for(var output=[],i=start,tmp;i<end;i+=3)tmp=(uint8[i]<<16)+(uint8[i+1]<<8)+uint8[i+2],output.push(tripletToBase64(tmp));return output.join("")}function fromByteArray(uint8){inited||init();for(var len=uint8.length,extraBytes=len%3,output="",parts=[],maxChunkLength=16383,i=0,len2=len-extraBytes,tmp;i<len2;i+=maxChunkLength)parts.push(encodeChunk(uint8,i,i+maxChunkLength>len2?len2:i+maxChunkLength));return 1===extraBytes?(tmp=uint8[len-1],output+=lookup[tmp>>2],output+=lookup[63&tmp<<4],output+="=="):2===extraBytes&&(tmp=(uint8[len-2]<<8)+uint8[len-1],output+=lookup[tmp>>10],output+=lookup[63&tmp>>4],output+=lookup[63&tmp<<2],output+="="),parts.push(output),parts.join("")}function read(buffer,offset,isLE,mLen,nBytes){var _Mathpow=Math.pow,eLen=8*nBytes-mLen-1,eMax=(1<<eLen)-1,eBias=eMax>>1,nBits=-7,i=isLE?nBytes-1:0,d=isLE?-1:1,s=buffer[offset+i],e,m;for(i+=d,e=s&(1<<-nBits)-1,s>>=-nBits,nBits+=eLen;0<nBits;e=256*e+buffer[offset+i],i+=d,nBits-=8);for(m=e&(1<<-nBits)-1,e>>=-nBits,nBits+=mLen;0<nBits;m=256*m+buffer[offset+i],i+=d,nBits-=8);if(0===e)e=1-eBias;else{if(e===eMax)return m?NaN:(s?-1:1)*(1/0);m+=_Mathpow(2,mLen),e-=eBias}return(s?-1:1)*m*_Mathpow(2,e-mLen)}function write(buffer,value,offset,isLE,mLen,nBytes){var _MathLN=Math.LN2,_Mathlog=Math.log,_Mathpow2=Math.pow,_Mathfloor2=Math.floor,_Mathabs2=Math.abs,eLen=8*nBytes-mLen-1,eMax=(1<<eLen)-1,eBias=eMax>>1,rt=23===mLen?_Mathpow2(2,-24)-_Mathpow2(2,-77):0,i=isLE?0:nBytes-1,d=isLE?1:-1,s=0>value||0===value&&0>1/value?1:0,e,m,c;for(value=_Mathabs2(value),isNaN(value)||value===1/0?(m=isNaN(value)?1:0,e=eMax):(e=_Mathfloor2(_Mathlog(value)/_MathLN),1>value*(c=_Mathpow2(2,-e))&&(e--,c*=2),value+=1<=e+eBias?rt/c:rt*_Mathpow2(2,1-eBias),2<=value*c&&(e++,c/=2),e+eBias>=eMax?(m=0,e=eMax):1<=e+eBias?(m=(value*c-1)*_Mathpow2(2,mLen),e+=eBias):(m=value*_Mathpow2(2,eBias-1)*_Mathpow2(2,mLen),e=0));8<=mLen;buffer[offset+i]=255&m,i+=d,m/=256,mLen-=8);for(e=e<<mLen|m,eLen+=mLen;0<eLen;buffer[offset+i]=255&e,i+=d,e/=256,eLen-=8);buffer[offset+i-d]|=128*s}var toString={}.toString,isArray=Array.isArray||function(arr){return"[object Array]"==toString.call(arr)},INSPECT_MAX_BYTES=50;Buffer.TYPED_ARRAY_SUPPORT=!(global$1.TYPED_ARRAY_SUPPORT!==void 0)||global$1.TYPED_ARRAY_SUPPORT,kMaxLength();function kMaxLength(){return Buffer.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function createBuffer(that,length){if(kMaxLength()<length)throw new RangeError("Invalid typed array length");return Buffer.TYPED_ARRAY_SUPPORT?(that=new Uint8Array(length),that.__proto__=Buffer.prototype):(null===that&&(that=new Buffer(length)),that.length=length),that}function Buffer(arg,encodingOrOffset,length){if(!Buffer.TYPED_ARRAY_SUPPORT&&!(this instanceof Buffer))return new Buffer(arg,encodingOrOffset,length);if("number"==typeof arg){if("string"==typeof encodingOrOffset)throw new Error("If encoding is specified then the first argument must be a string");return allocUnsafe(this,arg)}return from(this,arg,encodingOrOffset,length)}Buffer.poolSize=8192,Buffer._augment=function(arr){return arr.__proto__=Buffer.prototype,arr};function from(that,value,encodingOrOffset,length){if("number"==typeof value)throw new TypeError("\"value\" argument must not be a number");return"undefined"!=typeof ArrayBuffer&&value instanceof ArrayBuffer?fromArrayBuffer(that,value,encodingOrOffset,length):"string"==typeof value?fromString(that,value,encodingOrOffset):fromObject(that,value)}if(Buffer.from=function(value,encodingOrOffset,length){return from(null,value,encodingOrOffset,length)},Buffer.TYPED_ARRAY_SUPPORT&&(Buffer.prototype.__proto__=Uint8Array.prototype,Buffer.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&Buffer[Symbol.species]===Buffer));function assertSize(size){if("number"!=typeof size)throw new TypeError("\"size\" argument must be a number");else if(0>size)throw new RangeError("\"size\" argument must not be negative")}function alloc(that,size,fill,encoding){return assertSize(size),0>=size?createBuffer(that,size):void 0===fill?createBuffer(that,size):"string"==typeof encoding?createBuffer(that,size).fill(fill,encoding):createBuffer(that,size).fill(fill)}Buffer.alloc=function(size,fill,encoding){return alloc(null,size,fill,encoding)};function allocUnsafe(that,size){if(assertSize(size),that=createBuffer(that,0>size?0:0|checked(size)),!Buffer.TYPED_ARRAY_SUPPORT)for(var i=0;i<size;++i)that[i]=0;return that}Buffer.allocUnsafe=function(size){return allocUnsafe(null,size)},Buffer.allocUnsafeSlow=function(size){return allocUnsafe(null,size)};function fromString(that,string,encoding){if(("string"!=typeof encoding||""===encoding)&&(encoding="utf8"),!Buffer.isEncoding(encoding))throw new TypeError("\"encoding\" must be a valid string encoding");var length=0|byteLength(string,encoding);that=createBuffer(that,length);var actual=that.write(string,encoding);return actual!==length&&(that=that.slice(0,actual)),that}function fromArrayLike(that,array){var length=0>array.length?0:0|checked(array.length);that=createBuffer(that,length);for(var i=0;i<length;i+=1)that[i]=255&array[i];return that}function fromArrayBuffer(that,array,byteOffset,length){if(array.byteLength,0>byteOffset||array.byteLength<byteOffset)throw new RangeError("'offset' is out of bounds");if(array.byteLength<byteOffset+(length||0))throw new RangeError("'length' is out of bounds");return array=void 0===byteOffset&&void 0===length?new Uint8Array(array):void 0===length?new Uint8Array(array,byteOffset):new Uint8Array(array,byteOffset,length),Buffer.TYPED_ARRAY_SUPPORT?(that=array,that.__proto__=Buffer.prototype):that=fromArrayLike(that,array),that}function fromObject(that,obj){if(internalIsBuffer(obj)){var len=0|checked(obj.length);return(that=createBuffer(that,len),0===that.length)?that:(obj.copy(that,0,0,len),that)}if(obj){if("undefined"!=typeof ArrayBuffer&&obj.buffer instanceof ArrayBuffer||"length"in obj)return"number"!=typeof obj.length||isnan(obj.length)?createBuffer(that,0):fromArrayLike(that,obj);if("Buffer"===obj.type&&isArray(obj.data))return fromArrayLike(that,obj.data)}throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}function checked(length){if(length>=kMaxLength())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+kMaxLength().toString(16)+" bytes");return 0|length}Buffer.isBuffer=isBuffer;function internalIsBuffer(b){return!!(null!=b&&b._isBuffer)}Buffer.compare=function compare(a,b){if(!internalIsBuffer(a)||!internalIsBuffer(b))throw new TypeError("Arguments must be Buffers");if(a===b)return 0;for(var x=a.length,y=b.length,i=0,len=Math.min(x,y);i<len;++i)if(a[i]!==b[i]){x=a[i],y=b[i];break}return x<y?-1:y<x?1:0},Buffer.isEncoding=function isEncoding(encoding){switch((encoding+"").toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},Buffer.concat=function concat(list,length){if(!isArray(list))throw new TypeError("\"list\" argument must be an Array of Buffers");if(0===list.length)return Buffer.alloc(0);var i;if(length===void 0)for(length=0,i=0;i<list.length;++i)length+=list[i].length;var buffer=Buffer.allocUnsafe(length),pos=0;for(i=0;i<list.length;++i){var buf=list[i];if(!internalIsBuffer(buf))throw new TypeError("\"list\" argument must be an Array of Buffers");buf.copy(buffer,pos),pos+=buf.length}return buffer};function byteLength(string,encoding){if(internalIsBuffer(string))return string.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(string)||string instanceof ArrayBuffer))return string.byteLength;"string"!=typeof string&&(string=""+string);var len=string.length;if(0===len)return 0;for(var loweredCase=!1;;)switch(encoding){case"ascii":case"latin1":case"binary":return len;case"utf8":case"utf-8":case void 0:return utf8ToBytes(string).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*len;case"hex":return len>>>1;case"base64":return base64ToBytes(string).length;default:if(loweredCase)return utf8ToBytes(string).length;encoding=(""+encoding).toLowerCase(),loweredCase=!0}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){var loweredCase=!1;if((void 0===start||0>start)&&(start=0),start>this.length)return"";if((void 0===end||end>this.length)&&(end=this.length),0>=end)return"";if(end>>>=0,start>>>=0,end<=start)return"";for(encoding||(encoding="utf8");!0;)switch(encoding){case"hex":return hexSlice(this,start,end);case"utf8":case"utf-8":return utf8Slice(this,start,end);case"ascii":return asciiSlice(this,start,end);case"latin1":case"binary":return latin1Slice(this,start,end);case"base64":return base64Slice(this,start,end);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return utf16leSlice(this,start,end);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(encoding+"").toLowerCase(),loweredCase=!0}}Buffer.prototype._isBuffer=!0;function swap(b,n,m){var i=b[n];b[n]=b[m],b[m]=i}Buffer.prototype.swap16=function swap16(){var len=this.length;if(0!=len%2)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var i=0;i<len;i+=2)swap(this,i,i+1);return this},Buffer.prototype.swap32=function swap32(){var len=this.length;if(0!=len%4)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var i=0;i<len;i+=4)swap(this,i,i+3),swap(this,i+1,i+2);return this},Buffer.prototype.swap64=function swap64(){var len=this.length;if(0!=len%8)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var i=0;i<len;i+=8)swap(this,i,i+7),swap(this,i+1,i+6),swap(this,i+2,i+5),swap(this,i+3,i+4);return this},Buffer.prototype.toString=function toString(){var length=0|this.length;return 0==length?"":0===arguments.length?utf8Slice(this,0,length):slowToString.apply(this,arguments)},Buffer.prototype.equals=function equals(b){if(!internalIsBuffer(b))throw new TypeError("Argument must be a Buffer");return this===b||0===Buffer.compare(this,b)},Buffer.prototype.inspect=function inspect(){var str="",max=INSPECT_MAX_BYTES;return 0<this.length&&(str=this.toString("hex",0,max).match(/.{2}/g).join(" "),this.length>max&&(str+=" ... ")),"<Buffer "+str+">"},Buffer.prototype.compare=function compare(target,start,end,thisStart,thisEnd){var _Mathmin2=Math.min;if(!internalIsBuffer(target))throw new TypeError("Argument must be a Buffer");if(void 0===start&&(start=0),void 0===end&&(end=target?target.length:0),void 0===thisStart&&(thisStart=0),void 0===thisEnd&&(thisEnd=this.length),0>start||end>target.length||0>thisStart||thisEnd>this.length)throw new RangeError("out of range index");if(thisStart>=thisEnd&&start>=end)return 0;if(thisStart>=thisEnd)return-1;if(start>=end)return 1;if(start>>>=0,end>>>=0,thisStart>>>=0,thisEnd>>>=0,this===target)return 0;for(var x=thisEnd-thisStart,y=end-start,len=_Mathmin2(x,y),thisCopy=this.slice(thisStart,thisEnd),targetCopy=target.slice(start,end),i=0;i<len;++i)if(thisCopy[i]!==targetCopy[i]){x=thisCopy[i],y=targetCopy[i];break}return x<y?-1:y<x?1:0};function bidirectionalIndexOf(buffer,val,byteOffset,encoding,dir){if(0===buffer.length)return-1;if("string"==typeof byteOffset?(encoding=byteOffset,byteOffset=0):2147483647<byteOffset?byteOffset=2147483647:-2147483648>byteOffset&&(byteOffset=-2147483648),byteOffset=+byteOffset,isNaN(byteOffset)&&(byteOffset=dir?0:buffer.length-1),0>byteOffset&&(byteOffset=buffer.length+byteOffset),byteOffset>=buffer.length){if(dir)return-1;byteOffset=buffer.length-1}else if(0>byteOffset)if(dir)byteOffset=0;else return-1;if("string"==typeof val&&(val=Buffer.from(val,encoding)),internalIsBuffer(val))return 0===val.length?-1:arrayIndexOf(buffer,val,byteOffset,encoding,dir);if("number"==typeof val)return val&=255,Buffer.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?dir?Uint8Array.prototype.indexOf.call(buffer,val,byteOffset):Uint8Array.prototype.lastIndexOf.call(buffer,val,byteOffset):arrayIndexOf(buffer,[val],byteOffset,encoding,dir);throw new TypeError("val must be string, number or Buffer")}function arrayIndexOf(arr,val,byteOffset,encoding,dir){function read(buf,i){return 1===indexSize?buf[i]:buf.readUInt16BE(i*indexSize)}var indexSize=1,arrLength=arr.length,valLength=val.length;if(void 0!==encoding&&(encoding=(encoding+"").toLowerCase(),"ucs2"===encoding||"ucs-2"===encoding||"utf16le"===encoding||"utf-16le"===encoding)){if(2>arr.length||2>val.length)return-1;indexSize=2,arrLength/=2,valLength/=2,byteOffset/=2}var i;if(dir){var foundIndex=-1;for(i=byteOffset;i<arrLength;i++)if(read(arr,i)!==read(val,-1===foundIndex?0:i-foundIndex))-1!==foundIndex&&(i-=i-foundIndex),foundIndex=-1;else if(-1===foundIndex&&(foundIndex=i),i-foundIndex+1===valLength)return foundIndex*indexSize}else for(byteOffset+valLength>arrLength&&(byteOffset=arrLength-valLength),i=byteOffset;0<=i;i--){for(var found=!0,j=0;j<valLength;j++)if(read(arr,i+j)!==read(val,j)){found=!1;break}if(found)return i}return-1}Buffer.prototype.includes=function includes(val,byteOffset,encoding){return-1!==this.indexOf(val,byteOffset,encoding)},Buffer.prototype.indexOf=function indexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,!0)},Buffer.prototype.lastIndexOf=function lastIndexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,!1)};function hexWrite(buf,string,offset,length){offset=+offset||0;var remaining=buf.length-offset;length?(length=+length,length>remaining&&(length=remaining)):length=remaining;var strLen=string.length;if(0!=strLen%2)throw new TypeError("Invalid hex string");length>strLen/2&&(length=strLen/2);for(var i=0,parsed;i<length;++i){if(parsed=parseInt(string.substr(2*i,2),16),isNaN(parsed))return i;buf[offset+i]=parsed}return i}function utf8Write(buf,string,offset,length){return blitBuffer(utf8ToBytes(string,buf.length-offset),buf,offset,length)}function asciiWrite(buf,string,offset,length){return blitBuffer(asciiToBytes(string),buf,offset,length)}function latin1Write(buf,string,offset,length){return asciiWrite(buf,string,offset,length)}function base64Write(buf,string,offset,length){return blitBuffer(base64ToBytes(string),buf,offset,length)}function ucs2Write(buf,string,offset,length){return blitBuffer(utf16leToBytes(string,buf.length-offset),buf,offset,length)}Buffer.prototype.write=function write(string,offset,length,encoding){if(void 0===offset)encoding="utf8",length=this.length,offset=0;else if(void 0===length&&"string"==typeof offset)encoding=offset,length=this.length,offset=0;else if(isFinite(offset))offset|=0,isFinite(length)?(length|=0,void 0===encoding&&(encoding="utf8")):(encoding=length,length=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");var remaining=this.length-offset;if((void 0===length||length>remaining)&&(length=remaining),0<string.length&&(0>length||0>offset)||offset>this.length)throw new RangeError("Attempt to write outside buffer bounds");encoding||(encoding="utf8");for(var loweredCase=!1;;)switch(encoding){case"hex":return hexWrite(this,string,offset,length);case"utf8":case"utf-8":return utf8Write(this,string,offset,length);case"ascii":return asciiWrite(this,string,offset,length);case"latin1":case"binary":return latin1Write(this,string,offset,length);case"base64":return base64Write(this,string,offset,length);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ucs2Write(this,string,offset,length);default:if(loweredCase)throw new TypeError("Unknown encoding: "+encoding);encoding=(""+encoding).toLowerCase(),loweredCase=!0}},Buffer.prototype.toJSON=function toJSON(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function base64Slice(buf,start,end){return 0===start&&end===buf.length?fromByteArray(buf):fromByteArray(buf.slice(start,end))}function utf8Slice(buf,start,end){end=Math.min(buf.length,end);for(var res=[],i=start;i<end;){var firstByte=buf[i],codePoint=null,bytesPerSequence=239<firstByte?4:223<firstByte?3:191<firstByte?2:1;if(i+bytesPerSequence<=end){var secondByte,thirdByte,fourthByte,tempCodePoint;1===bytesPerSequence?128>firstByte&&(codePoint=firstByte):2===bytesPerSequence?(secondByte=buf[i+1],128==(192&secondByte)&&(tempCodePoint=(31&firstByte)<<6|63&secondByte,127<tempCodePoint&&(codePoint=tempCodePoint))):3===bytesPerSequence?(secondByte=buf[i+1],thirdByte=buf[i+2],128==(192&secondByte)&&128==(192&thirdByte)&&(tempCodePoint=(15&firstByte)<<12|(63&secondByte)<<6|63&thirdByte,2047<tempCodePoint&&(55296>tempCodePoint||57343<tempCodePoint)&&(codePoint=tempCodePoint))):4===bytesPerSequence?(secondByte=buf[i+1],thirdByte=buf[i+2],fourthByte=buf[i+3],128==(192&secondByte)&&128==(192&thirdByte)&&128==(192&fourthByte)&&(tempCodePoint=(15&firstByte)<<18|(63&secondByte)<<12|(63&thirdByte)<<6|63&fourthByte,65535<tempCodePoint&&1114112>tempCodePoint&&(codePoint=tempCodePoint))):void 0}null===codePoint?(codePoint=65533,bytesPerSequence=1):65535<codePoint&&(codePoint-=65536,res.push(55296|1023&codePoint>>>10),codePoint=56320|1023&codePoint),res.push(codePoint),i+=bytesPerSequence}return decodeCodePointsArray(res)}var MAX_ARGUMENTS_LENGTH=4096;function decodeCodePointsArray(codePoints){var _StringfromCharCode=String.fromCharCode,len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH)return _StringfromCharCode.apply(String,codePoints);for(var res="",i=0;i<len;)res+=_StringfromCharCode.apply(String,codePoints.slice(i,i+=MAX_ARGUMENTS_LENGTH));return res}function asciiSlice(buf,start,end){var ret="";end=Math.min(buf.length,end);for(var i=start;i<end;++i)ret+=String.fromCharCode(127&buf[i]);return ret}function latin1Slice(buf,start,end){var ret="";end=Math.min(buf.length,end);for(var i=start;i<end;++i)ret+=String.fromCharCode(buf[i]);return ret}function hexSlice(buf,start,end){var len=buf.length;(!start||0>start)&&(start=0),(!end||0>end||end>len)&&(end=len);for(var out="",i=start;i<end;++i)out+=toHex(buf[i]);return out}function utf16leSlice(buf,start,end){for(var bytes=buf.slice(start,end),res="",i=0;i<bytes.length;i+=2)res+=String.fromCharCode(bytes[i]+256*bytes[i+1]);return res}Buffer.prototype.slice=function slice(start,end){var len=this.length;start=~~start,end=end===void 0?len:~~end,0>start?(start+=len,0>start&&(start=0)):start>len&&(start=len),0>end?(end+=len,0>end&&(end=0)):end>len&&(end=len),end<start&&(end=start);var newBuf;if(Buffer.TYPED_ARRAY_SUPPORT)newBuf=this.subarray(start,end),newBuf.__proto__=Buffer.prototype;else{var sliceLen=end-start;newBuf=new Buffer(sliceLen,void 0);for(var i=0;i<sliceLen;++i)newBuf[i]=this[i+start]}return newBuf};function checkOffset(offset,ext,length){if(0!=offset%1||0>offset)throw new RangeError("offset is not uint");if(offset+ext>length)throw new RangeError("Trying to access beyond buffer length")}Buffer.prototype.readUIntLE=function readUIntLE(offset,byteLength,noAssert){offset|=0,byteLength|=0,noAssert||checkOffset(offset,byteLength,this.length);for(var val=this[offset],mul=1,i=0;++i<byteLength&&(mul*=256);)val+=this[offset+i]*mul;return val},Buffer.prototype.readUIntBE=function readUIntBE(offset,byteLength,noAssert){offset|=0,byteLength|=0,noAssert||checkOffset(offset,byteLength,this.length);for(var val=this[offset+--byteLength],mul=1;0<byteLength&&(mul*=256);)val+=this[offset+--byteLength]*mul;return val},Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){return noAssert||checkOffset(offset,1,this.length),this[offset]},Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){return noAssert||checkOffset(offset,2,this.length),this[offset]|this[offset+1]<<8},Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){return noAssert||checkOffset(offset,2,this.length),this[offset]<<8|this[offset+1]},Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+16777216*this[offset+3]},Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),16777216*this[offset]+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3])},Buffer.prototype.readIntLE=function readIntLE(offset,byteLength,noAssert){var _Mathpow3=Math.pow;offset|=0,byteLength|=0,noAssert||checkOffset(offset,byteLength,this.length);for(var val=this[offset],mul=1,i=0;++i<byteLength&&(mul*=256);)val+=this[offset+i]*mul;return mul*=128,val>=mul&&(val-=_Mathpow3(2,8*byteLength)),val},Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){var _Mathpow4=Math.pow;offset|=0,byteLength|=0,noAssert||checkOffset(offset,byteLength,this.length);for(var i=byteLength,mul=1,val=this[offset+--i];0<i&&(mul*=256);)val+=this[offset+--i]*mul;return mul*=128,val>=mul&&(val-=_Mathpow4(2,8*byteLength)),val},Buffer.prototype.readInt8=function readInt8(offset,noAssert){return noAssert||checkOffset(offset,1,this.length),128&this[offset]?-1*(255-this[offset]+1):this[offset]},Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){noAssert||checkOffset(offset,2,this.length);var val=this[offset]|this[offset+1]<<8;return 32768&val?4294901760|val:val},Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){noAssert||checkOffset(offset,2,this.length);var val=this[offset+1]|this[offset]<<8;return 32768&val?4294901760|val:val},Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24},Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3]},Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),read(this,offset,!0,23,4)},Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){return noAssert||checkOffset(offset,4,this.length),read(this,offset,!1,23,4)},Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){return noAssert||checkOffset(offset,8,this.length),read(this,offset,!0,52,8)},Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){return noAssert||checkOffset(offset,8,this.length),read(this,offset,!1,52,8)};function checkInt(buf,value,offset,ext,max,min){if(!internalIsBuffer(buf))throw new TypeError("\"buffer\" argument must be a Buffer instance");if(value>max||value<min)throw new RangeError("\"value\" argument is out of bounds");if(offset+ext>buf.length)throw new RangeError("Index out of range")}Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){var _Mathpow5=Math.pow;if(value=+value,offset|=0,byteLength|=0,!noAssert){var maxBytes=_Mathpow5(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var mul=1,i=0;for(this[offset]=255&value;++i<byteLength&&(mul*=256);)this[offset+i]=255&value/mul;return offset+byteLength},Buffer.prototype.writeUIntBE=function writeUIntBE(value,offset,byteLength,noAssert){var _Mathpow6=Math.pow;if(value=+value,offset|=0,byteLength|=0,!noAssert){var maxBytes=_Mathpow6(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var i=byteLength-1,mul=1;for(this[offset+i]=255&value;0<=--i&&(mul*=256);)this[offset+i]=255&value/mul;return offset+byteLength},Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){var _Mathfloor3=Math.floor;return value=+value,offset|=0,noAssert||checkInt(this,value,offset,1,255,0),Buffer.TYPED_ARRAY_SUPPORT||(value=_Mathfloor3(value)),this[offset]=255&value,offset+1};function objectWriteUInt16(buf,value,offset,littleEndian){0>value&&(value=65535+value+1);for(var i=0,j=Math.min(buf.length-offset,2);i<j;++i)buf[offset+i]=(value&255<<8*(littleEndian?i:1-i))>>>8*(littleEndian?i:1-i)}Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=255&value,this[offset+1]=value>>>8):objectWriteUInt16(this,value,offset,!0),offset+2},Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,2,65535,0),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=value>>>8,this[offset+1]=255&value):objectWriteUInt16(this,value,offset,!1),offset+2};function objectWriteUInt32(buf,value,offset,littleEndian){0>value&&(value=4294967295+value+1);for(var i=0,j=Math.min(buf.length-offset,4);i<j;++i)buf[offset+i]=255&value>>>8*(littleEndian?i:3-i)}Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[offset+3]=value>>>24,this[offset+2]=value>>>16,this[offset+1]=value>>>8,this[offset]=255&value):objectWriteUInt32(this,value,offset,!0),offset+4},Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,4,4294967295,0),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=value>>>24,this[offset+1]=value>>>16,this[offset+2]=value>>>8,this[offset+3]=255&value):objectWriteUInt32(this,value,offset,!1),offset+4},Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){var _Mathpow7=Math.pow;if(value=+value,offset|=0,!noAssert){var limit=_Mathpow7(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=0,mul=1,sub=0;for(this[offset]=255&value;++i<byteLength&&(mul*=256);)0>value&&0===sub&&0!==this[offset+i-1]&&(sub=1),this[offset+i]=255&(value/mul>>0)-sub;return offset+byteLength},Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){var _Mathpow8=Math.pow;if(value=+value,offset|=0,!noAssert){var limit=_Mathpow8(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=byteLength-1,mul=1,sub=0;for(this[offset+i]=255&value;0<=--i&&(mul*=256);)0>value&&0===sub&&0!==this[offset+i+1]&&(sub=1),this[offset+i]=255&(value/mul>>0)-sub;return offset+byteLength},Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){var _Mathfloor4=Math.floor;return value=+value,offset|=0,noAssert||checkInt(this,value,offset,1,127,-128),Buffer.TYPED_ARRAY_SUPPORT||(value=_Mathfloor4(value)),0>value&&(value=255+value+1),this[offset]=255&value,offset+1},Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=255&value,this[offset+1]=value>>>8):objectWriteUInt16(this,value,offset,!0),offset+2},Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,2,32767,-32768),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=value>>>8,this[offset+1]=255&value):objectWriteUInt16(this,value,offset,!1),offset+2},Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,4,2147483647,-2147483648),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=255&value,this[offset+1]=value>>>8,this[offset+2]=value>>>16,this[offset+3]=value>>>24):objectWriteUInt32(this,value,offset,!0),offset+4},Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){return value=+value,offset|=0,noAssert||checkInt(this,value,offset,4,2147483647,-2147483648),0>value&&(value=4294967295+value+1),Buffer.TYPED_ARRAY_SUPPORT?(this[offset]=value>>>24,this[offset+1]=value>>>16,this[offset+2]=value>>>8,this[offset+3]=255&value):objectWriteUInt32(this,value,offset,!1),offset+4};function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError("Index out of range");if(0>offset)throw new RangeError("Index out of range")}function writeFloat(buf,value,offset,littleEndian,noAssert){return noAssert||checkIEEE754(buf,value,offset,4),write(buf,value,offset,littleEndian,23,4),offset+4}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,!0,noAssert)},Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,!1,noAssert)};function writeDouble(buf,value,offset,littleEndian,noAssert){return noAssert||checkIEEE754(buf,value,offset,8),write(buf,value,offset,littleEndian,52,8),offset+8}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,!0,noAssert)},Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,!1,noAssert)},Buffer.prototype.copy=function copy(target,targetStart,start,end){if(start||(start=0),end||0===end||(end=this.length),targetStart>=target.length&&(targetStart=target.length),targetStart||(targetStart=0),0<end&&end<start&&(end=start),end===start)return 0;if(0===target.length||0===this.length)return 0;if(0>targetStart)throw new RangeError("targetStart out of bounds");if(0>start||start>=this.length)throw new RangeError("sourceStart out of bounds");if(0>end)throw new RangeError("sourceEnd out of bounds");end>this.length&&(end=this.length),target.length-targetStart<end-start&&(end=target.length-targetStart+start);var len=end-start,i;if(this===target&&start<targetStart&&targetStart<end)for(i=len-1;0<=i;--i)target[i+targetStart]=this[i+start];else if(1e3>len||!Buffer.TYPED_ARRAY_SUPPORT)for(i=0;i<len;++i)target[i+targetStart]=this[i+start];else Uint8Array.prototype.set.call(target,this.subarray(start,start+len),targetStart);return len},Buffer.prototype.fill=function fill(val,start,end,encoding){if("string"==typeof val){if("string"==typeof start?(encoding=start,start=0,end=this.length):"string"==typeof end&&(encoding=end,end=this.length),1===val.length){var code=val.charCodeAt(0);256>code&&(val=code)}if(void 0!==encoding&&"string"!=typeof encoding)throw new TypeError("encoding must be a string");if("string"==typeof encoding&&!Buffer.isEncoding(encoding))throw new TypeError("Unknown encoding: "+encoding)}else"number"==typeof val&&(val&=255);if(0>start||this.length<start||this.length<end)throw new RangeError("Out of range index");if(end<=start)return this;start>>>=0,end=end===void 0?this.length:end>>>0,val||(val=0);var i;if("number"==typeof val)for(i=start;i<end;++i)this[i]=val;else{var bytes=internalIsBuffer(val)?val:utf8ToBytes(new Buffer(val,encoding).toString()),len=bytes.length;for(i=0;i<end-start;++i)this[i+start]=bytes[i%len]}return this};var INVALID_BASE64_RE=/[^+\/0-9A-Za-z-_]/g;function base64clean(str){if(str=stringtrim(str).replace(INVALID_BASE64_RE,""),2>str.length)return"";for(;0!=str.length%4;)str+="=";return str}function stringtrim(str){return str.trim?str.trim():str.replace(/^\s+|\s+$/g,"")}function toHex(n){return 16>n?"0"+n.toString(16):n.toString(16)}function utf8ToBytes(string,units){units=units||1/0;for(var length=string.length,leadSurrogate=null,bytes=[],i=0,codePoint;i<length;++i){if(codePoint=string.charCodeAt(i),55295<codePoint&&57344>codePoint){if(!leadSurrogate){if(56319<codePoint){-1<(units-=3)&&bytes.push(239,191,189);continue}else if(i+1===length){-1<(units-=3)&&bytes.push(239,191,189);continue}leadSurrogate=codePoint;continue}if(56320>codePoint){-1<(units-=3)&&bytes.push(239,191,189),leadSurrogate=codePoint;continue}codePoint=(leadSurrogate-55296<<10|codePoint-56320)+65536}else leadSurrogate&&-1<(units-=3)&&bytes.push(239,191,189);if(leadSurrogate=null,128>codePoint){if(0>(units-=1))break;bytes.push(codePoint)}else if(2048>codePoint){if(0>(units-=2))break;bytes.push(192|codePoint>>6,128|63&codePoint)}else if(65536>codePoint){if(0>(units-=3))break;bytes.push(224|codePoint>>12,128|63&codePoint>>6,128|63&codePoint)}else if(1114112>codePoint){if(0>(units-=4))break;bytes.push(240|codePoint>>18,128|63&codePoint>>12,128|63&codePoint>>6,128|63&codePoint)}else throw new Error("Invalid code point")}return bytes}function asciiToBytes(str){for(var byteArray=[],i=0;i<str.length;++i)byteArray.push(255&str.charCodeAt(i));return byteArray}function utf16leToBytes(str,units){for(var byteArray=[],i=0,c,hi,lo;i<str.length&&!(0>(units-=2));++i)c=str.charCodeAt(i),hi=c>>8,lo=c%256,byteArray.push(lo),byteArray.push(hi);return byteArray}function base64ToBytes(str){return toByteArray(base64clean(str))}function blitBuffer(src,dst,offset,length){for(var i=0;i<length&&!(i+offset>=dst.length||i>=src.length);++i)dst[i+offset]=src[i];return i}function isnan(val){return val!==val}function isBuffer(obj){return null!=obj&&(!!obj._isBuffer||isFastBuffer(obj)||isSlowBuffer(obj))}function isFastBuffer(obj){return!!obj.constructor&&"function"==typeof obj.constructor.isBuffer&&obj.constructor.isBuffer(obj)}function isSlowBuffer(obj){return"function"==typeof obj.readFloatLE&&"function"==typeof obj.slice&&isFastBuffer(obj.slice(0,0))}class CsvError extends Error{constructor(code,message,options,...contexts){Array.isArray(message)&&(message=message.join(" ").trim()),super(message),Error.captureStackTrace!==void 0&&Error.captureStackTrace(this,CsvError),this.code=code;for(const context of contexts)for(const key in context){const value=context[key];this[key]=isBuffer(value)?value.toString(options.encoding):null==value?value:JSON.parse(JSON.stringify(value))}}}const is_object=function(obj){return"object"==typeof obj&&null!==obj&&!Array.isArray(obj)},normalize_columns_array=function(columns){const normalizedColumns=[];for(let i=0,l=columns.length;i<l;i++){const column=columns[i];if(column===void 0||null===column||!1===column)normalizedColumns[i]={disabled:!0};else if("string"==typeof column)normalizedColumns[i]={name:column};else if(is_object(column)){if("string"!=typeof column.name)throw new CsvError("CSV_OPTION_COLUMNS_MISSING_NAME",["Option columns missing name:",`property "name" is required at position ${i}`,"when column is an object literal"]);normalizedColumns[i]=column}else throw new CsvError("CSV_INVALID_COLUMN_DEFINITION",["Invalid column definition:","expect a string or a literal object,",`got ${JSON.stringify(column)} at position ${i}`])}return normalizedColumns};class ResizeableBuffer{constructor(size=100){this.size=size,this.length=0,this.buf=Buffer.allocUnsafe(size)}prepend(val){if(isBuffer(val)){const length=this.length+val.length;if(length>=this.size&&(this.resize(),length>=this.size))throw Error("INVALID_BUFFER_STATE");const buf=this.buf;this.buf=Buffer.allocUnsafe(this.size),val.copy(this.buf,0),buf.copy(this.buf,val.length),this.length+=val.length}else{const length=this.length++;length===this.size&&this.resize();const buf=this.clone();this.buf[0]=val,buf.copy(this.buf,1,0,length)}}append(val){const length=this.length++;length===this.size&&this.resize(),this.buf[length]=val}clone(){return Buffer.from(this.buf.slice(0,this.length))}resize(){const length=this.length;this.size*=2;const buf=Buffer.allocUnsafe(this.size);this.buf.copy(buf,0,0,length),this.buf=buf}toString(encoding){return encoding?this.buf.slice(0,this.length).toString(encoding):Uint8Array.prototype.slice.call(this.buf.slice(0,this.length))}toJSON(){return this.toString("utf8")}reset(){this.length=0}}const np=12,cr$1=13,nl$1=10,space=32,tab=9,init_state=function(options){var _Mathmax3=Math.max;return{bomSkipped:!1,bufBytesStart:0,castField:options.cast_function,commenting:!1,error:void 0,enabled:1===options.from_line,escaping:!1,escapeIsQuote:isBuffer(options.escape)&&isBuffer(options.quote)&&0===Buffer.compare(options.escape,options.quote),expectedRecordLength:Array.isArray(options.columns)?options.columns.length:void 0,field:new ResizeableBuffer(20),firstLineToHeaders:options.cast_first_line_to_header,needMoreDataSize:_Mathmax3(null===options.comment?0:options.comment.length,...options.delimiter.map(delimiter=>delimiter.length),null===options.quote?0:options.quote.length),previousBuf:void 0,quoting:!1,stop:!1,rawBuffer:new ResizeableBuffer(100),record:[],recordHasError:!1,record_length:0,recordDelimiterMaxLength:0===options.record_delimiter.length?0:_Mathmax3(...options.record_delimiter.map(v=>v.length)),trimChars:[Buffer.from(" ",options.encoding)[0],Buffer.from("\t",options.encoding)[0]],wasQuoting:!1,wasRowDelimiter:!1,timchars:[Buffer.from(Buffer.from([cr$1],"utf8").toString(),options.encoding),Buffer.from(Buffer.from([nl$1],"utf8").toString(),options.encoding),Buffer.from(Buffer.from([np],"utf8").toString(),options.encoding),Buffer.from(Buffer.from([space],"utf8").toString(),options.encoding),Buffer.from(Buffer.from([tab],"utf8").toString(),options.encoding)]}},underscore=function(str){return str.replace(/([A-Z])/g,function(_,match){return"_"+match.toLowerCase()})},normalize_options=function(opts){var _NumberisInteger=Number.isInteger,_Mathfloor5=Math.floor;const options={};for(const opt in opts)options[underscore(opt)]=opts[opt];if(void 0===options.encoding||!0===options.encoding)options.encoding="utf8";else if(null===options.encoding||!1===options.encoding)options.encoding=null;else if("string"!=typeof options.encoding&&null!==options.encoding)throw new CsvError("CSV_INVALID_OPTION_ENCODING",["Invalid option encoding:","encoding must be a string or null to return a buffer,",`got ${JSON.stringify(options.encoding)}`],options);if(void 0===options.bom||null===options.bom||!1===options.bom)options.bom=!1;else if(!0!==options.bom)throw new CsvError("CSV_INVALID_OPTION_BOM",["Invalid option bom:","bom must be true,",`got ${JSON.stringify(options.bom)}`],options);if(options.cast_function=null,void 0===options.cast||null===options.cast||!1===options.cast||""===options.cast)options.cast=void 0;else if("function"==typeof options.cast)options.cast_function=options.cast,options.cast=!0;else if(!0!==options.cast)throw new CsvError("CSV_INVALID_OPTION_CAST",["Invalid option cast:","cast must be true or a function,",`got ${JSON.stringify(options.cast)}`],options);if(void 0===options.cast_date||null===options.cast_date||!1===options.cast_date||""===options.cast_date)options.cast_date=!1;else if(!0===options.cast_date)options.cast_date=function(value){const date=Date.parse(value);return isNaN(date)?value:new Date(date)};else if("function"!=typeof options.cast_date)throw new CsvError("CSV_INVALID_OPTION_CAST_DATE",["Invalid option cast_date:","cast_date must be true or a function,",`got ${JSON.stringify(options.cast_date)}`],options);if(options.cast_first_line_to_header=void 0,!0===options.columns)options.cast_first_line_to_header=void 0;else if("function"==typeof options.columns)options.cast_first_line_to_header=options.columns,options.columns=!0;else if(Array.isArray(options.columns))options.columns=normalize_columns_array(options.columns);else if(void 0===options.columns||null===options.columns||!1===options.columns)options.columns=!1;else throw new CsvError("CSV_INVALID_OPTION_COLUMNS",["Invalid option columns:","expect an array, a function or true,",`got ${JSON.stringify(options.columns)}`],options);if(void 0===options.group_columns_by_name||null===options.group_columns_by_name||!1===options.group_columns_by_name)options.group_columns_by_name=!1;else if(!0!==options.group_columns_by_name)throw new CsvError("CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME",["Invalid option group_columns_by_name:","expect an boolean,",`got ${JSON.stringify(options.group_columns_by_name)}`],options);else if(!1===options.columns)throw new CsvError("CSV_INVALID_OPTION_GROUP_COLUMNS_BY_NAME",["Invalid option group_columns_by_name:","the `columns` mode must be activated."],options);if(void 0===options.comment||null===options.comment||!1===options.comment||""===options.comment)options.comment=null;else if("string"==typeof options.comment&&(options.comment=Buffer.from(options.comment,options.encoding)),!isBuffer(options.comment))throw new CsvError("CSV_INVALID_OPTION_COMMENT",["Invalid option comment:","comment must be a buffer or a string,",`got ${JSON.stringify(options.comment)}`],options);if(void 0===options.comment_no_infix||null===options.comment_no_infix||!1===options.comment_no_infix)options.comment_no_infix=!1;else if(!0!==options.comment_no_infix)throw new CsvError("CSV_INVALID_OPTION_COMMENT",["Invalid option comment_no_infix:","value must be a boolean,",`got ${JSON.stringify(options.comment_no_infix)}`],options);const delimiter_json=JSON.stringify(options.delimiter);if(Array.isArray(options.delimiter)||(options.delimiter=[options.delimiter]),0===options.delimiter.length)throw new CsvError("CSV_INVALID_OPTION_DELIMITER",["Invalid option delimiter:","delimiter must be a non empty string or buffer or array of string|buffer,",`got ${delimiter_json}`],options);if(options.delimiter=options.delimiter.map(function(delimiter){if(void 0===delimiter||null===delimiter||!1===delimiter)return Buffer.from(",",options.encoding);if("string"==typeof delimiter&&(delimiter=Buffer.from(delimiter,options.encoding)),!isBuffer(delimiter)||0===delimiter.length)throw new CsvError("CSV_INVALID_OPTION_DELIMITER",["Invalid option delimiter:","delimiter must be a non empty string or buffer or array of string|buffer,",`got ${delimiter_json}`],options);return delimiter}),void 0===options.escape||!0===options.escape?options.escape=Buffer.from("\"",options.encoding):"string"==typeof options.escape?options.escape=Buffer.from(options.escape,options.encoding):(null===options.escape||!1===options.escape)&&(options.escape=null),null!==options.escape&&!isBuffer(options.escape))throw new Error(`Invalid Option: escape must be a buffer, a string or a boolean, got ${JSON.stringify(options.escape)}`);if(void 0===options.from||null===options.from)options.from=1;else if("string"==typeof options.from&&/\d+/.test(options.from)&&(options.from=parseInt(options.from)),!_NumberisInteger(options.from))throw new Error(`Invalid Option: from must be an integer, got ${JSON.stringify(options.from)}`);else if(0>options.from)throw new Error(`Invalid Option: from must be a positive integer, got ${JSON.stringify(opts.from)}`);if(void 0===options.from_line||null===options.from_line)options.from_line=1;else if("string"==typeof options.from_line&&/\d+/.test(options.from_line)&&(options.from_line=parseInt(options.from_line)),!_NumberisInteger(options.from_line))throw new Error(`Invalid Option: from_line must be an integer, got ${JSON.stringify(opts.from_line)}`);else if(0>=options.from_line)throw new Error(`Invalid Option: from_line must be a positive integer greater than 0, got ${JSON.stringify(opts.from_line)}`);if(void 0===options.ignore_last_delimiters||null===options.ignore_last_delimiters)options.ignore_last_delimiters=!1;else if("number"==typeof options.ignore_last_delimiters)options.ignore_last_delimiters=_Mathfloor5(options.ignore_last_delimiters),0===options.ignore_last_delimiters&&(options.ignore_last_delimiters=!1);else if("boolean"!=typeof options.ignore_last_delimiters)throw new CsvError("CSV_INVALID_OPTION_IGNORE_LAST_DELIMITERS",["Invalid option `ignore_last_delimiters`:","the value must be a boolean value or an integer,",`got ${JSON.stringify(options.ignore_last_delimiters)}`],options);if(!0===options.ignore_last_delimiters&&!1===options.columns)throw new CsvError("CSV_IGNORE_LAST_DELIMITERS_REQUIRES_COLUMNS",["The option `ignore_last_delimiters`","requires the activation of the `columns` option"],options);if(void 0===options.info||null===options.info||!1===options.info)options.info=!1;else if(!0!==options.info)throw new Error(`Invalid Option: info must be true, got ${JSON.stringify(options.info)}`);if(void 0===options.max_record_size||null===options.max_record_size||!1===options.max_record_size)options.max_record_size=0;else if(_NumberisInteger(options.max_record_size)&&0<=options.max_record_size);else if("string"==typeof options.max_record_size&&/\d+/.test(options.max_record_size))options.max_record_size=parseInt(options.max_record_size);else throw new Error(`Invalid Option: max_record_size must be a positive integer, got ${JSON.stringify(options.max_record_size)}`);if(void 0===options.objname||null===options.objname||!1===options.objname)options.objname=void 0;else if(isBuffer(options.objname)){if(0===options.objname.length)throw new Error(`Invalid Option: objname must be a non empty buffer`);if(null===options.encoding);else options.objname=options.objname.toString(options.encoding)}else if("string"==typeof options.objname){if(0===options.objname.length)throw new Error(`Invalid Option: objname must be a non empty string`);}else if("number"==typeof options.objname);else throw new Error(`Invalid Option: objname must be a string or a buffer, got ${options.objname}`);if(void 0!==options.objname)if("number"==typeof options.objname){if(!1!==options.columns)throw Error("Invalid Option: objname index cannot be combined with columns or be defined as a field");}else if(!1===options.columns)throw Error("Invalid Option: objname field must be combined with columns or be defined as an index");if(void 0===options.on_record||null===options.on_record)options.on_record=void 0;else if("function"!=typeof options.on_record)throw new CsvError("CSV_INVALID_OPTION_ON_RECORD",["Invalid option `on_record`:","expect a function,",`got ${JSON.stringify(options.on_record)}`],options);if(void 0!==options.on_skip&&null!==options.on_skip&&"function"!=typeof options.on_skip)throw new Error(`Invalid Option: on_skip must be a function, got ${JSON.stringify(options.on_skip)}`);if(null===options.quote||!1===options.quote||""===options.quote)options.quote=null;else if(void 0===options.quote||!0===options.quote?options.quote=Buffer.from("\"",options.encoding):"string"==typeof options.quote&&(options.quote=Buffer.from(options.quote,options.encoding)),!isBuffer(options.quote))throw new Error(`Invalid Option: quote must be a buffer or a string, got ${JSON.stringify(options.quote)}`);if(void 0===options.raw||null===options.raw||!1===options.raw)options.raw=!1;else if(!0!==options.raw)throw new Error(`Invalid Option: raw must be true, got ${JSON.stringify(options.raw)}`);if(void 0===options.record_delimiter)options.record_delimiter=[];else if("string"==typeof options.record_delimiter||isBuffer(options.record_delimiter)){if(0===options.record_delimiter.length)throw new CsvError("CSV_INVALID_OPTION_RECORD_DELIMITER",["Invalid option `record_delimiter`:","value must be a non empty string or buffer,",`got ${JSON.stringify(options.record_delimiter)}`],options);options.record_delimiter=[options.record_delimiter]}else if(!Array.isArray(options.record_delimiter))throw new CsvError("CSV_INVALID_OPTION_RECORD_DELIMITER",["Invalid option `record_delimiter`:","value must be a string, a buffer or array of string|buffer,",`got ${JSON.stringify(options.record_delimiter)}`],options);if(options.record_delimiter=options.record_delimiter.map(function(rd,i){if("string"!=typeof rd&&!isBuffer(rd))throw new CsvError("CSV_INVALID_OPTION_RECORD_DELIMITER",["Invalid option `record_delimiter`:","value must be a string, a buffer or array of string|buffer",`at index ${i},`,`got ${JSON.stringify(rd)}`],options);else if(0===rd.length)throw new CsvError("CSV_INVALID_OPTION_RECORD_DELIMITER",["Invalid option `record_delimiter`:","value must be a non empty string or buffer",`at index ${i},`,`got ${JSON.stringify(rd)}`],options);return"string"==typeof rd&&(rd=Buffer.from(rd,options.encoding)),rd}),"boolean"==typeof options.relax_column_count);else if(void 0===options.relax_column_count||null===options.relax_column_count)options.relax_column_count=!1;else throw new Error(`Invalid Option: relax_column_count must be a boolean, got ${JSON.stringify(options.relax_column_count)}`);if("boolean"==typeof options.relax_column_count_less);else if(void 0===options.relax_column_count_less||null===options.relax_column_count_less)options.relax_column_count_less=!1;else throw new Error(`Invalid Option: relax_column_count_less must be a boolean, got ${JSON.stringify(options.relax_column_count_less)}`);if("boolean"==typeof options.relax_column_count_more);else if(void 0===options.relax_column_count_more||null===options.relax_column_count_more)options.relax_column_count_more=!1;else throw new Error(`Invalid Option: relax_column_count_more must be a boolean, got ${JSON.stringify(options.relax_column_count_more)}`);if("boolean"==typeof options.relax_quotes);else if(void 0===options.relax_quotes||null===options.relax_quotes)options.relax_quotes=!1;else throw new Error(`Invalid Option: relax_quotes must be a boolean, got ${JSON.stringify(options.relax_quotes)}`);if("boolean"==typeof options.skip_empty_lines);else if(void 0===options.skip_empty_lines||null===options.skip_empty_lines)options.skip_empty_lines=!1;else throw new Error(`Invalid Option: skip_empty_lines must be a boolean, got ${JSON.stringify(options.skip_empty_lines)}`);if("boolean"==typeof options.skip_records_with_empty_values);else if(void 0===options.skip_records_with_empty_values||null===options.skip_records_with_empty_values)options.skip_records_with_empty_values=!1;else throw new Error(`Invalid Option: skip_records_with_empty_values must be a boolean, got ${JSON.stringify(options.skip_records_with_empty_values)}`);if("boolean"==typeof options.skip_records_with_error);else if(void 0===options.skip_records_with_error||null===options.skip_records_with_error)options.skip_records_with_error=!1;else throw new Error(`Invalid Option: skip_records_with_error must be a boolean, got ${JSON.stringify(options.skip_records_with_error)}`);if(void 0===options.rtrim||null===options.rtrim||!1===options.rtrim)options.rtrim=!1;else if(!0!==options.rtrim)throw new Error(`Invalid Option: rtrim must be a boolean, got ${JSON.stringify(options.rtrim)}`);if(void 0===options.ltrim||null===options.ltrim||!1===options.ltrim)options.ltrim=!1;else if(!0!==options.ltrim)throw new Error(`Invalid Option: ltrim must be a boolean, got ${JSON.stringify(options.ltrim)}`);if(void 0===options.trim||null===options.trim||!1===options.trim)options.trim=!1;else if(!0!==options.trim)throw new Error(`Invalid Option: trim must be a boolean, got ${JSON.stringify(options.trim)}`);if(!0===options.trim&&!1!==opts.ltrim?options.ltrim=!0:!0!==options.ltrim&&(options.ltrim=!1),!0===options.trim&&!1!==opts.rtrim?options.rtrim=!0:!0!==options.rtrim&&(options.rtrim=!1),void 0===options.to||null===options.to)options.to=-1;else if(-1!==options.to)if("string"==typeof options.to&&/\d+/.test(options.to)&&(options.to=parseInt(options.to)),!_NumberisInteger(options.to))throw new Error(`Invalid Option: to must be an integer, got ${JSON.stringify(opts.to)}`);else if(0>=options.to)throw new Error(`Invalid Option: to must be a positive integer greater than 0, got ${JSON.stringify(opts.to)}`);if(void 0===options.to_line||null===options.to_line)options.to_line=-1;else if(-1!==options.to_line)if("string"==typeof options.to_line&&/\d+/.test(options.to_line)&&(options.to_line=parseInt(options.to_line)),!_NumberisInteger(options.to_line))throw new Error(`Invalid Option: to_line must be an integer, got ${JSON.stringify(opts.to_line)}`);else if(0>=options.to_line)throw new Error(`Invalid Option: to_line must be a positive integer greater than 0, got ${JSON.stringify(opts.to_line)}`);return options},isRecordEmpty=function(record){return record.every(field=>null==field||field.toString&&""===field.toString().trim())},cr=13,nl=10,boms={utf8:Buffer.from([239,187,191]),utf16le:Buffer.from([255,254])},transform=function(original_options={}){var _StringfromCharCode2=String.fromCharCode;const info={bytes:0,comment_lines:0,empty_lines:0,invalid_field_length:0,lines:1,records:0},options=normalize_options(original_options);return{info:info,original_options:original_options,options:options,state:init_state(options),__needMoreData:function(i,bufLen,end){if(end)return!1;const{encoding,escape,quote}=this.options,{quoting,needMoreDataSize,recordDelimiterMaxLength}=this.state,numOfCharLeft=bufLen-i-1,requiredLength=Math.max(needMoreDataSize,0===recordDelimiterMaxLength?Buffer.from("\r\n",encoding).length:recordDelimiterMaxLength,quoting?(null===escape?0:escape.length)+quote.length:0,quoting?quote.length+recordDelimiterMaxLength:0);return numOfCharLeft<requiredLength},parse:function(nextBuf,end,push,close){const{bom,comment_no_infix,encoding,from_line,ltrim,max_record_size,raw,relax_quotes,rtrim,skip_empty_lines,to,to_line}=this.options;let{comment,escape,quote,record_delimiter}=this.options;const{bomSkipped,previousBuf,rawBuffer,escapeIsQuote}=this.state;let buf;if(previousBuf===void 0){if(void 0===nextBuf)return void close();buf=nextBuf}else buf=void 0!==previousBuf&&void 0===nextBuf?previousBuf:Buffer.concat([previousBuf,nextBuf]);if(!1===bomSkipped)if(!1===bom)this.state.bomSkipped=!0;else if(!(3>buf.length)){for(const encoding in boms)if(0===boms[encoding].compare(buf,0,boms[encoding].length)){const bomLength=boms[encoding].length;this.state.bufBytesStart+=bomLength,buf=buf.slice(bomLength);const options=normalize_options({...this.original_options,encoding:encoding});for(const key in options)this.options[key]=options[key];({comment,escape,quote}=this.options);break}this.state.bomSkipped=!0}else if(!1===end)return void(this.state.previousBuf=buf);const bufLen=buf.length;let pos;for(pos=0;pos<bufLen&&!this.__needMoreData(pos,bufLen,end);pos++){if(!0===this.state.wasRowDelimiter&&(this.info.lines++,this.state.wasRowDelimiter=!1),-1!==to_line&&this.info.lines>to_line)return this.state.stop=!0,void close();if(!1===this.state.quoting&&0===record_delimiter.length){const record_delimiterCount=this.__autoDiscoverRecordDelimiter(buf,pos);record_delimiterCount&&(record_delimiter=this.options.record_delimiter)}const chr=buf[pos];if(!0===raw&&rawBuffer.append(chr),(chr===cr||chr===nl)&&!1===this.state.wasRowDelimiter&&(this.state.wasRowDelimiter=!0),!0===this.state.escaping)this.state.escaping=!1;else{if(null!==escape&&!0===this.state.quoting&&this.__isEscape(buf,pos,chr)&&pos+escape.length<bufLen)if(!escapeIsQuote){this.state.escaping=!0,pos+=escape.length-1;continue}else if(this.__isQuote(buf,pos+escape.length)){this.state.escaping=!0,pos+=escape.length-1;continue}if(!1===this.state.commenting&&this.__isQuote(buf,pos))if(!0===this.state.quoting){const nextChr=buf[pos+quote.length],isNextChrTrimable=rtrim&&this.__isCharTrimable(buf,pos+quote.length),isNextChrComment=null!==comment&&this.__compareBytes(comment,buf,pos+quote.length,nextChr),isNextChrDelimiter=this.__isDelimiter(buf,pos+quote.length,nextChr),isNextChrRecordDelimiter=0===record_delimiter.length?this.__autoDiscoverRecordDelimiter(buf,pos+quote.length):this.__isRecordDelimiter(nextChr,buf,pos+quote.length);if(null!==escape&&this.__isEscape(buf,pos,chr)&&this.__isQuote(buf,pos+escape.length))pos+=escape.length-1;else if(!nextChr||isNextChrDelimiter||isNextChrRecordDelimiter||isNextChrComment||isNextChrTrimable){this.state.quoting=!1,this.state.wasQuoting=!0,pos+=quote.length-1;continue}else if(!1===relax_quotes){const err=this.__error(new CsvError("CSV_INVALID_CLOSING_QUOTE",["Invalid Closing Quote:",`got "${_StringfromCharCode2(nextChr)}"`,`at line ${this.info.lines}`,"instead of delimiter, record delimiter, trimable character","(if activated) or comment"],this.options,this.__infoField()));if(void 0!==err)return err}else this.state.quoting=!1,this.state.wasQuoting=!0,this.state.field.prepend(quote),pos+=quote.length-1}else if(0===this.state.field.length){this.state.quoting=!0,pos+=quote.length-1;continue}else if(!1===relax_quotes){const info=this.__infoField(),bom=Object.keys(boms).map(b=>!!boms[b].equals(this.state.field.toString())&&b).filter(Boolean)[0],err=this.__error(new CsvError("INVALID_OPENING_QUOTE",["Invalid Opening Quote:",`a quote is found on field ${JSON.stringify(info.column)} at line ${info.lines}, value is ${JSON.stringify(this.state.field.toString(encoding))}`,bom?`(${bom} bom)`:void 0],this.options,info,{field:this.state.field}));if(void 0!==err)return err}if(!1===this.state.quoting){const recordDelimiterLength=this.__isRecordDelimiter(chr,buf,pos);if(0!==recordDelimiterLength){const skipCommentLine=this.state.commenting&&!1===this.state.wasQuoting&&0===this.state.record.length&&0===this.state.field.length;if(skipCommentLine)this.info.comment_lines++;else{if(!1===this.state.enabled&&this.info.lines+(!0===this.state.wasRowDelimiter?1:0)>=from_line){this.state.enabled=!0,this.__resetField(),this.__resetRecord(),pos+=recordDelimiterLength-1;continue}if(!0===skip_empty_lines&&!1===this.state.wasQuoting&&0===this.state.record.length&&0===this.state.field.length){this.info.empty_lines++,pos+=recordDelimiterLength-1;continue}this.info.bytes=this.state.bufBytesStart+pos;const errField=this.__onField();if(void 0!==errField)return errField;this.info.bytes=this.state.bufBytesStart+pos+recordDelimiterLength;const errRecord=this.__onRecord(push);if(void 0!==errRecord)return errRecord;if(-1!==to&&this.info.records>=to)return this.state.stop=!0,void close()}this.state.commenting=!1,pos+=recordDelimiterLength-1;continue}if(this.state.commenting)continue;if(null!==comment&&(!1===comment_no_infix||0===this.state.record.length&&0===this.state.field.length)){const commentCount=this.__compareBytes(comment,buf,pos,chr);if(0!==commentCount){this.state.commenting=!0;continue}}const delimiterLength=this.__isDelimiter(buf,pos,chr);if(0!==delimiterLength){this.info.bytes=this.state.bufBytesStart+pos;const errField=this.__onField();if(void 0!==errField)return errField;pos+=delimiterLength-1;continue}}}if(!1===this.state.commenting&&0!==max_record_size&&this.state.record_length+this.state.field.length>max_record_size)return this.__error(new CsvError("CSV_MAX_RECORD_SIZE",["Max Record Size:","record exceed the maximum number of tolerated bytes",`of ${max_record_size}`,`at line ${this.info.lines}`],this.options,this.__infoField()));const lappend=!1===ltrim||!0===this.state.quoting||0!==this.state.field.length||!this.__isCharTrimable(buf,pos),rappend=!1===rtrim||!1===this.state.wasQuoting;if(!0==lappend&&!0===rappend)this.state.field.append(chr);else{if(!0===rtrim&&!this.__isCharTrimable(buf,pos))return this.__error(new CsvError("CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE",["Invalid Closing Quote:","found non trimable byte after quote",`at line ${this.info.lines}`],this.options,this.__infoField()));!1===lappend&&(pos+=this.__isCharTrimable(buf,pos)-1);continue}}if(!(!0===end))this.state.bufBytesStart+=pos,this.state.previousBuf=buf.slice(pos);else if(!0===this.state.quoting){const err=this.__error(new CsvError("CSV_QUOTE_NOT_CLOSED",["Quote Not Closed:",`the parsing is finished with an opening quote at line ${this.info.lines}`],this.options,this.__infoField()));if(void 0!==err)return err}else if(!0===this.state.wasQuoting||0!==this.state.record.length||0!==this.state.field.length){this.info.bytes=this.state.bufBytesStart+pos;const errField=this.__onField();if(void 0!==errField)return errField;const errRecord=this.__onRecord(push);if(void 0!==errRecord)return errRecord}else!0===this.state.wasRowDelimiter?this.info.empty_lines++:!0===this.state.commenting&&this.info.comment_lines++;!0===this.state.wasRowDelimiter&&(this.info.lines++,this.state.wasRowDelimiter=!1)},__onRecord:function(push){const{columns,group_columns_by_name,encoding,info,from,relax_column_count,relax_column_count_less,relax_column_count_more,raw,skip_records_with_empty_values}=this.options,{enabled,record}=this.state;if(!1===enabled)return this.__resetRecord();const recordLength=record.length;if(!0===columns)return!0===skip_records_with_empty_values&&isRecordEmpty(record)?void this.__resetRecord():this.__firstLineToColumns(record);if(!1===columns&&0===this.info.records&&(this.state.expectedRecordLength=recordLength),recordLength!==this.state.expectedRecordLength){const err=!1===columns?new CsvError("CSV_RECORD_INCONSISTENT_FIELDS_LENGTH",["Invalid Record Length:",`expect ${this.state.expectedRecordLength},`,`got ${recordLength} on line ${this.info.lines}`],this.options,this.__infoField(),{record:record}):new CsvError("CSV_RECORD_INCONSISTENT_COLUMNS",["Invalid Record Length:",`columns length is ${columns.length},`,`got ${recordLength} on line ${this.info.lines}`],this.options,this.__infoField(),{record:record});if(!0===relax_column_count||!0===relax_column_count_less&&recordLength<this.state.expectedRecordLength||!0===relax_column_count_more&&recordLength>this.state.expectedRecordLength)this.info.invalid_field_length++,this.state.error=err;else{const finalErr=this.__error(err);if(finalErr)return finalErr}}if(!0===skip_records_with_empty_values&&isRecordEmpty(record))return void this.__resetRecord();if(!0===this.state.recordHasError)return this.__resetRecord(),void(this.state.recordHasError=!1);if(this.info.records++,1===from||this.info.records>=from){const{objname}=this.options;if(!1!==columns){const obj={};for(let i=0,l=record.length;i<l;i++)void 0===columns[i]||columns[i].disabled||(obj[columns[i].name]=!0===group_columns_by_name&&void 0!==obj[columns[i].name]?Array.isArray(obj[columns[i].name])?obj[columns[i].name].concat(record[i]):[obj[columns[i].name],record[i]]:record[i]);if(!0===raw||!0===info){const extRecord=Object.assign({record:obj},!0===raw?{raw:this.state.rawBuffer.toString(encoding)}:{},!0===info?{info:this.__infoRecord()}:{}),err=this.__push(void 0===objname?extRecord:[obj[objname],extRecord],push);if(err)return err}else{const err=this.__push(void 0===objname?obj:[obj[objname],obj],push);if(err)return err}}else if(!0===raw||!0===info){const extRecord=Object.assign({record:record},!0===raw?{raw:this.state.rawBuffer.toString(encoding)}:{},!0===info?{info:this.__infoRecord()}:{}),err=this.__push(void 0===objname?extRecord:[record[objname],extRecord],push);if(err)return err}else{const err=this.__push(void 0===objname?record:[record[objname],record],push);if(err)return err}}this.__resetRecord()},__firstLineToColumns:function(record){const{firstLineToHeaders}=this.state;try{const headers=void 0===firstLineToHeaders?record:firstLineToHeaders.call(null,record);if(!Array.isArray(headers))return this.__error(new CsvError("CSV_INVALID_COLUMN_MAPPING",["Invalid Column Mapping:","expect an array from column function,",`got ${JSON.stringify(headers)}`],this.options,this.__infoField(),{headers:headers}));const normalizedHeaders=normalize_columns_array(headers);return this.state.expectedRecordLength=normalizedHeaders.length,this.options.columns=normalizedHeaders,void this.__resetRecord()}catch(err){return err}},__resetRecord:function(){!0===this.options.raw&&this.state.rawBuffer.reset(),this.state.error=void 0,this.state.record=[],this.state.record_length=0},__onField:function(){const{cast,encoding,rtrim,max_record_size}=this.options,{enabled,wasQuoting}=this.state;if(!1===enabled)return this.__resetField();let field=this.state.field.toString(encoding);if(!0===rtrim&&!1===wasQuoting&&(field=field.trimRight()),!0===cast){const[err,f]=this.__cast(field);if(void 0!==err)return err;field=f}this.state.record.push(field),0!==max_record_size&&"string"==typeof field&&(this.state.record_length+=field.length),this.__resetField()},__resetField:function(){this.state.field.reset(),this.state.wasQuoting=!1},__push:function(record,push){const{on_record}=this.options;if(on_record!==void 0){const info=this.__infoRecord();try{record=on_record.call(null,record,info)}catch(err){return err}if(record===void 0||null===record)return}push(record)},__cast:function(field){const{columns,relax_column_count}=this.options,isColumns=Array.isArray(columns);if(!0===isColumns&&relax_column_count&&this.options.columns.length<=this.state.record.length)return[void 0,void 0];if(null!==this.state.castField)try{const info=this.__infoField();return[void 0,this.state.castField.call(null,field,info)]}catch(err){return[err]}if(this.__isFloat(field))return[void 0,parseFloat(field)];if(!1!==this.options.cast_date){const info=this.__infoField();return[void 0,this.options.cast_date.call(null,field,info)]}return[void 0,field]},__isCharTrimable:function(buf,pos){const isTrim=(buf,pos)=>{const{timchars}=this.state;loop1:for(let i=0;i<timchars.length;i++){const timchar=timchars[i];for(let j=0;j<timchar.length;j++)if(timchar[j]!==buf[pos+j])continue loop1;return timchar.length}return 0};return isTrim(buf,pos)},__isFloat:function(value){return 0<=value-parseFloat(value)+1},__compareBytes:function(sourceBuf,targetBuf,targetPos,firstByte){if(sourceBuf[0]!==firstByte)return 0;const sourceLength=sourceBuf.length;for(let i=1;i<sourceLength;i++)if(sourceBuf[i]!==targetBuf[targetPos+i])return 0;return sourceLength},__isDelimiter:function(buf,pos,chr){const{delimiter,ignore_last_delimiters}=this.options;if(!0===ignore_last_delimiters&&this.state.record.length===this.options.columns.length-1)return 0;if(!1!==ignore_last_delimiters&&"number"==typeof ignore_last_delimiters&&this.state.record.length===ignore_last_delimiters-1)return 0;loop1:for(let i=0;i<delimiter.length;i++){const del=delimiter[i];if(del[0]===chr){for(let j=1;j<del.length;j++)if(del[j]!==buf[pos+j])continue loop1;return del.length}}return 0},__isRecordDelimiter:function(chr,buf,pos){const{record_delimiter}=this.options,recordDelimiterLength=record_delimiter.length;loop1:for(let i=0;i<recordDelimiterLength;i++){const rd=record_delimiter[i],rdLength=rd.length;if(rd[0]===chr){for(let j=1;j<rdLength;j++)if(rd[j]!==buf[pos+j])continue loop1;return rd.length}}return 0},__isEscape:function(buf,pos,chr){const{escape}=this.options;if(null===escape)return!1;const l=escape.length;if(escape[0]===chr){for(let i=0;i<l;i++)if(escape[i]!==buf[pos+i])return!1;return!0}return!1},__isQuote:function(buf,pos){const{quote}=this.options;if(null===quote)return!1;const l=quote.length;for(let i=0;i<l;i++)if(quote[i]!==buf[pos+i])return!1;return!0},__autoDiscoverRecordDelimiter:function(buf,pos){const{encoding}=this.options,rds=[Buffer.from("\r\n",encoding),Buffer.from("\n",encoding),Buffer.from("\r",encoding)];loop:for(let i=0;i<rds.length;i++){const l=rds[i].length;for(let j=0;j<l;j++)if(rds[i][j]!==buf[pos+j])continue loop;return this.options.record_delimiter.push(rds[i]),this.state.recordDelimiterMaxLength=rds[i].length,rds[i].length}return 0},__error:function(msg){const{encoding,raw,skip_records_with_error}=this.options,err="string"==typeof msg?new Error(msg):msg;if(skip_records_with_error){if(this.state.recordHasError=!0,void 0!==this.options.on_skip)try{this.options.on_skip(err,raw?this.state.rawBuffer.toString(encoding):void 0)}catch(err){return err}return}return err},__infoDataSet:function(){return{...this.info,columns:this.options.columns}},__infoRecord:function(){const{columns,raw,encoding}=this.options;return{...this.__infoDataSet(),error:this.state.error,header:!0===columns,index:this.state.record.length,raw:raw?this.state.rawBuffer.toString(encoding):void 0}},__infoField:function(){const{columns}=this.options,isColumns=Array.isArray(columns);return{...this.__infoRecord(),column:!0===isColumns?columns.length>this.state.record.length?columns[this.state.record.length].name:null:this.state.record.length,quoting:this.state.wasQuoting}}}},parse=function(data,opts={}){"string"==typeof data&&(data=Buffer.from(data));const records=opts&&opts.objname?{}:[],parser=transform(opts),push=record=>{parser.options.objname===void 0?records.push(record):records[record[0]]=record[1]},close=()=>{},error=parser.parse(data,!0,push,close);if(error!==void 0)throw error;return records};var __decorate$X=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const WEB_FEATURE_ID_RE=/^[a-z0-9]+(-[a-z0-9]+)*$/,CHROMESTATUS_URL_RE=/https:\/\/(wwww.)?chromestatus.com\/feature\/(?<id>[0-9]+)/;let ChromedashBulkEditPage=class ChromedashBulkEditPage extends i$4{constructor(){super(...arguments),this.parsing=!1,this.cells=[],this.featureIdIndex=-1,this.chromestatusUrlIndex=-1,this.items=[],this.submitting=!1}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + section { + margin: var(--content-padding); + } + .diff.old { + background: #fdd; + } + .diff.new { + background: #dfd; + } + `]}parseChromestatusIdFromURL(url){const match=url.match(CHROMESTATUS_URL_RE);if(match)return+match.groups?.id;try{return+url}catch{}return 0}isFeatureIdHeader(header,index){const headerOk="feature id"===header||"web-features"===header||header.includes("feature")&&!header.includes("chrome"),firstValueOk=1<this.cells.length&&this.cells[1][index].match(WEB_FEATURE_ID_RE);return headerOk&&firstValueOk}isChromestatusURL(header,index){const headerOk=header.includes("chromestatus")||header.includes("chrome")&&header.includes("status")||"id"===header,firstValueOk=1<this.cells.length&&this.parseChromestatusIdFromURL(this.cells[1][index]);return headerOk&&firstValueOk}detectColumns(){if(this.cells.length){const headerCells=this.cells[0].map(header=>header.toLowerCase());this.featureIdIndex=headerCells.findIndex(this.isFeatureIdHeader.bind(this)),this.chromestatusUrlIndex=headerCells.findIndex(this.isChromestatusURL.bind(this))}}selectItems(){if(this.items=[],-1!==this.featureIdIndex&&-1!==this.chromestatusUrlIndex)for(let i=1;i<this.cells.length;i++){const row=this.cells[i],webFeatureId=row[this.featureIdIndex],csUrl=row[this.chromestatusUrlIndex],csFid=this.parseChromestatusIdFromURL(csUrl);if(0<csFid){const item={row:i+1,csFid:csFid,existing:"Loading...",desired:webFeatureId};this.items.push(item)}}}fetchFeature(item){return window.csClient.getFeature(item.csFid).then(fe=>{item.entryName=fe.name,item.existing=fe.web_feature,this.requestUpdate()})}parseFileContent(fileContent){try{this.cells=parse(fileContent)}catch(error){showToastMessage(`An error occurred in parsing CSV file. ${JSON.stringify(error)}`)}try{this.detectColumns()}catch(error){showToastMessage(`An error occurred while detecting columns. ${JSON.stringify(error)}`)}try{this.selectItems()}catch(error){showToastMessage(`An error occurred while converting cells. ${JSON.stringify(error)}`)}}async getFileAndParse(){const fileField=this.shadowRoot.querySelector("#id_file_form_field");if(!fileField?.files?.length)return this.cells=[],this.featureIdIndex=-1,this.chromestatusUrlIndex=-1,this.items=[],void(this.parsing=!1);try{const file=fileField.files[0],fileContent=await file.text();this.parseFileContent(fileContent),await Promise.all(this.items.map(item=>this.fetchFeature(item)))}catch(error){showToastMessage(`An error occurred while processing the file. ${JSON.stringify(error)}`)}finally{this.parsing=!1}}saveFeature(item){const submitBody={feature_changes:{id:item.csFid,web_feature:item.desired},stages:[],has_changes:!0};return window.csClient.updateFeature(submitBody).then(resp=>{this.fetchFeature(item)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}async handleSubmit(e){e.preventDefault(),this.submitting=!0;for(const item of this.items)item.existing!=item.desired&&(await this.saveFeature(item));this.submitting=!1}async handleChange(){this.parsing=!0,await this.getFileAndParse()}renderForm(){return x$1` + <form name="bulk_edit_form"> + <table cellspacing="6"> + <tbody> + <tr> + <th> + <label for="id_file_form_field">CSV file:</label> + </th> + <td> + <input + id="id_file_form_field" + name="file_form_field" + type="file" + accept="text/csv" + @change=${this.handleChange} + /> + </td> + </tr> + </tbody> + </table> + </form> + `}isDifferent(item){return"Loading..."!=item.existing&&item.existing!=item.desired}renderItemRow(item){const different=this.isDifferent(item),differentClass=different?"diff":"";return x$1` + <tr> + <td style="text-align: right; width: 4em">${item.row}</td> + <td> + <a href="/feature/${item.csFid}" target="_blank" + >${item.entryName||item.csFid}</a + > + </td> + <td class="${differentClass} old">${item.existing||"Not set"}</td> + <td>${different?x$1`←`:"=="}</td> + <td class="${differentClass} new">${item.desired}</td> + </tr> + `}renderPreview(){if(0==this.items.length)return x$1` + <p id="instructions"> + Select a CSV file to see the preview. The CSV file should have one + column labeled "Chrome Status Entry" and one column labled "Feature + ID", although some variations may work. Once the file is parsed, the + table below will preview changes that will be made. + </p> + `;const totalCount=this.items.length,matchCount=this.items.filter(item=>!this.isDifferent(item)).length,updateCount=this.items.filter(item=>this.isDifferent(item)).length;return x$1` + <table class="data-table"> + <tr> + <th>Row</th> + <th>ChromeStatus feature</th> + <th>Existing web feature ID</th> + <th></th> + <th>Desired web feature ID</th> + </tr> + ${this.items.map(item=>this.renderItemRow(item))} + </table> + <p> + ${totalCount} rows: ${matchCount} already matching and ${updateCount} to + be updated. + </p> + `}renderControls(){return x$1` + <sl-button + ?disabled=${this.parsing||this.submitting||0==this.items.length} + @click=${this.handleSubmit} + size="small" + variant="primary" + > + Update all + </sl-button> + `}render(){return x$1` + <div id="subheader"> + <h2>Bulk edit</h2> + </div> + <section>${this.renderForm()}</section> + <section> + <h3>Preview</h3> + ${this.renderPreview()} + </section> + <section>${this.renderControls()}</section> + ${this.parsing||this.submitting?x$1` <div class="loading"> + <div id="spinner"><img src="/static/img/ring.svg" /></div> + </div>`:E$1} + `}};__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"parsing",void 0),__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"cells",void 0),__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"featureIdIndex",void 0),__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"chromestatusUrlIndex",void 0),__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"items",void 0),__decorate$X([r$6()],ChromedashBulkEditPage.prototype,"submitting",void 0),ChromedashBulkEditPage=__decorate$X([t$3("chromedash-bulk-edit-page")],ChromedashBulkEditPage);var __decorate$W=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashCallout=class ChromedashCallout extends i$4{constructor(){super(...arguments),this.targetId="",this.side="south",this.cue="",this.dismissedCues=[],this.signedIn=!1,this.hidden=!0,this.top=0,this.left=0}connectedCallback(){if(super.connectedCallback(),!this.dismissedCues.includes(this.cue))try{this.attachToTarget(this.parentNode.querySelector("#"+this.targetId))}catch(error){console.error("Failed to attach target",error)}}static get styles(){return[...SHARED_STYLES,i$7` + #bubble { + position: absolute; + display: inline-block; + background: var(--callout-bg-color); + border-radius: var(--large-border-radius); + padding: var(--content-padding-half); + max-width: 24em; + color: var(--callout-text-color); + font-weight: bold; + } + #bubble[hidden] { + display: none; + } + #bubble:after { + content: ''; + position: absolute; + border: 20px solid transparent; + } + /* Bubble will be located on the south side of target element. */ + #bubble.south:after { + top: -20px; + left: 20px; + width: 0; + height: 0; + border-bottom-color: var(--callout-bg-color); + border-top: 0; + } + #closebox { + float: right; + margin-left: var(--content-padding-half); + color: var(--light-icon-fill-color); + } + #cue-content-container { + margin: var(--content-padding-quarter); + } + `]}contentOffsetTop(el){let offset=0;for(;el.offsetParent&&el!=this.offsetParent;)offset+=el.offsetTop,el=el.offsetParent;return offset}contentOffsetLeft(el){let offset=0;for(;el.offsetParent&&el!=this.offsetParent;)offset+=el.offsetLeft,el=el.offsetParent;return offset}attachToTarget(el){if("south"==this.side){const targetBottom=this.contentOffsetTop(el)+el.offsetHeight;this.top=targetBottom+20,this.left=Math.max(this.contentOffsetLeft(el)-20,0)}this.hidden=!1}dismiss(){this.hidden=!0,this.signedIn&&window.csClient.dismissCue(this.cue)}render(){return x$1` + <div + id="bubble" + class="${this.side}" + ?hidden=${this.hidden} + style="top:${this.top}px; left:${this.left}px;" + > + <sl-icon id="closebox" name="x" @click=${this.dismiss}></sl-icon> + <div id="cue-content-container"> + <slot></slot> + </div> + </div> + `}};__decorate$W([n$5({type:String})],ChromedashCallout.prototype,"targetId",void 0),__decorate$W([n$5({type:String})],ChromedashCallout.prototype,"side",void 0),__decorate$W([n$5({type:String})],ChromedashCallout.prototype,"cue",void 0),__decorate$W([n$5({attribute:!1,type:Array})],ChromedashCallout.prototype,"dismissedCues",void 0),__decorate$W([n$5({type:Boolean})],ChromedashCallout.prototype,"signedIn",void 0),__decorate$W([n$5({type:Boolean})],ChromedashCallout.prototype,"hidden",void 0),__decorate$W([r$6()],ChromedashCallout.prototype,"top",void 0),__decorate$W([r$6()],ChromedashCallout.prototype,"left",void 0),ChromedashCallout=__decorate$W([t$3("chromedash-callout")],ChromedashCallout);var __decorate$V=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let addStageDialogEl,currentFeatureId$1;async function openAddStageDialog(featureId,featureType,onSubmitCustomHandler){addStageDialogEl&¤tFeatureId$1===featureId&&onSubmitCustomHandler===addStageDialogEl.onSubmitCustomHandler||(addStageDialogEl=document.createElement("chromedash-add-stage-dialog"),addStageDialogEl.featureId=featureId,addStageDialogEl.featureType=featureType,addStageDialogEl.onSubmitCustomHandler=onSubmitCustomHandler,document.body.appendChild(addStageDialogEl),await addStageDialogEl.updateComplete),currentFeatureId$1=featureId,addStageDialogEl.show()}let ChromedashAddStageDialog=class ChromedashAddStageDialog extends i$4{constructor(){super(...arguments),this.featureId=0,this.featureType=0,this.canSubmit=!1,this.onSubmitCustomHandler=null}static get styles(){return[...SHARED_STYLES,i$7` + #controls { + padding: var(--content-padding); + text-align: right; + display: flex; + justify-content: space-between; + align-items: center; + } + #controls * + * { + padding-left: var(--content-padding); + } + `]}show(){this.dialog.show()}renderSelectMenuItems(){const menuItems=[];for(const stageType of CREATEABLE_STAGES[this.featureType]){const stageInfo=FORMS_BY_STAGE_TYPE[stageType];menuItems.push(x$1` + <sl-option value="${stageType}"> ${stageInfo.name} </sl-option> + `)}return menuItems}getStageSelectValue(){return this.stageCreateSelect.value}handleStageCreate(){return this.onSubmitCustomHandler?(this.onSubmitCustomHandler({stage_type:+this.getStageSelectValue()}),this.onSubmitCustomHandler=null,void this.dialog.hide()):void window.csClient.createStage(this.featureId,{stage_type:{form_field_name:"stage_type",value:this.getStageSelectValue()}}).then(()=>{this.dialog.hide(),location.reload()})}checkCanSubmit(){this.canSubmit=0!==this.getStageSelectValue()}renderStageSelect(){return x$1` + <div id="controls"> + <sl-select + placement="top" + hoist + value="0" + id="stage_create_select" + size="small" + @sl-change=${this.checkCanSubmit} + style="width:16rem" + > + <sl-option value="0" disabled>Select a stage to create</sl-option> + ${this.renderSelectMenuItems()} + </sl-select> + <sl-button + variant="primary" + @click=${this.handleStageCreate} + ?disabled=${!this.canSubmit} + size="small" + >Create stage</sl-button + > + </div> + `}render(){return x$1` + <sl-dialog label="Create a new stage"> + <p>Here, you can add additional stages to your feature as needed.</p> + ${this.renderStageSelect()} + </sl-dialog> + `}};__decorate$V([n$5({type:Number})],ChromedashAddStageDialog.prototype,"featureId",void 0),__decorate$V([n$5({type:Number})],ChromedashAddStageDialog.prototype,"featureType",void 0),__decorate$V([n$5({type:Boolean})],ChromedashAddStageDialog.prototype,"canSubmit",void 0),__decorate$V([n$5({attribute:!1})],ChromedashAddStageDialog.prototype,"onSubmitCustomHandler",void 0),__decorate$V([e$6("#stage_create_select")],ChromedashAddStageDialog.prototype,"stageCreateSelect",void 0),__decorate$V([e$6("sl-dialog")],ChromedashAddStageDialog.prototype,"dialog",void 0),ChromedashAddStageDialog=__decorate$V([t$3("chromedash-add-stage-dialog")],ChromedashAddStageDialog);var __decorate$U=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let dialogEl$1,currentFeatureId,currentStageId;const dialogTypes={CREATION:1,EXTENSION:2,END_MILESTONE_EXPLANATION:3,FINALIZE_EXTENSION:4};async function openPrereqsDialog(featureId,stage,dialogType){dialogEl$1&¤tFeatureId===featureId&¤tStageId===stage.id||(dialogEl$1=document.createElement("chromedash-ot-prereqs-dialog"),dialogEl$1.featureId=featureId,dialogEl$1.stage=stage,dialogEl$1.dialogType=dialogType,document.body.appendChild(dialogEl$1),await dialogEl$1.updateComplete),currentFeatureId=featureId,currentStageId=stage.id,dialogEl$1.show()}async function openInfoDialog(dialogType){dialogEl$1||(dialogEl$1=document.createElement("chromedash-ot-prereqs-dialog"),dialogEl$1.dialogType=dialogType,document.body.appendChild(dialogEl$1),await dialogEl$1.updateComplete),dialogEl$1.show()}async function openFinalizeExtensionDialog(featureId,stage,milestone,dialogType){dialogEl$1&¤tFeatureId===featureId&¤tStageId===stage.id||(dialogEl$1=document.createElement("chromedash-ot-prereqs-dialog"),dialogEl$1.featureId=featureId,dialogEl$1.stage=stage,dialogEl$1.dialogType=dialogType,dialogEl$1.milestone=milestone,document.body.appendChild(dialogEl$1),await dialogEl$1.updateComplete),dialogEl$1.dialogType=dialogType,currentFeatureId=featureId,currentStageId=stage.id,dialogEl$1.show()}let ChromedashOTPrereqsDialog=class ChromedashOTPrereqsDialog extends i$4{constructor(){super(...arguments),this.featureId=0,this.milestone=0,this.dialogType=0}static get styles(){return[...SHARED_STYLES,i$7` + #prereqs-list li { + margin-left: 8px; + margin-bottom: 8px; + } + #prereqs-header { + margin-bottom: 8px; + } + #update-button { + margin-right: 8px; + } + .float-right { + float: right; + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}renderEndMilestoneExplanationDialog(){return x$1` <sl-dialog label="End milestone date"> + <p> + When a specific milestone is approved by API owners, the trial's end + date is set based on the stable release date of (end milestone +2). Most + of the time when a trial ends, the feature will be enabled by default + within the next Chrome release. This additional trial time window + ensures users don't see breakage before upgrading to the version with + the feature enabled by default. + </p> + </sl-dialog>`}submitTrialExtension(){window.csClient.extendOriginTrial(this.featureId,this.stage.id).then(()=>{showToastMessage("Extension processed!"),setTimeout(()=>{location.assign(`/feature/${this.featureId}`)},1e3)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}renderThreadMissingDialog(){return x$1`<sl-dialog label="Intent thread not found"> + <p> + LGTMs have been detected for this trial extension, but + <strong>no intent thread link has been detected or provided</strong>. + All extension proposals must be discussed publicly on blink-dev. Please + add the value to the "Intent to Extend Experiment link" field by + selecting "Edit fields" button on your feature's "Origin Trial" section. + </p> + </sl-dialog>`}renderFinalizeExtensionDialog(){return this.stage.intent_thread_url?x$1` <sl-dialog label="Finalize trial extension"> + <p> + LGTMs have been detected for this trial extension. This origin trial + will be extended <strong>through milestone ${this.milestone}</strong>. + Is this correct? + </p> + <br /> + <sl-button + class="float-right" + variant="primary" + size="small" + @click=${()=>this.submitTrialExtension()} + >Proceed</sl-button + > + <sl-button + class="float-right" + id="update-button" + variant="info" + size="small" + @click=${()=>location.assign(`/guide/stage/${this.featureId}/${this.stage.id}?updateExtension`)} + >Change milestone</sl-button + > + </sl-dialog>`:this.renderThreadMissingDialog()}renderExtensionPrereqs(){return x$1` <sl-dialog label="Origin trial extension prerequisites"> + <div id="prereqs-header"> + <strong>Before submitting an extension request</strong>, please ensure + that your Intent to Extend Experiment has been drafted, and the required + LGTMs have been received. + <br /> + <a + target="_blank" + href="https://www.chromium.org/blink/origin-trials/running-an-origin-trial/#what-is-the-process-to-extend-an-origin-trial" + > + View documentation on the trial extension process + </a> + </div> + <br /> + <sl-button + id="continue-button" + variant="primary" + @click=${()=>location.assign(`/ot_extension_request/${this.featureId}/${this.stage.id}`)} + size="small" + >Proceed</sl-button + > + </sl-dialog>`}renderCreationPrereqs(){return x$1` <sl-dialog label="Origin trial creation prerequisites"> + <div id="prereqs-header"> + <strong>Before submitting a creation request</strong>, please ensure the + following prerequisite steps have been completed: + </div> + <br /> + <ul id="prereqs-list"> + <li> + The trial's UseCounter has landed on + <a + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom" + target="_blank" + > + web_feature.mojom + </a> + and is being properly used. + </li> + <li> + A Chromium trial name has landed on + <a + href="https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5" + target="_blank" + > + runtime_enabled_features.json5 + </a> + <strong>that has not been used for any previous trials</strong>. No + trial names can be reused, even if used for the same feature! + </li> + <li> + For a third-party trial, the feature entry in + <a + href="https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5" + target="_blank" + > + runtime_enabled_features.json5 + </a> + contains the key "origin_trial_allows_third_party: true". + </li> + <li> + For a critical trial, the feature name has been added to the + <a + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc;l=17" + target="_blank" + > + kHasExpiryGracePeriod array </a + >. + </li> + </ul> + <br /> + <p> + If you haven't already, please review the docs for + <a + href="https://www.chromium.org/blink/origin-trials/running-an-origin-trial/" + > + running an origin trial </a + >. If you have any further questions, contact us at + origin-trials-support@google.com. + </p> + <br /> + <sl-button + class="float-right" + variant="primary" + @click=${()=>location.assign(`/ot_creation_request/${this.featureId}/${this.stage.id}`)} + size="small" + >Proceed</sl-button + > + </sl-dialog>`}render(){return this.dialogType===dialogTypes.END_MILESTONE_EXPLANATION?this.renderEndMilestoneExplanationDialog():this.dialogType===dialogTypes.FINALIZE_EXTENSION?this.renderFinalizeExtensionDialog():this.dialogType===dialogTypes.EXTENSION?this.renderExtensionPrereqs():this.renderCreationPrereqs()}};__decorate$U([n$5({type:Number})],ChromedashOTPrereqsDialog.prototype,"featureId",void 0),__decorate$U([n$5({attribute:!1})],ChromedashOTPrereqsDialog.prototype,"stage",void 0),__decorate$U([n$5({type:Number})],ChromedashOTPrereqsDialog.prototype,"milestone",void 0),__decorate$U([n$5({type:Number})],ChromedashOTPrereqsDialog.prototype,"dialogType",void 0),ChromedashOTPrereqsDialog=__decorate$U([t$3("chromedash-ot-prereqs-dialog")],ChromedashOTPrereqsDialog);var __decorate$T=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let preflightDialogEl;async function openPreflightDialog(feature,progress,process,action,stage,feStage,featureGates,url){preflightDialogEl||(preflightDialogEl=document.createElement("chromedash-preflight-dialog"),document.body.appendChild(preflightDialogEl),await preflightDialogEl.updateComplete),preflightDialogEl.openWithContext(feature,progress,process,action,stage,feStage,featureGates,url)}function somePendingPrereqs(action,progress){return action.prerequisites.some(itemName=>!progress.hasOwnProperty(itemName))}function somePendingGates(featureGates,feStage){return 0<findPendingGates(featureGates,feStage).length}function findPendingGates(featureGates,feStage){const gatesForStage=featureGates.filter(g=>g.stage_id==feStage.id),otherGates=gatesForStage.filter(g=>"API Owners"!=g.team_name),pendingGates=otherGates.filter(g=>!GATE_FINISHED_REVIEW_STATES.includes(g.state));return pendingGates.sort((g1,g2)=>GATE_TEAM_ORDER.indexOf(g1.team_name)-GATE_TEAM_ORDER.indexOf(g2.team_name)),pendingGates}let ChromedashPreflightDialog=class ChromedashPreflightDialog extends i$4{static get styles(){return[...SHARED_STYLES,i$7` + li { + margin-top: 0.5em; + } + + .missing-prereqs-list { + padding-bottom: 1em; + } + + .edit-progress-item { + visibility: hidden; + margin-left: var(--content-padding-half); + } + + .active .edit-progress-item, + .missing-prereqs .edit-progress-item, + .pending:hover .edit-progress-item, + .done:hover .edit-progress-item { + visibility: visible; + } + + sl-button { + float: right; + margin: var(--content-padding-half); + } + `]}openWithContext(feature,progress,process,action,stage,feStage,featureGates,url){this._feature=feature,this._progress=progress,this._process=process,this._action=action,this._stage=stage,this._feStage=feStage,this._featureGates=featureGates,this._url=url,this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}handleCancel(){this.hide()}handleProceed(){this.hide()}renderEditLink(stage,feStage,pi){if(!pi.field)return E$1;const pathSegment=stage?`${stage.outgoing_stage}/${feStage.id}`:"metadata";return x$1` + <a + class="edit-progress-item" + href="/guide/stage/${this._feature.id}/${pathSegment}#id_${pi.field}" + @click=${this.hide} + > + Edit + </a> + `}makePrereqItem(itemName){if("Web feature"===itemName)return{name:itemName,field:"web_feature",stage:null};if("Tracking bug URL"===itemName)return{name:itemName,field:"bug_url",stage:null};for(const s of this._process.stages||[])for(const pi of s.progress_items)if(itemName==pi.name)return{...pi,stage:s};throw new Error("prerequiste is not a defined progress item: "+itemName)}renderDialogContent(){if(null==this._feature)return E$1;const prereqItems=[];for(const itemName of this._action.prerequisites||[])this._progress.hasOwnProperty(itemName)||prereqItems.push(this.makePrereqItem(itemName));const pendingGates=findPendingGates(this._featureGates,this._feStage);return x$1` + Before you ${this._action.name}, it is strongly recommended that you do + the following: + <ul class="missing-prereqs-list"> + ${prereqItems.map(item=>x$1` <li class="pending"> + ${item.stage?.name||"Metadata"}: ${item.name} + ${this.renderEditLink(item.stage,findFirstFeatureStage(item.stage?.outgoing_stage,this._stage,this._feature),item)} + </li>`)} + ${pendingGates.map(g=>x$1` + <li class="pending"> + Get approval or NA from the + <a + href="/feature/${this._feature.id}?gate=${g.id}" + @click=${this.hide} + >${g.team_name}</a + > + team + </li> + `)} + </ul> + + <sl-button + href="${this._url}" + target="_blank" + size="small" + @click=${this.handleProceed} + >Proceed anyway + </sl-button> + <sl-button size="small" variant="warning" @click=${this.handleCancel} + >Don't draft email yet</sl-button + > + `}render(){return x$1` + <sl-dialog + class="missing-prereqs" + label="Missing Prerequisites" + style="--width:fit-content" + > + ${this.renderDialogContent()} + </sl-dialog> + `}};__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_feature",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_featureGates",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_progress",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_process",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_action",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_stage",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_feStage",void 0),__decorate$T([r$6()],ChromedashPreflightDialog.prototype,"_url",void 0),ChromedashPreflightDialog=__decorate$T([t$3("chromedash-preflight-dialog")],ChromedashPreflightDialog);function resolveFieldForFeature(field,feature){const result={...field};return field.computedChoices&&(result.choices=field.computedChoices(feature)),result}const USER_REGEX="[A-Za-z0-9_#$&*+\\/=?\\{\\}~^.\\-]+",DOMAIN_NAME_REGEX="(([A-Za-z0-9\\-]+\\.)+[A-Za-z]{2,6})",LOCALHOST_REGEX="(localhost|127\\.0\\.0\\.1)",DOMAIN_REGEX="("+DOMAIN_NAME_REGEX+"|"+LOCALHOST_REGEX+")",FINCH_NAMES_REGEX="[\\-_a-zA-Z0-9,]*",EMAIL_ADDRESS_REGEX="[A-Za-z0-9_#$&*+\\/=?\\{\\}~^.\\-]+@"+DOMAIN_NAME_REGEX,GOOGLE_EMAIL_ADDRESS_REGEX=`${"[A-Za-z0-9_#$&*+\\/=?\\{\\}~^.\\-]+"}@google.com`,EMAIL_ADDRESSES_REGEX=EMAIL_ADDRESS_REGEX+"([ ]*,[ ]*"+EMAIL_ADDRESS_REGEX+")*",PORTNUM_REGEX="(:[0-9]+)?",URL_REGEX="(https?)://"+DOMAIN_REGEX+PORTNUM_REGEX+"(/\\S*)?",URL_PADDED_REGEX="\\s*"+URL_REGEX+"\\s*",URL_FIELD_ATTRS={title:"Enter a full URL https://...",type:"url",placeholder:"https://...",pattern:URL_PADDED_REGEX},MULTI_STRING_FIELD_ATTRS={title:"Enter one or more comma-separated complete words.",type:"text",multiple:!0,placeholder:"EnableFeature1, Feature1Policy"},MULTI_EMAIL_FIELD_ATTRS={title:"Enter one or more comma-separated complete email addresses.",type:"text",multiple:!0,placeholder:"user1@domain.com, user2@chromium.org",pattern:EMAIL_ADDRESSES_REGEX},TEXT_FIELD_ATTRS={type:"text"},MILESTONE_NUMBER_FIELD_ATTRS={type:"number",placeholder:"Milestone number"},OT_MILESTONE_DESKTOP_RANGE={earlier:"ot_milestone_desktop_start",later:"ot_milestone_desktop_end"},OT_MILESTONE_ANDROID_RANGE={earlier:"ot_milestone_android_start",later:"ot_milestone_android_end"},OT_MILESTONE_WEBVIEW_RANGE={earlier:"ot_milestone_webview_start",later:"ot_milestone_webview_end"},OT_ALL_SHIPPED_MILESTONE_DESKTOP_RANGE={earlier:"ot_milestone_desktop_start",allLater:"shipped_milestone",warning:"Origin trial starting milestone should be before all feature shipping milestones."},ALL_OT_SHIPPED_MILESTONE_DESKTOP_RANGE={allEarlier:"ot_milestone_desktop_start",later:"shipped_milestone",warning:"All origin trials starting milestones should be before feature shipping milestone."},OT_ALL_SHIPPED_MILESTONE_WEBVIEW_RANGE={earlier:"ot_milestone_webview_start",allLater:"shipped_webview_milestone",warning:"Origin trial starting milestone should be before all feature shipping milestones."},ALL_OT_SHIPPED_MILESTONE_WEBVIEW_RANGE={allEarlier:"ot_milestone_webview_start",later:"shipped_webview_milestone",warning:"All origin trials starting milestones should be before feature shipping milestone."},OT_ALL_SHIPPED_MILESTONE_ANDROID_RANGE={earlier:"ot_milestone_android_start",allLater:"shipped_android_milestone",warning:"Origin trial starting milestone should be before all feature shipping milestones."},ALL_OT_SHIPPED_MILESTONE_ANDROID_RANGE={allEarlier:"ot_milestone_android_start",later:"shipped_android_milestone",warning:"All origin trials starting milestones should be before feature shipping milestone."},DT_ALL_SHIPPED_MILESTONE_DESKTOP_RANGE={earlier:"dt_milestone_desktop_start",allLater:"shipped_milestone",warning:"Shipped milestone should be later than dev trial."},ALL_DT_SHIPPED_MILESTONE_DESKTOP_RANGE={allEarlier:"dt_milestone_desktop_start",later:"shipped_milestone",warning:"Shipped milestone should be later than dev trial."},DT_ALL_SHIPPED_MILESTONE_ANDROID_RANGE={earlier:"dt_milestone_android_start",allLater:"shipped_android_milestone",warning:"Shipped milestone should be later than dev trial start milestone."},ALL_DT_SHIPPED_MILESTONE_ANDROID_RANGE={allEarlier:"dt_milestone_android_start",later:"shipped_android_milestone",warning:"Shipped milestone should be later than dev trial start milestone."},DT_ALL_SHIPPED_MILESTONE_IOS_RANGE={earlier:"dt_milestone_ios_start",allLater:"shipped_ios_milestone",warning:"Shipped milestone should be later than dev trial start milestone."},ALL_DT_SHIPPED_MILESTONE_IOS_RANGE={allEarlier:"dt_milestone_ios_start",later:"shipped_ios_milestone",warning:"Shipped milestone should be later than dev trial start milestone."},MULTI_URL_FIELD_ATTRS={title:"Enter one or more full URLs, one per line:\nhttps://...\nhttps://...",multiple:!0,placeholder:"https://...\nhttps://...",rows:4,cols:50,maxlength:5e3,chromedash_single_pattern:URL_REGEX,chromedash_split_pattern:"\\s+"},SHIPPED_HELP_TXT=x$1` First milestone to ship with this status. Applies +to: Enabled by default, Deprecated, and Removed.`,SHIPPED_WEBVIEW_HELP_TXT=x$1` First milestone to ship with this status. +Applies to Enabled by default, Deprecated, and Removed.`,ALL_FIELDS={name:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!0,label:"Feature name",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` <p> + Capitalize only the first letter and the beginnings of proper nouns. + </p>`,extra_help:x$1` <p> + Each feature should have a unique name that is written as a noun phrase. + </p> + <ul> + <li> + Capitalize only the first letter and the beginnings of proper nouns. + </li> + <li> + Avoid using verbs such as "add", "enhance", "deprecate", or "delete". + Instead, simply name the feature itself and use the feature type and + stage fields to indicate the intent of change. + </li> + <li> + Do not include markup or markdown because they will not be rendered.. + </li> + <li> + Write keywords and identifiers as they would appear to a web + developer, not as they are in source code. In particular, do not use + static method/property syntax for instance methods/properties. For + example, for an instance method doStuff() on an interface + NewInterface, write "NewInterface's doStuff() method" (not + "NewInterface.doStuff() method"). Or for a method on a well-known + global like Document, write "document.doStuff()" (not + "Document.doStuff()"). + </li> + </ul> + + <h4>Examples</h4> + <ul> + <li>Conversion Measurement API</li> + <li>CSS Flexbox: intrinsic size algorithm</li> + <li>Permissions-Policy header</li> + </ul>`,check:(_value,getFieldValue)=>checkFeatureNameAndType(getFieldValue)},summary:{type:"textarea",required:!0,label:"Summary",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,enterprise_offer_markdown:!0,enterprise_help_text:x$1` <p> + This text will be used in the + <a + href="https://support.google.com/chrome/a/answer/7679408" + target="_blank" + >enterprise release notes</a + >, which are publicly visible and primarily written for IT admins. All + Enterprise policies must be included in this summary section. + </p> + <p> + Explain what's changing from the point of view of an end-user, + developer, or administrator. Indicate what the motivation is for this + change, especially if there’s security or privacy benefits to the + change. If an admin should do something (like test or set a flag or an + enterprise policy), please explain. Finally, if the change has a + user-visible benefit (eg. better security or privacy), explain that + motivation. If there are already publicly visible comms (e.g. blog + posts), you should link to them here as well. + </p> + <p> + See + <a + href="https://docs.google.com/document/d/1SdQ-DKeA5O7I8ju5Cb8zSM5S4NPwUACNJ9qbEhz-AYU" + target="_blank" + >go/releasenotes-examples</a + > + for examples. + </p>`,help_text:x$1` + <p> + Text in the beta release post, the enterprise release notes, and other + external sources will be based on this text. + </p> + <p> + Write from a web developer's point of view. Begin with one line + explaining what the feature does. Add one or two lines explaining how + this feature helps developers. Write in a matter-of-fact manner and in + the present tense. (This summary will be visible long after your project + is finished.) Avoid language such as "a new feature" and "we propose". + </p> + `,extra_help:x$1` + <p> + Provide a one sentence description followed by one or two lines + explaining how this feature works and how it helps web developers. + </p> + + <p> + Note: This text communicates with more than just the rest of Chromium + development. It's the part most visible to external readers and is used + in the beta release announcement, enterprise release notes, and other + communications. + </p> + + <ul> + <li> + Write from a web developer's point of view, not a browser developer's + </li> + <li> + Do not use markup or markdown because they will not be rendered. + </li> + <li> + Do not use hard or soft returns because they will not be rendered. + </li> + <li> + Avoid phrases such as "a new feature". Every feature on the site was + new when it was created. You don't need to repeat that information. + </li> + + <li> + The first line should be a sentence fragment beginning with a verb. + (See below.) This is the rare exception to the requirement to always + use complete sentences. + </li> + + <li> + "Conformance with spec" is not adequate. Most if not all features are + in conformance to spec. + </li> + </ul> + + <h4>Example</h4> + <blockquote> + Splits the HTTP cache using the top frame origin (and possibly subframe + origin) to prevent documents from one origin from knowing whether a + resource from another origin was cached. The HTTP cache is currently one + per profile, with a single namespace for all resources and subresources + regardless of origin or renderer process. Splitting the cache on top + frame origins helps the browser deflect side-channel attacks where one + site can detect resources in another site's cache. + </blockquote> + `,enterprise_extra_help:"",check:value=>value&&"string"==typeof value&&0<value.length&&(100>value.length||5e3<value.length)?{warning:"Feature summary should be between 100 and 5000 characters long."}:void 0},owner:{type:"input",name:"owner_emails",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!0,label:"Feature owners",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Comma separated list of full email addresses.`},editors:{type:"input",name:"editor_emails",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"Feature editors",usage:{},help_text:x$1` Comma separated list of full email addresses. These users + will be allowed to edit this feature, but will not be listed as feature + owners. User groups are not supported.`},cc_recipients:{type:"input",name:"cc_emails",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"CC",usage:{},help_text:x$1` Comma separated list of full email addresses. These users + will be notified of any changes to the feature, but do not gain permission + to edit. User groups must allow posting from + admin@cr-status.appspotmail.com.`},unlisted:{type:"checkbox",label:"Unlisted",initial:!1,usage:{},help_text:x$1` Check this box to hide draft features in list views. Anyone + with a link will be able to view the feature's detail page.`},accurate_as_of:{type:"checkbox",label:"Confirm accuracy",initial:!0,usage:{},help_text:x$1` Check this box to indicate that feature information is + accurate as of today. (Selecting this avoids reminder emails for four + weeks.)`},blink_components:{type:"datalist",required:!0,choices:void 0,label:"Blink component",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,attrs:{placeholder:"Please select a Blink component"},help_text:x$1` Select the most specific component. If unsure, leave as + "Blink".`},web_feature:{type:"datalist",required:!1,choices:void 0,label:"Web Feature ID",attrs:{placeholder:"Please select a Web feature ID"},usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Select the web feature this belongs to in the + <a href="https://github.com/web-platform-dx/web-features" target="_blank" + >web-features project</a + >. If your feature is not listed, + <a + href="https://github.com/web-platform-dx/web-features/issues/new?template=new-feature.yml" + target="_blank" + >propose a new web feature ID</a + >, then return to this tab and choose "Missing feature".`},category:{type:"select",choices:FEATURE_CATEGORIES,initial:FEATURE_CATEGORIES.MISC[0],label:"Category",usage:{},help_text:x$1` Select the most specific category. If unsure, leave as + "Miscellaneous".`},enterprise_product_category:{type:"radios",name:"enterprise_product_category",choices:ENTERPRISE_PRODUCT_CATEGORY,label:"Enterprise product category",usage:{},help_text:x$1` Select the appropriate category.`},feature_type:{type:"select",disabled:!0,choices:FEATURE_TYPES,label:"Feature type",usage:{},help_text:x$1` Feature type chosen at time of creation. + <br /> + <p style="color: red"> + <strong>Note:</strong> The feature type field cannot be changed. If this + field needs to be modified, a new feature would need to be created. + </p>`,check:(_value,getFieldValue)=>checkFeatureNameAndType(getFieldValue)},feature_type_radio_group:{name:"feature_type",type:"radios",choices:FEATURE_TYPES_WITHOUT_ENTERPRISE,label:"Feature type",usage:{},help_text:x$1`If all goes well, how will developers experience the change + you're planning to make to Chromium? + <br /> + <p style="color: red"> + <strong>Note:</strong> The feature type field cannot be changed. If this + field needs to be modified, a new feature would need to be created. + </p>`,check:(_value,getFieldValue)=>checkFeatureNameAndType(getFieldValue)},active_stage_id:{type:"select",computedChoices(formattedFeature){const result={};for(const stage of formattedFeature.stages){const name=unambiguousStageName(stage,formattedFeature);name&&(result[stage.id]=[stage.id,name])}return result},label:"Active stage",usage:{},help_text:x$1`The active stage opens by default in this feature's page. + And, it roughly indicates progress in the process.`},search_tags:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!1,label:"Search tags",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Comma separated keywords used only in search.`},bug_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Tracking bug URL",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Tracking bug url (https://bugs.chromium.org/...). This bug + should have "Type=Feature" set and be world readable. Note: This field + only accepts one URL. + <br /><br /> + <a + target="_blank" + href="https://bugs.chromium.org/p/chromium/issues/entry" + > + Create tracking bug</a + >`},launch_bug_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Launch URL",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Launch URL (https://launch.corp.google.com/...) to track + internal approvals, if any. + <br /><br /> + <a target="_blank" href="https://launch.corp.google.com/"> + Create a launch</a + >.`},screenshot_links:{type:"attachments",attrs:MULTI_URL_FIELD_ATTRS,required:!1,label:"Screenshot link(s)",usage:{[FeatureType.Incubate]:new Set([UsageType.ReleaseNotes]),[FeatureType.Existing]:new Set([UsageType.ReleaseNotes]),[FeatureType.CodeChange]:new Set([UsageType.ReleaseNotes]),[FeatureType.Deprecation]:new Set([UsageType.ReleaseNotes]),[FeatureType.Enterprise]:new Set([UsageType.ReleaseNotes])},help_text:x$1` Optional: Links to screenshots showcasing this feature (one + URL per line). Be sure to link directly to the image with a URL ending in + .png, .gif, or .jpg, rather than linking to an HTML page that contains the + image. Or, use the upload button to upload an image to be served from + chromestatus.com. These will be shared publicly.`,check:async value=>{const warning={warning:`One or more urls are not actual images or requires the consumer some kind + of authentication to access them. Use a valid link to an actual image free + of authentication or upload your image.`},urls=value.split("\n").filter(x=>!!x).map(x=>x.trim());if(urls.length){if(urls.some(x=>{try{return new URL(x),!1}catch{return!0}}))return warning;const urlTypes=await Promise.all(urls.map(url=>fetch(url,{method:"HEAD"}).then(response=>response.blob()).then(blob=>blob.type).catch(()=>"error")));return urlTypes.some(type=>!type.startsWith("image"))?warning:void 0}}},first_enterprise_notification_milestone:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"First notification milestone",usage:{},help_text:x$1` Optional: Unless you're sure you need to use this, leave it + blank. + <br /><br /> + If you leave this blank, we will automatically find the right milestone. + <br /><br /> + If you're not ready to communicate this feature to enterprises yet, what + is the earliest milestone that you expect to be ready to communicate it? + You can change this later. In general, you should provide enterprises + notice at least 3 milestones before making an impactful change.`,check:(value,_,initialValue)=>checkFirstEnterpriseNotice(value,initialValue)},motivation:{type:"textarea",required:!1,label:"Motivation",usage:{[FeatureType.Incubate]:new Set([UsageType.Prototype]),[FeatureType.Existing]:new Set([UsageType.Prototype]),[FeatureType.Deprecation]:new Set([UsageType.DeprecateAndRemove])},help_text:x$1` Explain why the web needs this change. It may be useful to + describe what web developers are forced to do without it. When possible, + add links to your explainer (under + <a href="#id_explainer_links">Explainer link(s)</a>) backing up your + claims. <br /><br /> + This text is sometimes included with the summary in the beta post, + enterprise release notes and other external documents. Write in a + matter-of-fact manner and in the present tense. + <br /><br /> + <a + target="_blank" + href="https://github.com/GoogleChrome/chromium-dashboard/wiki/EditingHelp#motivation-example" + > + Example</a + >`},deprecation_motivation:{name:"motivation",type:"textarea",required:!1,label:"Motivation",usage:{[FeatureType.Deprecation]:new Set([UsageType.DeprecateAndRemove])},help_text:x$1` Deprecations and removals must have strong reasons, backed + up by measurements. There must be clear and actionable paths forward for + developers. + <br /><br /> + This text is sometimes included with the summary in the beta post, + enterprise release notes and other external documents. Write in a + matter-of-fact manner and in the present tense. + <br /><br /> + Please see + <a + target="_blank" + href="https://docs.google.com/a/chromium.org/document/d/1LdqUfUILyzM5WEcOgeAWGupQILKrZHidEXrUxevyi_Y/edit?usp=sharing" + > + Removal guidelines</a + >.`},initial_public_proposal_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Initial public proposal URL",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link to the first public proposal to create this feature.`,extra_help:x$1` If there isn't another obvious place to propose your + feature, create a + <a + target="_blank" + href="https://github.com/WICG/proposals#what-does-a-proposal-look-like" + > + WICG proposal</a + >. You can use your proposal document to help you socialize the problem + with other vendors and developers.`},explainer_links:{type:"textarea",attrs:MULTI_URL_FIELD_ATTRS,required:!1,label:"Explainer link(s)",usage:{[FeatureType.Incubate]:ALL_FEATURE_TYPE_INCUBATE_INTENTS,[FeatureType.Deprecation]:ALL_FEATURE_TYPE_DEPRECATION_INTENTS},help_text:x$1`Link to explainer(s) (one URL per line). See the + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/#start-incubating" + >launch process</a + > + for detailed advice, or expand the extra help here for a summary.`,extra_help:x$1`<p> + Host your explainer somewhere like Github (and <i>not</i> Google Docs) + that makes it easy to file issues. Your organization may recommend a + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/#start-incubating" + >particular place</a + >. + </p> + <p> + See the TAG guide to writing + <a target="_blank" href="https://tag.w3.org/explainers/">Explainers</a> + for several examples of good explainers and tips for effective + explainers. + </p> + <p> + If you've already made an initial public proposal (see above), post your + explainer to that thread. Otherwise, make an initial proposal based on + your explainer. + </p> + <p> + Once a second organization is interested in the WICG proposal, you can + move the explainer into the WICG. The + <a href="https://wicg.github.io/admin/charter.html#chairs" + >WICG co-chairs</a + > + can help you. + </p> + <p> + If you want help, ask for a + <a + target="_blank" + href="https://sites.google.com/a/chromium.org/dev/blink/spec-mentors" + >specification mentor</a + >. + </p>`,check:value=>checkNotGoogleDocs(value,"Explainers should not be hosted on Google Docs.")},spec_link:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Spec link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link to the spec, if and when available. When implementing + a spec update, please link to a heading in a published spec rather than a + pull request when possible.`,extra_help:x$1`<p> + Specifications should be written in the format and hosted in the URL space + expected by your target standards body. For example, the W3C expects + <a href="https://respec.org/" target="_blank">Respec</a> or + <a href="https://speced.github.io/bikeshed/" target="_blank">Bikeshed</a> + hosted on w3.org or in Github Pages. The IETF expects an + <a href="https://authors.ietf.org/" target="_blank">Internet-Draft</a> + hosted in the + <a href="https://datatracker.ietf.org/" target="_blank">Datatracker</a>. + </p>`,check:value=>checkNotGoogleDocs(value,"Specifications should not be hosted on Google Docs.")},comments:{type:"textarea",name:"feature_notes",attrs:{rows:4},required:!1,label:"Comments",usage:{},help_text:x$1` Additional comments, caveats, info...`},standard_maturity:{type:"select",choices:STANDARD_MATURITY_CHOICES,initial:STANDARD_MATURITY_CHOICES.PROPOSAL_STD[0],label:"Standard maturity",usage:{},help_text:x$1` How far along is the standard that this feature implements?`},api_spec:{type:"checkbox",initial:!1,label:"API spec",usage:{},help_text:x$1` The spec document has details in a specification language + such as Web IDL, or there is an existing MDN page.`},automation_spec:{type:"checkbox",initial:!1,label:"Automation spec",usage:{},help_text:x$1` The platform has sufficient automation features for website + authors to test use of this new feature. These automation features can + include new automation APIs, like WebDriver BiDi modules, that are defined + in this feature's specification.`},spec_mentors:{type:"input",name:"spec_mentor_emails",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"Spec mentors",usage:{},help_text:x$1` Experienced + <a target="_blank" href="https://www.chromium.org/blink/spec-mentors"> + spec mentors</a + > + are available to help you improve your feature spec.`},intent_to_implement_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Intent to Prototype link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` After you have started the "Intent to Prototype" discussion + thread, link to it here.`},doc_links:{type:"textarea",attrs:MULTI_URL_FIELD_ATTRS,required:!1,label:"Doc link(s)",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Links to design doc(s) (one URL per line), if and when + available. [This is not required to send out an Intent to Prototype. Please + update the intent thread with the design doc when ready]. An explainer + and/or design doc is sufficient to start this process. [Note: Please include + links and data, where possible, to support any claims.`},measurement:{type:"textarea",attrs:{rows:4},required:!1,label:"Measurement",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` It's important to measure the adoption and success of + web-exposed features. Note here what measurements you have added to track + the success of this feature, such as a link to the UseCounter(s) you have + set up.`},availability_expectation:{type:"textarea",attrs:{rows:4},required:!1,label:"Availability expectation",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` What is your availability expectation for this feature? + Examples:`,extra_help:x$1` + <ul> + <li> + Feature is available on Web Platform Baseline within 12 months of + launch in Chrome. + </li> + + <li> + Feature is available only in Chromium browsers for the foreseeable + future. + </li> + </ul> + `},adoption_expectation:{type:"textarea",attrs:{rows:4},required:!1,label:"Adoption expectation",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` What is your adoption expectation for this feature? + Examples:`,extra_help:x$1` + <ul> + <li> + Feature is considered a best practice for some use case within 12 + months of reaching Web Platform baseline. + </li> + + <li> + Feature is used by specific partner(s) to provide functionality within + 12 months of launch in Chrome. + </li> + + <li> + At least 3 major abstractions replace their use of an existing feature + with this feature within 24 months of reaching mainline. + </li> + </ul> + `},adoption_plan:{type:"textarea",attrs:{rows:4},required:!1,label:"Adoption plan",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` What is the plan to achieve the stated expectations? Please + provide a plan that covers availability and adoption for the feature.`},security_review_status:{type:"select",choices:REVIEW_STATUS_CHOICES,initial:REVIEW_STATUS_CHOICES.REVIEW_PENDING[0],label:"Security review status",usage:{},help_text:x$1` Status of the security review.`},privacy_review_status:{type:"select",choices:REVIEW_STATUS_CHOICES,initial:REVIEW_STATUS_CHOICES.REVIEW_PENDING[0],label:"Privacy review status",usage:{},help_text:x$1`Status of the privacy review.`},tag_review:{type:"textarea",attrs:{rows:2},required:!1,label:"TAG specification review",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link(s) to TAG specification review(s), or explanation why + this is not needed.`,extra_help:x$1` <p> + The + <a target="_blank" href="https://www.w3.org/2001/tag/" + >W3C Technical Architecture Group</a + > + (TAG) is a special working group of the W3C that consists of a few + appointed and elected members, all of whom are experienced members of + the web standards community. The Blink launch process has a + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/wide-review/#tag" + >formal requirement for requesting a TAG specification review</a + > + for all features. The review happens publicly on a GitHub issue. + </p> + <p> + You will likely have asked for an "<a + target="_blank" + href="https://github.com/w3ctag/design-reviews/issues/new?template=000-incubation-review.yaml" + >Early design/incubation review</a + >" earlier in the process to get the TAG familiar with your feature. + This isn't that. + </p> + <p> + It's recommended that you file a TAG specification review as soon as + your specification is written, and at least a month ahead of sending an + Intent to Ship. There may be some work involved in preparing your + feature for review. See the + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/wide-review/#tag" + >launch process</a + > + for help picking which kind of specification review to file, and then + look through that template to find what data to collect. + </p> + <p> + A large number of Intents to Ship are delayed because a TAG + specification review was only recently filed and engagement from the TAG + can take multiple weeks to multiple months. Note that the API owners can + approve shipping even if the TAG hasn't replied to your review request, + as long as you've made a reasonable effort to obtain their review with + enough time for them to give feedback. + </p>`},tag_review_status:{type:"select",choices:REVIEW_STATUS_CHOICES,initial:REVIEW_STATUS_CHOICES.REVIEW_PENDING[0],label:"TAG specification review status",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`Status of the TAG specification review.`},intent_to_ship_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Intent to Ship link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`After you have started the "Intent to Ship" discussion + thread, link to it here.`},announcement_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Ready for Developer Testing link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`After you have started the "Ready for Developer Testing" + discussion thread, link to it here.`},intent_to_experiment_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Intent to Experiment link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`After you have started the "Intent to Experiment" discussion + thread, link to it here.`},intent_to_extend_experiment_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Intent to Extend Experiment link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`If this feature has an "Intent to Extend Experiment" + discussion thread, link to it here.`},ot_extension__intent_to_extend_experiment_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!0,label:"Intent to Extend Experiment link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link to the approved Intent to Extend Experiment, as per + <a + target="_blank" + href="https://www.chromium.org/blink/origin-trials/running-an-origin-trial/#what-is-the-process-to-extend-an-origin-trial" + > + the trial extension process </a + >.`},r4dt_url:{name:"intent_to_experiment_url",type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Request for Deprecation Trial link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1`After you have started the "Request for Deprecation Trial" + discussion thread, link to it here.`},interop_compat_risks:{type:"textarea",required:!1,label:"Interoperability and compatibility risks",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Describe the degree of + <a + target="_blank" + href="https://www.chromium.org/blink/guidelines/web-platform-changes-guidelines#finding-balance" + > + interoperability risk</a + >. For a new feature, the main risk is that it fails to become an + interoperable part of the web platform if other browsers do not implement + it. For a removal, please review our + <a + target="_blank" + href="https://docs.google.com/document/d/1RC-pBBvsazYfCNNUSkPqAVpSpNJ96U8trhNkfV0v9fk/edit" + > + principles of web compatibility</a + >.<br /> + <br /> + Please include citation links below where possible. Examples include + resolutions from relevant standards bodies (e.g. W3C working group), + tracking bugs, or links to online conversations. + <a + target="_blank" + href="https://github.com/GoogleChrome/chromium-dashboard/wiki/EditingHelp#interoperability-and-compatibility-risks-example" + > + Example</a + >.`},safari_views:{type:"select",choices:VENDOR_VIEWS_COMMON,initial:VENDOR_VIEWS_COMMON.NO_PUBLIC_SIGNALS[0],label:"WebKit views",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` See + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/wide-review/" + > + chromium.org/blink/launching-features/wide-review + </a>`},safari_views_link:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"",displayLabel:"WebKit views link",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1`Citation link.`},safari_views_notes:{type:"textarea",attrs:{rows:2,placeholder:"Notes"},required:!1,label:"",displayLabel:"WebKit views notes",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:""},ff_views:{type:"select",choices:VENDOR_VIEWS_GECKO,initial:VENDOR_VIEWS_GECKO.NO_PUBLIC_SIGNALS[0],label:"Firefox views",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` See + <a + target="_blank" + href="https://www.chromium.org/blink/launching-features/wide-review/" + > + chromium.org/blink/launching-features/wide-review + </a>`},ff_views_link:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"",displayLabel:"Firefox views link",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Citation link.`},ff_views_notes:{type:"textarea",attrs:{rows:2,placeholder:"Notes"},required:!1,label:"",displayLabel:"Firefox views notes",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:""},web_dev_views:{type:"select",choices:WEB_DEV_VIEWS,initial:WEB_DEV_VIEWS.DEV_NO_SIGNALS[0],label:"Web / Framework developer views",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` If unsure, default to "No signals". See + <a target="_blank" href="https://goo.gle/developer-signals"> + https://goo.gle/developer-signals</a + >`},web_dev_views_link:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"",displayLabel:"Web / Framework developer views link",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Citation link.`},web_dev_views_notes:{type:"textarea",attrs:{rows:2,placeholder:"Notes"},required:!1,label:"",displayLabel:"Web / Framework developer views notes",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Reference known representative examples of opinions, both + positive and negative.`},other_views_notes:{type:"textarea",attrs:{rows:4,placeholder:"Notes"},required:!1,label:"Other views",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` For example, other browsers.`},ergonomics_risks:{type:"textarea",required:!1,label:"Ergonomics risks",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Are there any other platform APIs this feature will + frequently be used in tandem with? Could the default usage of this API make + it hard for Chrome to maintain good performance (i.e. synchronous return, + must run on a certain thread, guaranteed return timing)?`},activation_risks:{type:"textarea",required:!1,label:"Activation risks",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Will it be challenging for developers to take advantage of + this feature immediately, as-is? Would this feature benefit from having + polyfills, significant documentation and outreach, and/or libraries built on + top of it to make it easier to use?`},security_risks:{type:"textarea",required:!1,label:"Security Risks",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` List any security considerations that were taken into + account when designing this feature.`},webview_risks:{type:"textarea",required:!1,label:"WebView application risks",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Does this feature deprecate or change behavior of existing + APIs, such that it has potentially high risk for Android WebView-based + applications? (See + <a + target="_blank" + href="https://new.chromium.org/developers/webview-changes/" + > + here</a + > + for a definition of "potentially high risk", information on why changes to + this platform carry higher risk, and general rules of thumb for which + changes have higher or lower risk) If so: + <ul> + <li> + Please use a base::Feature killswitch (<a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/common/features.h" + >examples here</a + >) that can be flipped off in case of compat issues + </li> + <li>Consider contacting android-webview-dev@chromium.org for advice</li> + <li> + If you are not sure, just put "not sure" as the answer and the API + owners can help during the review of your Intent to Ship + </li> + </ul>`},experiment_goals:{type:"textarea",required:!1,label:"Experiment goals",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Which pieces of the API surface are you looking to gain + insight on? What metrics/measurement/feedback will you be using to + validate designs? Double check that your experiment makes sense given that + a large developer (e.g. a Google product or Facebook) likely can't use it + in production due to the limits enforced by origin trials. + <br /><br /> + If you send an Intent to Extend Origin Trial, highlight areas for + experimentation. They should not be an exact copy of the goals from the + first Intent to Experiment.`},experiment_timeline:{type:"textarea",attrs:{rows:2,placeholder:"This field is deprecated",disabled:!0},required:!1,label:"Experiment timeline",usage:{[FeatureType.Incubate]:new Set([UsageType.Experiment]),[FeatureType.Existing]:new Set([UsageType.Experiment]),[FeatureType.Deprecation]:new Set([UsageType.Experiment])},help_text:x$1` When does the experiment start and expire? Deprecated: + Please use the numeric fields above instead.`,deprecated:!0},ot_milestone_desktop_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT desktop start",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First desktop milestone that will support an origin trial + of this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_DESKTOP_RANGE,OT_ALL_SHIPPED_MILESTONE_DESKTOP_RANGE],getFieldValue)},ot_milestone_desktop_end:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT desktop end",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Last desktop milestone that will support an origin trial of + this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_DESKTOP_RANGE],getFieldValue)},ot_milestone_android_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT Android start",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First android milestone that will support an origin trial + of this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_ANDROID_RANGE,OT_ALL_SHIPPED_MILESTONE_ANDROID_RANGE],getFieldValue)},ot_milestone_android_end:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT Android end",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Last android milestone that will support an origin trial of + this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_ANDROID_RANGE],getFieldValue)},ot_milestone_webview_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT WebView start",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First WebView milestone that will support an origin trial + of this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_WEBVIEW_RANGE,OT_ALL_SHIPPED_MILESTONE_WEBVIEW_RANGE],getFieldValue)},ot_milestone_webview_end:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"OT WebView end",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Last WebView milestone that will support an origin trial of + this feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_WEBVIEW_RANGE],getFieldValue)},experiment_risks:{type:"textarea",required:!1,label:"Experiment risks",usage:{},help_text:x$1` When this experiment comes to an end are there any risks to + the sites that were using it, for example losing access to important storage + due to an experimental storage API?`},experiment_extension_reason:{type:"textarea",required:!1,label:"Experiment extension reason",usage:{[FeatureType.Incubate]:new Set([UsageType.Experiment]),[FeatureType.Existing]:new Set([UsageType.Experiment]),[FeatureType.Deprecation]:new Set([UsageType.Experiment])},help_text:x$1` If this is a repeated or extended experiment, explain why + it's being repeated or extended. Also, fill in discussion link fields below.`},extension_desktop_last:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!0,label:"Trial extension end milestone",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` The last desktop milestone in which the trial will be + available after extension.`},extension_android_last:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Trial extension Android end",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` The last android milestone in which the trial will be + available after extension.`},extension_webview_last:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Trial extension WebView end",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` The last WebView milestone in which the trial will be + available after extension.`},ot_extension__milestone_desktop_last:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!0,label:"Trial extension end milestone",usage:{},help_text:x$1` The last milestone in which the trial will be available + after extension.`,check:_value=>checkExtensionMilestoneIsValid(_value)},ongoing_constraints:{type:"textarea",required:!1,label:"Ongoing Constraints",usage:{[FeatureType.Incubate]:new Set([UsageType.Experiment]),[FeatureType.Existing]:new Set([UsageType.Experiment]),[FeatureType.Deprecation]:new Set([UsageType.Experiment])},help_text:x$1` Do you anticipate adding any ongoing technical constraints + to the codebase while implementing this feature? We prefer to avoid features + that require or assume a specific architecture. For most features, the + answer is "None."`},rollout_plan:{type:"select",choices:ROLLOUT_PLAN,initial:ROLLOUT_PLAN.ROLLOUT_100[0],label:"Rollout plan",usage:{[FeatureType.Incubate]:new Set([UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.Experiment,UsageType.Ship])},help_text:x$1`Normally, WP features that ship in a milestone go to all + users of that milestone. If your feature needs to roll out in any other way, + mark that here.`},origin_trial_feedback_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Origin trial feedback summary",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` If your feature was available as an origin trial, link to a + summary of usage and developer feedback. If not, leave this empty. DO NOT + USE FEEDBACK VERBATIM without prior consultation with the Origin Trials + team.`},ot_chromium_trial_name:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!0,label:"Chromium trial name",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Name for the trial, given as the value of the property + "origin_trial_feature_name" as specified in + <a + target="_blank" + href="https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5" + >runtime_enabled_features.json5</a + >. + <br /> + <p style="color: red"> + <strong>Note:</strong> This name should be unique and should not be used + by any previous origin trials! + </p>`},ot_documentation_url:{type:"input",attrs:URL_FIELD_ATTRS,label:"Documentation link",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link to more information to help developers use the trial's + feature (e.g. blog post, Github explainer, etc.).`},ot_creation__ot_documentation_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!0,label:"Documentation link",usage:{},help_text:x$1` Link to more information to help developers use the trial's + feature (e.g. blog post, Github explainer, etc.).`},ot_emails:{type:"input",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"Origin trial contacts",usage:{},help_text:x$1` List any other individuals or groups to include on the + contact list (e.g. for reminders on trial milestones). Mailing list emails + can be used here, but only email addresses of individuals will receive + access to view registrant data on + <a target="_blank" href="http://go/ot-registrants-dashboard" + >go/ot-registrants-dashboard</a + >. + <p> + <strong> + Please prefer using "@google.com" domain email addresses for any + contacts that have one. + </strong> + </p>`},ot_has_third_party_support:{type:"checkbox",initial:!1,label:"Origin trial supports third party origins",usage:{},help_text:x$1` Whether this trial supports third party origins. See + <a href="https://web.dev/third-party-origin-trials/">this article</a> + for more information. The feature should have + "origin_trial_allows_third_party" set to "true" in + <a + target="_blank" + href="https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5" + >runtime_enabled_features.json5</a + >`},ot_is_critical_trial:{type:"checkbox",initial:!1,label:"Critical origin trial",usage:{},help_text:x$1` See + <a href="https://goto.google.com/running-an-origin-trial" + >go/running-an-origin-trial</a + > + for criteria and additional process requirements. The feature name must be + added to the "kHasExpiryGracePeriod" array in + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/common/origin_trials/manual_completion_origin_trial_features.cc" + >manual_completion_origin_trial_features.cc</a + >`},ot_is_deprecation_trial:{type:"checkbox",initial:!1,label:"Deprecation trial",usage:{},help_text:x$1` Is this a deprecation trial? See the + <a + href="https://www.chromium.org/blink/launching-features/#deprecation-trial" + >deprecation trial section</a + > + for more information.`},ot_request_note:{type:"textarea",required:!1,label:"Anything else?",usage:{},help_text:x$1`<p> + Let us know if you have any further questions or comments. + </p>`},ot_webfeature_use_counter:{type:"input",attrs:{...TEXT_FIELD_ATTRS,placeholder:"e.g. \"kWebFeature\"",pattern:"k\\S*"},label:"UseCounter name",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` For measuring usage, this must be a single named value from + the WebFeature, WebDXFeature, or CSSSampleId enum, e.g. kWorkerStart. The + use counter must be landed in either + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom" + >web_feature.mojom</a + >, + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom" + >webdx_feature.mojom</a + >, or + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom" + >css_property_id.mojom</a + >. Not required for deprecation trials.`},ot_webfeature_use_counter__type:{type:"radios",label:"Use counter type",choices:WEBFEATURE_USE_COUNTER_TYPES,usage:{},help_text:x$1`Which type of use counter the feature is using. This can be + determined by which file the use counter is defined in.`},ot_require_approvals:{type:"checkbox",initial:!1,label:"Trial participation requires approval",usage:{},help_text:x$1` <p> + Will this trial require registrants to receive approval before + participating? Please reach out to origin-trials-support@google.com + beforehand to discuss options here. + </p>`},ot_approval_buganizer_component:{type:"input",attrs:{type:"number"},required:!0,label:"Approvals Buganizer component ID",usage:{},help_text:x$1`Buganizer component ID used for approvals requests.`},ot_approval_buganizer_custom_field_id:{type:"input",attrs:{type:"number"},required:!0,label:"Approvals Buganizer custom field ID",usage:{},help_text:x$1`The Buganizer custom field ID for trial registration + approval. This custom field in Buganizer provides approval/rejection + rationales for registration requests under ot_approval_buganizer_component.`},ot_approval_group_email:{type:"input",required:!0,attrs:{...TEXT_FIELD_ATTRS,pattern:GOOGLE_EMAIL_ADDRESS_REGEX,placeholder:"ex. \"approval-requests@google.com\""},label:"Registration request notifications group",usage:{},help_text:x$1` <p> + Google group email to be used for new registration request notifications. + Please supply a '@google.com' domain email address only. + </p>`},ot_approval_criteria_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!0,label:"Approval criteria link",usage:{},help_text:x$1` <p> + Link to public documentation describing the requirements to be approved + for trial participation. + </p>`},ot_creation__intent_to_experiment_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!0,label:"Intent to Experiment link",usage:{},help_text:x$1`Your "Intent to Experiment" discussion thread. The necessary + LGTMs should already have been received.`},ot_creation__milestone_desktop_first:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!0,label:"Trial milestone start",usage:{},help_text:x$1` First milestone that will support an origin trial of this + feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_DESKTOP_RANGE,OT_ALL_SHIPPED_MILESTONE_DESKTOP_RANGE],getFieldValue)},ot_creation__milestone_desktop_last:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!0,label:"Trial milestone end",usage:{},help_text:x$1` Last milestone that will support an origin trial of this + feature.`,check:(_value,getFieldValue)=>checkMilestoneRanges([OT_MILESTONE_DESKTOP_RANGE],getFieldValue)},ot_creation__bypass_file_checks:{type:"checkbox",initial:!1,label:"Bypass Chromium file checks (staging testing)",usage:{},help_text:x$1`This option should only be visible in ChromeStatus staging + environments. Allow this form to be submitted without verifying Chromium + code has landed.`},anticipated_spec_changes:{type:"textarea",attrs:{rows:4},required:!1,label:"Anticipated spec changes",usage:{[FeatureType.Incubate]:ALL_FEATURE_TYPE_INCUBATE_INTENTS,[FeatureType.Existing]:ALL_FEATURE_TYPE_EXISTING_INTENTS,[FeatureType.Deprecation]:ALL_FEATURE_TYPE_DEPRECATION_INTENTS},help_text:x$1` Open questions about a feature may be a source of future + web compat or interop issues. Please list open issues (e.g. links to known + github issues in the repo for the feature specification) whose resolution + may introduce web compat/interop risk (e.g., changing the naming or + structure of the API in a non-backward-compatible way).`},finch_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"Finch experiment",usage:{},help_text:x$1` If your feature will roll out gradually via a + <a target="_blank" href="http://go/finch">Finch experiment</a>, link to it + here.`},i2e_lgtms:{type:"input",attrs:{...MULTI_EMAIL_FIELD_ATTRS,placeholder:"This field is deprecated",disabled:!0},required:!1,label:"Intent to Experiment LGTM by",usage:{},help_text:x$1` Full email address of API owner who LGTM'd the Intent to + Experiment email thread.`,deprecated:!0},i2s_lgtms:{type:"input",attrs:{...MULTI_EMAIL_FIELD_ATTRS,placeholder:"This field is deprecated",disabled:!0},required:!1,label:"Intent to Ship LGTMs by",usage:{},help_text:x$1` + Comma separated list of email addresses of API owners who LGTM'd the + Intent to Ship email thread. + `,deprecated:!0},r4dt_lgtms:{name:"i2e_lgtms",type:"input",attrs:{...MULTI_EMAIL_FIELD_ATTRS,placeholder:"This field is deprecated",disabled:!0},required:!1,label:"Request for Deprecation Trial LGTM by",usage:{},help_text:x$1` Full email addresses of API owners who LGTM'd the Request + for Deprecation Trial email thread.`,deprecated:!0},debuggability:{type:"textarea",required:!1,label:"Debuggability",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Description of the DevTools debugging support for your + feature. Please follow the + <a target="_blank" href="https://goo.gle/devtools-checklist"> + DevTools support checklist</a + > + for guidance.`},all_platforms:{type:"checkbox",initial:!1,label:"Supported on all platforms?",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Will this feature be supported on all six Blink platforms + (Windows, Mac, Linux, ChromeOS, Android, and Android WebView)?`},all_platforms_descr:{type:"textarea",attrs:{rows:2},required:!1,label:"Platform support explanation",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Explain why this feature is, or is not, supported on all + platforms.`},wpt:{type:"checkbox",initial:!1,label:"Web Platform Tests",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Is this feature fully tested in Web Platform Tests?`},wpt_descr:{type:"textarea",required:!1,label:"Web Platform Tests or other automated test description",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Please link to the + <a target="_blank" href="https://wpt.fyi/results">results on wpt.fyi</a>. + If any part of the feature is not tested by web-platform-tests, please + include links to other automated tests or links to issues, e.g. a + web-platform-tests issue with the "infra" label explaining why a certain + thing cannot be tested (<a + target="_blank" + href="https://github.com/w3c/web-platform-tests/issues/3867" + >example</a + >), a spec issue for some change that would make it possible to test. (<a + target="_blank" + href="https://github.com/whatwg/fullscreen/issues/70" + >example</a + >), or a Chromium issue to upstream some existing tests (<a + target="_blank" + href="https://bugs.chromium.org/p/chromium/issues/detail?id=695486" + >example</a + >).`},sample_links:{type:"textarea",attrs:MULTI_URL_FIELD_ATTRS,required:!1,label:"Demo and sample links",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Links to demos and samples (one URL per line).`},non_oss_deps:{type:"textarea",required:!1,label:"Non-OSS dependencies",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Does the feature depend on any code or APIs outside the + Chromium open source repository and its open-source dependencies to + function? (e.g. server-side APIs, operating system APIs tailored to this + feature or closed-source code bundles) Yes or no. If yes, explain why this + is necessary.`},devrel:{type:"input",name:"devrel_emails",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"Developer relations emails",usage:{},help_text:x$1` Comma separated list of full email addresses.`},shipped_milestone:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Chrome for desktop",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:SHIPPED_HELP_TXT,check:(_value,getFieldValue)=>checkMilestoneRanges([ALL_OT_SHIPPED_MILESTONE_DESKTOP_RANGE,ALL_DT_SHIPPED_MILESTONE_DESKTOP_RANGE],getFieldValue)},shipped_android_milestone:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Chrome for Android",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:SHIPPED_HELP_TXT,check:(_value,getFieldValue)=>checkMilestoneRanges([ALL_OT_SHIPPED_MILESTONE_ANDROID_RANGE,ALL_DT_SHIPPED_MILESTONE_ANDROID_RANGE],getFieldValue)},shipped_ios_milestone:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Chrome for iOS (RARE)",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:SHIPPED_HELP_TXT,check:(_value,getFieldValue)=>checkMilestoneRanges([ALL_DT_SHIPPED_MILESTONE_IOS_RANGE],getFieldValue)},shipped_webview_milestone:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"Android Webview",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:SHIPPED_WEBVIEW_HELP_TXT,check:(_value,getFieldValue)=>checkMilestoneRanges([ALL_OT_SHIPPED_MILESTONE_WEBVIEW_RANGE],getFieldValue)},requires_embedder_support:{type:"checkbox",initial:!1,label:"Requires embedder support",usage:{[FeatureType.Incubate]:ALL_FEATURE_TYPE_INCUBATE_INTENTS,[FeatureType.Existing]:ALL_FEATURE_TYPE_EXISTING_INTENTS,[FeatureType.Deprecation]:ALL_FEATURE_TYPE_DEPRECATION_INTENTS},help_text:x$1` Will this feature require support in //chrome? That + includes any code in //chrome, even if that is for functionality on top of + the spec. Other //content embedders will need to be aware of that + functionality. Please add a row to this + <a + target="_blank" + href="https://docs.google.com/spreadsheets/d/1QV4SW4JBG3IyLzaonohUhim7nzncwK4ioop2cgUYevw/edit#gid=0" + > + tracking spreadsheet</a + >.`},devtrial_instructions:{type:"input",attrs:URL_FIELD_ATTRS,required:!1,label:"DevTrial instructions",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` Link to a HOWTO or FAQ describing how developers can get + started using this feature in a DevTrial. + <br /><br /> + <a + target="_blank" + href="https://github.com/samuelgoto/WebID/blob/master/HOWTO.md" + > + Example 1</a + >. + <a + target="_blank" + href="https://github.com/WICG/idle-detection/blob/main/HOWTO.md" + > + Example 2</a + >.`},dt_milestone_desktop_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"DevTrial on desktop",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First milestone that allows web developers to try this + feature on desktop platforms by setting a flag. When flags are enabled by + default in preparation for shipping or removal, please use the fields in the + ship stage.`,check:(_value,getFieldValue)=>checkMilestoneRanges([DT_ALL_SHIPPED_MILESTONE_DESKTOP_RANGE],getFieldValue)},dt_milestone_android_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"DevTrial on Android",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First milestone that allows web developers to try this + feature on Android by setting a flag. When flags are enabled by default in + preparation for shipping or removal, please use the fields in the ship + stage.`,check:(_value,getFieldValue)=>checkMilestoneRanges([DT_ALL_SHIPPED_MILESTONE_ANDROID_RANGE],getFieldValue)},dt_milestone_ios_start:{type:"input",attrs:MILESTONE_NUMBER_FIELD_ATTRS,required:!1,label:"DevTrial on iOS (RARE)",usage:ALL_INTENT_USAGE_BY_FEATURE_TYPE,help_text:x$1` First milestone that allows web developers to try this + feature on iOS by setting a flag. When flags are enabled by default in + preparation for shipping or removal, please use the fields in the ship + stage.`,check:(_value,getFieldValue)=>checkMilestoneRanges([DT_ALL_SHIPPED_MILESTONE_IOS_RANGE],getFieldValue)},flag_name:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!1,label:"Flag name on about://flags",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` Name of the flag on about://flags that allows a web + developer to enable this feature in their own browser to try it out. E.g., + "storage-buckets". These are defined in + <a + target="_blank" + href="https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/about_flags.cc" + >about_flags.cc</a + >.`},finch_name:{type:"input",attrs:{...TEXT_FIELD_ATTRS,placeholder:"e.g. \"StorageBuckets\"",pattern:FINCH_NAMES_REGEX},required:!1,label:"Finch feature name",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` String name of the <code>base::Feature</code> defined via + the <code>BASE_FEATURE</code> macro in your feature implementation code. + E.g., "StorageBuckets". These names are used in + <a + target="_blank" + href="https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/platform/runtime_enabled_features.json5" + >runtime_enabled_features.json5</a + > + (or + <a + target="_blank" + href="https://chromium.googlesource.com/chromium/src/+/main/content/public/common/content_features.cc" + >content_features.cc</a + >), and finch GCL files`},non_finch_justification:{type:"textarea",required:!1,label:"Non-finch justification",usage:{[FeatureType.Incubate]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.Existing]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship]),[FeatureType.CodeChange]:new Set([UsageType.DeveloperTesting,UsageType.PSA]),[FeatureType.Deprecation]:new Set([UsageType.DeveloperTesting,UsageType.Experiment,UsageType.Ship])},help_text:x$1` The + <a + target="_blank" + href="https://chromium.googlesource.com/chromium/src/+/main/docs/flag_guarding_guidelines.md" + >Flag Guarding Guidelines</a + > + require new features to have a finch flag. If your feature does not have a + finch flag, explain why.`},prefixed:{type:"checkbox",label:"Prefixed?",initial:!1,usage:{},help_text:""},display_name:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!1,label:"Stage display name",usage:{},help_text:x$1` <p> + Optional. Stage name to display on the feature detail page. + </p>`,extra_help:x$1` <p> + This name is only used for displaying stages on this site. Use this to + differentiate stages of the same type. + </p> + <h4>Examples</h4> + <ul> + <li>Extended deprecation trial</li> + <li>Second origin trial run</li> + <li>Delayed ship for Android</li> + </ul>`},ot_display_name:{type:"input",attrs:TEXT_FIELD_ATTRS,required:!0,label:"Origin trial display name",usage:{},help_text:x$1` <p> + Name shown in the + <a href="https://developer.chrome.com/origintrials/" target="_blank"> + Origin Trials Console + </a> + and included in reminder emails. + </p>`},ot_description:{type:"textarea",required:!0,label:"Trial description",usage:{},help_text:x$1` <p> + A brief description of the feature to interest web developers in joining + the trial (1-2 sentences). Shown as the trial description in the + <a href="https://developer.chrome.com/origintrials/" target="_blank"> + Origin Trials Console </a + >. + </p>`},ot_owner_email:{type:"input",required:!0,attrs:{...TEXT_FIELD_ATTRS,pattern:GOOGLE_EMAIL_ADDRESS_REGEX},usage:{},label:"Google point of contact",help_text:x$1` <p> + A Googler contact for this origin trial. Please supply a '@google.com' + domain email address only. + </p>`},ot_feedback_submission_url:{type:"input",attrs:URL_FIELD_ATTRS,required:!0,label:"Feature feedback link",usage:{},help_text:x$1` Link for developers to file feedback on the feature (e.g. + GitHub issues, or WICG page).`},shipping_year:{type:"input",attrs:{type:"number",min:2e3,max:2050},required:!0,label:"Estimated shipping year",usage:{},help_text:x$1` Estimate of the calendar year in which this will first ship + on any platform. E.g., 2024.`},enterprise_policies:{type:"input",attrs:MULTI_STRING_FIELD_ATTRS,required:!1,label:"Enterprise policies",usage:{[FeatureType.Incubate]:new Set([UsageType.CrossFunctionReview]),[FeatureType.Existing]:new Set([UsageType.CrossFunctionReview]),[FeatureType.CodeChange]:new Set([UsageType.CrossFunctionReview]),[FeatureType.Deprecation]:new Set([UsageType.CrossFunctionReview]),[FeatureType.Enterprise]:new Set([UsageType.CrossFunctionReview])},help_text:x$1` List the policies that are being introduced, removed, or + can be used to control the feature at this stage, if any.`,disabled:!0,deprecated:!0},enterprise_feature_categories:{type:"multiselect",choices:ENTERPRISE_FEATURE_CATEGORIES,required:!1,label:"Enterprise feature categories",usage:{},help_text:x$1` If your feature impacts enterprise users, select at least + one.`,enterprise_help_text:x$1` Select at least one.`},enterprise_impact:{type:"select",choices:ENTERPRISE_IMPACT,initial:ENTERPRISE_IMPACT.IMPACT_NONE[0],enterprise_initial:ENTERPRISE_IMPACT.IMPACT_MEDIUM[0],label:"Enterprise impact / risk",usage:{},help_text:x$1` + <b>Low Risk:</b> Important for Admin Awareness. Negligible disruption, but + provides value (new APIs, optional features, strictly additive) or + requires minor internal documentation updates. Select this to ensure the + feature is published in the Release Notes. + <br /> + <b>Med Risk:</b>Noticeable impact. Potential to alter some workflows or + cause minor confusion/help desk calls. Admins may want to review and set a + policy. An escape hatch is often recommended. + <br /> + <b>High Risk:</b> Significant disruption. Intentional "breaking changes" + or major new functionality that will require mandatory preparation, + testing, and communication from IT admins. Requires an escape hatch or + permanent policy. + `},rollout_milestone:{type:"input",attrs:{...MILESTONE_NUMBER_FIELD_ATTRS,min:100},required:!0,label:"Chrome milestone",usage:{},help_text:x$1` The milestone in which this stage rolls out to the stable + channel (even a 1% rollout). If you don't yet know which milestone it will + be, put in your best estimate. You can always change this later.`},rollout_platforms:{type:"multiselect",choices:PLATFORM_CATEGORIES,required:!0,label:"Rollout platforms",usage:{},help_text:x$1` The platform(s) affected by this stage`},rollout_details:{type:"textarea",always_markdown:!0,attrs:{rows:4},required:!1,label:"Rollout details (optional)",usage:{},help_text:x$1` Explain what specifically is changing in this milestone, + for the given platforms. Many features are composed of multiple stages on + different milestones. For example, you may have a stage that introduces a + change and a temporary policy to control it, then another stage on a + subsequent milestone that removes the policy. Alternatively, you may ship + the feature to different platforms in different milestones.`},rollout_stage_plan:{type:"select",choices:ROLLOUT_STAGE_PLAN_CATEGORIES,initial:ROLLOUT_STAGE_PLAN_CATEGORIES.ROLLOUT_STAGE_PLAN_SLOW[0],required:!0,label:"Rollout plan",usage:{},help_text:x$1` Select the type of rollout that matches what will happen in + the stage`},breaking_change:{type:"checkbox",label:"Breaking change",initial:!1,usage:{},help_text:x$1` This is a breaking change: customers or developers must + take action to continue using some existing functionaity.`},confidential:{type:"checkbox",label:"Confidential",initial:!0,usage:{},help_text:x$1`Most enterprise feature entries should be marked + confidential until they have been reviewed for publication. Confidential + entrys are only visible to admins, chromium contributors and the feature's + owners, contributors and creator.`},intent_cc_emails:{type:"input",attrs:MULTI_EMAIL_FIELD_ATTRS,required:!1,label:"Intent email CC list",usage:{},help_text:x$1`Add emails to the CC list of the intent email.<br /> + Comma separated list of full email addresses.`}};function categorizeFieldType(field){if(field.attrs===MULTI_URL_FIELD_ATTRS)return"multi-url";return field.attrs===URL_FIELD_ATTRS?"url":"checkbox"===field.type?"checkbox":"text"}function makeHumanReadable(fieldName){return fieldName=fieldName.replace("_"," "),fieldName.charAt(0).toUpperCase()+fieldName.slice(1)}function makeDisplaySpec(fieldName){const fieldProps=ALL_FIELDS[fieldName],displayName=fieldProps.label||fieldProps.displayLabel||makeHumanReadable(fieldName),fieldType=categorizeFieldType(fieldProps),deprecated=fieldProps.deprecated,alwaysMarkdown=fieldProps.always_markdown;return[fieldName,displayName,fieldType,deprecated,alwaysMarkdown]}function makeDisplaySpecs(fieldNames){return fieldNames.map(fieldName=>makeDisplaySpec(fieldName))}function findMinMilestone(fieldName,stageTypes,getFieldValue){let minMilestone=1/0;const feature=getFieldValue.feature;for(const stage of feature.stages)if(stageTypes.has(stage.stage_type)){const milestone=getFieldValue(fieldName,stage);null!=milestone&&""!==milestone&&(minMilestone=Math.min(minMilestone,milestone))}return minMilestone===1/0?void 0:minMilestone}function findMaxMilestone(fieldName,stageTypes,getFieldValue){let maxMilestone=-Infinity;const feature=getFieldValue.feature;for(const stage of feature.stages)if(stageTypes.has(stage.stage_type)){const milestone=getFieldValue(fieldName,stage);null!=milestone&&""!==milestone&&(maxMilestone=Math.max(maxMilestone,milestone))}return maxMilestone===-Infinity?void 0:maxMilestone}function checkEarlierBeforeAllLaterMilestones(fieldPair,getFieldValue){const{earlier,allLater,warning}=fieldPair,stageTypes=allLater&&SHIPPED_MILESTONE_FIELDS.has(allLater)?STAGE_TYPES_SHIPPING:null,earlierValue=getNumericValue(earlier,getFieldValue);if(stageTypes&&allLater){const laterValue=findMinMilestone(allLater,stageTypes,getFieldValue);if(null!=earlierValue&&null!=laterValue&&+earlierValue>=laterValue)return warning?{warning}:{error:`Earlier milestone #${earlierValue} should be before shipped milestone #${laterValue}.`}}}function checkAllEarlierBeforeLaterMilestone(fieldPair,getFieldValue){const{allEarlier,later,warning,error}=fieldPair,stageTypes=allEarlier&&OT_MILESTONE_START_FIELDS.has(allEarlier)?STAGE_TYPES_ORIGIN_TRIAL:allEarlier&&DT_MILESTONE_FIELDS.has(allEarlier)?STAGE_TYPES_DEV_TRIAL:null;if(stageTypes&&allEarlier){const earlierValue=findMaxMilestone(allEarlier,stageTypes,getFieldValue),laterValue=getNumericValue(later,getFieldValue);if(null!=earlierValue&&null!=laterValue&&earlierValue>=+laterValue)return warning?{warning}:{error:error||`Earlier milestone #${earlierValue} should be before shipped milestone #${laterValue}.`}}}function getNumericValue(name,getFieldValue){const value=getFieldValue(name,"current stage");return"string"==typeof value?""===value?void 0:+value:value}function checkMilestoneRanges(ranges,getFieldValue){let result;for(const range of ranges){const{earlier,allEarlier,later,allLater,warning,error}=range;if(allLater)result=checkEarlierBeforeAllLaterMilestones(range,getFieldValue);else if(allEarlier)result=checkAllEarlierBeforeLaterMilestone(range,getFieldValue);else{const earlierMilestone=getNumericValue(earlier,getFieldValue),laterMilestone=getNumericValue(later,getFieldValue);null!=earlierMilestone&&null!=laterMilestone&&laterMilestone<=earlierMilestone&&(result=warning?{warning}:{error:error||"Start milestone must be before end milestone"})}if(result)return result}}function checkFeatureNameAndType(getFieldValue){const name=((getFieldValue("name")||"")+"").toLowerCase(),featureType=+(getFieldValue("feature_type")||"0"),isdeprecationName=name.includes("deprecat")||name.includes("remov"),isdeprecationType=featureType===FEATURE_TYPES.FEATURE_TYPE_DEPRECATION_ID[0];if(isdeprecationName!==isdeprecationType)return isdeprecationName?{warning:`If the feature name contains "deprecate" or "remove", + the feature type should be "Feature deprecation"`}:{warning:`If the feature type is "Feature deprecation", + the feature name should contain "deprecate" or "remove"`}}async function checkFirstEnterpriseNotice(value,initialValue){if(!value)return;const newChannelStableDate=await window.csClient.getSpecifiedChannels(value,value).then(channels=>channels[value]?.stable_date),previousChannelStableDate=initialValue?await window.csClient.getSpecifiedChannels(initialValue,initialValue).then(channels=>channels[value]?.stable_date):void 0;return newChannelStableDate?previousChannelStableDate&&Date.parse(previousChannelStableDate)<Date.now()?{warning:`Feature was already shown in milestone ${initialValue}, this cannot be changed`}:Date.parse(newChannelStableDate)<=Date.now()?{warning:`Milestone ${value} was already released, choose a future milestone`}:void 0:{error:`Unknown milestone ${value}`}}async function checkExtensionMilestoneIsValid(value){if("number"==typeof value&&isNaN(value))return{error:"Invalid milestone format."};for(let i=0;i<value.length;i++)if("0">value[i]||"9"<value[i])return{error:"Invalid milestone format."};const intValue=parseInt(value);if(1e3<=intValue)return{error:"Milestone is too distant."};const resp=await fetch("https://chromiumdash.appspot.com/fetch_milestone_schedule"),json=await resp.json();return parseInt(json.mstones[0].mstone)>intValue?{error:"End milestone cannot be in the past."}:void 0}function checkNotGoogleDocs(value,warning="Avoid using Google Docs"){return /docs\.google\.com\/document/.test(value)?{warning}:void 0}var __decorate$S=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const GATE_STATE_TO_NAME={0:"Preparing",1:"Not applicable",2:"Pending",3:"Pending",4:"Needs work",5:"Approved",6:"Denied",8:"Internal review",9:"N/A requested",10:"N/A (self-certified)",11:"N/A (self-certified then verified)"},GATE_STATE_TO_ICON={0:"arrow_circle_right_20px",2:"pending_20px",3:"pending_20px",4:"autorenew_20px",5:"check_circle_filled_20px",6:"block_20px"},GATE_STATE_TO_ABBREV={1:"N/A",8:"INT",9:"N/A?",10:"N/A (self)",11:"N/A (ver)"};let ChromedashGateChip=class ChromedashGateChip extends i$4{constructor(){super(...arguments),this.selectedGateId=0}static get styles(){return[...SHARED_STYLES,i$7` + sl-icon { + font-size: 1.2rem; + } + + sl-button::part(label) { + padding: 0 4px; + } + + sl-button::part(suffix) { + padding-right: 4px; + } + + sl-button::part(base) { + border: var(--chip-border); + padding: 0 0 0 4px; + align-items: center; + } + + sl-button.selected::part(base) { + box-shadow: 0 0 0 2px var(--dark-spot-color); + } + + sl-button:hover .teamname { + text-decoration: underline; + } + + sl-button.not_applicable::part(base), + sl-button.na_self-certified::part(base) { + background: var(--gate-not-applicable-background); + color: var(--gate-not-applicable-color); + } + sl-button.na_self-certified_then_verified::part(base) { + background: var(--gate-not-applicable-background); + color: var(--gate-not-applicable-color); + } + sl-button.not_applicable::part(prefix), + sl-button.na_self-certified::part(prefix) { + align-items: baseline; + } + + sl-button.preparing::part(base) { + background: var(--gate-preparing-background); + color: var(--gate-preparing-color); + } + .preparing sl-icon { + color: var(--gate-preparing-icon-color); + } + + sl-button.pending::part(base) { + background: var(--gate-pending-background); + color: var(--gate-pending-color); + } + .pending sl-icon { + color: var(--gate-pending-icon-color); + } + + sl-button.needs_work::part(base) { + background: var(--gate-needs-work-background); + color: var(--gate-needs-work-color); + } + .needs_work sl-icon { + color: var(--gate-needs-work-icon-color); + } + + sl-button.approved::part(base) { + background: var(--gate-approved-background); + color: var(--gate-approved-color); + } + .approved sl-icon { + color: var(--gate-approved-icon-color); + } + + sl-button.denied::part(base) { + background: var(--gate-denied-background); + color: var(--gate-denied-color); + } + .denied sl-icon { + color: var(--gate-denied-icon-color); + } + + sl-button.internal_review::part(base) { + background: var(--gate-pending-background); + color: var(--gate-pending-color); + } + sl-button.internal_review::part(prefix) { + align-items: baseline; + } + + sl-button.na_requested::part(base) { + background: var(--gate-pending-background); + color: var(--gate-pending-color); + } + sl-button.na_requested::part(prefix) { + align-items: baseline; + } + + .abbrev { + padding-left: var(--content-padding-quarter); + font-weight: 900; + } + + sl-button sl-icon.overdue { + color: var(--slo-overdue-color); + } + `]}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}handleClick(){updateURLParams("gate",this.gate.id),this._fireEvent("show-gate-column",{feature:this.feature,stage:this.stage,gate:this.gate})}render(){if(this.gate===void 0||null==this.gate)return E$1;const teamName=this.gate.team_name,stateName=GATE_STATE_TO_NAME[this.gate.state],className=stateName.toLowerCase().replaceAll(" ","_").replaceAll("(","").replaceAll(")","").replaceAll("/",""),selected=this.gate.id==this.selectedGateId?"selected":"",statusIconName=GATE_STATE_TO_ICON[this.gate.state],abbrev=GATE_STATE_TO_ABBREV[this.gate.state]||stateName;let statusIcon=x$1`<b class="abbrev" slot="prefix">${abbrev}</b>`;statusIconName&&(statusIcon=x$1` + <sl-icon + slot="prefix" + library="material" + name=${statusIconName} + ></sl-icon> + `);const overdue=0>this.gate.slo_initial_response_remaining,overdueIcon=overdue?x$1`<sl-icon + slot="suffix" + library="material" + class="overdue" + name="clock_loader_60_20px" + ></sl-icon>`:E$1,overdueTitle=overdue?". Overdue.":"";return x$1` + <sl-button + pill + size="small" + class="${className} ${selected}" + title="${teamName}: ${stateName}${overdueTitle}" + @click=${this.handleClick} + > + ${statusIcon} + <span class="teamname">${teamName}</span> + ${overdueIcon} + </sl-button> + `}};__decorate$S([n$5({type:Object})],ChromedashGateChip.prototype,"feature",void 0),__decorate$S([n$5({type:Object})],ChromedashGateChip.prototype,"stage",void 0),__decorate$S([n$5({type:Object})],ChromedashGateChip.prototype,"gate",void 0),__decorate$S([n$5({type:Number})],ChromedashGateChip.prototype,"selectedGateId",void 0),ChromedashGateChip=__decorate$S([t$3("chromedash-gate-chip")],ChromedashGateChip);var __decorate$R=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashWPTEvalButton=class ChromedashWPTEvalButton extends i$4{constructor(){super(...arguments),this.featureId=0}static{this.styles=i$7` + :host { + display: inline-block; + } + + .gemini-icon { + width: 1.5em; + height: 1.5em; + transform-origin: center center; + transition: transform 0.7s ease-in-out; + } + + sl-button:hover .gemini-icon { + transform: rotate(360deg); + } + `}render(){return x$1` + <sl-button href="/feature/${this.featureId}/ai-coverage-evaluation"> + <img + slot="prefix" + class="gemini-icon" + src="https://www.gstatic.com/images/branding/productlogos/gemini_2025/v1/192px.svg" + alt="Gemini AI Logo" + /> + Evaluate test coverage + </sl-button> + `}};__decorate$R([n$5({type:Number})],ChromedashWPTEvalButton.prototype,"featureId",void 0),ChromedashWPTEvalButton=__decorate$R([t$3("chromedash-wpt-eval-button")],ChromedashWPTEvalButton);var __decorate$Q=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const DETAILS_STYLES=[i$7` + sl-details { + border: var(--card-border); + box-shadow: var(--card-box-shadow); + margin: var(--content-padding-half); + border-radius: 4px; + background: var(--card-background); + } + sl-details::part(base), + sl-details::part(header) { + background: transparent; + } + sl-details::part(header) { + padding-bottom: 8px; + } + + .card { + background: var(--card-background); + max-width: var(--max-content-width); + padding: 16px; + } + `],LONG_TEXT=60;class ChromedashFeatureDetail extends i$4{constructor(){super(...arguments),this.appTitle="",this.canEdit=!1,this.selectedGateId=0,this.anyCollapsed=!0,this.openStage=0,this.previousStageTypeRendered=0,this.sameTypeRendered=0}static get styles(){const ICON_WIDTH=18,GAP=10,CONTENT_PADDING=16;return[...SHARED_STYLES,...DETAILS_STYLES,i$7` + :host { + display: block; + position: relative; + box-sizing: border-box; + contain: content; + overflow: hidden; + background: inherit; + } + + h2 { + margin-top: var(--content-padding); + display: flex; + } + h2 span { + flex: 1; + } + + .description, + .gates { + padding: 8px 16px; + } + + sl-details sl-button, + sl-details sl-dropdown { + float: right; + margin-right: 4px; + } + sl-details sl-dropdown sl-icon-button { + font-size: 1.4rem; + } + + sl-details sl-button[variant='default']::part(base) { + color: var(--sl-color-primary-600); + border: 1px solid var(--sl-color-primary-600); + } + + dl { + padding: 0 var(--content-padding-half); + } + + dt { + font-weight: 500; + display: flex; + gap: ${GAP}px; + align-items: center; + } + dt sl-icon { + color: var(--gate-approved-color); + font-size: 1.3em; + } + + dd { + padding: var(--content-padding-half); + padding-left: ${18+GAP+CONTENT_PADDING}px; + padding-bottom: var(--content-padding-large); + } + + .inline-list { + display: inline-block; + padding: 0; + } + + .longtext { + display: block; + white-space: pre-wrap; + } + + .longurl { + display: block; + padding: var(--content-padding-half); + } + + #new-stage { + margin-left: 8px; + margin-bottom: 4px; + } + + #footnote { + margin-left: 8px; + margin-bottom: 4px; + margin-top: 4px; + } + `]}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}connectedCallback(){super.connectedCallback(),this.intializeGateColumn()}initializeExtensionDialog(rawQuery){if(!("initiateExtension"in rawQuery))return;const gateId=parseInt(rawQuery.gate),extensionGate=this.gates.find(g=>g.id===gateId);if(!extensionGate||!GATE_APPROVED_REVIEW_STATES.includes(extensionGate.state))return;let extensionStage;for(const stage of this.feature.stages){const foundStage=stage.extensions.find(s=>s.id===extensionGate.stage_id);if(foundStage){extensionStage=foundStage;break}}extensionStage&&extensionStage.ot_action_requested&&openFinalizeExtensionDialog(this.feature.id,extensionStage,extensionStage.desktop_last,dialogTypes.FINALIZE_EXTENSION)}intializeGateColumn(){const rawQuery=parseRawQuery(window.location.search);if(!rawQuery.hasOwnProperty("gate"))return;const gateVal=+rawQuery.gate,foundGates=this.gates.filter(g=>g.id==gateVal);if(!foundGates.length)return;const gate=foundGates[0],foundStages=this.feature.stages.filter(s=>s.id===gate.stage_id||s.extensions.some(e=>e.id===gate.stage_id));if(!foundStages.length)return;let stage=foundStages[0];this.openStage=stage.id,gate.gate_type===GATE_TYPES.API_EXTEND_ORIGIN_TRIAL&&(stage=stage.extensions.find(e=>e.id===gate.stage_id)),this._fireEvent("show-gate-column",{feature:this.feature,stage:stage,gate:gate}),this.initializeExtensionDialog(rawQuery)}isAnyCollapsed(){const sections=this.renderRoot.querySelectorAll(".stage"),open=this.renderRoot.querySelectorAll(".stage[open]");return open.length<sections.length}updateCollapsed(){this.anyCollapsed=this.isAnyCollapsed()}toggleAll(){const shouldOpen=this.anyCollapsed;this.renderRoot.querySelectorAll(".stage").forEach(el=>{el.open=shouldOpen})}handleAddXfnGates(feStage){const prompt="Would you like to add gates for Privacy, Security, etc.? \n\nThis is needed if the API Owners ask you to add them, or if you send an \"Intent to Ship\" rather than a PSA.";confirm("Would you like to add gates for Privacy, Security, etc.? \n\nThis is needed if the API Owners ask you to add them, or if you send an \"Intent to Ship\" rather than a PSA.")&&window.csClient.addXfnGates(feStage.feature_id,feStage.id).then(()=>{this._fireEvent("refetch-needed",{})})}renderControls(){const editAllButton=x$1` + <sl-button variant="text" href="/guide/editall/${this.feature.id}"> + Edit all fields + </sl-button> + `,toggleLabel=this.anyCollapsed?"Expand all":"Collapse all";return x$1` + <!-- Enterprise features don't provide spec URLs or Web Platform Tests info. --> + ${this.canEdit&&this.feature.feature_type_int!==FEATURE_TYPES.FEATURE_TYPE_ENTERPRISE_ID[0]?E$1:E$1} + ${this.canEdit?editAllButton:E$1} + <sl-button + variant="text" + title="Expand or collapse all sections" + @click=${this.toggleAll} + > + ${toggleLabel} + </sl-button> + `}renderText(value,isMarkdown=!1){value=value+"";const markup=autolink(value,this.featureLinks,isMarkdown);return isMarkdown?x$1`${markup}`:value.length>LONG_TEXT||value.includes("\n")?x$1`<span class="longtext">${markup}</span>`:x$1`<span class="text">${markup}</span>`}renderUrl(value){return value.startsWith("http")?x$1`<chromedash-link + href=${value} + class="url ${value.length>LONG_TEXT?"longurl":""}" + .featureLinks=${this.featureLinks} + ></chromedash-link>`:this.renderText(value)}renderValue(fieldType,value,isMarkdown){if("checkbox"==fieldType)return this.renderText(value?"True":"False");return"url"==fieldType?this.renderUrl(value):"multi-url"==fieldType?x$1` + <ul class="inline-list"> + ${value.map(url=>x$1`<li>${this.renderUrl(url)}</li>`)} + </ul> + `:this.renderText(value,isMarkdown)}renderField(fieldDef,feStage){const[fieldId,fieldDisplayName,fieldType,deprecated,alwaysMarkdown]=fieldDef,value=getFieldValueFromFeature(fieldId,feStage,this.feature),isDefined=isDefinedValue(value);if(!isDefined&&deprecated)return E$1;const isMarkdown=(this.feature.markdown_fields||[]).includes(fieldId)||alwaysMarkdown,icon=isDefined?x$1`<sl-icon library="material" name="check_circle_20px"></sl-icon>`:x$1`<sl-icon library="material" name="blank_20px"></sl-icon>`;return x$1` + <dt id=${fieldId}>${icon} ${fieldDisplayName}</dt> + <dd> + ${isDefined?this.renderValue(fieldType,value,isMarkdown):x$1`<i>No information provided yet</i>`} + </dd> + `}stageHasAnyFilledFields(fields,feStage){return fields.some(fieldDef=>hasFieldValue(fieldDef[0],feStage,this.feature))}renderExtensionFields(extensionStages){const extensionFields=[],fieldNames=flattenSections(FLAT_TRIAL_EXTENSION_FIELDS),fields=makeDisplaySpecs(fieldNames);return extensionStages.forEach((extensionStage,i)=>{this.stageHasAnyFilledFields(fields,extensionStage)&&extensionFields.push(x$1` + <div> + <h3>Trial extension ${0===i?E$1:i+1}</h3> + <br /> + ${fields.map(fieldDef=>this.renderField(fieldDef,extensionStage))} + </div> + `)}),extensionFields}renderSectionFields(fields,feStage){if(this.stageHasAnyFilledFields(fields,feStage)){const extensionFields=feStage.extensions?this.renderExtensionFields(feStage.extensions):[];return x$1` <dl> + ${fields.map(fieldDef=>this.renderField(fieldDef,feStage))} + ${extensionFields} + </dl>`}return x$1`<p>No relevant fields have been filled in.</p>`}renderSection(summary,content,isActive=!1,defaultOpen=!1,isStage=!0){return x$1` + <sl-details + summary=${summary} + @sl-after-show=${this.updateCollapsed} + @sl-after-hide=${this.updateCollapsed} + ?open=${isActive||defaultOpen} + class="${isStage?"stage":""}" + > + ${content} + </sl-details> + `}getStageForm(stageType){return FORMS_BY_STAGE_TYPE[stageType]||null}renderMetadataSection(){const fieldNames=flattenSections(this.feature.is_enterprise_feature?FLAT_ENTERPRISE_METADATA_FIELDS:FLAT_METADATA_FIELDS);if(fieldNames===void 0||0===fieldNames.length)return E$1;const fields=makeDisplaySpecs(fieldNames),editButton=x$1` + <sl-button + size="small" + style="float:right" + href="/guide/stage/${this.feature.id}/metadata" + >Edit fields</sl-button + > + `,content=x$1` + <p class="description">${this.canEdit?editButton:E$1}</p> + <section class="card">${this.renderSectionFields(fields,{})}</section> + `;return this.renderSection("Metadata",content,!1,this.feature.is_enterprise_feature,!1)}renderGateChip(feStage,gate){return x$1` + <chromedash-gate-chip + .feature=${this.feature} + .stage=${feStage} + .gate=${gate} + selectedGateId=${this.selectedGateId} + > + </chromedash-gate-chip> + `}hasActiveGates(feStage){const gatesForStage=this.gates.filter(g=>g.stage_id==feStage.id);return gatesForStage.some(g=>GATE_ACTIVE_REVIEW_STATES.includes(g.state))}hasMixedGates(feStage){const gatesForStage=this.gates.filter(g=>g.stage_id==feStage.id);return gatesForStage.some(g=>GATE_FINISHED_REVIEW_STATES.includes(g.state))&&gatesForStage.some(g=>GATE_PREPARING==g.state)}renderGateChips(feStage){const gatesForStage=this.gates.filter(g=>(this.feature.feature_type_int!==FEATURE_TYPES.FEATURE_TYPE_CODE_CHANGE_ID[0]||g.gate_type!==GATE_TYPES.API_SHIP)&&g.stage_id===feStage.id);return gatesForStage.sort((g1,g2)=>GATE_TEAM_ORDER.indexOf(g1.team_name)-GATE_TEAM_ORDER.indexOf(g2.team_name)),gatesForStage.map(g=>this.renderGateChip(feStage,g))}hasStageActions(stage,feStage){if(0<stage?.actions?.length&&this.feature.feature_type_int===FEATURE_TYPES.FEATURE_TYPE_CODE_CHANGE_ID[0])return!0;const hasOwnersGate=this.gates.some(g=>"API Owners"===g.team_name&&g.stage_id===feStage.id);return!(!(0<stage?.actions?.length)||hasOwnersGate)}renderStageAction(action,stage,feStage){const label=action.name,url=action.url.replace("{feature_id}",this.feature.id).replace("{stage_id}",feStage.id).replace("{gate_id}","0"),gatesForStage=this.gates.filter(g=>g.stage_id==feStage.id),checkCompletion=()=>{if(somePendingPrereqs(action,this.progress)||somePendingGates(gatesForStage,feStage))return void openPreflightDialog(this.feature,this.progress,this.process,action,stage,feStage,gatesForStage,url);else{const draftWindow=window.open(url,"_blank");draftWindow?.focus()}};return x$1` + <sl-button size="small" @click=${checkCompletion}>${label}</sl-button> + `}renderStageActions(stage,feStage){return this.canEdit?x$1` + ${stage.actions.map(act=>this.renderStageAction(act,stage,feStage))} + `:E$1}renderProcessStage(feStage){const stageForm=this.getStageForm(feStage.stage_type),fieldNames=null===stageForm?[]:flattenSections(stageForm);if(fieldNames===void 0||0==fieldNames.length)return E$1;const fields=makeDisplaySpecs(fieldNames),processStage=findProcessStage(feStage,this.process);if(!processStage)return E$1;let numberDifferentiation="";this.previousStageTypeRendered===feStage.stage_type?(this.sameTypeRendered+=1,numberDifferentiation=` ${this.sameTypeRendered}`):(this.previousStageTypeRendered=feStage.stage_type,this.sameTypeRendered=1);let name=`${processStage.name}${numberDifferentiation}`;feStage.display_name&&(name=`${processStage.name}: ${feStage.display_name}`);const isActive=this.feature.active_stage_id===feStage.id,stageMenu=this.renderStageMenu(feStage),addExtensionButton=this.renderExtensionButton(feStage),editButton=this.renderEditButton(feStage,processStage),trialButton=this.renderOriginTrialButton(feStage),registrantsDashboardButton=this.renderRegistrantsDashboardButton(feStage),extensionGateChips=feStage.extensions?.map(extension=>x$1` <div class="gates"> + ${STAGE_SHORT_NAMES[extension.stage_type]}: + ${this.renderGateChips(extension)} + </div>`);let gatesPrefix="";0<extensionGateChips.length&&(gatesPrefix=`${STAGE_SHORT_NAMES[feStage.stage_type]}: `);const content=x$1` + <p class="description"> + ${stageMenu} ${trialButton} ${registrantsDashboardButton} + ${this.hasStageActions(processStage,feStage)?this.renderStageActions(processStage,feStage):E$1} + ${editButton} ${addExtensionButton} ${processStage.description} + </p> + <div class="gates">${gatesPrefix}${this.renderGateChips(feStage)}</div> + ${extensionGateChips} + <section class="card"> + ${this.renderSectionFields(fields,feStage)} + </section> + `,defaultOpen=this.feature.is_enterprise_feature||feStage.id==this.openStage||this.hasActiveGates(feStage)||this.hasMixedGates(feStage);return this.renderSection(name,content,isActive,defaultOpen)}renderEditButton(feStage,processStage){return this.canEdit?x$1` <sl-button + size="small" + href="/guide/stage/${this.feature.id}/${processStage.outgoing_stage}/${feStage.id}" + >Edit fields</sl-button + >`:E$1}renderFinalizeExtensionButton(extensionStage){return x$1` <sl-button + size="small" + variant="primary" + @click=${()=>openFinalizeExtensionDialog(this.feature.id,extensionStage,extensionStage.desktop_last,dialogTypes.FINALIZE_EXTENSION)} + >Finalize Extension</sl-button + >`}renderDisabledExtensionButton(){const tooltipText="A pending extension request exists. Follow the process for obtaining extension approval, or contact origin-trials-support@google.com for help.";return x$1` <sl-tooltip content=${"A pending extension request exists. Follow the process for obtaining extension approval, or contact origin-trials-support@google.com for help."}> + <sl-button size="small" disabled>Trial Extension Pending</sl-button> + </sl-tooltip>`}renderExtensionButton(feStage){const userCannotViewOTControls=!this.user||!this.user.email.endsWith("@chromium.org")&&!this.user.email.endsWith("@google.com"),isNotOriginTrialStage=!STAGE_TYPES_ORIGIN_TRIAL.has(feStage.stage_type),originTrialNotCreatedYet=!feStage.origin_trial_id;if(userCannotViewOTControls||isNotOriginTrialStage||originTrialNotCreatedYet)return E$1;const extensionReadyForFinalize=feStage.extensions.find(e=>{const extensionGate=this.gates.find(g=>g.stage_id===e.id);return e.ot_action_requested&&extensionGate&&GATE_APPROVED_REVIEW_STATES.includes(extensionGate.state)});if(extensionReadyForFinalize)return this.renderFinalizeExtensionButton(extensionReadyForFinalize);const extensionInProgress=feStage.extensions&&feStage.extensions.some(e=>e.ot_action_requested);if(extensionInProgress)return this.renderDisabledExtensionButton();let extensionButtonText="Request a trial extension";feStage.extensions&&0<feStage.extensions.length&&(extensionButtonText="Request another trial extension");const stageId=feStage.id;return x$1` <sl-button + size="small" + @click=${()=>location.assign(`/ot_extension_request/${this.feature.id}/${stageId}`)} + >${extensionButtonText}</sl-button + >`}renderOriginTrialButton(feStage){if(!STAGE_TYPES_ORIGIN_TRIAL.has(feStage.stage_type))return E$1;if(feStage.origin_trial_id){let originTrialsURL=`https://origintrials-staging.corp.google.com/origintrials/#/view_trial/${feStage.origin_trial_id}`;return"Chrome Platform Status"===this.appTitle&&(originTrialsURL=`https://developer.chrome.com/origintrials/#/view_trial/${feStage.origin_trial_id}`),x$1` <sl-button + size="small" + variant="primary" + href=${originTrialsURL} + target="_blank" + >View Origin Trial</sl-button + >`}const canSeeOTControls=this.user&&(this.user.email.endsWith("@chromium.org")||this.user.email.endsWith("@google.com"));if(!canSeeOTControls)return E$1;const trialIsApproved=this.gates.every(g=>g.stage_id!==feStage.id||GATE_APPROVED_REVIEW_STATES.includes(g.state));if(feStage.ot_setup_status&&feStage.ot_setup_status!==OT_SETUP_STATUS_OPTIONS.OT_NOT_CREATED)return x$1` <sl-tooltip + content="Action already requested. For further inquiries, contact origin-trials-support@google.com." + > + <sl-button size="small" variant="primary" disabled + >Request Trial Creation</sl-button + > + </sl-tooltip>`;return trialIsApproved?x$1` <sl-button + size="small" + variant="primary" + @click="${()=>openPrereqsDialog(this.feature.id,feStage,dialogTypes.CREATION)}" + >Request Trial Creation</sl-button + >`:x$1` <sl-tooltip + content="Approvals must be obtained before submission. For questions, contact origin-trials-support@google.com." + > + <sl-button size="small" variant="primary" disabled + >Request Trial Creation</sl-button + > + </sl-tooltip>`}renderRegistrantsDashboardButton(feStage){return STAGE_TYPES_ORIGIN_TRIAL.has(feStage.stage_type)&&this.canEdit&&feStage.origin_trial_id?this.user&&(this.user.email.endsWith("@chromium.org")||this.user.email.endsWith("@google.com"))?x$1` <sl-button + size="small" + style="float:right" + href="http://go/ot-registrants-dashboard?f=trial_id:in:${feStage.origin_trial_id}" + >Registrant data</sl-button + >`:E$1:E$1}offerAddXfnGates(feStage){const stageGates=this.gates.filter(g=>g.stage_id==feStage.id);return feStage.stage_type==STAGE_PSA_SHIPPING&&6>stageGates.length}renderFootnote(){return x$1` + <section id="footnote"> + Please see the + <a + href="https://www.chromium.org/blink/launching-features" + target="_blank" + rel="noopener" + > + Launching features + </a> + page for process instructions. + </section> + `}renderStageMenu(feStage){const items=[];return this.offerAddXfnGates(feStage)&&items.push(x$1` + <sl-menu-item @click=${()=>this.handleAddXfnGates(feStage)}> + Add cross-functional gates + </sl-menu-item> + `),0===items.length?E$1:x$1` + <sl-dropdown> + <sl-icon-button + library="material" + name="more_vert_24px" + label="Stage menu" + slot="trigger" + ></sl-icon-button> + <sl-menu>${items}</sl-menu> + </sl-dropdown> + `}renderAddStageButton(){if(!this.canEdit)return E$1;const text=this.feature.is_enterprise_feature?"Add Step":"Add Stage";return x$1` <sl-button + id="new-stage" + size="small" + @click="${()=>openAddStageDialog(this.feature.id,this.feature.feature_type_int)}" + > + ${text} + </sl-button>`}renderSectionHeader(){const text=this.feature.is_enterprise_feature?"Rollout steps":"Development stages";return x$1` <span + >${text} + <sl-icon-button + name="info-circle" + href="https://www.chromium.org/blink/launching-features" + style="font-size: 0.8rem;" + target="_blank" + label="Launching feature guide" + > + </sl-icon-button> + </span>`}render(){return x$1` + ${this.renderMetadataSection()} + <h2>${this.renderSectionHeader()} ${this.renderControls()}</h2> + ${this.feature.stages.map(feStage=>this.renderProcessStage(feStage))} + ${this.renderAddStageButton()} ${this.renderFootnote()} + `}}__decorate$Q([n$5({type:String})],ChromedashFeatureDetail.prototype,"appTitle",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"featureLinks",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"user",void 0),__decorate$Q([n$5({type:Boolean})],ChromedashFeatureDetail.prototype,"canEdit",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"feature",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"gates",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"process",void 0),__decorate$Q([n$5({attribute:!1})],ChromedashFeatureDetail.prototype,"progress",void 0),__decorate$Q([n$5({type:Number})],ChromedashFeatureDetail.prototype,"selectedGateId",void 0),__decorate$Q([r$6()],ChromedashFeatureDetail.prototype,"anyCollapsed",void 0),__decorate$Q([r$6()],ChromedashFeatureDetail.prototype,"openStage",void 0),__decorate$Q([r$6()],ChromedashFeatureDetail.prototype,"previousStageTypeRendered",void 0),__decorate$Q([r$6()],ChromedashFeatureDetail.prototype,"sameTypeRendered",void 0),customElements.define("chromedash-feature-detail",ChromedashFeatureDetail);var __decorate$P=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGantt=class ChromedashGantt extends i$4{static get styles(){return[...SHARED_STYLES,i$7` + :host { + width: 600px; + } + ul { + padding: 0; + } + + label { + display: block; + font-weight: 500; + margin-right: 5px; + padding-top: var(--content-padding); + } + + .platform-row { + margin: var(--content-padding) 0; + list-style: none; + } + + .platform { + display: inline-block; + padding-top: 7px; + vertical-align: top; + width: 100px; + } + + /* On small displays, show milestones as a bullet list. */ + .chart li { + margin-left: var(--content-padding); + } + + .empty { + display: none; + } + + /* On large displays, show milestones as a gantt chart. */ + @media only screen and (min-width: 701px) { + .chart { + display: inline-grid; + grid-auto-columns: 50px; + grid-auto-rows: 30px; + gap: 2px; + } + + .chart li { + list-style: none; + margin-left: 0; + height: 30px; + overflow: visible; + white-space: nowrap; + padding: 4px; + line-height: 22px; + } + + .empty { + display: block; + background: #eee; + } + + .chart .dev_trial { + background: #cfe2f3ff; + } + + .chart .origin_trial { + background: #6fa8dcff; + } + + .chart .shipping { + background: #0b5394ff; + color: white; + } + } + `]}_isInactive(){const status=this.feature.browsers.chrome.status.text;return"No active development"===status||"On hold"===status||"No longer pursuing"===status}renderChartRow(gridRow,first,last,sortedMilestones,cssClass,label){var _Mathmax4=Math.max;const cellsOnRow=[];for(let col=0;col<sortedMilestones.length;col++){const m=sortedMilestones[col];(m<first||m>last)&&cellsOnRow.push(x$1` + <li + style="grid-row: ${gridRow}; + grid-column: ${col+1}" + class="empty" + ></li> + `)}const firstCol=sortedMilestones.indexOf(first),lastCol=sortedMilestones.indexOf(last),span=_Mathmax4(0,lastCol-firstCol)+1;return cellsOnRow.push(x$1` + <li + style="grid-row: ${gridRow}; + grid-column: ${firstCol+1} / span ${span}" + class="${cssClass}" + > + ${label} + </li> + `),cellsOnRow}getByStageType(){const dtStages=[],otStages=[],shipStages=[];for(const stage of this.feature.stages)STAGE_TYPES_DEV_TRIAL.has(stage.stage_type)?dtStages.push(stage):STAGE_TYPES_ORIGIN_TRIAL.has(stage.stage_type)?otStages.push(stage):STAGE_TYPES_SHIPPING.has(stage.stage_type)&&shipStages.push(stage);return[dtStages,otStages,shipStages]}renderPlatform(platform,platformParam,dtStages,otStages,shipStages,sortedMilestones){var _Mathmax5=Math.max;const dtStartMilestones=dtStages.map(s=>s[`${platformParam}_first`]),otStartMilestones=otStages.map(s=>s[`${platformParam}_first`]),otEndMilestones=otStages.map(s=>{let maxEnd=s[`${platformParam}_last`];for(const e of s.extensions)e.desktop_last&&!maxEnd?maxEnd=e.desktop_last:e.desktop_last&&maxEnd&&(maxEnd=_Mathmax5(maxEnd,e.desktop_last));return maxEnd}),shipStartMilestones=shipStages.map(s=>s[`${platformParam}_first`]);if(0===dtStartMilestones.length&&0===otStartMilestones.length&&0===shipStartMilestones.length)return E$1;const maxMilestone=_Mathmax5(...sortedMilestones);let currentRow=1;const validShipMilestones=shipStartMilestones.filter(x=>x),dtChartRows=[];for(const dtMilestone of dtStartMilestones){if(!dtMilestone)continue;let devTrialMilestoneLast=maxMilestone;if(0<validShipMilestones.length){const shippingIndex=sortedMilestones.indexOf(Math.min(...validShipMilestones));devTrialMilestoneLast=sortedMilestones[shippingIndex-1]}dtChartRows.push(this.renderChartRow(currentRow,dtMilestone,devTrialMilestoneLast,sortedMilestones,"dev_trial","Dev Trial: "+dtMilestone)),currentRow++}const otChartRows=[];for(let i=0;i<otStartMilestones.length;i++){const otStartMilestone=otStartMilestones[i],otEndMilestone=otEndMilestones[i];otStartMilestone&&otEndMilestone&&(otChartRows.push(this.renderChartRow(currentRow,otStartMilestone,otEndMilestone,sortedMilestones,"origin_trial",`Origin Trial: ${otStartMilestone} to ${otEndMilestone}`)),currentRow++)}const shipChartRows=[];for(const shipMilestone of shipStartMilestones)shipMilestone&&(shipChartRows.push(this.renderChartRow(currentRow,shipMilestone,maxMilestone,sortedMilestones,"shipping",`Shipping: ${shipMilestone}`)),currentRow++);return x$1` + <li class="platform-row"> + <div class="platform">${platform}</div> + + <ul class="chart" id="${platformParam}-chart"> + ${dtChartRows} ${otChartRows} ${shipChartRows} + </ul> + </li> + `}concatAllMilestones(allMilestones,stage){return stage?allMilestones.concat([stage.desktop_first,stage.desktop_last,stage.android_first,stage.android_last,stage.ios_first,stage.ios_last,stage.webview_first,stage.webview_last]):allMilestones}render(){var _Mathmin3=Math.min,_Mathmax6=Math.max;if(!this.feature||this._isInactive())return E$1;const[dtStages,otStages,shipStages]=this.getByStageType();let allMilestones=[];for(const stage of[...dtStages,...otStages,...shipStages]){if(stage.extensions)for(const extension of stage.extensions)allMilestones=this.concatAllMilestones(allMilestones,extension);allMilestones=this.concatAllMilestones(allMilestones,stage)}if(allMilestones=allMilestones.filter(x=>x),0==allMilestones.length)return x$1`<p>No milestones specified</p>`;const allValidMilestones=allMilestones.filter(x=>void 0!==x),minMilestone=_Mathmin3(...allValidMilestones),maxMilestone=_Mathmax6(...allValidMilestones),milestoneRange=maxMilestone-minMilestone+1+1;let sortedMilestones;if(12>=milestoneRange)sortedMilestones=Array(milestoneRange).fill(minMilestone).map((x,y)=>x+y);else{const augmentedMilestoneSet=new Set(allValidMilestones);for(const m of allValidMilestones)augmentedMilestoneSet.add(m+1);if(sortedMilestones=Array.from(augmentedMilestoneSet).sort((a,b)=>a-b),12<sortedMilestones.length){const milestoneSet=new Set(allValidMilestones);sortedMilestones=Array.from(milestoneSet).sort((a,b)=>a-b),sortedMilestones.push(maxMilestone+1)}}return x$1` + <label>Estimated milestones:</label> + <ul> + ${this.renderPlatform("Desktop","desktop",dtStages,otStages,shipStages,sortedMilestones)} + ${this.renderPlatform("Android","android",dtStages,otStages,shipStages,sortedMilestones)} + ${this.renderPlatform("iOS","ios",dtStages,otStages,shipStages,sortedMilestones)} + ${this.renderPlatform("Webview","webview",dtStages,otStages,shipStages,sortedMilestones)} + </ul> + `}};__decorate$P([n$5({type:Object})],ChromedashGantt.prototype,"feature",void 0),ChromedashGantt=__decorate$P([t$3("chromedash-gantt")],ChromedashGantt);var __decorate$O=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashVendorViews=class ChromedashVendorViews extends i$4{constructor(){super(...arguments),this.featureLinks=[]}urlIsStandardsPosition(url){return /github.com\/(mozilla|WebKit)\/standards-positions\/issues/.test(url)}render(){return this.href?x$1`<chromedash-link + href=${this.href} + ?showContentAsLabel=${!this.urlIsStandardsPosition(this.href)} + .featureLinks=${this.featureLinks} + ><slot></slot + ></chromedash-link>`:x$1`<slot></slot>`}};__decorate$O([n$5({type:String})],ChromedashVendorViews.prototype,"href",void 0),__decorate$O([n$5({attribute:!1})],ChromedashVendorViews.prototype,"featureLinks",void 0),ChromedashVendorViews=__decorate$O([t$3("chromedash-vendor-views")],ChromedashVendorViews);var __decorate$N=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFeatureHighlights=class ChromedashFeatureHighlights extends i$4{constructor(){super(...arguments),this.feature={},this.featureLinks=[],this.canDeleteFeature=!1,this.canEditFeature=!1}static get styles(){return[...SHARED_STYLES,...DETAILS_STYLES,i$7` + section { + margin-bottom: 1em; + } + section h3 { + margin: 24px 0 12px; + } + section label { + font-weight: 500; + margin-right: 5px; + } + + #consensus li { + display: flex; + } + #consensus li label { + width: 125px; + } + + #history p { + margin-top: var(--content-padding-half); + } + + sl-dropdown { + float: right; + margin-right: -16px; + margin-top: -20px; + } + #archive-feature::part(base) { + color: var(--error-color); + } + .suspended { + background: var(--table-header-background); + } + `]}isSuspended(){return this.feature?.browsers.chrome.status.val===IMPLEMENTATION_STATUS.ON_HOLD[0]}handleArchiveFeature(){this.dispatchEvent(new Event("archive",{bubbles:!0,composed:!0}))}handleSuspend(){this.dispatchEvent(new Event("suspend",{bubbles:!0,composed:!0}))}handleResume(){this.dispatchEvent(new Event("resume",{bubbles:!0,composed:!0}))}renderSummary(){if(this.feature.summary){const isMarkdown=(this.feature.markdown_fields||[]).includes("summary"),markup=autolink(this.feature.summary,this.featureLinks,isMarkdown);return x$1` + <section id="summary"> + ${isMarkdown?markup:x$1`<p class="preformatted">${markup}</p>`} + </section> + `}return x$1``}renderEnterpriseFeatureContent(){return this.renderSummary()}renderFeatureContent(){return x$1` + ${this.renderSummary()} + ${this.feature.motivation?x$1` + <section id="motivation"> + <h3>Motivation</h3> + <!-- prettier-ignore --> + <p class="preformatted">${autolink(this.feature.motivation,this.featureLinks)}</p> + </section> + `:E$1} + ${this.feature.resources?.samples?.length?x$1` + <section id="demo"> + <h3>Demos and samples</h3> + <ul> + ${this.feature.resources.samples.map(sampleLink=>x$1` + <li>${enhanceUrl(sampleLink,this.featureLinks)}</li> + `)} + </ul> + </section> + `:E$1} + ${this.feature.resources?.docs?.length?x$1` + <section id="documentation"> + <h3>Documentation</h3> + <ul> + ${this.feature.resources.docs.map(docLink=>x$1` + <li>${enhanceUrl(docLink,this.featureLinks)}</li> + `)} + </ul> + </section> + `:E$1} + ${this.feature.standards.spec?x$1` + <section id="specification"> + <h3>Specification</h3> + <p> + ${enhanceUrl(this.feature.standards.spec,this.featureLinks)} + </p> + <p>Spec status: ${this.feature.standards.maturity.text}</p> + </section> + `:this.feature.explainer_links?.length?x$1` + <section id="specification"> + <h3>Explainer(s)</h3> + <ul> + ${this.feature.explainer_links?.map(link=>x$1`<li>${enhanceUrl(link,this.featureLinks)}</li>`)} + </ul> + </section> + `:E$1} + `}renderEnterpriseFeatureStatus(){return x$1` + ${this.feature.browsers.chrome.owners?x$1` + <section id="owner"> + <h3> + ${1==this.feature.browsers.chrome.owners.length?"Owner":"Owners"} + </h3> + <ul> + ${this.feature.browsers.chrome.owners.map(owner=>x$1` + <li><a href="mailto:${owner}">${owner}</a></li> + `)} + </ul> + </section> + `:E$1} + `}renderFeatureStatus(){return x$1` + <section id="status"> + <h3>Status in Chromium</h3> + <p> + ${this.isSuspended()?x$1` <label>Implementation status:</label> + <b>Development work is on hold</b>`:E$1} + ${this.feature.browsers.chrome.bug?x$1`<chromedash-link + href=${this.feature.browsers.chrome.bug} + .featureLinks=${this.featureLinks} + alwaysInTag + >tracking bug</chromedash-link + >`:E$1} + <chromedash-gantt .feature=${this.feature}></chromedash-gantt> + </p> + </section> + + <section id="consensus"> + <h3>Consensus & Standardization</h3> + <div style="font-size:smaller;"> + After a feature ships in Chrome, the values listed here are not + guaranteed to be up to date. + </div> + <br /> + <ul> + ${this.feature.browsers.ff.view.val?x$1` + <li> + <label>Firefox:</label> + <chromedash-vendor-views + href=${this.feature.browsers.ff.view.url||E$1} + .featureLinks=${this.featureLinks} + >${this.feature.browsers.ff.view.text}</chromedash-vendor-views + > + </li> + `:E$1} + ${this.feature.browsers.safari.view.val?x$1` + <li> + <label>WebKit:</label> + <chromedash-vendor-views + href=${this.feature.browsers.safari.view.url||E$1} + .featureLinks=${this.featureLinks} + >${this.feature.browsers.safari.view.text}</chromedash-vendor-views + > + </li> + `:E$1} + <li> + <label>Web Developers:</label> ${this.feature.browsers.webdev.view.text} + </li> + </ul> + </section> + + ${this.feature.browsers.chrome.owners?x$1` + <section id="owner"> + <h3> + ${1==this.feature.browsers.chrome.owners.length?"Owner":"Owners"} + </h3> + <ul> + ${this.feature.browsers.chrome.owners.map(owner=>x$1` + <li><a href="mailto:${owner}">${owner}</a></li> + `)} + </ul> + </section> + `:E$1} + ${this.feature.intent_to_implement_url?x$1` + <section id="intent_to_implement_url"> + <h3>Intent to Prototype url</h3> + <a href=${this.feature.intent_to_implement_url} + >Intent to Prototype thread</a + > + </section> + `:E$1} + ${this.feature.comments?x$1` + <section id="comments"> + <h3>Comments</h3> + <!-- prettier-ignore --> + <p class="preformatted">${autolink(this.feature.comments,this.featureLinks)}</p> + </section> + `:E$1} + <section id="metadata"> + <h3>Metadata</h3> + <p> + <label>Feature type:</label> + ${this.feature.feature_type} + </p> + <p> + <label>Web feature ID:</label> + ${this.feature.web_feature} + </p> + <p> + <label>Blink components:</label> + ${this.feature.browsers.chrome.blink_components.map(c=>x$1` + <a + href="https://issues.chromium.org/issues?q=customfield1222907:%22${c}%22" + target="_blank" + rel="noopener" + >${c}</a + > + `)} + </p> + ${this.feature.tags?.length?x$1` <p> + <label>Search tags:</label> + ${this.feature.tags.map(tag=>x$1` + <a href="/features?q=tag:${tag}">${tag}</a + ><span class="conditional-comma">, </span> + `)} + </p>`:E$1} + </section> + `}renderHistory(){return x$1` + <section id="history"> + <h3>History</h3> + <p> + Entry created on + ${renderAbsoluteDate(this.feature.created?.when,!0)} + ${renderRelativeDate(this.feature.created?.when)} + </p> + <p> + Last updated on + ${renderAbsoluteDate(this.feature.updated?.when,!0)} + ${renderRelativeDate(this.feature.updated?.when)} + </p> + + <p> + <a href="/feature/${this.feature.id}/activity"> + All comments & activity + </a> + </p> + </section> + `}renderDotDotDotMenu(){if(!this.canDeleteFeature&&!this.canEditFeature)return E$1;let archiveItem=x$1``,suspendItem=x$1``,resumeItem=x$1``;return this.canDeleteFeature&&(archiveItem=x$1` + <sl-menu-item id="archive-feature" @click=${this.handleArchiveFeature}> + Archive feature + </sl-menu-item> + `),this.canEditFeature&&(this.isSuspended()?resumeItem=x$1` + <sl-menu-item @click=${this.handleResume}> + Resume active development + </sl-menu-item> + `:suspendItem=x$1` + <sl-menu-item @click=${this.handleSuspend}> + Suspend development + </sl-menu-item> + `),x$1` + <sl-dropdown placement="left-start"> + <sl-icon-button + library="material" + name="more_vert_24px" + label="Feature menu" + style="font-size: 1.3rem;" + slot="trigger" + ></sl-icon-button> + <sl-menu> ${suspendItem} ${resumeItem} ${archiveItem} </sl-menu> + </sl-dropdown> + `}render(){return x$1` + <sl-details summary="Overview" ?open=${!0}> + <section class="card ${this.isSuspended()?"suspended":""}"> + ${this.renderDotDotDotMenu()} + ${this.feature.is_enterprise_featqcure?this.renderEnterpriseFeatureContent():this.renderFeatureContent()} + ${this.feature.is_enterprise_feature?this.renderEnterpriseFeatureStatus():this.renderFeatureStatus()} + ${this.renderHistory()} + </section> + </sl-details> + `}};__decorate$N([n$5({attribute:!1})],ChromedashFeatureHighlights.prototype,"feature",void 0),__decorate$N([n$5({attribute:!1})],ChromedashFeatureHighlights.prototype,"featureLinks",void 0),__decorate$N([n$5({type:Boolean})],ChromedashFeatureHighlights.prototype,"canDeleteFeature",void 0),__decorate$N([n$5({type:Boolean})],ChromedashFeatureHighlights.prototype,"canEditFeature",void 0),ChromedashFeatureHighlights=__decorate$N([t$3("chromedash-feature-highlights")],ChromedashFeatureHighlights);var __decorate$M=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const INACTIVE_STATES=["No longer pursuing","Deprecated","Removed"];let ChromedashFeaturePage=class ChromedashFeaturePage extends i$4{constructor(){super(...arguments),this.featureId=0,this.featureLinks=[],this.gates=[],this.comments=[],this.contextLink="",this.appTitle="",this.selectedGateId=0,this.starred=!1,this.loading=!0,this.currentDate=Date.now(),this.shippingInfo={closestShippingDate:"",hasShipped:!1,isUpcoming:!1}}static get styles(){return[...SHARED_STYLES,...DETAILS_STYLES,i$7` + #feature { + background: var(--card-background); + border-radius: var(--default-border-radius); + border: var(--card-border); + box-shadow: var(--card-box-shadow); + + box-sizing: border-box; + word-wrap: break-word; + margin-bottom: var(--content-padding); + max-width: var(--max-content-width); + } + #feature ul { + list-style-position: inside; + list-style: none; + } + section { + margin-bottom: 1em; + } + section h3 { + margin: 24px 0 12px; + } + section label { + font-weight: 500; + margin-right: 5px; + } + + sl-skeleton { + margin-bottom: 1em; + width: 60%; + } + + sl-skeleton:nth-of-type(even) { + width: 50%; + } + + h3 sl-skeleton { + width: 30%; + height: 1.5em; + } + + @media only screen and (max-width: 700px) { + #feature { + border-radius: 0 !important; + margin: 7px initial !important; + } + } + + @media only screen and (min-width: 701px) { + #feature { + padding: 30px 40px; + } + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}isFeatureLoaded(){return this.feature&&0!==Object.keys(this.feature).length}fetchData(){this.loading=!0,Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getGates(this.featureId),window.csClient.getComments(this.featureId,null),window.csClient.getFeatureProcess(this.featureId),window.csClient.getStars(),window.csClient.getFeatureProgress(this.featureId),window.csClient.getChannels()]).then(async([feature,gatesRes,commentRes,process,starredFeatures,progress,channels])=>{this.feature=feature,this.gates=gatesRes.gates,this.comments=commentRes.comments,this.process=process,this.progress=progress,starredFeatures.includes(this.featureId)&&(this.starred=!0),this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.shippingInfo=await findClosestShippingDate(channels,feature.stages),this.loading=!1}).catch(error=>{error instanceof FeatureNotFoundError?this.loading=!1:showToastMessage("Some errors occurred. Please refresh the page or try again later.")}),window.csClient.getFeatureLinks(this.featureId).then(featureLinks=>{this.featureLinks=featureLinks?.data||[],featureLinks?.has_stale_links&&setTimeout(this.refetchFeatureLinks.bind(this),1e4)})}async refetchFeatureLinks(){const featureLinks=await window.csClient.getFeatureLinks(this.featureId,!1);this.featureLinks=featureLinks?.data||[]}refetch(){Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getGates(this.featureId),window.csClient.getComments(this.featureId,null)]).then(([feature,gatesRes,commentRes])=>{this.feature=feature,this.gates=gatesRes.gates,this.comments=commentRes.comments}).catch(error=>{error instanceof FeatureNotFoundError?this.loading=!1:showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}handleStarClick(e){e.preventDefault(),window.csClient.setStar(this.featureId,!this.starred).then(()=>{this.starred=!this.starred})}handleShareClick(e){if(e.preventDefault(),navigator.share){const url="/feature/"+this.featureId;navigator.share({title:this.feature.name,text:this.feature.summary,url:url}).then(()=>{ga("send","social",{socialNetwork:"web",socialAction:"share",socialTarget:url})})}}handleCopyLinkClick(e){e.preventDefault();const url=e.currentTarget.href;navigator.clipboard.writeText(url).then(()=>{showToastMessage("Link copied")})}canDeleteFeature(){return this.user?.is_admin||userCanEdit(this.user,this.featureId)}handleArchiveFeature(){confirm("Archive feature? It will only be visible to users who can edit it")&&window.csClient.doDelete(`/features/${this.feature.id}`).then(resp=>{"Done"===resp.message&&(location.href="/features")})}handleSuspend(){if(confirm("Suspend development of this feature? It will not appear on the roadmap.")){const submitBody={feature_changes:{id:this.feature.id,impl_status_chrome:IMPLEMENTATION_STATUS.ON_HOLD[0]},stages:[],has_changes:!0};window.csClient.updateFeature(submitBody).then(resp=>{window.location.reload()})}}handleResume(){if(confirm("Resume active development of this feature? It will appear on the roadmap if it has milestones set.")){const submitBody={feature_changes:{id:this.feature.id,impl_status_chrome:IMPLEMENTATION_STATUS.PROPOSED[0]},stages:[],has_changes:!0};window.csClient.updateFeature(submitBody).then(resp=>{window.location.reload()})}}renderSkeletonSection(){return x$1` + <section> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}renderSkeletons(){return x$1` + <div id="feature" style="margin-top: 65px;"> + ${this.renderSkeletonSection()} ${this.renderSkeletonSection()} + ${this.renderSkeletonSection()} ${this.renderSkeletonSection()} + </div> + `}featureIsInactive(){const status=this.feature&&this.feature.browsers.chrome.status.text||"";return INACTIVE_STATES.includes(status)}pairedUserCanEdit(){return this.paired_user?.can_edit_all||this.paired_user?.editable_features.includes(this.featureId)}renderSubHeader(){const canShare="function"==typeof navigator.share;return x$1` + <div id="subheader" style="display:block"> + <div class="tooltips" style="float:right; font-size:1.1rem"> + ${this.user?x$1` + <span + class="tooltip" + title="Receive an email notification when there are updates" + > + <a + href="#" + data-tooltip + id="star-when-signed-in" + @click=${this.handleStarClick} + > + <sl-icon + name=${this.starred?"star-fill":"star"} + class="pushicon" + ></sl-icon> + </a> + </span> + `:E$1} + <span class="tooltip" title="File a bug against this feature"> + <a + href=${o$6(this.feature.new_crbug_url)} + class="newbug" + data-tooltip + target="_blank" + rel="noopener" + > + <sl-icon name="bug"></sl-icon> + </a> + </span> + <span + class="tooltip ${canShare?"":"no-web-share"}" + title="Share this feature" + > + <a + href="#" + data-tooltip + id="share-feature" + @click=${this.handleShareClick} + > + <sl-icon name="share"></sl-icon> + </a> + </span> + <span + class="tooltip copy-to-clipboard" + title="Copy link to clipboard" + > + <a + href="/feature/${this.featureId}" + data-tooltip + id="copy-link" + @click=${this.handleCopyLinkClick} + > + <sl-icon library="material" name="link"></sl-icon> + </a> + </span> + </div> + <h2 id="breadcrumbs"> + <a href="${this.contextLink}"> + <sl-icon name="arrow-left"></sl-icon> + </a> + <a href="/feature/${this.featureId}"> + Feature: ${this.feature.name} + </a> + ${this.featureIsInactive()?x$1`(${this.feature.browsers.chrome.status.text})`:E$1} + </h2> + </div> + `}renderWarnings(){const warnings=[];this.feature.deleted&&warnings.push(x$1` + <div id="archived" class="warning"> + This feature is archived. It does not appear in feature lists and is + only viewable by users who can edit it. + </div> + `),this.feature.unlisted&&warnings.push(x$1` + <div id="access" class="warning"> + This feature is only shown in the feature list to users with access to + edit this feature. + </div> + `);const canEdit=userCanEdit(this.user,this.featureId);!canEdit&&this.pairedUserCanEdit()&&warnings.push(x$1` + <div id="switch_to_edit" class="warning"> + User ${this.user.email} cannot edit this feature or request reviews. + But, ${this.paired_user.email} can do that. + <br /> + To switch users: sign out and then sign in again. + </div> + `),0==this.user?.approvable_gate_types.length&&0<this.paired_user?.approvable_gate_types.length&&warnings.push(x$1` + <div id="switch_to_review" class="warning"> + User ${this.user.email} cannot review this feature. But, + ${this.paired_user.email} can do that. + <br /> + To switch users: sign out and then sign in again. + </div> + `);const featureOutdatedBanner=getFeatureOutdatedBanner(this.feature,this.shippingInfo,this.currentDate,canEdit);return featureOutdatedBanner&&warnings.push(featureOutdatedBanner),warnings}renderFeatureDetails(){return x$1` + <chromedash-feature-detail + appTitle=${this.appTitle} + .user=${this.user} + ?canEdit=${userCanEdit(this.user,this.featureId)} + .feature=${this.feature} + .gates=${this.gates} + .comments=${this.comments} + .process=${this.process} + .progress=${this.progress} + .featureLinks=${this.featureLinks} + selectedGateId=${this.selectedGateId} + > + </chromedash-feature-detail> + `}render(){return this.loading?this.renderSkeletons():this.isFeatureLoaded()?x$1` + ${this.renderSubHeader()} ${this.renderWarnings()} + <chromedash-feature-highlights + .feature=${this.feature} + .featureLinks=${this.featureLinks} + ?canDeleteFeature=${this.canDeleteFeature()} + ?canEditFeature=${userCanEdit(this.user,this.featureId)} + @archive=${this.handleArchiveFeature} + @suspend=${this.handleSuspend} + @resume=${this.handleResume} + ></chromedash-feature-highlights> + ${this.renderFeatureDetails()} + `:x$1`Feature not found.`}};__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"user",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"paired_user",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"featureId",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"feature",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"featureLinks",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"gates",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"comments",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"process",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"progress",void 0),__decorate$M([n$5({attribute:!1})],ChromedashFeaturePage.prototype,"contextLink",void 0),__decorate$M([n$5({type:String})],ChromedashFeaturePage.prototype,"appTitle",void 0),__decorate$M([n$5({type:Number})],ChromedashFeaturePage.prototype,"selectedGateId",void 0),__decorate$M([r$6()],ChromedashFeaturePage.prototype,"starred",void 0),__decorate$M([r$6()],ChromedashFeaturePage.prototype,"loading",void 0),__decorate$M([r$6()],ChromedashFeaturePage.prototype,"currentDate",void 0),__decorate$M([r$6()],ChromedashFeaturePage.prototype,"shippingInfo",void 0),ChromedashFeaturePage=__decorate$M([t$3("chromedash-feature-page")],ChromedashFeaturePage);var __decorate$L=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFooter=class ChromedashFooter extends i$4{static get styles(){return[...SHARED_STYLES,i$7` + footer { + background: var(--page-background); + box-shadow: 0 -2px 5px var(--shadow-color); + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + align-items: center; + padding: var(--content-padding-half); + position: relative; /* Ensure the z-index has an effect so the box-shadow appears. */ + z-index: 800; + } + + footer div > * + * { + margin-left: var(--content-padding); + padding-left: var(--content-padding); + } + + #footer-spacer { + display: none; + height: calc(28px + var(--content-padding-half)); + } + + @media only screen and (min-width: 601px) and (min-height: 601px) { + footer { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + } + + #footer-spacer { + display: block; + } + } + `]}render(){return x$1` + <div id="footer-spacer"></div> + <footer> + <div> + <a + href="https://github.com/GoogleChrome/chromium-dashboard/wiki/" + target="_blank" + rel="noopener" + >Help</a + > + <a + href="https://groups.google.com/a/chromium.org/forum/#!newtopic/blink-dev" + target="_blank" + rel="noopener" + >Discuss</a + > + <a + href="https://github.com/GoogleChrome/chromium-dashboard/issues" + target="_blank" + rel="noopener" + >File an issue</a + > + <a + href="https://policies.google.com/privacy" + target="_blank" + rel="noopener" + >Privacy</a + > + </div> + </footer> + `}};ChromedashFooter=__decorate$L([t$3("chromedash-footer")],ChromedashFooter);var __decorate$K=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const DEFAULT_PLACEHOLDER="https://...\nhttps://...",DEFAULT_SPLIT_PATTERN="\\s+";let ChromedashAttachments=class ChromedashAttachments extends i$4{constructor(){super(...arguments),this.textareaRef=e$1(),this.fileInputRef=e$1(),this.chromedash_single_pattern=URL_REGEX,this.chromedash_split_pattern=DEFAULT_SPLIT_PATTERN}createRenderRoot(){return this}validate(){this.textareaRef?.value?.validate&&this.textareaRef.value.validate()}handleFieldUpdated(e){let fieldValue=e.target.value;this.value=fieldValue,this.dispatchEvent(new CustomEvent("sl-change"))}handleFileSelected(e){let inputEl=e.target;if(inputEl.files?.[0]){const file=inputEl.files?.[0];window.csClient.addAttachment(this.featureId,inputEl.name,file).then(resp=>{this.value+="\n"+resp.attachment_url,this.dispatchEvent(new CustomEvent("sl-change"))})}}renderOneThumbnail(url){if(""==url)return E$1;const linkStyles={display:"inline-block",padding:"var(--content-padding-quarter)",margin:"var(--content-padding-half)",border:`2px solid var(--link-color)`,cursor:`zoom-in`},imgStyles={maxHeight:"150px",maxWidth:"200px"};var imgSrc=url;return url.includes("/feature/"+this.featureId+"/attachment/")&&(imgSrc+="/thumbnail"),x$1` + <a href=${url} target="_blank" style=${o$3(linkStyles)}> + <img style=${o$3(imgStyles)} src=${imgSrc}></img> + </a> + `}renderThumbnails(){if(!this.value?.length)return E$1;const items=this.value.split(new RegExp(this.chromedash_split_pattern));return items.map(url=>this.renderOneThumbnail(url))}renderUploadButton(){const buttonContainerStyles={display:"inline-block",margin:"var(--content-padding-half)"};return x$1` + <input + ${n$2(this.fileInputRef)} + id="file-field" + type="file" + name="screenshots" + @change=${e=>this.handleFileSelected(e)} + accept="image/png, image/jpeg, image/png, image/wepb, text/plain" + style="display:none" + /> + <div style=${o$3(buttonContainerStyles)}> + <sl-button + id="upload-button" + @click=${e=>this.fileInputRef?.value?.click()} + > + <sl-icon slot="prefix" name="upload"></sl-icon> + Upload image + </sl-button> + <div>Max size: 1MB</div> + </div> + `}render(){return x$1` + <chromedash-textarea + ${n$2(this.textareaRef)} + size="small" + name=${this.name} + value=${this.value} + multiple + placeholder=${DEFAULT_PLACEHOLDER} + pattern=${this.pattern} + chromedash_single_pattern=${this.chromedash_single_pattern} + chromedash_split_pattern=${this.chromedash_split_pattern} + @sl-change=${this.handleFieldUpdated} + @keyup=${this.handleFieldUpdated} + ></chromedash-textarea> + <div>${this.renderThumbnails()} ${this.renderUploadButton()}</div> + `}firstUpdated(){this.validate()}updated(){this.validate()}};__decorate$K([n$5({type:String})],ChromedashAttachments.prototype,"name",void 0),__decorate$K([n$5({type:String})],ChromedashAttachments.prototype,"value",void 0),__decorate$K([n$5({type:String})],ChromedashAttachments.prototype,"pattern",void 0),__decorate$K([n$5({type:String})],ChromedashAttachments.prototype,"chromedash_single_pattern",void 0),__decorate$K([n$5({type:String})],ChromedashAttachments.prototype,"chromedash_split_pattern",void 0),__decorate$K([n$5({type:Number})],ChromedashAttachments.prototype,"featureId",void 0),ChromedashAttachments=__decorate$K([t$3("chromedash-attachments")],ChromedashAttachments);var __decorate$J=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashTextarea=class ChromedashTextarea extends textarea_default{constructor(){super(...arguments),this.cols=50,this.rows=10,this.offerMarkdown=!1,this.isMarkdown=!1,this.alwaysMarkdown=!1,this.index=-1,this.maxlength=1400,this.showPreview=!1}customCheckValidity(value){if(this.multiple&&this.chromedash_split_pattern&&this.chromedash_single_pattern){const items=value.split(new RegExp(this.chromedash_split_pattern)),singleItemRegex=new RegExp("^"+this.chromedash_single_pattern+"$",""),valid=items.every(item=>{if(!item)return!0;const itemValid=singleItemRegex.test(item);return itemValid});if(!valid)return!1}if(this.pattern){const valueRegex=new RegExp("^"+this.pattern+"$","");return valueRegex.test(value)}return!0}validate(){if(null!==this.input){const invalidMsg=this.customCheckValidity(this.input.value)?"":"invalid";this.setCustomValidity&&this.setCustomValidity(invalidMsg)}}firstUpdated(){this.validate()}updated(){this.input&&this.validate()}handleMarkdownChecked(e){this.isMarkdown=!!e.target?.checked,this.isMarkdown||(this.showPreview=!1)}handlePreviewChecked(e){this.showPreview=!!e.target?.checked,e.stopPropagation()}render(){const editor=super.render();if(!this.offerMarkdown&&!this.alwaysMarkdown)return editor;const preview=x$1` + <div style="display:none">${editor}</div> + <div + id="preview" + style="border:var(--card-border); padding:0 var(--content-padding); min-height:14em; background:var(--table-alternate-background)" + > + ${autolink(this.value,[],!0)} + </div> + `;return x$1` + ${this.showPreview?preview:editor} + <sl-checkbox + id="use-markdown" + name="${this.name}_is_markdown" + ?checked=${this.isMarkdown||this.alwaysMarkdown} + ?disabled=${this.alwaysMarkdown} + @sl-change=${this.handleMarkdownChecked} + > + Use markdown + </sl-checkbox> + <sl-icon-button + name="info-circle" + id="info-button" + title="GitHub flavored markdown docs" + href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" + target="_blank" + ></sl-icon-button> + ${this.isMarkdown||this.alwaysMarkdown?x$1` <sl-checkbox + id="show-preview" + ?checked=${this.showPreview} + @sl-change=${this.handlePreviewChecked} + > + Preview + </sl-checkbox>`:E$1} + `}};__decorate$J([n$5({type:Boolean})],ChromedashTextarea.prototype,"multiple",void 0),__decorate$J([n$5({type:String})],ChromedashTextarea.prototype,"pattern",void 0),__decorate$J([n$5({type:String})],ChromedashTextarea.prototype,"chromedash_single_pattern",void 0),__decorate$J([n$5({type:String})],ChromedashTextarea.prototype,"chromedash_split_pattern",void 0),__decorate$J([n$5({type:Number})],ChromedashTextarea.prototype,"cols",void 0),__decorate$J([n$5({type:Number})],ChromedashTextarea.prototype,"rows",void 0),__decorate$J([n$5({type:Boolean})],ChromedashTextarea.prototype,"offerMarkdown",void 0),__decorate$J([n$5({type:Boolean})],ChromedashTextarea.prototype,"isMarkdown",void 0),__decorate$J([n$5({type:Boolean})],ChromedashTextarea.prototype,"alwaysMarkdown",void 0),__decorate$J([n$5({type:Number})],ChromedashTextarea.prototype,"index",void 0),__decorate$J([n$5({type:Number})],ChromedashTextarea.prototype,"maxlength",void 0),__decorate$J([r$6()],ChromedashTextarea.prototype,"showPreview",void 0),ChromedashTextarea=__decorate$J([t$3("chromedash-textarea")],ChromedashTextarea);var __decorate$I=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const USAGE_TYPE_DETAILS={[UsageType.Prototype]:{abbreviation:"I2P",className:"usage-tag--prototype",title:"Intent to Prototype"},[UsageType.DeveloperTesting]:{abbreviation:"R4DT",className:"usage-tag--dev-testing",title:"Ready for Developer Testing"},[UsageType.Experiment]:{abbreviation:"I2E",className:"usage-tag--experiment",title:"Intent to Experiment"},[UsageType.Ship]:{abbreviation:"I2S",className:"usage-tag--ship",title:"Intent to Ship"},[UsageType.PSA]:{abbreviation:"PSA",className:"usage-tag--psa",title:"Web-Facing Change PSA"},[UsageType.DeprecateAndRemove]:{abbreviation:"I2D",className:"usage-tag--deprecate",title:"Intent to Deprecate and Remove"},[UsageType.ReleaseNotes]:{abbreviation:"RN",className:"usage-tag--rn",title:"Release Notes"},[UsageType.CrossFunctionReview]:{abbreviation:"XFN",className:"usage-tag-xfn",title:"Cross-Functional Review"}};let ChromedashFormField=class ChromedashFormField extends i$4{constructor(){super(...arguments),this.name="",this.index=-1,this.checkboxLabel="",this.disabled=!1,this.shouldFadeIn=!1,this.forEnterprise=!1,this.disabledReason="",this.forceRequired=!1,this.value="",this.initialValue="",this.loading=!1,this.fetchedChoices={},this.checkMessage=""}getValue(){const useEnterpriseDefault=this.forEnterprise&&this.fieldProps.enterprise_initial!==void 0,initialValue=useEnterpriseDefault?this.fieldProps.enterprise_initial:this.fieldProps.initial;return!this.value&&initialValue?initialValue:this.value}connectedCallback(){super.connectedCallback(),this.fieldProps=resolveFieldForFeature(ALL_FIELDS[this.name]||{},this.feature);const app=document.querySelector("chromedash-app");app?.pageComponent&&app.pageComponent.allFormFieldComponentsList.push(this),"blink_components"===this.name?this.fetchChoices(window.csClient.getBlinkComponents(),"Error fetching Blink Components. Please refresh the page or try again later."):"web_feature"===this.name&&this.fetchChoices(window.csClient.getWebFeatureIDs().then(feature_ids=>{let choices={missing_feature:["Missing feature","Missing feature"]};for(let id of feature_ids)choices[id]=[id,id];return choices}),"Error fetching Web feature IDs. Please refresh the page or try again later.")}fetchChoices(fetchPromise,errorMessage){this.loading=!0,fetchPromise.then(choices=>{this.fetchedChoices=choices,this.loading=!1}).catch(()=>{showToastMessage(errorMessage)})}firstUpdated(){this.initialValue=JSON.parse(JSON.stringify(this.value)),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>setTimeout(()=>{this.doSemanticCheck()})):this.doSemanticCheck()}updateAttributes(el){if(!el)return;const attrs=this.fieldProps.attrs||{};Object.keys(attrs).map(attr=>{el.setAttribute(attr,attrs[attr])})}toggleExtraHelp(){const details=this.renderRoot.querySelector("sl-details");details.open=!details.open;const button=this.renderRoot.querySelector("sl-icon-button");button.name=details.open?"dash-square":"plus-square"}shouldDisplayFeatureLink(field_name,feature_value){return!("web_feature"!==field_name)&&!!feature_value&&"Missing feature"!==feature_value&&"TBD"!=feature_value}createRenderRoot(){return this}handleFieldUpdated(e){const type=this.fieldProps.type;let fieldValue;fieldValue="checkbox"===type?e.target.checked:"multiselect"===type?e.target.value.join(","):e.target.value,this.value=fieldValue;let isMarkdown;e.target.offerMarkdown&&(isMarkdown=e.target.isMarkdown);const eventOptions={detail:{value:fieldValue,index:this.index,isMarkdown}};this.dispatchEvent(new CustomEvent("form-field-update",eventOptions));const app=document.querySelector("chromedash-app");app?.pageComponent?app.pageComponent.allFormFieldComponentsList.forEach(formFieldComponent=>formFieldComponent.doSemanticCheck()):this.doSemanticCheck()}async doSemanticCheck(){const getFieldValue=(fieldName,stageOrId)=>("current stage"===stageOrId&&(stageOrId=this.stageId),getFieldValueWithStage(fieldName,stageOrId,this.fieldValues||[]));getFieldValue.feature=this.fieldValues?.feature;const checkFunctionWrapper=async checkFunction=>{const fieldValue=this.getValue(),initialValue=this.initialValue;if(null==fieldValue)return!1;const checkResult=await checkFunction(fieldValue,getFieldValue,initialValue);return null!=checkResult&&(this.checkMessage=x$1` <span + class="check-${checkResult.message?"message":checkResult.warning?"warning":checkResult.error?"error":"unknown"}" + > + ${checkResult.message?checkResult.message:checkResult.warning?x$1`<b>Warning</b>: ${checkResult.warning}`:checkResult.error?x$1`<b>Error</b>: ${checkResult.error}`:""} + </span>`,!0)},checkFunctionOrArray=this.fieldProps.check||[],checkFunctions="function"==typeof checkFunctionOrArray?[checkFunctionOrArray]:checkFunctionOrArray;0<checkFunctions.length&&(this.checkMessage="");for(const checkFunction of checkFunctions)if(await checkFunctionWrapper(checkFunction))return}renderWidget(){const type=this.fieldProps.type,fieldDisabled=this.fieldProps.disabled,fieldValue=this.getValue(),isRequired=this.fieldProps.required||this.forceRequired,offerMarkdown=!(this.forEnterprise?!this.fieldProps.enterprise_offer_markdown:!this.fieldProps.offer_markdown),fieldName=this.fieldProps.name||this.name,isMarkdown=(this.feature?.markdown_fields||[]).includes(fieldName),choices=this.fieldProps.choices||this.fetchedChoices;let fieldHTML=x$1``;if("checkbox"===type){const label=this.checkboxLabel||this.fieldProps.label;fieldHTML=x$1` + <sl-checkbox + name="${fieldName}" + id="id_${this.name}" + size="small" + ?checked=${!0===fieldValue||"true"===fieldValue||"True"===fieldValue} + ?disabled=${this.disabled||fieldDisabled} + @sl-change="${this.handleFieldUpdated}" + > + ${label} + </sl-checkbox> + `}else if("select"===type)fieldHTML=x$1` + <sl-select + name="${fieldName}" + id="id_${this.name}" + value="${fieldValue}" + size="small" + hoist + ?disabled=${fieldDisabled||this.disabled||this.loading} + @sl-change="${this.handleFieldUpdated}" + > + ${Object.values(choices).map(([value,label])=>x$1` + <sl-option value="${value}"> ${label} </sl-option> + `)} + </sl-select> + `;else if("multiselect"===type){const valueArray=fieldValue.split(","),availableOptions=Object.values(choices).filter(([value,label,obsolete])=>!obsolete||valueArray.includes(""+value));fieldHTML=x$1` + <sl-select + name="${fieldName}" + id="id_${this.name}" + .value=${valueArray} + size="small" + hoist + multiple + cleareable + ?required=${isRequired} + ?disabled=${fieldDisabled||this.disabled||this.loading} + @sl-change="${this.handleFieldUpdated}" + > + ${availableOptions.map(([value,label])=>x$1` + <sl-option value="${value}"> ${label} </sl-option> + `)} + </sl-select> + `}else"input"===type?fieldHTML=x$1` + <sl-input + ${n$2(this.updateAttributes)} + name="${fieldName}" + id="id_${this.name}" + stageId="${this.stageId}" + size="small" + autocomplete="off" + .value=${fieldValue} + help-text="${this.disabledReason}" + ?disabled=${this.disabled||this.disabledReason||fieldDisabled} + ?required=${isRequired} + @sl-change="${this.handleFieldUpdated}" + > + </sl-input> + `:"textarea"===type?fieldHTML=x$1` + <chromedash-textarea + ${n$2(this.updateAttributes)} + name="${fieldName}" + id="id_${this.name}" + size="small" + resize="auto" + value=${fieldValue} + index=${this.index} + ?required=${isRequired} + ?offerMarkdown=${offerMarkdown} + ?isMarkdown=${isMarkdown} + ?alwaysMarkdown=${this.fieldProps.always_markdown} + @sl-change="${this.handleFieldUpdated}" + > + </chromedash-textarea> + `:"attachments"===type?fieldHTML=x$1` + <chromedash-attachments + ${n$2(this.updateAttributes)} + name="${fieldName}" + featureId=${this.feature.id} + id="id_${this.name}" + size="small" + value=${fieldValue} + ?required=${isRequired} + @sl-change="${this.handleFieldUpdated}" + > + </chromedash-attachments> + `:"radios"===type?fieldHTML=x$1` + ${Object.values(choices).map(([value,label,description])=>x$1` + <input + id="id_${this.name}_${value}" + name="${fieldName}" + value="${value}" + .checked="${value===+fieldValue}" + type="radio" + required + @change=${this.handleFieldUpdated} + /> + <label for="id_${this.name}_${value}">${label}</label> + <p>${description}</p> + `)} + `:"datalist"===type?fieldHTML=x$1` + <div class="datalist-input-wrapper" data-testid="${this.name}_wrapper"> + <input + ${n$2(this.updateAttributes)} + name="${fieldName}" + id="id_${this.name}" + value="${fieldValue}" + class="datalist-input" + type="search" + list="${this.name}_list" + ?required=${isRequired} + @change=${this.handleFieldUpdated} + /> + </div> + <datalist id="${this.name}_list"> + ${Object.values(choices).map(([value])=>x$1` <option value="${value}"></option> `)} + </datalist> + `:console.error(`unknown form field type: ${type}`);return fieldHTML}renderUsageIcons(fieldUsageInfo,featureType){if(featureType===void 0)return[];const intentTypesUsed=fieldUsageInfo[featureType];if(!intentTypesUsed)return[];if(ALL_INTENT_USAGE_BY_FEATURE_TYPE[featureType]?.isSubsetOf(intentTypesUsed))return[x$1`<span + class="usage-tag usage-tag--all" + title="This field is used to populate all intent templates when provided" + > + All + </span>`];const intentIcons=[];for(const intentType of intentTypesUsed){const details=USAGE_TYPE_DETAILS[intentType];if(details){const tooltipText=`This field is used to populate the ${details.title} template`;intentIcons.push(x$1` + <span class="usage-tag ${details.className}" title="${tooltipText}" + >${details.abbreviation}</span + > + `)}}return intentIcons}render(){if(this.fieldProps.deprecated&&!this.value)return E$1;const helpText=this.forEnterprise&&this.fieldProps.enterprise_help_text!==void 0?this.fieldProps.enterprise_help_text:this.fieldProps.help_text,extraHelpText=this.forEnterprise&&this.fieldProps.enterprise_extra_help!==void 0?this.fieldProps.enterprise_extra_help:this.fieldProps.extra_help,fadeInClass=this.shouldFadeIn?"fade-in":"";return x$1` + ${this.fieldProps.label?x$1` + <tr class="${fadeInClass}"> + <th class="form-field-header"> + <div> + <b>${this.fieldProps.label}:</b> + </div> + <div> + ${this.renderUsageIcons(this.fieldProps.usage,this.feature?.feature_type_int)} + </div> + </th> + </tr> + `:E$1} + <tr class=${fadeInClass}> + <td>${this.renderWidget()} ${this.checkMessage}</td> + <td> + ${helpText?x$1`<span class="helptext"> ${helpText} </span>`:E$1} + ${extraHelpText?x$1` + <sl-icon-button + name="plus-square" + label="Toggle extra help" + style="position:absolute" + @click="${this.toggleExtraHelp}" + > + + + </sl-icon-button> + `:E$1} + </td> + </tr> + + ${extraHelpText?x$1` + <tr> + <td colspan="2" class="extrahelp"> + <sl-details summary=""> + <span class="helptext"> ${extraHelpText} </span> + </sl-details> + </td> + </tr> + `:E$1} + ${this.shouldDisplayFeatureLink(this.name,this.value)?x$1` + <tr> + <td colspan="2" class="webdx"> + See web feature + <a + href="https://webstatus.dev/features/${enumLabelToFeatureKey(this.value)}" + target="_blank" + > + ${this.value} + </a> + in webstatus.dev + </td> + </tr> + `:E$1} + `}};__decorate$I([n$5({type:String})],ChromedashFormField.prototype,"name",void 0),__decorate$I([n$5({type:Number})],ChromedashFormField.prototype,"index",void 0),__decorate$I([n$5({type:Object})],ChromedashFormField.prototype,"fieldValues",void 0),__decorate$I([n$5({type:Object,attribute:!1})],ChromedashFormField.prototype,"feature",void 0),__decorate$I([n$5({type:String})],ChromedashFormField.prototype,"checkboxLabel",void 0),__decorate$I([n$5({type:Boolean})],ChromedashFormField.prototype,"disabled",void 0),__decorate$I([n$5({type:Boolean})],ChromedashFormField.prototype,"shouldFadeIn",void 0),__decorate$I([n$5({type:Boolean})],ChromedashFormField.prototype,"forEnterprise",void 0),__decorate$I([n$5({type:String})],ChromedashFormField.prototype,"disabledReason",void 0),__decorate$I([n$5({type:Boolean})],ChromedashFormField.prototype,"forceRequired",void 0),__decorate$I([n$5({type:Number})],ChromedashFormField.prototype,"stageId",void 0),__decorate$I([n$5({type:Number})],ChromedashFormField.prototype,"stageType",void 0),__decorate$I([n$5({type:String})],ChromedashFormField.prototype,"value",void 0),__decorate$I([r$6()],ChromedashFormField.prototype,"initialValue",void 0),__decorate$I([r$6()],ChromedashFormField.prototype,"loading",void 0),__decorate$I([r$6()],ChromedashFormField.prototype,"fetchedChoices",void 0),__decorate$I([r$6()],ChromedashFormField.prototype,"checkMessage",void 0),__decorate$I([r$6()],ChromedashFormField.prototype,"fieldProps",void 0),ChromedashFormField=__decorate$I([t$3("chromedash-form-field")],ChromedashFormField);function enumLabelToFeatureKey(label){let result="";for(let i=0;i<label.length;i++){const char=label[i];if(0==i){result+=char.toLowerCase();continue}if(char===char.toUpperCase()&&/[a-zA-Z]/.test(char)){result+="-"+char.toLowerCase();continue}0<i&&/[a-zA-Z]/.test(label[i-1])&&"0"<=char&&"9">=char&&(result+="-"),result+=char}return result}function getFieldValueWithStage(fieldName,stageOrId,formFieldValues){let stageId;"number"==typeof stageOrId?stageId=stageOrId:"object"==typeof stageOrId&&(stageId=stageOrId.id);for(const obj of formFieldValues)if(obj.name===fieldName&&(null==stageId||obj.stageId==stageId))return obj.value;const feature=formFieldValues?.feature;if(null==feature)return null;const feStage="object"==typeof stageOrId?stageOrId:null==stageId?feature.stages[0]:feature.stages.find(s=>s.id==stageId);if(!feStage)return null;const value=getFieldValueFromFeature(fieldName,feStage,feature);return value}var __decorate$H=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashFormTable=class ChromedashFormTable extends i$4{static get styles(){return[i$7` + :host { + display: table; + max-width: 80em; + } + `]}render(){return x$1` <slot>fallback content</slot> `}};__decorate$H([n$5({type:String})],ChromedashFormTable.prototype,"class",void 0),ChromedashFormTable=__decorate$H([t$3("chromedash-form-table")],ChromedashFormTable);const BLINK_GENERIC_QUESTIONNAIRE=x$1` <p> + To request a review, use the "Draft intent..." button above to generate an + intent messsage, and then post that message to blink-dev@chromium.org. + </p> + <p> + Be sure to update your feature entry in response to any suggestions on that + email thread. + </p>`,PRIVACY_GENERIC_QUESTIONNAIRE=x$1` <p> + <b + >Please fill out the Security & Privacy self-review questionnaire: + <a + href="https://www.w3.org/TR/security-privacy-questionnaire/" + target="_blank" + >https://www.w3.org/TR/security-privacy-questionnaire/</a + ></b + > + </p> + <p> + Share it as a public document, as a file in your repository, or in any other + public format of your choice. + </p> + <p> + You can reuse the same filled-out questionnaire in the security review + below, across all stages of this ChromeStatus entry, and across all entries + related to the same API. If you updated an existing questionnaire to reflect + new changes to the API, please highlight them for an easier review. + </p> + <p> + <b>If you believe your feature has no privacy impact</b> and none of the + questions in the questionnaire apply, you can provide a justification + instead, e.g. "Removing a prefix from the API, no changes to functionality" + or "New CSS property that doesn't depend on the user state, therefore + doesn't reveal any user information". Note that if your reviewer disagrees + with the justification, they may ask you to fill out the questionnaire + nevertheless. + </p>`,SECURITY_GENERIC_QUESTIONNAIRE=x$1` <p> + <b + >Please fill out the Security & Privacy self-review questionnaire: + <a + href="https://www.w3.org/TR/security-privacy-questionnaire/" + target="_blank" + >https://www.w3.org/TR/security-privacy-questionnaire/</a + ></b + > + </p> + <p> + Share it as a public document, as a file in your repository, or in any other + public format of your choice. + </p> + <p> + You can reuse the same filled-out questionnaire in the privacy review above, + across all stages of this ChromeStatus entry, and across all entries related + to an API. If you updated an existing questionnaire to reflect new changes + to the API, please highlight them for an easier review. + </p> + <p> + <b>If you believe your feature has no security impact</b> and none of the + questions in the questionnaire apply, you can provide a justification + instead. Note that if your reviewer disagrees with the justification, they + may ask you to fill out the questionnaire nevertheless. + </p>`,ENTERPRISE_SHIP_QUESTIONNAIRE=x$1` <p> + <b>(1) Does this launch include a breaking change?</b> Does this launch + remove or modify existing behavior or does it interrupt an existing user + flow? (e.g. removing or restricting an API, or significant UI change). + Answer with one of the following options, and/or describe anything you're + unsure about: + </p> + <ul> + <li> + No. There's no change visible to users, developers, or IT admins (e.g. + internal refactoring) + </li> + <li>No. This launch is strictly additive functionality</li> + <li> + Yes. Something that exists is changing or being removed (even if usage is + very small) + </li> + <li> + I don't know. Enterprise reviewers, please help me decide. The relevant + information is: ______ + </li> + </ul> + <p> + <b + >(2) Is there any other reason you expect that enterprises will care about + this launch?</b + > + (e.g. they may perceive a risk of data leaks if the browser is uploading new + information, or it may be a surprise to employees resulting in them calling + their help desk). Answer with one of the following options, and/or describe + anything you're unsure about: + </p> + <ul> + <li>No. Enterprises won't care about this</li> + <li>Yes. They'll probably care because ______</li> + <li> + I don't know. Enterprise reviewers, please help me decide. The relevant + information is: ______ + </li> + </ul> + <p> + <b + >(3) Does your launch have an enterprise policy to control it, and will it + be available when this rolls out to stable (even to 1%)?</b + > + Only required if you answered Yes to either of the first 2 questions. Answer + with one of the following options, and/or describe anything you're unsure + about: + </p> + <ul> + <li> + Yes. It's called ______. It will be a permanent policy, and it will be + available when stable rollout starts + </li> + <li> + Yes. It's called ______. This is a temporary transition period, so the + policy will stop working on milestone ___. It will be available when + stable rollout starts + </li> + <li> + No. A policy is infeasible because ______ (e.g. this launch is a change in + how we compile Chrome) + </li> + <li> + No. A policy isn't necessary because ______ (e.g. there's a better method + of control available to admins) + </li> + </ul> + <p> + <b + >(4) Provide a brief title and description of this launch, which can be + shared with enterprises.</b + > + Only required if you answered Yes to either of the first 2 questions. This + may be added to browser release notes. Where applicable, explain the benefit + to users, and describe the policy to control it. + </p>`,DEBUGGABILITY_ORIGIN_TRIAL_QUESTIONNAIRE=x$1` + <p> + (1) Does the introduction of the new Web Platform feature break Chrome + DevTools' existing developer experience? + </p> + + <p> + (2) Does Chrome DevTools' existing set of tooling features interact with the + new Web Platform feature in an expected way? + </p> + + <p> + (3) Would the new Web Platform feature's acceptance and/or adoption benefit + from adding a new developer workflow to Chrome DevTools? + </p> + + <p> + (4) Can the feature be tested with a WebDriver BiDi module or other + appropriate automation? + </p> + + <p> + When in doubt, please check out + <a href="https://goo.gle/devtools-checklist" target="_blank" + >https://goo.gle/devtools-checklist</a + > + for details! + </p> +`,DEBUGGABILITY_SHIP_QUESTIONNAIRE=DEBUGGABILITY_ORIGIN_TRIAL_QUESTIONNAIRE,TESTING_SHIP_QUESTIONNAIRE=x$1` <p> + <b + >(1) Does your feature have sufficient automated test coverage (Unit + tests, WPT, browser tests and other integration tests)?</b + > + Chrome requires at least 70% automation code coverage (<a + href="https://analysis.chromium.org/coverage/p/chromium" + target="_blank" + >dashboard</a + >) running on the main/release branch and 70% Changelist + <a + href="https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/testing/code_coverage_in_gerrit.md" + target="_blank" + >code coverage in Gerrit</a + >? Do the automated tests have more than 93% green (flakiness < 7%) on CQ + and CI builders? + </p> + <ul> + <li> + Yes. My feature met the minimum automated test coverage and health + requirements. + </li> + <li>No. My feature does not meet the requirements since __________.</li> + </ul> + <p> + <b>(2) How are performance tests conducted on Chromium builders?</b> List + links to tests if any. + </p> + <p> + <b + >(3) Does this feature have non-automatable test cases that require manual + testing? Do you have a plan to get them tested?</b + > + </p> + <ul> + <li>No. All feature related test cases are automated.</li> + <li> + Yes. There are non-automatable test cases and I have completed test + execution or allocated resources to ensure the coverage of these test + cases. + </li> + <li> + Yes. There are non-automatable test cases and my feature impacts Google + products. + </li> + </ul> + <p> + <b + >(4) If your feature impacts Google products, please fill in + <a href="http://go/chrome-wp-test-survey" target="_blank" + >go/chrome-wp-test-survey</a + >.</b + > + Make a copy, answer the survey questions, and provide a link to your + document here. + </p>`,GATE_QUESTIONNAIRES={[GATE_TYPES.API_PROTOTYPE]:BLINK_GENERIC_QUESTIONNAIRE,[GATE_TYPES.API_ORIGIN_TRIAL]:BLINK_GENERIC_QUESTIONNAIRE,[GATE_TYPES.API_EXTEND_ORIGIN_TRIAL]:BLINK_GENERIC_QUESTIONNAIRE,[GATE_TYPES.API_SHIP]:BLINK_GENERIC_QUESTIONNAIRE,[GATE_TYPES.API_PLAN]:BLINK_GENERIC_QUESTIONNAIRE,[GATE_TYPES.PRIVACY_ORIGIN_TRIAL]:PRIVACY_GENERIC_QUESTIONNAIRE,[GATE_TYPES.PRIVACY_SHIP]:PRIVACY_GENERIC_QUESTIONNAIRE,[GATE_TYPES.SECURITY_ORIGIN_TRIAL]:SECURITY_GENERIC_QUESTIONNAIRE,[GATE_TYPES.SECURITY_SHIP]:SECURITY_GENERIC_QUESTIONNAIRE,[GATE_TYPES.ENTERPRISE_SHIP]:ENTERPRISE_SHIP_QUESTIONNAIRE,[GATE_TYPES.ENTERPRISE_PLAN]:ENTERPRISE_SHIP_QUESTIONNAIRE,[GATE_TYPES.DEBUGGABILITY_ORIGIN_TRIAL]:DEBUGGABILITY_ORIGIN_TRIAL_QUESTIONNAIRE,[GATE_TYPES.DEBUGGABILITY_SHIP]:DEBUGGABILITY_SHIP_QUESTIONNAIRE,[GATE_TYPES.DEBUGGABILITY_PLAN]:DEBUGGABILITY_SHIP_QUESTIONNAIRE,[GATE_TYPES.TESTING_SHIP]:TESTING_SHIP_QUESTIONNAIRE,[GATE_TYPES.TESTING_PLAN]:TESTING_SHIP_QUESTIONNAIRE},LAUNCHING_FEATURES_URL="https://www.chromium.org/blink/launching-features/",BLINK_GENERIC_RATIONALE=x$1` + The API Owners review provides a final check on all aspects of your feature + and how you have followed the + <a href=${LAUNCHING_FEATURES_URL} target="_blank">Blink launch process</a>. +`,PRIVACY_GENERIC_RATIONALE=x$1` + The Web Platform privacy review puts you in touch with the privacy team so + that they can consult further with you when needed. +`,SECURITY_GENERIC_RATIONALE=x$1` + The Web Platform Security review helps ensure that new or changed web APIs + uphold the security principles of the web - the same origin policy, no + cross-site leaks, compliance with CSP, CORS, permission norms, etc. It aims to + show that the API can be implemented safely. It doesn’t necessarily try to + prove that it has been implemented safely within Chromium - for Chrome team + features, that’s done by the Chrome launch review process. +`,ENTERPRISE_GENERIC_RATIONALE=x$1` + The enterprise review helps identify the impact of your feature on + enterprises. Features need to be enterprise-friendly. That is: + + <ul> + <li>Breaking changes need to have sufficient notice</li> + <li> + Breaking changes need to have a soft deadline and transition period where + feasible + </li> + <li>Admins need to have central controls where appropriate</li> + </ul> +`,DEBUGGABILITY_GENERIC_RATIONALE=x$1` + The debuggability review helps identify opportunities to make your feature + more successful by integrating with Chrome Dev Tools. +`,TESTING_GENERIC_RATIONALE=x$1` + The test review helps identify gaps in test coverage and ensures that all + crucial functionalities are thoroughly tested. This can lead to a more + polished final product and reduce the odds of missed defects and issues. +`,GATE_RATIONALE={[GATE_TYPES.API_PROTOTYPE]:BLINK_GENERIC_RATIONALE,[GATE_TYPES.API_ORIGIN_TRIAL]:BLINK_GENERIC_RATIONALE,[GATE_TYPES.API_EXTEND_ORIGIN_TRIAL]:BLINK_GENERIC_RATIONALE,[GATE_TYPES.API_SHIP]:BLINK_GENERIC_RATIONALE,[GATE_TYPES.API_PLAN]:BLINK_GENERIC_RATIONALE,[GATE_TYPES.PRIVACY_ORIGIN_TRIAL]:PRIVACY_GENERIC_RATIONALE,[GATE_TYPES.PRIVACY_SHIP]:PRIVACY_GENERIC_RATIONALE,[GATE_TYPES.SECURITY_ORIGIN_TRIAL]:SECURITY_GENERIC_RATIONALE,[GATE_TYPES.SECURITY_SHIP]:SECURITY_GENERIC_RATIONALE,[GATE_TYPES.ENTERPRISE_SHIP]:ENTERPRISE_GENERIC_RATIONALE,[GATE_TYPES.ENTERPRISE_PLAN]:ENTERPRISE_GENERIC_RATIONALE,[GATE_TYPES.DEBUGGABILITY_ORIGIN_TRIAL]:DEBUGGABILITY_GENERIC_RATIONALE,[GATE_TYPES.DEBUGGABILITY_SHIP]:DEBUGGABILITY_GENERIC_RATIONALE,[GATE_TYPES.DEBUGGABILITY_PLAN]:DEBUGGABILITY_GENERIC_RATIONALE,[GATE_TYPES.TESTING_SHIP]:TESTING_GENERIC_RATIONALE,[GATE_TYPES.TESTING_PLAN]:TESTING_GENERIC_RATIONALE};var __decorate$G=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashSurveyQuestions=class ChromedashSurveyQuestions extends i$4{constructor(){super(...arguments),this.loading=!0}static get styles(){return[...SHARED_STYLES,i$7` + #questionnaire { + padding: var(--content-padding-half); + border-radius: var(--border-radius); + background: var(--accordion-background); + } + #questionnaire * + * { + padding-top: var(--content-padding); + } + #questionnaire ul { + padding-left: var(--content-padding); + } + #questionnaire ol { + padding-left: var(--content-padding); + } + #questionnaire ol li { + list-style: auto; + } + .question { + padding: var(--content-padding-half); + } + .instructions { + padding: var(--content-padding-half); + margin-bottom: var(--content-padding-large); + } + `]}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}canEditSurvey(){return this.user&&(this.user.can_edit_all||this.user.editable_features.includes(this.feature.id))}renderQuestionnaireSkeleton(){return x$1` + <div id="questionnaire">Loading...</div> + <p class="instructions"> </p> + `}handleFieldChange(name,value){window.csClient.updateGate(this.feature.id,this.gate.id,null,{[name]:value}).then(()=>{this._fireEvent("refetch-needed",{})})}handleFieldKeyup(name,value){1>=(value||"").trim().length&&window.csClient.updateGate(this.feature.id,this.gate.id,null,{[name]:value})}renderBooleanField(name,desc){const value=this.gate.survey_answers?.[name];return x$1` + <li class="question"> + <sl-checkbox + name=${name} + ?checked=${value} + ?disabled=${!this.canEditSurvey()} + @sl-change=${e=>this.handleFieldChange(name,e.target?.checked)} + ></sl-checkbox> + ${desc} + </li> + `}renderStringField(name,desc){const value=this.gate.survey_answers?.[name];return x$1` + <li class="question"> + ${desc} + <sl-input + name="${name}" + size="small" + value=${value} + ?disabled=${!this.canEditSurvey()} + @sl-change=${e=>this.handleFieldChange(name,e.target?.value)} + @keyup=${e=>this.handleFieldKeyup(name,e.target?.value)} + ></sl-input> + </li> + `}renderTextField(name,desc){const value=this.gate.survey_answers?.[name];return x$1` + <li class="question"> + ${desc} + <sl-textarea + name="${name}" + size="small" + rows="2" + resize="auto" + value=${value} + ?disabled=${!this.canEditSurvey()} + @sl-change=${e=>this.handleFieldChange(name,e.target?.value)} + @keyup=${e=>this.handleFieldKeyup(name,e.target?.value)} + ></sl-textarea> + </li> + `}renderPrivacyForm(){return x$1` + <div id="questionnaire"> + <ol> + ${this.renderBooleanField("is_language_polyfill",x$1`This is a <b>new JS language construct</b> that has + <b>already been polyfillable</b>.`)} + ${this.renderBooleanField("is_api_polyfill",x$1`This is a <b>new API</b> that ergonomically provides a function + that was <b>already polyfillable under the same conditions</b>. By + "same conditions" we mean, for example, that if a polyfill was + only possible when the user has granted a certain permission, the + API respects the same permission.`)} + ${this.renderBooleanField("is_same_origin_css",x$1`This is a <b>CSS addition</b> or change such that the style + <b>only depends on same-origin information</b> and + <b>NOT on user data</b>. CSS changes are usually benign, however: + if the style relies on iframes or subresources, it could reveal + cross-origin information. If the style depends on user data, such + as browsing history (like :visited), cookies, or user input (like + hidden=until-found), the style could be used by the website to + read this data.`)} + ${this.renderStringField("launch_or_contact",x$1`If there is a Google-internal launch entry filed for this exact + same issue, enter its URL here. Or, if this has previously been + discussed with someone on the privacy team, enter their email + address. Or, enter "None".`)} + ${this.renderTextField("explanation",x$1`<b>Required</b>: If you checked any box above, explain why you + checked it, and provide any other relevant context.`)} + </ol> + </div> + `}renderTestingForm(){return x$1` + <div id="questionnaire"> + Does your feature have WPT or other automated tests that cover the + following? + <ol> + ${this.renderBooleanField("covers_existence",x$1`<b>Feature existence</b>. This is typically done with + surface-level tests like idlharness.js for APIs or + parsing-testcommon.js for CSS. These tests don’t verify actual + behavior. + <a + href="https://wpt.fyi/results/idle-detection/idlharness.https.window.html" + target="_blank" + >API example</a + >. + <a + href="https://wpt.fyi/results/css/css-logical/parsing/inset-valid.html" + target="_blank" + >CSS example</a + >.`)} + ${this.renderBooleanField("covers_common_cases",x$1`<b>Common use cases</b>. Use the feature in a realistic and + straightforward way and verify the expected behavior. + <a + href="https://github.com/web-platform-tests/wpt/blob/master/requestidlecallback/basic.html" + target="_blank" + >API example</a + >. + <a + href="https://wpt.fyi/results/css/css-flexbox/gap-001-ltr.html" + target="_blank" + >CSS example</a + >. + <a href="https://wpt.fyi/results/cors/basic.htm" target="_blank" + >HTML example</a + >.`)} + ${this.renderBooleanField("covers_errors",x$1`<b>Likely error scenarios</b>. Test realistic error scenarios + like out-of-bounds inputs, network errors, or the user rejecting a + permission prompt. + <a + href="https://wpt.fyi/results/fetch/api/basic/error-after-response.any.html" + target="_blank" + >API example</a + >. + <a + href="https://wpt.fyi/results/css/css-color/hsl-clamp-negative-saturation.html" + target="_blank" + >CSS example</a + >. + <a + href="https://wpt.fyi/results/client-hints/accept-ch-malformed-header.https.html" + target="_blank" + >HTML example</a + >. `)} + ${this.renderBooleanField("covers_invalidation",x$1`<b>Invalidation</b>. Rendering or other output often needs to + be invalidated when the inputs change. This kind of test is common + for CSS features, but can make sense for other features too. Often + called “dynamic†when an initial state is updated by script. Or, + if your feature needs no invalidation tests, check this box. + <a + href="https://wpt.fyi/results/dom/nodes/Element-childElementCount-dynamic-add.html" + target="_blank" + >API example</a + >. + <a + href="https://wpt.fyi/results/css/css-content/quotes-lang-dynamic-001.html" + target="_blank" + >CSS example</a + >. `)} + ${this.renderBooleanField("covers_integration",x$1`<b>Integration with other features</b>. If the feature + integrates with other features in some meaningful way, test that + the combination of the two features behaves as expected. Or, if + your feature needs no integration tests, check this box. + <a + href="https://wpt.fyi/results/permissions-policy/reporting/fullscreen-reporting.html" + target="_blank" + >API example</a + >. + <a + href="https://wpt.fyi/results/css/css-anchor-position/anchor-scroll-to-sticky-001.html" + target="_blank" + >CSS example</a + >. + <a + href="https://wpt.fyi/results/clear-site-data/set-cookie-before-clear-cookies.https.html" + target="_blank" + >HTML example</a + >. `)} + </ol> + </div> + `}renderQuestionnaire(){if(this.gate.gate_type===GATE_TYPES.PRIVACY_ORIGIN_TRIAL||this.gate.gate_type===GATE_TYPES.PRIVACY_SHIP)return this.renderPrivacyForm();if(this.gate.gate_type===GATE_TYPES.TESTING_PLAN||this.gate.gate_type===GATE_TYPES.TESTING_SHIP)return this.renderTestingForm();const questionnaireText=GATE_QUESTIONNAIRES[this.gate.gate_type];if(!questionnaireText)return x$1`No questions`;const markup="string"==typeof questionnaireText?autolink(questionnaireText):questionnaireText;return x$1` + <div id="questionnaire">${markup}</div> + <p class="instructions">Please post responses in the comments below.</p> + `}render(){return x$1` + <h2>Survey questions</h2> + ${this.loading?this.renderQuestionnaireSkeleton():this.renderQuestionnaire()} + `}};__decorate$G([n$5({type:Object})],ChromedashSurveyQuestions.prototype,"user",void 0),__decorate$G([r$6()],ChromedashSurveyQuestions.prototype,"feature",void 0),__decorate$G([r$6()],ChromedashSurveyQuestions.prototype,"gate",void 0),__decorate$G([r$6()],ChromedashSurveyQuestions.prototype,"loading",void 0),ChromedashSurveyQuestions=__decorate$G([t$3("chromedash-survey-questions")],ChromedashSurveyQuestions);var __decorate$F=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let naRationalDialogEl;async function openNaRationaleDialog(gate){return naRationalDialogEl||(naRationalDialogEl=document.createElement("chromedash-na-rationale-dialog"),document.body.appendChild(naRationalDialogEl),await naRationalDialogEl.updateComplete),new Promise(resolve=>{naRationalDialogEl.openOn(gate,resolve)})}let ChromedashNaRationaleDialog=class ChromedashNaRationaleDialog extends i$4{constructor(){super(...arguments),this.rationaleDialogRef=e$1(),this.rationaleRef=e$1(),this.gate=void 0,this.resolve=()=>{console.log("Missing resolve action")}}static get styles(){return[...SHARED_STYLES,i$7``]}openOn(gate,resolve){this.gate=gate,this.resolve=resolve,this.rationaleDialogRef.value?.show()}handlePost(){this.resolve(this.rationaleRef.value?.value),this.rationaleDialogRef.value?.hide()}renderDialogContent(){return void 0===this.gate?E$1:x$1` + <p style="padding: var(--content-padding)"> + Please briefly explain why your feature does not require a review. Your + response will be posted as a comment on this review gate and it will + generate a notification to the reviewers. The ${this.gate.team_name} + reviewers will still evaluate whether to give an "N/A" response or do a + review. + </p> + <sl-textarea ${n$2(this.rationaleRef)}></sl-textarea> + <sl-button + slot="footer" + variant="primary" + size="small" + @click=${this.handlePost} + >Post</sl-button + > + `}render(){return x$1` + <sl-dialog ${n$2(this.rationaleDialogRef)} label="Request an N/A"> + ${this.renderDialogContent()} + </sl-dialog> + `}};__decorate$F([n$5({type:Object,attribute:!1})],ChromedashNaRationaleDialog.prototype,"gate",void 0),__decorate$F([n$5({attribute:!1})],ChromedashNaRationaleDialog.prototype,"resolve",void 0),ChromedashNaRationaleDialog=__decorate$F([t$3("chromedash-na-rationale-dialog")],ChromedashNaRationaleDialog);var __decorate$E=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let certifyDialogEl;function shouldShowCertifyDialog(gate){return gate.self_certify_possible&&gate.self_certify_eligible}async function maybeOpenCertifyDialog(gate,voteValue){return shouldShowCertifyDialog(gate)?new Promise(resolve=>{openCertifyDialog(gate,voteValue,resolve)}):Promise.resolve()}async function openCertifyDialog(gate,voteValue,resolve){certifyDialogEl||(certifyDialogEl=document.createElement("chromedash-self-certify-dialog"),document.body.appendChild(certifyDialogEl)),certifyDialogEl.gate=gate,certifyDialogEl.voteValue=voteValue,certifyDialogEl.resolve=resolve,await certifyDialogEl.updateComplete,certifyDialogEl.show()}let ChromedashSelfCertifyDialog=class ChromedashSelfCertifyDialog extends i$4{constructor(){super(...arguments),this.resolve=()=>{console.log("Missing resolve action")}}static get styles(){return[...SHARED_STYLES,i$7` + #prereqs-list li { + margin-left: 8px; + margin-bottom: 8px; + } + #prereqs-header { + margin-bottom: 8px; + } + sl-button { + float: right; + margin: var(--content-padding-half); + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}handleSelfCertify(){this.resolve(!0),this.hide()}handleFullReview(){this.resolve(!1),this.hide()}renderContentWhenEligible(){const voteWord=this.voteValue==VOTE_OPTIONS.APPROVED[0]?"approval":"N/A";return x$1` + <div id="prereqs-header"> + Based on your answers to the survey questions, you may self-certify an + ${voteWord} for this gate. Alternatively, if you want to start a + consulation with the review team, you may request a full review. + </div> + <br /> + <sl-button size="small" @click=${this.handleFullReview} + >Request full review</sl-button + > + <sl-button size="small" variant="primary" @click=${this.handleSelfCertify} + >Self-certify ${voteWord}</sl-button + > + `}render(){return void 0===this.gate?x$1`Loading gates...`:x$1` <sl-dialog label="Self-certification"> + ${this.renderContentWhenEligible()} + </sl-dialog>`}};__decorate$E([n$5({type:Object})],ChromedashSelfCertifyDialog.prototype,"gate",void 0),__decorate$E([n$5({type:Number})],ChromedashSelfCertifyDialog.prototype,"voteValue",void 0),__decorate$E([n$5({attribute:!1})],ChromedashSelfCertifyDialog.prototype,"resolve",void 0),ChromedashSelfCertifyDialog=__decorate$E([t$3("chromedash-self-certify-dialog")],ChromedashSelfCertifyDialog);var __decorate$D=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let secondarySurveyDialogEl;function isTestingGate(gate){return gate.gate_type===GATE_TYPES.TESTING_PLAN||gate.gate_type===GATE_TYPES.TESTING_SHIP}function shouldShowSecondarySurveyDialog(gate){return isTestingGate(gate)}async function maybeOpenSecondarySurveyDialog(gate){return shouldShowSecondarySurveyDialog(gate)?new Promise(resolve=>{openSecondarySurveyDialog(gate,resolve)}):Promise.resolve()}async function openSecondarySurveyDialog(gate,resolve){secondarySurveyDialogEl||(secondarySurveyDialogEl=document.createElement("chromedash-secondary-survey-dialog"),document.body.appendChild(secondarySurveyDialogEl)),secondarySurveyDialogEl.gate=gate,secondarySurveyDialogEl.resolve=resolve,await secondarySurveyDialogEl.updateComplete,secondarySurveyDialogEl.show()}let ChromedashSecondarySurveyDialog=class ChromedashSecondarySurveyDialog extends i$4{constructor(){super(...arguments),this.resolve=()=>{console.log("Missing resolve action")}}static get styles(){return[...SHARED_STYLES,i$7` + ol { + padding-left: var(--content-padding-half); + } + + ol li { + margin-bottom: var(--content-padding); + } + sl-button { + float: right; + margin: var(--content-padding-half); + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}generateTestingComment(){const answer1=this.renderRoot.querySelector("#coverage").value,answer2=this.renderRoot.querySelector("#performance_tests").value,answer3=this.renderRoot.querySelector("#automation").value,answer4=this.renderRoot.querySelector("#impact").value,commentText=`Survey answers: +> 1. Does your feature have sufficient automated +> test coverage (Unit tests, WPT, browser tests +> and other integration tests)? + +${answer1} + +> 2. How are performance tests conducted on +> Chromium builders? + +${answer2} + +> 3. Does this feature have non-automatable test +> cases that require manual testing? Do you have +> a plan to get them tested? + +${answer3} + +> 4. If your feature impacts Google products, +> please fill in go/chrome-wp-test-survey. + +${answer4} +`;this.resolve(commentText)}handleGenerateComment(){isTestingGate(this.gate)&&this.generateTestingComment(),this.hide()}renderTestingContent(){const option1a="Yes. My feature met the minimum automated test coverage and health requirements.",option1b="No. My feature does not meet the requirements.",option3a="No. All feature related test cases are automated.",option3b="Yes. There are non-automatable test cases and I have completed test execution or allocated resources to ensure the coverage of these test cases.",option3c="Yes. There are non-automatable test cases and my feature impacts Google products.";return x$1` + <ol> + <li> + <b + >Does your feature have sufficient automated test coverage (Unit + tests, WPT, browser tests and other integration tests)?</b + > + Chrome requires at least 70% automation code coverage (<a + href="https://analysis.chromium.org/coverage/p/chromium" + target="_blank" + >dashboard</a + >) running on the main/release branch and 70% Changelist + <a + href="https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/testing/code_coverage_in_gerrit.md" + target="_blank" + >code coverage in Gerrit</a + >? Do the automated tests have more than 93% green (flakiness < 7%) on + CQ and CI builders? + + <sl-radio-group id="coverage"> + <sl-radio value="${"Yes. My feature met the minimum automated test coverage and health requirements."}" size="small"> ${"Yes. My feature met the minimum automated test coverage and health requirements."} </sl-radio> + <sl-radio value="${option1b}" size="small"> ${option1b} </sl-radio> + </sl-radio-group> + </li> + + <li> + <b>How are performance tests conducted on Chromium builders?</b> List + links to tests if any. + + <sl-textarea id="performance_tests" size="small" rows="2"> + </sl-textarea> + </li> + + <li> + <b + >Does this feature have non-automatable test cases that require + manual testing? Do you have a plan to get them tested?</b + > + + <sl-radio-group id="automation"> + <sl-radio value="${option3a}" size="small"> ${option3a} </sl-radio> + <sl-radio value="${option3b}" size="small"> ${option3b} </sl-radio> + <sl-radio value="${option3c}" size="small"> ${option3c} </sl-radio> + </sl-radio-group> + </li> + + <li> + <b + >If your feature impacts Google products, please fill in + <a href="http://go/chrome-wp-test-survey" target="_blank" + >go/chrome-wp-test-survey</a + >.</b + > + Make a copy, answer the survey questions, and provide a link to your + document here. + <sl-textarea id="impact" size="small" rows="2"> </sl-textarea> + </li> + </ol> + `}render(){return void 0===this.gate?x$1`Loading gates...`:x$1` <sl-dialog label="Additional questions"> + ${isTestingGate(this.gate)?this.renderTestingContent():E$1} + <div> + <sl-button + id="generate_button" + size="small" + variant="primary" + @click=${this.handleGenerateComment} + >Generate comment and request review</sl-button + > + </div> + </sl-dialog>`}};__decorate$D([n$5({type:Object})],ChromedashSecondarySurveyDialog.prototype,"gate",void 0),__decorate$D([n$5({attribute:!1})],ChromedashSecondarySurveyDialog.prototype,"resolve",void 0),ChromedashSecondarySurveyDialog=__decorate$D([t$3("chromedash-secondary-survey-dialog")],ChromedashSecondarySurveyDialog);var __decorate$C=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let prevoteDialogEl;function findMissingFields(feature){const missingFields=[];return feature.web_feature&&"Missing feature"!==feature.web_feature||missingFields.push({name:"Web feature",field:"web_feature"}),missingFields}function shouldShowPrevoteDialog(feature,pendingGates,gate,vote){return(0<pendingGates.length||0<findMissingFields(feature).length)&&gate.gate_type==GATE_TYPES.API_SHIP&&vote==VOTE_OPTIONS.APPROVED[0]}async function maybeOpenPrevoteDialog(feature,featureGates,stage,gate,vote){const pendingGates=findPendingGates(featureGates,stage);return shouldShowPrevoteDialog(feature,pendingGates,gate,vote)?new Promise(resolve=>{openPrevoteDialog(feature,pendingGates,resolve)}):Promise.resolve()}async function openPrevoteDialog(feature,pendingGates,resolve){prevoteDialogEl||(prevoteDialogEl=document.createElement("chromedash-prevote-dialog"),document.body.appendChild(prevoteDialogEl)),prevoteDialogEl.feature=feature,prevoteDialogEl.pendingGates=pendingGates,prevoteDialogEl.resolve=resolve,await prevoteDialogEl.updateComplete,prevoteDialogEl.show()}let ChromedashPrevoteDialog=class ChromedashPrevoteDialog extends i$4{constructor(){super(...arguments),this.resolve=()=>{console.log("Missing resolve action")}}static get styles(){return[...SHARED_STYLES,i$7` + #prereqs-list li { + margin-left: 8px; + margin-bottom: 8px; + } + #prereqs-header { + margin-bottom: 8px; + } + sl-button { + float: right; + margin: var(--content-padding-half); + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}handleCancel(){this.hide()}handleProceed(){this.resolve(),this.hide()}renderGateItem(gate){return x$1` + <li> + <a + href="/feature/${gate.feature_id}?gate=${gate.id}" + @click=${this.hide} + >${gate.team_name}</a + > + </li> + `}renderGatesSection(){return void 0===this.pendingGates?x$1`Loading gates...`:0==this.pendingGates.length?E$1:x$1` + <div id="gates-header">The following gates are missing approvals:</div> + <ul id="gates-list"> + ${this.pendingGates.map(gate=>this.renderGateItem(gate))} + </ul> + <br /> + `}renderEditLink(item){return x$1` + <a + class="edit-progress-item" + href="/guide/stage/${this.feature.id}/metadata#id_${item.field}" + @click=${this.hide} + > + Edit + </a> + `}renderFieldItem(item){return x$1` <li class="pending"> + Metadata: ${item.name} ${this.renderEditLink(item)} + </li>`}renderFieldsSection(){const missingFields=findMissingFields(this.feature);return 0==missingFields.length?E$1:x$1` + <div id="fields-header"> + The following prerequisite fields are missing: + </div> + <ul id="fields-list"> + ${missingFields.map(mf=>this.renderFieldItem(mf))} + </ul> + <br /> + `}render(){return x$1` <sl-dialog label="Prerequsites for API Owner approval"> + ${this.renderFieldsSection()} ${this.renderGatesSection()} + <sl-button size="small" @click=${this.handleProceed} + >Approve anyway</sl-button + > + <sl-button size="small" variant="warning" @click=${this.handleCancel} + >Don't approve yet</sl-button + > + </sl-dialog>`}};__decorate$C([n$5({type:Object})],ChromedashPrevoteDialog.prototype,"feature",void 0),__decorate$C([n$5({type:Array})],ChromedashPrevoteDialog.prototype,"pendingGates",void 0),__decorate$C([n$5({attribute:!1})],ChromedashPrevoteDialog.prototype,"resolve",void 0),ChromedashPrevoteDialog=__decorate$C([t$3("chromedash-prevote-dialog")],ChromedashPrevoteDialog);var __decorate$B=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGateColumn=class ChromedashGateColumn extends i$4{constructor(){super(...arguments),this.voteSelectRef=e$1(),this.commentAreaRef=e$1(),this.postToThreadRef=e$1(),this.assigneeSelectRef=e$1(),this.votes=[],this.comments=[],this.needsSave=!1,this.showSaved=!1,this.submittingComment=!1,this.submittingVote=!1,this.needsPost=!1,this.loading=!0}static get styles(){return[...SHARED_STYLES,i$7` + #close-button { + font-size: 2em; + position: absolute; + top: var(--content-padding-quarter); + right: var(--content-padding-quarter); + } + + #review-status-area { + margin: var(--content-padding-half) 0; + } + .status { + display: flex; + gap: var(--content-padding-half); + align-items: center; + font-weight: 500; + } + sl-icon { + font-size: 1.3rem; + } + .approved { + color: var(--gate-approved-color); + } + .approved sl-icon { + color: var(--gate-approved-icon-color); + } + .denied { + color: var(--gate-denied-color); + } + .denied sl-icon { + color: var(--gate-denied-icon-color); + } + #slo-area sl-icon { + font-size: 16px; + vertical-align: text-bottom; + color: var(--unimportant-text-color); + } + .overdue, + #slo-area .overdue sl-icon { + color: var(--slo-overdue-color); + } + + .process-notice { + margin: var(--content-padding-half) 0; + padding: var(--content-padding-half); + background: var(--light-accent-color); + border-radius: 8px; + } + + #votes-area { + margin: var(--content-padding) 0; + } + #votes-area table { + border-spacing: var(--content-padding-half) var(--content-padding); + } + #votes-area th { + font-weight: 500; + } + table .your-vote { + font-style: italic; + white-space: nowrap; + } + + .instructions { + padding: var(--content-padding-half); + margin-bottom: var(--content-padding-large); + } + + #controls { + padding: var(--content-padding); + text-align: right; + display: flex; + justify-content: space-between; + align-items: center; + } + #controls * + * { + padding-left: var(--content-padding); + } + `]}setContext(feature,stageId,gate){this.loading=!0,this.feature=feature,this.gate=gate;const featureId=this.feature.id;Promise.all([window.csClient.getFeatureProgress(featureId),window.csClient.getFeatureProcess(featureId),window.csClient.getStage(featureId,stageId),window.csClient.getVotes(featureId,null),window.csClient.getComments(featureId,gate.id)]).then(([progress,process,stage,votesRes,commentRes])=>{this.progress=progress,this.process=process,this.stage=stage,this.votes=votesRes.votes.filter(v=>v.gate_id==this.gate.id),this.comments=commentRes.comments,this.needsSave=!1,this.showSaved=!1,this.submittingComment=!1,this.submittingVote=!1,this.needsPost=!1,this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),this.handleCancel()})}reloadComments(){const commentArea=this.commentAreaRef.value;commentArea&&(commentArea.value=""),this.needsPost=!1,Promise.all([window.csClient.getComments(this.feature.id,this.gate.id)]).then(([commentRes])=>{this.comments=commentRes.comments}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),this.handleCancel()})}refetch(){const featureId=this.feature.id;Promise.all([window.csClient.getGates(featureId),window.csClient.getVotes(featureId,null),window.csClient.getComments(featureId,this.gate.id)]).then(([gatesRes,votesRes,commentRes])=>{for(const g of gatesRes.gates)g.id==this.gate.id&&(this.gate=g);this.votes=votesRes.votes.filter(v=>v.gate_id==this.gate.id),this.comments=commentRes.comments,this.needsSave=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),this.handleCancel()})}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}checkNeedsPost(){let newNeedsPost=!1;const commentArea=this.commentAreaRef.value,newVal=commentArea&&commentArea.value.trim()||"";""!=newVal&&(newNeedsPost=!0),this.needsPost=newNeedsPost}handlePost(){const commentArea=this.commentAreaRef.value,commentText=commentArea?.value.trim(),postToThreadType=this.postToThreadRef.value?.checked?this.gate.gate_type:0;this.postComment(commentText,postToThreadType)}async postComment(commentText,postToThreadType=0){this.submittingVote=!0,""!=commentText&&(await window.csClient.postComment(this.feature.id,this.gate.id,commentText,+postToThreadType).then(()=>{this.reloadComments(),this.submittingVote=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),this.submittingVote=!1}))}handleSelectChanged(){this.needsSave=!0,this.showSaved=!1}saveVote(){this.submittingComment=!0;const vote=+this.voteSelectRef.value.value;window.csClient.setVote(this.feature.id,this.gate.id,vote).then(()=>{this.needsSave=!1,this.showSaved=!0,this.submittingComment=!1,this._fireEvent("refetch-needed",{})}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),this.submittingComment=!1})}handleSave(){Promise.all([window.csClient.getGates(this.feature.id)]).then(([gatesRes])=>{this.featureGates=gatesRes.gates;const vote=+this.voteSelectRef.value.value;maybeOpenPrevoteDialog(this.feature,this.featureGates,this.stage,this.gate,vote).then(()=>{this.saveVote()})}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleCancel(){this._fireEvent("close",{})}renderHeadingsSkeleton(){return x$1` + <h3 class="sl-skeleton-header-container" style="width: 60%"> + <sl-skeleton effect="sheen"></sl-skeleton> + </h3> + <h2 + class="sl-skeleton-header-container" + style="margin-top: 4px; width: 75%" + > + <sl-skeleton effect="sheen"></sl-skeleton> + </h2> + `}renderHeadings(){const processStage=findProcessStage(this.stage,this.process),processStageName=processStage?processStage.name:E$1;return x$1` + <h3>${processStageName}</h3> + <h2>${this.gate.team_name}</h2> + `}renderReviewStatusSkeleton(){return x$1` + <h3 class="sl-skeleton-header-container"> + Status: <sl-skeleton effect="sheen"></sl-skeleton> + </h3> + `}async handleReviewRequested(){const featureId=this.feature.id;window.csClient.getGates(featureId).then(gatesRes=>{for(const g of gatesRes.gates)g.id==this.gate.id&&(this.gate=g);maybeOpenCertifyDialog(this.gate,VOTE_NA_SELF).then(selfCertifying=>{selfCertifying?this.handleSelfCertify(VOTE_NA_SELF):maybeOpenSecondarySurveyDialog(this.gate).then(commentText=>{commentText&&this.postComment(commentText),this.handleFullReviewRequest()})})})}async handleNARequested(){const featureId=this.feature.id;window.csClient.getGates(featureId).then(gatesRes=>{for(const g of gatesRes.gates)g.id==this.gate.id&&(this.gate=g);maybeOpenCertifyDialog(this.gate,VOTE_NA_SELF).then(selfCertifying=>{selfCertifying?this.handleSelfCertify(VOTE_NA_SELF):this.handleFullNARequested()})})}handleFullNARequested(){openNaRationaleDialog(this.gate).then(rationale=>{this.handleNARequestSubmitted(rationale)})}async handleFullReviewRequest(){await window.csClient.setVote(this.feature.id,this.gate.id,GATE_REVIEW_REQUESTED),this._fireEvent("refetch-needed",{})}async handleSelfCertify(voteValue){await window.csClient.setVote(this.feature.id,this.gate.id,voteValue);const commentText="This \"N/A\" was self-certified.";await this.postComment("This \"N/A\" was self-certified."),this._fireEvent("refetch-needed",{})}async handleNARequestSubmitted(rationale){await window.csClient.setVote(this.feature.id,this.gate.id,GATE_NA_REQUESTED);const commentText="An \"N/A\" response is requested because: "+rationale;await this.postComment(commentText),this._fireEvent("refetch-needed",{})}userCanRequestReview(){return this.user&&(this.user.can_edit_all||this.user.editable_features.includes(this.feature.id))}userCanVote(){return this.user&&this.user.approvable_gate_types.includes(this.gate.gate_type)}renderAction(processStage,action){const label=action.name,url=action.url.replace("{feature_id}",this.feature.id).replace("{gate_id}",this.gate.id||0),checkCompletion=()=>somePendingPrereqs(action,this.progress)||somePendingGates(this.featureGates,this.stage)?void openPreflightDialog(this.feature,this.progress,this.process,action,processStage,this.stage,this.featureGates,url):void setTimeout(()=>{const draftWindow=window.open(url,"_blank");draftWindow.focus()}),loadThenCheckCompletion=()=>{Promise.all([window.csClient.getGates(this.feature.id)]).then(([gatesRes])=>{this.featureGates=gatesRes.gates,checkCompletion()}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})};return x$1` + <sl-button + @click=${loadThenCheckCompletion} + size="small" + variant="primary" + >${label}</sl-button + > + `}renderReviewStatusPreparing(){if(!this.userCanRequestReview())return x$1` Review has not been requested yet. `;const processStage=findProcessStage(this.stage,this.process);return 0<processStage?.actions?.length&&"API Owners"==this.gate.team_name?processStage.actions.map(act=>this.renderAction(processStage,act)):x$1` + <sl-button + size="small" + variant="primary" + @click=${this.handleReviewRequested} + >Request review</sl-button + > + <sl-button size="small" @click=${this.handleNARequested} + >Request N/A</sl-button + > + `}renderReviewStatusNeedsWork(){const rereviewButton=this.userCanRequestReview()?x$1` + <div> + <sl-button + size="small" + variant="primary" + @click=${this.handleReviewRequested} + >Re-request review</sl-button + > + </div> + `:E$1;return x$1` + <div>Reviewer has indicated a need for rework.</div> + ${rereviewButton} + `}renderReviewRequest(){for(const v of this.votes)if(v.state===GATE_REVIEW_REQUESTED||v.state===GATE_NA_REQUESTED){const shortVoter=v.set_by.split("@")[0]+"@";return x$1` + ${shortVoter} requested on + ${renderAbsoluteDate(this.gate.requested_on)} + ${renderRelativeDate(this.gate.requested_on)} + `}return E$1}renderReviewStatusApproved(){return x$1` + <div class="status approved"> + <sl-icon library="material" name="check_circle_filled_20px"></sl-icon> + Approved + </div> + `}renderReviewStatusNa(){return x$1` + <div class="status approved"> + <sl-icon library="material" name="check_circle_filled_20px"></sl-icon> + N/a + </div> + `}renderReviewStatusNaSelf(){return x$1` + <div class="status approved"> + <sl-icon library="material" name="check_circle_filled_20px"></sl-icon> + N/a (self-certified) + </div> + `}renderReviewStatusNaVerified(){return x$1` + <div class="status approved"> + <sl-icon library="material" name="check_circle_filled_20px"></sl-icon> + N/a (self-certified then verified) + </div> + `}renderReviewStatusDenied(){return x$1` + <div class="status denied"> + <sl-icon library="material" name="block_20px"></sl-icon> + Denied + </div> + `}renderReviewStatus(){return this.gate.state==GATE_PREPARING?this.renderReviewStatusPreparing():this.gate.state==VOTE_OPTIONS.NEEDS_WORK[0]?this.renderReviewStatusNeedsWork():this.gate.state==VOTE_OPTIONS.NA[0]?this.renderReviewStatusNa():this.gate.state==VOTE_NA_SELF?this.renderReviewStatusNaSelf():this.gate.state==VOTE_NA_VERIFIED?this.renderReviewStatusNaVerified():this.gate.state==VOTE_OPTIONS.APPROVED[0]?this.renderReviewStatusApproved():this.gate.state==VOTE_OPTIONS.DENIED[0]?this.renderReviewStatusDenied():E$1}renderSLOStatusSkeleton(){return x$1` + <details> + <summary>SLO initial response:</summary> + Loading... + </details> + <details> + <summary>SLO resolution:</summary> + Loading... + </details> + `}dayPhrase(count){return count+""+(1==count?" day":" days")}renderSLOSummary(limit,remaining,took){if("number"==typeof took)return x$1`took ${this.dayPhrase(took)}`;if("number"==typeof remaining){let msg=x$1`due today`,className="";return 0<remaining?msg=x$1`${this.dayPhrase(remaining)} remaining`:0>remaining&&(className="overdue",msg=x$1`${this.dayPhrase(-remaining)} overdue`),x$1` + <span class="${className}"> + <sl-icon library="material" name="clock_loader_60_20px"></sl-icon> + ${msg} + </span> + `}return"number"==typeof limit?x$1`${this.dayPhrase(limit)} allowed`:E$1}renderSLOStatus(){const initialLimit=this.gate?.slo_initial_response,initialRemaining=this.gate?.slo_initial_response_remaining,initialTook=this.gate?.slo_initial_response_took,resolveLimit=this.gate?.slo_resolve,resolveRemaining=this.gate?.slo_resolve_remaining,resolveTook=this.gate?.slo_resolve_took,needsWorkStartedOn=this.gate?.needs_work_started_on,initialLine=x$1` + <details> + <summary> + SLO initial response: + ${this.renderSLOSummary(initialLimit,initialRemaining,initialTook)} + </summary> + Reviewers are encouraged to provide an initial review status update or a + comment within this number of weekdays. + </details> + `;let resolveLine=x$1` + <details> + <summary> + SLO resolution: + ${this.renderSLOSummary(resolveLimit,resolveRemaining,resolveTook)} + </summary> + Reviewers are encouraged to resolve the review within this number of + weekdays. If a reviewer responds with "Needs work", this clock pauses + until a feature owner clicks "Re-request review". + </details> + `,needsWorkLine=E$1;return"string"==typeof needsWorkStartedOn&&(resolveLine=E$1,needsWorkLine=x$1` + <details> + <summary> + SLO resolution: Needs work since ${needsWorkStartedOn.split(" ")[0]} + </summary> + A reviewer has asked the feature owner to do needed work. Check the + comments for a description of the needed work. The SLO clock is paused + until a feature owner clicks "Re-request review". + </details> + `),x$1`${initialLine} ${resolveLine} ${needsWorkLine}`}renderGateRationale(){const rationale=GATE_RATIONALE[this.gate?.gate_type];return rationale?x$1` + <details> + <summary>Why this gate?</summary> + ${rationale} + </details> + `:E$1}renderWarnings(){return this.gate&&["Privacy","WP Security"].includes(this.gate.team_name)?x$1` + <div class="process-notice"> + Googlers: Please follow the instructions at + <a + href="https://goto.corp.google.com/wp-launch-guidelines" + target="_blank" + rel="noopener" + >go/wp-launch-guidelines</a + > + (internal document) to determine whether you also require an internal + review. + </div> + `:E$1}renderVotesSkeleton(){return x$1` + <table> + <tr> + <th>Reviewer</th> + <th>Review status</th> + </tr> + <tr> + <td><sl-skeleton effect="sheen"></sl-skeleton></td> + <td><sl-skeleton effect="sheen"></sl-skeleton></td> + </tr> + </table> + `}findStateName(state){if(state==GATE_REVIEW_REQUESTED)return"Review requested";if(state==VOTE_NA_SELF)return"N/a (self-certified)";if(state==VOTE_NA_VERIFIED)return"N/a (verified)";for(const item of Object.values(VOTE_OPTIONS))if(item[0]==state)return item[1];return`State ${state}`}renderVoteReadOnly(vote){return this.findStateName(vote.state)}renderVoteMenu(state){return x$1` + <sl-select + name="${this.gate.id}" + value="${state}" + ${n$2(this.voteSelectRef)} + @sl-change=${this.handleSelectChanged} + hoist + size="small" + > + ${this.votes.some(v=>v.state===VOTE_NA_SELF||v.state===VOTE_NA_VERIFIED)?x$1` <sl-option value="${VOTE_NA_VERIFIED}" + >N/a verified</sl-option + >`:E$1} + ${Object.values(VOTE_OPTIONS).map(valName=>x$1` <sl-option value="${valName[0]}">${valName[1]}</sl-option>`)} + </sl-select> + `}renderSaveButton(){return x$1` + <sl-button + size="small" + variant="primary" + @click=${this.handleSave} + ?disabled=${this.submittingComment} + >Save</sl-button + > + `}renderVoteRow(vote,canVote){const shortVoter=vote.set_by.split("@")[0]+"@";let saveButton=E$1,voteCell=this.renderVoteReadOnly(vote);return canVote&&vote.set_by==this.user?.email&&(voteCell=this.renderVoteMenu(vote.state),this.needsSave?saveButton=this.renderSaveButton():this.showSaved&&(saveButton=x$1`<b>Saved</b>`)),x$1` + <tr> + <td title=${vote.set_by}>${shortVoter}</td> + <td>${voteCell}</td> + <td>${saveButton}</td> + </tr> + `}renderAddVoteRow(){const assignedToMe=this.gate.assignee_emails.includes(this.user.email),shortVoter=this.user.email.split("@")[0]+"@",yourLabel=assignedToMe?x$1`<td title=${this.user.email}>${shortVoter}</td>`:x$1`<td class="your-vote">Awaiting review</td>`,voteCell=this.renderVoteMenu(VOTE_OPTIONS.NO_RESPONSE[0]),saveButton=this.needsSave?this.renderSaveButton():E$1;return x$1` + <tr> + ${yourLabel} + <td>${voteCell}</td> + <td>${saveButton}</td> + </tr> + `}renderPendingVote(assigneeEmail){const shortVoter=assigneeEmail.split("@")[0]+"@";return x$1` + <tr> + <td title=${assigneeEmail}>${shortVoter}</td> + <td>No response yet</td> + <td></td> + </tr> + `}saveAssignedReviewer(){const assignee=this.assigneeSelectRef.value?.value,assigneeList=""===assignee?[]:[assignee];window.csClient.updateGate(this.feature.id,this.gate.id,assigneeList).then(()=>this._fireEvent("refetch-needed",{}))}renderAssignReviewerControls(){if(!this.userCanRequestReview()&&!this.userCanVote())return E$1;if(this.gate.state===VOTE_OPTIONS.APPROVED[0])return E$1;const currentAssignee=0<this.gate.assignee_emails?.length?this.gate.assignee_emails[0]:"";return x$1` + <details> + <summary>Assign a reviewer</summary> + <sl-select + hoist + size="small" + ${n$2(this.assigneeSelectRef)} + value=${currentAssignee} + > + <sl-option value="">None</sl-option> + ${this.gate.possible_assignee_emails.map(email=>x$1` <sl-option value="${email}">${email}</sl-option>`)} + </sl-select> + <sl-button + size="small" + variant="primary" + @click=${()=>this.saveAssignedReviewer()} + >Assign</sl-button + > + </details> + `}isReviewRequest(vote){return vote.state===GATE_REVIEW_REQUESTED||vote.state===GATE_NA_REQUESTED}renderVotes(){const canVote=this.userCanVote(),responses=this.votes.filter(v=>!this.isReviewRequest(v)),responseEmails=responses.map(v=>v.set_by),othersPending=this.gate.assignee_emails.filter(ae=>!responseEmails.includes(ae)&&ae!=this.user?.email),myResponseExists=responses.some(v=>v.set_by==this.user?.email),addVoteRow=canVote&&!myResponseExists?this.renderAddVoteRow():E$1,assignControls=this.renderAssignReviewerControls();return canVote||0!==responses.length||0!==othersPending.length?x$1` + <table> + <tr> + <th>Reviewer</th> + <th>Review status</th> + </tr> + ${responses.map(v=>this.renderVoteRow(v,canVote))} + ${othersPending.map(ae=>this.renderPendingVote(ae))} ${addVoteRow} + </table> + ${assignControls} + `:x$1` + <p>No review activity yet.</p> + ${assignControls} + `}renderCommentsSkeleton(){return x$1` + <h2>Comments</h2> + <sl-skeleton effect="sheen"></sl-skeleton> + `}gateHasIntentThread(){return"API Owners"===this.gate.team_name}canPostTo(threadArchiveUrl){return threadArchiveUrl&&(threadArchiveUrl.startsWith("https://groups.google.com/a/chromium.org/d/msgid/blink-dev/")||threadArchiveUrl.startsWith("https://groups.google.com/d/msgid/jrobbins-test"))}renderControls(){const canComment=this.user?.can_comment||this.userCanRequestReview();if(!canComment)return E$1;const postButton=x$1` + <sl-button + variant="primary" + @click=${this.handlePost} + ?disabled=${!this.needsPost||this.submittingVote} + size="small" + >Post</sl-button + > + `,checkboxLabel=this.stage.intent_thread_url?x$1` + Also post to + <a href=${this.stage.intent_thread_url} target="_blank" + >intent thread</a + > + `:"Also post to intent thread",postToThreadCheckbox=this.gateHasIntentThread()?x$1` + <sl-checkbox + ${n$2(this.postToThreadRef)} + ?disabled=${!this.canPostTo(this.stage.intent_thread_url)} + size="small" + >${checkboxLabel}</sl-checkbox + > + `:E$1,escalation=this.gate.escalation_email?x$1`If needed, you can + <a href="mailto:${this.gate.escalation_email}" target="_blank" + >email the team directly</a + >.`:E$1;return x$1` + <sl-textarea + id="comment_area" + rows="2" + cols="40" + resize="auto" + ${n$2(this.commentAreaRef)} + @sl-change=${this.checkNeedsPost} + @keypress=${this.checkNeedsPost} + placeholder="Add a comment" + ></sl-textarea> + <div id="controls">${postButton} ${postToThreadCheckbox}</div> + <div class="instructions"> + Comments will be visible publicly. Only reviewers will be notified when + a comment is posted. ${escalation} + </div> + `}renderComments(){return x$1` + <h2>Comments</h2> + ${this.renderControls()} + <chromedash-activity-log + .user=${this.user} + .featureId=${this.feature.id} + .narrow=${!0} + .reverse=${!0} + .comments=${this.comments} + > + </chromedash-activity-log> + `}render(){return x$1` + <sl-icon-button + title="Close" + name="x" + id="close-button" + @click=${()=>this.handleCancel()} + ></sl-icon-button> + + ${this.loading?this.renderHeadingsSkeleton():this.renderHeadings()} + + <div id="review-status-area"> + ${this.loading?this.renderReviewStatusSkeleton():this.renderReviewStatus()} + ${this.renderReviewRequest()} + </div> + <div id="slo-area"> + ${this.loading?this.renderSLOStatusSkeleton():this.renderSLOStatus()} + ${this.renderGateRationale()} + </div> + + ${this.renderWarnings()} + + <div id="votes-area"> + ${this.loading?this.renderVotesSkeleton():this.renderVotes()} + </div> + + <chromedash-survey-questions + .loading=${this.loading} + .user=${this.user} + .feature=${this.feature} + .gate=${this.gate} + ></chromedash-survey-questions> + ${this.loading?this.renderCommentsSkeleton():this.renderComments()} + `}};__decorate$B([n$5({type:Object})],ChromedashGateColumn.prototype,"user",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"feature",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"featureGates",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"stage",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"gate",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"progress",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"process",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"votes",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"comments",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"needsSave",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"showSaved",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"submittingComment",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"submittingVote",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"needsPost",void 0),__decorate$B([r$6()],ChromedashGateColumn.prototype,"loading",void 0),ChromedashGateColumn=__decorate$B([t$3("chromedash-gate-column")],ChromedashGateColumn);const u=(e,s,t)=>{const r=new Map;for(let l=s;l<=t;l++)r.set(e[l],l);return r},c=e$3(class extends i$3{constructor(e){if(super(e),e.type!==t.CHILD)throw Error("repeat() can only be used in text expressions")}dt(e,s,t){let r;void 0===t?t=s:void 0!==s&&(r=s);const l=[],o=[];let i=0;for(const s of e)l[i]=r?r(s,i):i,o[i]=t(s,i),i++;return{values:o,keys:l}}render(e,s,t){return this.dt(e,s,t).values}update(s,[t,r,c]){const d=p(s),{values:p$1,keys:a}=this.dt(t,r,c);if(!Array.isArray(d))return this.ut=a,p$1;const h=this.ut??=[],v=[];let x=0,j=d.length-1,k=0,w=p$1.length-1,m,y;for(;x<=j&&k<=w;)if(null===d[x])x++;else if(null===d[j])j--;else if(h[x]===a[k])v[k]=v$1(d[x],p$1[k]),x++,k++;else if(h[j]===a[w])v[w]=v$1(d[j],p$1[w]),j--,w--;else if(h[x]===a[w])v[w]=v$1(d[x],p$1[w]),s$1(s,v[w+1],d[x]),x++,w--;else if(h[j]===a[k])v[k]=v$1(d[j],p$1[k]),s$1(s,d[x],d[j]),j--,k++;else if(!(void 0===m&&(m=u(a,k,w),y=u(h,x,j)),m.has(h[x])))M$1(d[x]),x++;else if(m.has(h[j])){const e=y.get(a[k]),t=void 0===e?null:d[e];if(null===t){const e=s$1(s,d[x]);v$1(e,p$1[k]),v[k]=e}else v[k]=v$1(t,p$1[k]),s$1(s,d[x],t),d[e]=null;k++}else M$1(d[j]),j--;for(;k<=w;){const e=s$1(s,v[w+1]);v$1(e,p$1[k]),v[k++]=e}for(;x<=j;){const e=d[x++];null!==e&&M$1(e)}return this.ut=a,m$1(s,v),T$1}});var __decorate$A=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGuideEditallPage=class ChromedashGuideEditallPage extends i$4{constructor(){super(...arguments),this.featureId=0,this.appTitle="",this.nextStageToCreateId=0,this.loading=!0,this.submitting=!1,this.previousStageTypeRendered=0,this.sameTypeRendered=0,this.fieldValues=[],this.shippingInfo={closestShippingDate:"",hasShipped:!1,isUpcoming:!1}}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + .enterprise-help-text > *, + .enterprise-help-text li { + margin: revert; + padding: revert; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){this.loading=!0,Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getChannels()]).then(async([feature,channels])=>{this.feature=feature,this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.shippingInfo=await findClosestShippingDate(channels,feature.stages),this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerHandlers(el){if(!el)return;await el.updateComplete;const hiddenTokenField=this.renderRoot.querySelector("input[name=token]");hiddenTokenField.form?.addEventListener("submit",event=>{this.handleFormSubmit(event,hiddenTokenField)}),setupScrollToHash(this)}handleFormSubmit(e,hiddenTokenField){e.preventDefault(),this.submitting=!0;const submitBody=formatFeatureChanges(this.fieldValues,this.featureId);window.csClient.ensureTokenIsValid().then(()=>(hiddenTokenField.value=window.csClient.token,window.csClient.updateFeature(submitBody))).then(()=>{window.location.href=this.getNextPage()}).catch(()=>{this.submitting=!1,showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value}handleCancelClick(){window.location.href=`/feature/${this.featureId}`}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section class="flat_form"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section class="flat_form"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}getNextPage(){return`/feature/${this.featureId}`}renderSubheader(){return x$1` + <div id="subheader"> + <h2 id="breadcrumbs"> + <a href=${this.getNextPage()}> + <sl-icon name="arrow-left"></sl-icon> + Edit feature: ${this.loading?"loading...":this.feature.name} + </a> + </h2> + </div> + `}getStageForm(stageType){return FORMS_BY_STAGE_TYPE[stageType]||null}getHelpTextForStage(stageType){return stageType===STAGE_ENT_ROLLOUT?x$1` + <section class="enterprise-help-text"> + <h3>Rollout steps</h3> + <p> + The enterprise release notes focus on changes to the stable + channel. Please add a stage for each milestone where something is + changing on the stable channel. For finch rollouts, use the + milestone where the rollout starts. + </p> + <p> + For example, you may only have a single stage where you roll out + to 100% of users on milestone N. + </p> + <p>A more complex example might look like this:</p> + <ul> + <li> + On milestone N-1, you introduce a flag for early testing of an + upcoming change, or start a deprecation origin trial + </li> + <li> + On milestone N, you start a finch rollout of a feature at 1% and + introduce an enterprise policy for it + </li> + <li>On milestone N+3, you remove the enterprise policy</li> + </ul> + </section> + `:E$1}renderStageSection(formattedFeature,sectionBaseName,feStage,stageFields,featureFieldsDisplayed){if(!stageFields)return E$1;let numberDifferentiation="";this.previousStageTypeRendered&&this.previousStageTypeRendered===feStage.stage_type?(this.sameTypeRendered+=1,numberDifferentiation=` ${this.sameTypeRendered}`):(this.previousStageTypeRendered=feStage.stage_type,this.sameTypeRendered=1);let sectionName=`${sectionBaseName}${numberDifferentiation}`;feStage.display_name&&(sectionName=`${sectionBaseName}: ${feStage.display_name} `);const formFieldEls=stageFields.map(field=>{const featureJSONKey=ALL_FIELDS[field].name||field;if("display_name"===featureJSONKey&&!shouldShowDisplayNameField(this.feature.stages,feStage.stage_type))return E$1;let value=formattedFeature[field],stageId=null;if(STAGE_SPECIFIC_FIELDS.has(featureJSONKey))value=getStageValue(feStage,featureJSONKey),stageId=feStage.id;else if(featureFieldsDisplayed.has(featureJSONKey))return E$1;const index=this.fieldValues.length;return this.fieldValues.push({name:featureJSONKey,touched:!1,value,stageId}),featureFieldsDisplayed.add(featureJSONKey),x$1` + <chromedash-form-field + name=${field} + index=${index} + stageId=${stageId??0} + value=${value} + disabledReason="${getDisabledHelpText(field,feStage)}" + .fieldValues=${this.fieldValues} + .feature=${formattedFeature} + ?forEnterprise=${formattedFeature.is_enterprise_feature} + @form-field-update="${this.handleFormFieldUpdate}" + class="${"enterprise_product_category"===field?"choices":""}" + > + </chromedash-form-field> + `}),id=`${STAGE_SHORT_NAMES[feStage.stage_type]||"metadata"}${this.sameTypeRendered}`.toLowerCase(),isEnterpriseFeatureRollout=formattedFeature.is_enterprise_feature&&feStage.stage_type===STAGE_ENT_ROLLOUT;return{id:feStage.id,item:x$1` + ${renderHTMLIf(!isEnterpriseFeatureRollout,x$1`<h3 id="${id}">${sectionName}</h3>`)} + <section class="flat_form" stage="${feStage.stage_type}"> + ${renderHTMLIf(feStage.stage_type===STAGE_ENT_ROLLOUT,x$1` <sl-button + stage="${feStage.stage_type}" + size="small" + @click="${()=>this.deleteStage(feStage)}" + > + Delete + </sl-button>`)} + ${formFieldEls} + </section> + `}}getForms(formattedFeature,feStages){let fieldsOnly=flattenSections(formattedFeature.is_enterprise_feature?FLAT_ENTERPRISE_METADATA_FIELDS:FLAT_METADATA_FIELDS);const featureFieldsDisplayed=new Set,formsToRender=[this.renderStageSection(formattedFeature,FLAT_METADATA_FIELDS.name,{id:-1},fieldsOnly,featureFieldsDisplayed)];let previousStageType=null;for(const feStage of feStages){const stageForm=this.getStageForm(feStage.stage_type);if(!stageForm)continue;formattedFeature.is_enterprise_feature&&feStage.stage_type!==previousStageType&&(formsToRender.push({id:-2,item:this.getHelpTextForStage(feStage.stage_type)}),previousStageType=feStage.stage_type),fieldsOnly=flattenSections(stageForm),formsToRender.push(this.renderStageSection(formattedFeature,stageForm.name,feStage,fieldsOnly,featureFieldsDisplayed));const extensions=feStage.extensions||[];extensions.forEach(extensionStage=>{fieldsOnly=flattenSections(FLAT_TRIAL_EXTENSION_FIELDS);let sectionName=FLAT_TRIAL_EXTENSION_FIELDS.name;feStage.display_name&&(sectionName=` ${FLAT_TRIAL_EXTENSION_FIELDS.name}: ${feStage.display_name} `),formsToRender.push(this.renderStageSection(formattedFeature,sectionName,extensionStage,fieldsOnly,featureFieldsDisplayed))})}return formsToRender}renderAddStageButton(){const clickHandler=()=>{openAddStageDialog(this.feature.id,this.feature.feature_type_int,this.createNewStage.bind(this))};return renderHTMLIf(this.feature.is_enterprise_feature,x$1` <sl-button size="small" @click="${clickHandler}"> + Add Step + </sl-button>`)}createNewStage(newStage){window.csClient.createStage(this.featureId,{stage_type:{form_field_name:"stage_type",value:newStage.stage_type}}).then(()=>window.csClient.getFeature(this.featureId)).then(feature=>{this.feature=feature}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}deleteStage(stage){confirm("Delete feature?")&&window.csClient.deleteStage(this.featureId,stage.id).then(()=>window.csClient.getFeature(this.featureId)).then(feature=>{this.feature=feature}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}renderForm(){const formattedFeature=formatFeatureForEdit(this.feature);this.fieldValues.feature=this.feature;const submitButtonTitle=this.submitting?"Submitting...":"Submit",formsToRender=this.getForms(formattedFeature,this.feature.stages);return x$1` + <form name="feature_form"> + <input type="hidden" name="token" /> + <chromedash-form-table ${n$2(this.registerHandlers)}> + ${c(formsToRender,form=>form.id,(_,i)=>formsToRender[i].item)} + </chromedash-form-table> + ${this.renderAddStageButton()} + + <section class="final_buttons"> + <input + class="button" + type="submit" + value=${submitButtonTitle} + ?disabled=${this.submitting} + /> + <button + id="cancel-button" + type="reset" + @click=${this.handleCancelClick} + > + Cancel + </button> + </section> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?E$1:getFeatureOutdatedBanner(this.feature,this.shippingInfo,Date.now(),userCanEdit(this.user,this.feature.id))} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}};__decorate$A([n$5({attribute:!1})],ChromedashGuideEditallPage.prototype,"featureId",void 0),__decorate$A([n$5({attribute:!1})],ChromedashGuideEditallPage.prototype,"user",void 0),__decorate$A([n$5({type:String})],ChromedashGuideEditallPage.prototype,"appTitle",void 0),__decorate$A([n$5({type:Number})],ChromedashGuideEditallPage.prototype,"nextStageToCreateId",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"feature",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"loading",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"submitting",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"previousStageTypeRendered",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"sameTypeRendered",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"fieldValues",void 0),__decorate$A([r$6()],ChromedashGuideEditallPage.prototype,"shippingInfo",void 0),ChromedashGuideEditallPage=__decorate$A([t$3("chromedash-guide-editall-page")],ChromedashGuideEditallPage);var __decorate$z=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGuideNewPage=class ChromedashGuideNewPage extends i$4{constructor(){super(...arguments),this.userEmail="",this.isEnterpriseFeature=!1,this.fieldValues=[],this.submitting=!1}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + table td label input[type='radio']:focus { + box-shadow: 0 0 0 var(--sl-focus-ring-width) + var(--sl-input-focus-ring-color); + } + .process-notice { + margin: var(--content-padding-half) 0; + padding: var(--content-padding-half); + background: var(--light-accent-color); + border-radius: 8px; + } + .process-notice p + p { + margin-top: var(--content-padding-half); + } + `]}async registerHandlers(el){if(!el)return;await el.updateComplete;const hiddenTokenField=this.renderRoot.querySelector("input[name=token]");hiddenTokenField.form?.addEventListener("submit",event=>{this.handleFormSubmit(event,hiddenTokenField)}),setupScrollToHash(this)}handleFormSubmit(event,hiddenTokenField){event.preventDefault();const changesBody=formatFeatureChanges(this.fieldValues,this.featureId),createBody=changesBody.feature_changes;if(this.isEnterpriseFeature)createBody.feature_type=FEATURE_TYPES.FEATURE_TYPE_ENTERPRISE_ID[0];else{const selectedRadio=this.shadowRoot?.querySelector("input[name=\"feature_type\"]:checked");createBody.feature_type=selectedRadio?selectedRadio.value:FEATURE_TYPES.FEATURE_TYPE_INCUBATE_ID[0]}this.submitting=!0,window.csClient.createFeature(createBody).then(resp=>{window.location.href=`/feature/${resp.feature_id}`}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}maybeMakeWebFeatureRequired(){const webFeatureField=this.shadowRoot?.querySelector("chromedash-form-field[name=\"web_feature\"]");if(!webFeatureField)return;let featureType=FEATURE_TYPES.FEATURE_TYPE_INCUBATE_ID[0];for(const fv of this.fieldValues)if("feature_type"==fv.name&&fv.value!==void 0){featureType=fv.value;break}webFeatureField.forceRequired=featureType==FEATURE_TYPES.FEATURE_TYPE_INCUBATE_ID[0]||featureType==FEATURE_TYPES.FEATURE_TYPE_EXISTING_ID[0]}maybeMakeEnterpriseFeatureCategoriesRequired(){const enterpriseFeatureCategoriesField=this.shadowRoot?.querySelector("chromedash-form-field[name=\"enterprise_feature_categories\"]");if(!enterpriseFeatureCategoriesField)return;let enterpriseImpact=ENTERPRISE_IMPACT.IMPACT_NONE[0];for(const fv of this.fieldValues)if("enterprise_impact"===fv.name&&fv.value!==void 0){enterpriseImpact=fv.value;break}enterpriseFeatureCategoriesField.forceRequired=enterpriseImpact>ENTERPRISE_IMPACT.IMPACT_NONE[0]||this.isEnterpriseFeature}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value,this.fieldValues[index].isMarkdown=event.detail.isMarkdown,this.maybeMakeWebFeatureRequired(),this.maybeMakeEnterpriseFeatureCategoriesRequired()}renderSubHeader(){return x$1` + <div id="subheader" style="display:block"> + <span style="float:right; margin-right: 2em"> + <a + href="https://github.com/GoogleChrome/chromium-dashboard/issues/new?labels=Feedback&template=process-and-guide-ux-feedback.md" + target="_blank" + rel="noopener" + >Process and UI feedback</a + ></span + > + <h2 data-testid="add-a-feature">Add a feature</h2> + </div> + `}renderWarnings(){return this.isEnterpriseFeature?x$1` + <div class="process-notice"> + <p> + Use this form if your feature should be mentioned in the Enterprise + Release Notes. + </p> + </div> + `:x$1` + <div class="process-notice"> + <p> + Please see the + <a + href="https://www.chromium.org/blink/launching-features" + target="_blank" + rel="noopener" + >Launching features</a + > + page for process instructions. + </p> + + <p> + Googlers: Please follow the instructions at + <a + href="https://goto.corp.google.com/wp-launch-guidelines" + target="_blank" + rel="noopener" + >go/wp-launch-guidelines</a + > + (internal document) to determine whether you also require an + internal review. + </p> + </div> + `}renderForm(){const newFeatureInitialValues={owner:this.userEmail,shipping_year:new Date().getFullYear()};this.fieldValues.feature=this.feature;const formFields=this.isEnterpriseFeature?ENTERPRISE_NEW_FEATURE_FORM_FIELDS:NEW_FEATURE_FORM_FIELDS,renderFormField=(field,className)=>{const fieldProps=ALL_FIELDS[field],featureJSONKey=fieldProps.name||field,initialValue=this.isEnterpriseFeature?fieldProps.enterprise_initial??fieldProps.initial:fieldProps.initial,value=newFeatureInitialValues[field]??initialValue,index=this.fieldValues.length;return this.fieldValues.push({name:featureJSONKey,touched:!0,value}),x$1` + <chromedash-form-field + name=${field} + index=${index} + value=${value} + disabledReason="${getDisabledHelpText(field)}" + .fieldValues=${this.fieldValues} + ?forEnterprise=${this.isEnterpriseFeature} + @form-field-update="${this.handleFormFieldUpdate}" + class="${className||""}"></chromedash-form-field> + </chromedash-form-field> + `},submitLabel=this.submitting?"Submitting...":this.isEnterpriseFeature?"Continue":"Submit";return x$1` + <section id="stage_form"> + <form> + <input type="hidden" name="token" /> + <chromedash-form-table ${n$2(this.registerHandlers)}> + ${this.renderWarnings()} + ${this.isEnterpriseFeature?E$1:renderFormField("feature_type_radio_group","choices")} + ${formFields.map(field=>renderFormField(field,"enterprise_product_category"===field?"choices":null))} + </chromedash-form-table> + <input + type="submit" + class="primary" + value=${submitLabel} + ?disabled=${this.submitting} + /> + </form> + </section> + `}render(){return x$1` ${this.renderSubHeader()} ${this.renderForm()} `}};__decorate$z([n$5({attribute:!1})],ChromedashGuideNewPage.prototype,"userEmail",void 0),__decorate$z([n$5({type:Boolean})],ChromedashGuideNewPage.prototype,"isEnterpriseFeature",void 0),__decorate$z([n$5({type:Number})],ChromedashGuideNewPage.prototype,"featureId",void 0),__decorate$z([n$5({type:Object})],ChromedashGuideNewPage.prototype,"feature",void 0),__decorate$z([r$6()],ChromedashGuideNewPage.prototype,"fieldValues",void 0),__decorate$z([n$5({type:Boolean})],ChromedashGuideNewPage.prototype,"submitting",void 0),ChromedashGuideNewPage=__decorate$z([t$3("chromedash-guide-new-page")],ChromedashGuideNewPage);var __decorate$y=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGuideStagePage=class ChromedashGuideStagePage extends i$4{constructor(){super(...arguments),this.stageId=0,this.featureId=0,this.intentStage=0,this.appTitle="",this.stageName="",this.feature={},this.isActiveStage=!1,this.loading=!0,this.submitting=!1,this.fieldValues=[]}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7``]}connectedCallback(){super.connectedCallback(),this.fetchData()}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value,this.fieldValues[index].isMarkdown=event.detail.isMarkdown}fetchData(){this.loading=!0;const rawQuery=parseRawQuery(window.location.search);let gatePromise=Promise.resolve();"updateExtension"in rawQuery&&(gatePromise=window.csClient.getGates(this.featureId)),Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getStage(this.featureId,this.stageId),gatePromise]).then(([feature,stage,gates])=>{this.feature=feature,this.stage=stage,gates&&(this.gateId=gates.gates.find(g=>g.stage_id===this.stageId).id),this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.feature.active_stage_id===this.stage.id&&(this.isActiveStage=!0),this.featureFormFields=FORMS_BY_STAGE_TYPE[stage.stage_type]||{name:"",sections:[]},this.stageName=this.featureFormFields.name,this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerHandlers(el){if(!el)return;await el.updateComplete;const hiddenTokenField=this.renderRoot.querySelector("input[name=token]");hiddenTokenField.form?.addEventListener("submit",event=>{this.handleFormSubmit(event,hiddenTokenField)}),this.miscSetup(),setupScrollToHash(this)}handleFormSubmit(e,hiddenTokenField){e.preventDefault();const submitBody=formatFeatureChanges(this.fieldValues,this.featureId,this.stageId);this.submitting=!0,window.csClient.ensureTokenIsValid().then(()=>(hiddenTokenField.value=window.csClient.token,window.csClient.updateFeature(submitBody))).then(()=>{window.location.href=this.gateId?`/feature/${this.featureId}?gate=${this.gateId}&initiateExtension`:`/feature/${this.featureId}`}).catch(()=>{this.submitting=!1,showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}miscSetup(){const timelineField=this.renderRoot.querySelector("#id_experiment_timeline");timelineField&&timelineField.value&&(timelineField.disabled=!1)}handleCancelClick(){window.location.href=`/feature/${this.featureId}`}getFormFields(){const fields=this.featureFormFields.sections.reduce((combined,section)=>[...combined,...section.fields],[]);return fields.join()}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}getNextPage(){return`/feature/${this.featureId}`}renderSubheader(){return x$1` + <div id="subheader"> + <h2 id="breadcrumbs"> + <a href=${this.getNextPage()}> + <sl-icon name="arrow-left"></sl-icon> + Edit feature: ${this.feature.name} + </a> + </h2> + </div> + `}renderFields(formattedFeature,section,feStage){return feStage||(feStage=this.stage),section.fields.map(field=>{if("display_name"===field&&!shouldShowDisplayNameField(this.feature.stages,feStage.stage_type))return E$1;const featureJSONKey=ALL_FIELDS[field].name||field;let value=formattedFeature[featureJSONKey],stageId;STAGE_SPECIFIC_FIELDS.has(featureJSONKey)&&(value=getStageValue(feStage,featureJSONKey),stageId=feStage.id);const index=this.fieldValues.length;return this.fieldValues.push({name:featureJSONKey,touched:!1,value,stageId}),x$1` + <chromedash-form-field + name=${field} + index=${index} + value=${value} + disabledReason="${getDisabledHelpText(field,feStage)}" + .fieldValues=${this.fieldValues} + .feature=${formattedFeature} + stageId=${feStage.id} + ?forEnterprise=${formattedFeature.is_enterprise_feature} + @form-field-update="${this.handleFormFieldUpdate}" + > + </chromedash-form-field> + `})}renderSections(formattedFeature,stageSections){const formSections=[];if(stageSections.forEach(section=>{formSections.push(x$1` + <h3>${section.name}</h3> + <section class="stage_form"> + ${this.renderFields(formattedFeature,section)} + </section> + `)}),this.stage.extensions){let i=1;for(const extensionStage of this.stage.extensions){for(const section of FLAT_TRIAL_EXTENSION_FIELDS.sections)formSections.push(x$1` + <h3>${section.name} ${i}</h3> + <section class="stage_form"> + ${this.renderFields(formattedFeature,section,extensionStage)} + </section> + `);i++}}return formSections}renderForm(){const formattedFeature=formatFeatureForEdit(this.feature);this.fieldValues.feature=this.feature;const submitButtonTitle=this.submitting?"Submitting...":"Submit";return x$1` + <form name="feature_form"> + <input type="hidden" name="token" /> + <chromedash-form-table ${n$2(this.registerHandlers)}> + ${this.renderSections(formattedFeature,this.featureFormFields.sections)} + </chromedash-form-table> + <div class="final_buttons"> + <input + id="submit-button" + class="button" + type="submit" + value=${submitButtonTitle} + ?disabled=${this.submitting} + /> + <button + id="cancel-button" + type="reset" + @click=${this.handleCancelClick} + > + Cancel + </button> + </div> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}};__decorate$y([n$5({attribute:!1})],ChromedashGuideStagePage.prototype,"stageId",void 0),__decorate$y([n$5({attribute:!1})],ChromedashGuideStagePage.prototype,"featureId",void 0),__decorate$y([n$5({attribute:!1})],ChromedashGuideStagePage.prototype,"intentStage",void 0),__decorate$y([n$5({type:String})],ChromedashGuideStagePage.prototype,"appTitle",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"stageName",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"feature",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"stage",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"isActiveStage",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"featureFormFields",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"loading",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"submitting",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"fieldValues",void 0),__decorate$y([r$6()],ChromedashGuideStagePage.prototype,"gateId",void 0),ChromedashGuideStagePage=__decorate$y([t$3("chromedash-guide-stage-page")],ChromedashGuideStagePage);var __decorate$x=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashGuideMetadataPage=class ChromedashGuideMetadataPage extends i$4{constructor(){super(...arguments),this.featureId=0,this.appTitle="",this.loading=!0,this.fieldValues=[]}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7``]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){this.loading=!0,Promise.resolve(window.csClient.getFeature(this.featureId)).then(feature=>{this.feature=feature,this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerHandlers(el){if(!el)return;await el.updateComplete;const hiddenTokenField=this.renderRoot.querySelector("input[name=token]");hiddenTokenField.form?.addEventListener("submit",event=>{this.handleFormSubmit(event,hiddenTokenField)}),setupScrollToHash(this)}handleFormSubmit(e,hiddenTokenField){e.preventDefault();const submitBody=formatFeatureChanges(this.fieldValues,this.featureId);window.csClient.ensureTokenIsValid().then(()=>(hiddenTokenField.value=window.csClient.token,window.csClient.updateFeature(submitBody))).then(()=>{window.location.href=`/feature/${this.featureId}`}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value,this.fieldValues[index].isMarkdown=event.detail.isMarkdown}handleCancelClick(){window.location.href=`/feature/${this.featureId}`}getFormFields(){const sections=this.feature.is_enterprise_feature?FLAT_ENTERPRISE_METADATA_FIELDS.sections:FLAT_METADATA_FIELDS.sections,fields=sections.reduce((combined,section)=>[...combined,...section.fields],[]);return fields.join()}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}getNextPage(){return`/feature/${this.featureId}`}renderSubheader(){const link=this.loading?E$1:x$1` + <a href=${this.getNextPage()}> + <sl-icon name="arrow-left"></sl-icon> + Edit feature: ${this.feature.name} + </a> + `;return x$1` + <div id="subheader"> + <h2 id="breadcrumbs">${link}</h2> + </div> + `}renderFields(formattedFeature,section){return section.fields.map(field=>{const featureJSONKey=ALL_FIELDS[field].name||field,value=formattedFeature[featureJSONKey],index=this.fieldValues.length;return this.fieldValues.push({name:featureJSONKey,touched:!1,value}),x$1` + <chromedash-form-field + name=${field} + index=${index} + value=${value} + disabledReason="${getDisabledHelpText(field)}" + .fieldValues=${this.fieldValues} + .feature=${formattedFeature} + ?forEnterprise=${formattedFeature.is_enterprise_feature} + @form-field-update="${this.handleFormFieldUpdate}" + class="${"enterprise_product_category"===field?"choices":""}" + > + </chromedash-form-field> + `})}renderSections(formattedFeature,sections){return sections.map(section=>x$1` + <h3>${section.name}</h3> + <section class="stage_form"> + ${this.renderFields(formattedFeature,section)} + </section> + `)}renderForm(){const formattedFeature=formatFeatureForEdit(this.feature);this.fieldValues.feature=this.feature;let sections=FLAT_METADATA_FIELDS.sections;return formattedFeature.is_enterprise_feature&&(sections=FLAT_ENTERPRISE_METADATA_FIELDS.sections),x$1` + <form name="feature_form"> + <input type="hidden" name="token" /> + <chromedash-form-table ${n$2(this.registerHandlers)}> + ${this.renderSections(formattedFeature,sections)} + </chromedash-form-table> + + <div class="final_buttons"> + <input class="button" type="submit" value="Submit" /> + <button + id="cancel-button" + type="reset" + @click=${this.handleCancelClick} + > + Cancel + </button> + </div> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}};__decorate$x([n$5({type:Number})],ChromedashGuideMetadataPage.prototype,"featureId",void 0),__decorate$x([n$5({type:String})],ChromedashGuideMetadataPage.prototype,"appTitle",void 0),__decorate$x([r$6()],ChromedashGuideMetadataPage.prototype,"feature",void 0),__decorate$x([r$6()],ChromedashGuideMetadataPage.prototype,"loading",void 0),__decorate$x([r$6()],ChromedashGuideMetadataPage.prototype,"fieldValues",void 0),ChromedashGuideMetadataPage=__decorate$x([t$3("chromedash-guide-metadata-page")],ChromedashGuideMetadataPage);var __decorate$w=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashGuideVerifyAccuracyPage extends i$4{constructor(){super(...arguments),this.featureId=0,this.appTitle="",this.feature={},this.fieldValues=[],this.loading=!0,this.previousStageTypeRendered=0,this.sameTypeRendered=0,this.submitting=!1}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + .verify-banner { + margin-bottom: 12px; + } + #alertUnderline { + text-decoration: underline; + display: inline; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){this.loading=!0,window.csClient.getFeature(this.featureId).then(feature=>{this.feature=feature,this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerFormSubmitHandler(el){if(!el)return;await el.updateComplete;const hiddenTokenField=this.renderRoot.querySelector("input[name=token]");hiddenTokenField.form?.addEventListener("submit",event=>{this.handleFormSubmit(event,hiddenTokenField)})}navigateToFeaturePage(){window.location.href=`/feature/${this.featureId}`}handleFormSubmit(e,hiddenTokenField){e.preventDefault();const submitBody=formatFeatureChanges(this.fieldValues,this.featureId);window.csClient.ensureTokenIsValid().then(()=>(hiddenTokenField.value=window.csClient.token,this.submitting=!0,window.csClient.updateFeature(submitBody))).then(()=>{this.navigateToFeaturePage()}).catch(()=>{this.submitting=!1,showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}renderSubheader(){return x$1` + <div id="subheader"> + <h2 id="breadcrumbs"> + <a href="/feature/${this.featureId}"> + <sl-icon name="arrow-left"></sl-icon> + Verify feature data for ${this.feature.name} + </a> + </h2> + </div> + `}getStageForm(stageType){return VERIFY_ACCURACY_FORMS_BY_STAGE_TYPE[stageType]||null}renderStageSection(formattedFeature,name,feStage,stageFields){if(!stageFields)return E$1;let numberDifferentiation="";this.previousStageTypeRendered&&this.previousStageTypeRendered===feStage.stage_type?(this.sameTypeRendered+=1,numberDifferentiation=` ${this.sameTypeRendered}`):(this.previousStageTypeRendered=feStage.stage_type,this.sameTypeRendered=1);let sectionName=`${name}${numberDifferentiation}`;feStage.display_name&&(sectionName=`${name}: ${feStage.display_name}`);const formFieldEls=stageFields.map(field=>{let value=formattedFeature[field];const featureJSONKey=ALL_FIELDS[field].name||field;if(STAGE_SPECIFIC_FIELDS.has(field))value=getStageValue(feStage,featureJSONKey);else if(1<this.sameTypeRendered)return E$1;const index=this.fieldValues.length;let touched=!1;return"accurate_as_of"===featureJSONKey&&(touched=!0),this.fieldValues.push({name:featureJSONKey,touched,value,stageId:feStage.id}),x$1` + <chromedash-form-field + name=${field} + index=${index} + value=${value} + disabledReason="${getDisabledHelpText(field,feStage)}" + .fieldValues=${this.fieldValues} + .feature=${formattedFeature} + ?forEnterprise=${formattedFeature.is_enterprise_feature} + @form-field-update="${this.handleFormFieldUpdate}" + > + </chromedash-form-field> + `}),id=`${STAGE_SHORT_NAMES[feStage.stage_type]||"metadata"}${this.sameTypeRendered}`.toLowerCase();return x$1` + <h3 id="${id}">${sectionName}</h3> + <section class="flat_form">${formFieldEls}</section> + `}getForms(formattedFeature,feStages){let fieldsOnly=flattenSections(VERIFY_ACCURACY_METADATA_FIELDS);const formsToRender=[this.renderStageSection(formattedFeature,VERIFY_ACCURACY_METADATA_FIELDS.name,{},fieldsOnly)];let allFormFields=[...fieldsOnly];for(const feStage of feStages){const stageForm=this.getStageForm(feStage.stage_type);stageForm&&(fieldsOnly=flattenSections(stageForm),formsToRender.push(this.renderStageSection(formattedFeature,stageForm.name,feStage,fieldsOnly)),allFormFields=[...allFormFields,...fieldsOnly])}return fieldsOnly=flattenSections(VERIFY_ACCURACY_CONFIRMATION_FIELD),formsToRender.push(this.renderStageSection(formattedFeature,`${VERIFY_ACCURACY_CONFIRMATION_FIELD.name}`,{},fieldsOnly)),allFormFields=[...allFormFields,...fieldsOnly],[allFormFields,formsToRender]}getAllStageIds(){return this.feature.stages.map(feStage=>feStage.id)}renderForm(){const formattedFeature=formatFeatureForEdit(this.feature);this.fieldValues.feature=this.feature;const stageIds=this.getAllStageIds(),[allFormFields,formsToRender]=this.getForms(formattedFeature,this.feature.stages),title=this.feature.accurate_as_of?`Accuracy last verified ${this.feature.accurate_as_of.split(" ")[0]}.`:"Accuracy last verified at time of creation.",submitButtonTitle=this.submitting?"Submitting...":"Submit";return x$1` + <form name="feature_form" method="post"> + <input type="hidden" name="stages" .value="${stageIds}" /> + <input type="hidden" name="token" /> + <input + type="hidden" + name="form_fields" + value=${allFormFields.join(",")} + /> + <h3>${title}</h3> + <sl-alert variant="warning" open class="verify-banner"> + <sl-icon slot="icon" name="info-circle"></sl-icon> + <strong + >Please review your information below and click 'Submit' to confirm + it is accurate, + <p id="alertUnderline">even if no changes are made</p> + !</strong + > + </sl-alert> + <chromedash-form-table ${n$2(this.registerFormSubmitHandler)}> + ${formsToRender} + </chromedash-form-table> + + <section class="final_buttons"> + <input + class="button" + type="submit" + value="${submitButtonTitle}" + ?disabled=${this.submitting} + /> + <button + id="cancel-button" + type="reset" + @click=${this.navigateToFeaturePage} + > + Cancel + </button> + </section> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}}__decorate$w([n$5({attribute:!1})],ChromedashGuideVerifyAccuracyPage.prototype,"featureId",void 0),__decorate$w([n$5({type:String})],ChromedashGuideVerifyAccuracyPage.prototype,"appTitle",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"feature",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"fieldValues",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"loading",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"previousStageTypeRendered",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"sameTypeRendered",void 0),__decorate$w([r$6()],ChromedashGuideVerifyAccuracyPage.prototype,"submitting",void 0),customElements.define("chromedash-guide-verify-accuracy-page",ChromedashGuideVerifyAccuracyPage);var __decorate$v=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashHeader=class ChromedashHeader extends i$4{constructor(){super(...arguments),this.appTitle="",this.googleSignInClientId="",this.devMode="",this.currentPage="",this.user={},this.loading=!1}static get styles(){return[...SHARED_STYLES,i$7` + :host { + --nav-link-color: var(--sl-color-neutral-700); + --nav-link-font-size: 16px; + --nav-link-hover-background: var(--sl-color-neutral-100); + --nav-link-border: 2px solid transparent; + --nav-link-active-color: var(--cl-color-primary-900); + --nav-link-active-border: 2px solid var(--nav-link-active-color); + } + + header { + display: flex; + align-items: center; + user-select: none; + background: var(--card-background); + border-bottom: var(--card-border); + box-shadow: var(--card-box-shadow); + } + header a { + text-decoration: none !important; + } + header nav { + display: flex; + flex: 1; + align-items: center; + margin: 0 var(--content-padding); + -webkit-font-smoothing: initial; + } + + sl-button[slot='trigger']::part(base) { + color: var(--unimportant-text-color); + } + header aside a { + color: var(--logo-color); + } + header aside h1 { + line-height: 1; + } + header aside img { + height: 24px; + width: 24px; + } + + .flex-container { + display: flex; + justify-content: flex-end; + flex-wrap: wrap; + align-items: center; + width: 100%; + } + + .nav-dropdown-trigger { + display: flex; + align-items: flex-end; + } + .nav-dropdown-trigger sl-icon { + padding-left: var(--content-padding-half); + } + + .menu { + margin-left: 15px; + margin-right: 7px; + align-items: center; + } + .menu:hover { + color: black; + background: var(--nav-link-hover-background); + } + .menu [active] { + color: var(--nav-link-active-color); + border-bottom: var(--nav-link-active-border); + } + + @media only screen and (max-width: 700px) { + header { + --logoSize: 24px; + + margin: 0; + display: flex; + } + header aside { + display: flex; + padding: var(--content-padding-half); + border-radius: 0; + background: inherit; + } + } + `]}connectedCallback(){return super.connectedCallback(),IS_MOBILE||this.user&&this.user.email?void 0:this.user?void(this.loading=!0,window.csClient.getPermissions().then(user=>{this.user=user,this.user||(!window.isPlaywright&&this.initializeGoogleSignIn(),"True"==this.devMode&&this.initializeTestingSignIn())}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}).finally(()=>{this.loading=!1})):(window.isPlaywright||this.initializeGoogleSignIn(),void("True"==this.devMode&&this.initializeTestingSignIn()))}initializeGoogleSignIn(){google.accounts.id.initialize({client_id:this.googleSignInClientId,callback:this.handleCredentialResponse,use_fedcm_for_prompt:!0}),google.accounts.id.prompt();const signInButton=document.createElement("div");google.accounts.id.renderButton(signInButton,{type:"standard"});const appComponent=document.querySelector("chromedash-app");appComponent?appComponent.insertAdjacentElement("afterbegin",signInButton):this.insertAdjacentElement("afterbegin",signInButton)}initializeTestingSignIn(){const signInTestingButton=document.createElement("button");signInTestingButton.innerText="Sign in as example@chromium.org",signInTestingButton.setAttribute("type","button"),signInTestingButton.setAttribute("data-testid","dev-mode-sign-in-button"),signInTestingButton.setAttribute("style","margin-right: 300px; z-index:1000; background: lightblue; border: 1px solid blue;"),signInTestingButton.addEventListener("click",()=>{fetch("/dev/mock_login",{method:"POST"}).then(response=>{if(!response.ok)throw new Error(`Sign in failed! Response: ${response}`)}).then(()=>{setTimeout(()=>{redirectToCurrentPage()},1e3)}).catch(error=>{console.error("Sign in failed.",error)})});const signInButtonContainer=document.querySelector("chromedash-app");signInButtonContainer?signInButtonContainer.insertAdjacentElement("afterbegin",signInTestingButton):this.insertAdjacentElement("afterbegin",signInTestingButton)}handleCredentialResponse(credentialResponse){window.csClient.signIn(credentialResponse).then(()=>{setTimeout(()=>{redirectToCurrentPage()},1e3)}).catch(()=>{console.error("Sign in failed, so signing out to allow retry"),this.signOut()})}gotoSettings(){window.location.href="/settings"}signOut(){window.csClient.signOut().then(()=>{window.location.reload()})}isCurrentPage(href){return this.currentPage.startsWith(href)}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}handleDrawer(){this._fireEvent("drawer-clicked",{})}renderAccountMenu(){const alreadyOnNew=this.isCurrentPage("/guide/new")||this.isCurrentPage("/guide/enterprise/new");return x$1` + ${this.user?x$1` + ${this.user.can_create_feature&&!alreadyOnNew?x$1` + <sl-button + data-testid="create-feature-button" + href="/guide/new" + variant="primary" + size="small" + > + Create feature + </sl-button> + `:E$1} + <sl-dropdown> + <sl-button + slot="trigger" + variant="text" + size="medium" + data-testid="account-indicator" + caret + > + ${this.user.email} + </sl-button> + <sl-menu> + <sl-menu-item @click=${this.gotoSettings}> + Settings + </sl-menu-item> + <sl-menu-item + id="sign-out-link" + data-testid="sign-out-link" + @click=${this.signOut} + >Sign out</sl-menu-item + > + </sl-menu> + </sl-dropdown> + `:x$1` <slot></slot> `} + `}render(){let accountMenu=x$1``;return IS_MOBILE||this.loading||(accountMenu=x$1` <div class="flex-container"> + ${this.renderAccountMenu()} + </div>`),x$1` + <header data-testid="header"> + <sl-icon-button + data-testid="menu" + variant="text" + library="material" + class="menu" + style="font-size: 2.4rem;" + name="menu_20px" + @click="${this.handleDrawer}" + > + </sl-icon-button> + <aside> + <a href="/roadmap" target="_top"> + <h1> + <img + src="/static/img/chrome_logo.svg" + alt="" + role="presentation" + /> + ${this.appTitle} + </h1> + </a> + </aside> + <nav>${accountMenu}</nav> + </header> + `}};__decorate$v([n$5({type:String})],ChromedashHeader.prototype,"appTitle",void 0),__decorate$v([n$5({type:String})],ChromedashHeader.prototype,"googleSignInClientId",void 0),__decorate$v([n$5({type:String})],ChromedashHeader.prototype,"devMode",void 0),__decorate$v([n$5({type:String})],ChromedashHeader.prototype,"currentPage",void 0),__decorate$v([n$5({type:Object})],ChromedashHeader.prototype,"user",void 0),__decorate$v([r$6()],ChromedashHeader.prototype,"loading",void 0),ChromedashHeader=__decorate$v([t$3("chromedash-header")],ChromedashHeader);var __decorate$u=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashIntentContent=class ChromedashIntentContent extends i$4{constructor(){super(...arguments),this.appTitle="",this.subject="",this.intentBody=""}static get styles(){return[...SHARED_STYLES,i$7` + #copy-email-body { + cursor: pointer; + color: var(--link-color); + } + .email-content-border { + border: 1px solid #ddd; + box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; + margin: 8px 0 24px 0; + } + .email-content-div { + background: white; + padding: 12px; + } + p { + color: #444; + } + h3 { + margin-bottom: 10px; + &:before { + counter-increment: h3; + content: counter(h3) '.'; + margin-right: 5px; + } + } + #content section > div { + background: white; + border: 1px solid #ddd; + box-shadow: rgba(0, 0, 0, 0.067) 1px 1px 4px; + padding: 12px; + margin: 8px 0 16px 0; + } + #content section > p { + color: #444; + } + + .email .help { + font-style: italic; + color: #aaa; + } + .email h4 { + font-weight: 600; + } + .alertbox { + margin: 2em; + padding: 1em; + background: var(--warning-background); + color: var(--warning-color); + } + .subject { + font-size: 16px; + } + table { + tr[hidden] { + th, + td { + padding: 0; + } + } + + th { + padding: 12px 10px 5px 0; + vertical-align: top; + } + + td { + padding: 6px 10px; + vertical-align: top; + } + + td:first-of-type { + width: 60%; + } + + .helptext { + display: block; + font-size: small; + max-width: 40em; + margin-top: 2px; + } + + input[type='text'], + input[type='url'], + input[type='email'], + textarea { + width: 100%; + font: var(--form-element-font); + } + + select { + max-width: 350px; + } + + :required { + border: 1px solid $chromium-color-dark; + } + + .interacted:valid { + border: 1px solid green; + } + + .interacted:invalid { + border: 1px solid $invalid-color; + } + + input:not([type='submit']):not([type='search']) { + outline: 1px dotted var(--error-border-color); + background-color: #ffedf5; + } + } + `]}renderEmailBody(){return this.intentBody?o$2(this.intentBody):E$1}copyIntentBodyHandler(){const copyEmailBodyEl=this.renderRoot.querySelector("#copy-email-body"),emailBodyEl=this.renderRoot.querySelector(".email");if(copyEmailBodyEl&&emailBodyEl){window.getSelection()?.removeAllRanges();const range=document.createRange();range.selectNode(emailBodyEl),window.getSelection()?.addRange(range),document.execCommand("copy"),showToastMessage("Email body copied")}}render(){return x$1` + <p>Email to</p> + <div class="email-content-border"> + <div class="subject email-content-div">blink-dev@chromium.org</div> + </div> + + <p>Subject</p> + <div class="email-content-border"> + <div class="subject email-content-div" id="email-subject-content"> + ${this.subject} + </div> + </div> + <p> + Body + <span + class="tooltip copy-text" + style="float:right" + title="Copy text to clipboard" + > + <sl-icon + name="copy" + id="copy-email-body" + @click="${()=>this.copyIntentBodyHandler()}" + ></sl-icon> + </span> + </p> + + <div class="email-content-border"> + <div class="email email-content-div" id="email-body-content"> + ${this.renderEmailBody()} + </div> + </div> + `}};__decorate$u([n$5({type:String})],ChromedashIntentContent.prototype,"appTitle",void 0),__decorate$u([n$5({type:String})],ChromedashIntentContent.prototype,"subject",void 0),__decorate$u([n$5({type:String})],ChromedashIntentContent.prototype,"intentBody",void 0),ChromedashIntentContent=__decorate$u([t$3("chromedash-intent-content")],ChromedashIntentContent);var __decorate$t=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let dialogEl;async function openPostIntentDialog(featureId,stageId,ownerEmails,gateId=0){dialogEl||(dialogEl=document.createElement("chromedash-post-intent-dialog"),document.body.appendChild(dialogEl),dialogEl.featureId=featureId,dialogEl.stageId=stageId,dialogEl.gateId=gateId,dialogEl.ownerEmails=ownerEmails,await dialogEl.updateComplete),dialogEl.show()}let ChromedashPostIntentDialog=class ChromedashPostIntentDialog extends i$4{constructor(){super(...arguments),this.featureId=0,this.stageId=0,this.gateId=0,this.ownerEmails=[]}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + #prereqs-list li { + margin-left: 8px; + margin-bottom: 8px; + } + #prereqs-header { + margin-bottom: 8px; + } + #update-button { + margin-right: 8px; + } + .float-right { + float: right; + } + sl-input::part(base) { + margin-top: 8px; + } + sl-input[data-user-invalid]::part(base) { + border-color: red; + } + `]}show(){this.shadowRoot.querySelector("sl-dialog").show()}updateAttributes(el){if(!el)return;const attrs=ALL_FIELDS.intent_cc_emails.attrs||{};Object.keys(attrs).map(attr=>{el.setAttribute(attr,attrs[attr])})}renderIntentCCEmailOption(){const fieldInfo=ALL_FIELDS.intent_cc_emails,defaultCCEmails=this.ownerEmails.join(",");return x$1`${fieldInfo.help_text}<br /> + <sl-input + ${n$2(this.updateAttributes)} + id="id_${fieldInfo.name}" + size="small" + autocomplete="off" + .value=${defaultCCEmails} + ?required=${fieldInfo.required} + > + </sl-input>`}submitIntent(){const ccEmailsInput=this.shadowRoot.querySelector("sl-input");if(!ccEmailsInput||ccEmailsInput.hasAttribute("data-user-invalid"))return;const submitButton=this.shadowRoot.querySelector("#submit-intent-button");submitButton&&submitButton.setAttribute("disabled",""),window.csClient.postIntentToBlinkDev(this.featureId,this.stageId,{gate_id:this.gateId,intent_cc_emails:ccEmailsInput?.value?.split(",")}).then(()=>{showToastMessage("Intent submitted! Check for your thread on blink-dev shortly."),setTimeout(()=>{window.location.href=`/feature/${this.featureId}`},3e3)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later."),submitButton&&submitButton.removeAttribute("disabled")})}renderDialog(){return x$1`<sl-dialog label="Post intent to blink-dev"> + <p> + This intent will be sent directly to + <a + href="https://groups.google.com/a/chromium.org/g/blink-dev" + target="_blank" + rel="noopener noreferrer" + >blink-dev</a + >. + </p> + <br /><br /> + ${this.renderIntentCCEmailOption()} + <br /><br /> + <sl-button + class="float-right" + id="submit-intent-button" + variant="primary" + size="small" + @click=${()=>this.submitIntent()} + >Submit intent</sl-button + > + </sl-dialog>`}render(){return this.renderDialog()}};__decorate$t([n$5({type:Number})],ChromedashPostIntentDialog.prototype,"featureId",void 0),__decorate$t([n$5({type:Number})],ChromedashPostIntentDialog.prototype,"stageId",void 0),__decorate$t([n$5({type:Number})],ChromedashPostIntentDialog.prototype,"gateId",void 0),__decorate$t([n$5({attribute:!1})],ChromedashPostIntentDialog.prototype,"ownerEmails",void 0),ChromedashPostIntentDialog=__decorate$t([t$3("chromedash-post-intent-dialog")],ChromedashPostIntentDialog);var __decorate$s=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashIntentPreviewPage=class ChromedashIntentPreviewPage extends i$4{constructor(){super(...arguments),this.appTitle="",this.featureId=0,this.stageId=0,this.gateId=0,this.loading=!1,this.subject="",this.intentBody="",this.displayFeatureUnlistedWarning=!1}static get styles(){return[...SHARED_STYLES,i$7` + #content { + flex-direction: column; + counter-reset: h3; + height: auto; + } + #content section { + max-width: 800px; + flex: 1 0 auto; + margin-bottom: 15px; + } + h3 { + margin-bottom: 10px; + } + #content h3:before { + counter-increment: h3; + content: counter(h3) '.'; + margin-right: 5px; + } + #post-intent-button { + float: right; + } + .inline { + display: inline; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getGates(this.featureId)]).then(([feature,gates])=>{if(this.feature=feature,document.title=`${this.feature.name} - ${this.appTitle}`,this.gateId){if(this.gate=gates.gates.find(gate=>gate.id===this.gateId),!this.gate)throw new Error("Invalid gate ID");for(const stage of this.feature.stages){if(this.stage)break;if(stage.id===this.gate.stage_id&&(this.stage=stage),!this.stage){const extensionStage=stage.extensions.find(e=>e.id===this.gate.stage_id);extensionStage&&(this.stage=extensionStage)}}}else if(this.stageId){const matchingStage=this.feature.stages.find(s=>s.id===this.stageId);if(!matchingStage)throw new Error(`No matching stage found for ID ${this.stageId}`);this.stage=matchingStage}else throw new Error("Invalid gate ID");return this.feature.unlisted&&(this.displayFeatureUnlistedWarning=!0),window.csClient.getIntentBody(this.featureId,this.stage.id,this.gateId)}).then(intentResp=>{this.subject=intentResp.subject,this.intentBody=intentResp.email_body,this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}renderThreeLGTMSection(){return STAGE_TYPES_SHIPPING.has(this.stage?.stage_type)?x$1` <section> + <h3>Obtain LGTMs from 3 API Owners</h3> + <span class="help"> + You will need three LGTMs from API owners. According to the + <a href="http://www.chromium.org/blink#launch-process" + >Blink Launch process</a + > + after that, you're free to ship your feature. + </span> + </section>`:E$1}renderFeatureUnlistedAlert(){return this.displayFeatureUnlistedWarning?x$1`<div class="alertbox"> + Important: This feature is currently unlisted. Please only share feature + details with people who are collaborating with you on the feature. + </div>`:E$1}renderSkeletonSection(){return x$1` + <section> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}renderSkeletons(){return x$1` + <div id="feature" style="margin-top: 65px;"> + ${this.renderSkeletonSection()} ${this.renderSkeletonSection()} + ${this.renderSkeletonSection()} ${this.renderSkeletonSection()} + </div> + `}render(){return this.loading?this.renderSkeletons():x$1` + <div id="content"> + <div id="subheader"> + <div> + <h2>Next steps for the Blink launch process</h2> + </div> + </div> + ${this.renderFeatureUnlistedAlert()} + <section> + <h3>Reach out to a spec mentor</h3> + <p style="margin-left: 1em"> + Consider showing your draft intent email to your spec mentor or + sending it to spec-mentors@chromium.org. They can help make sure + that your intent email is ready for review. + </p> + </section> + <section> + <h3 class="inline">Send this text for your "Intent to ..." email</h3> + <input + ref() + id="post-intent-button" + class="button inline" + type="submit" + value="Post directly to blink-dev" + @click="${()=>openPostIntentDialog(this.feature.id,this.stage.id,this.feature.owner_emails,this.gate?.id)}" + /> + <chromedash-intent-content + appTitle="${this.appTitle}" + .feature=${this.feature} + .stage=${this.stage} + subject="${this.subject}" + intentBody="${this.intentBody}" + > + </chromedash-intent-content> + </section> + ${this.renderThreeLGTMSection()} + </div> + `}};__decorate$s([n$5({type:String})],ChromedashIntentPreviewPage.prototype,"appTitle",void 0),__decorate$s([n$5({type:Number})],ChromedashIntentPreviewPage.prototype,"featureId",void 0),__decorate$s([n$5({type:Number})],ChromedashIntentPreviewPage.prototype,"stageId",void 0),__decorate$s([n$5({type:Number})],ChromedashIntentPreviewPage.prototype,"gateId",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"feature",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"stage",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"gate",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"loading",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"subject",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"intentBody",void 0),__decorate$s([r$6()],ChromedashIntentPreviewPage.prototype,"displayFeatureUnlistedWarning",void 0),ChromedashIntentPreviewPage=__decorate$s([t$3("chromedash-intent-preview-page")],ChromedashIntentPreviewPage);var __decorate$r=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashLoginRequiredPage=class ChromedashLoginRequiredPage extends i$4{render(){return x$1` <div>Please login to see the content of this page.</div> `}};ChromedashLoginRequiredPage=__decorate$r([t$3("chromedash-login-required-page")],ChromedashLoginRequiredPage);var __decorate$q=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashMyFeaturesPage=class ChromedashMyFeaturesPage extends i$4{constructor(){super(...arguments),this.selectedGateId=0,this.starredFeatures=new Set}static get styles(){return[...SHARED_STYLES,i$7` + sl-details { + padding: 0 var(--content-padding); + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){window.csClient.getStars().then(starredFeatures=>{this.starredFeatures=new Set(starredFeatures)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}refetch(){const tables=Array.from(this.renderRoot.querySelectorAll("chromedash-feature-table"));for(const table of tables)table.refetch()}handleStarToggle(e){const newStarredFeatures=new Set(this.starredFeatures);window.csClient.setStar(e.detail.featureId,e.detail.doStar).then(()=>{e.detail.doStar?newStarredFeatures.add(e.detail.featureId):newStarredFeatures.delete(e.detail.featureId),this.starredFeatures=newStarredFeatures}).catch(()=>{showToastMessage("Unable to star the Feature. Please Try Again.")})}userCanApprove(){return this.user&&(this.user.is_admin||0<this.user.approvable_gate_types?.length)}renderBox(title,query,columns,sortSpec="",opened=!0){return x$1` + <sl-details summary="${title}" ?open=${opened}> + <chromedash-feature-table + query="${query}" + showEnterprise + sortSpec="${sortSpec}" + ?signedIn=${!!this.user} + ?canEdit=${this.user&&this.user.can_edit_all} + .starredFeatures=${this.starredFeatures} + @star-toggle-event=${this.handleStarToggle} + selectedGateId=${this.selectedGateId} + num="25" + columns=${columns} + > + </chromedash-feature-table> + </sl-details> + `}renderPendingAndRecentApprovals(){const adminNotice=this.user?.is_admin?x$1`<p>You see all pending approvals because you're a site admin.</p>`:E$1,pendingBox=this.renderBox("Features pending my approval","pending-approval-by:me","approvals","gate.requested_on"),recentBox=this.renderBox("Recently reviewed features","is:recently-reviewed","normal","-gate.reviewed_on",!1);return[adminNotice,pendingBox,recentBox]}renderIStarred(){return this.renderBox("Features I starred","starred-by:me","normal")}renderICanEdit(){return this.renderBox("Features I can edit","can_edit:me","normal")}render(){return x$1` + <div id="subheader"> + <h2>My features</h2> + </div> + <div id="deprecated" class="warning"> + This page will soon be removed from our site.<br /> + Please use one of the "My features" options in the main menu. + </div> + + ${this.userCanApprove()?this.renderPendingAndRecentApprovals():E$1} + ${this.renderICanEdit()} ${this.renderIStarred()} + `}};__decorate$q([n$5({attribute:!1})],ChromedashMyFeaturesPage.prototype,"user",void 0),__decorate$q([n$5({type:Number})],ChromedashMyFeaturesPage.prototype,"selectedGateId",void 0),__decorate$q([r$6()],ChromedashMyFeaturesPage.prototype,"starredFeatures",void 0),ChromedashMyFeaturesPage=__decorate$q([t$3("chromedash-myfeatures-page")],ChromedashMyFeaturesPage);var __decorate$p=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashOTCreationPage=class ChromedashOTCreationPage extends i$4{constructor(){super(...arguments),this.stageId=0,this.featureId=0,this.appTitle="",this.userEmail="",this.loading=!0,this.submitting=!1,this.fieldValues=[],this.showApprovalsFields=!1,this.isDeprecationTrial=!1,this.webfeatureUseCounterType=USE_COUNTER_TYPE_WEBFEATURE}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + #overlay { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.3); + z-index: 2; + cursor: pointer; + } + .submission-spinner { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + height: 300px; + } + + .warning { + border: 2px solid #555555; + border-radius: 10px; + padding: 4px; + margin-bottom: 32px; + } + .warning h3 { + text-align: center; + color: #555555; + font-weight: 300; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value,"ot_require_approvals"===this.fieldValues[index].name?(this.showApprovalsFields=!this.showApprovalsFields,this.requestUpdate()):"ot_is_deprecation_trial"===this.fieldValues[index].name&&(this.isDeprecationTrial=value,this.requestUpdate())}handleUseCounterTypeUpdate(event){this.webfeatureUseCounterType=parseInt(event.detail.value)}fetchData(){this.loading=!0,Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getStage(this.featureId,this.stageId),window.csClient.getGates(this.featureId)]).then(([feature,stage,gatesRes])=>{this.feature=feature,this.stage=stage,this.stage.ot_setup_status&&this.stage.ot_setup_status!==OT_SETUP_STATUS_OPTIONS.OT_NOT_CREATED&&(window.location.href=`/feature/${this.featureId}`);const relevantGates=gatesRes.gates.filter(g=>g.stage_id===this.stage.id);relevantGates.forEach(g=>{GATE_APPROVED_REVIEW_STATES.includes(g.state)||(window.location.href=`/feature/${this.featureId}`)}),this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.setFieldValues(),this.loading=!1})}addOptionalApprovalsFields(){const insertIndex=this.fieldValues.findIndex(fieldInfo=>"ot_require_approvals"===fieldInfo.name)+1;this.fieldValues.splice(insertIndex,0,{name:"ot_approval_buganizer_component",touched:!0,value:"",stageId:this.stage.id,isApprovalsField:!0},{name:"ot_approval_buganizer_custom_field_id",touched:!0,value:"",stageId:this.stage.id,isApprovalsField:!0},{name:"ot_approval_group_email",touched:!0,value:"",stageId:this.stage.id,isApprovalsField:!0},{name:"ot_approval_criteria_url",touched:!0,value:"",stageId:this.stage.id,isApprovalsField:!0})}addAdditionalFields(){this.fieldValues.push({name:"ot_action_requested",touched:!0,value:!0,stageId:this.stage.id,alwaysHidden:!0}),"Chrome Platform Status"!==this.appTitle&&this.fieldValues.push({name:"ot_creation__bypass_file_checks",touched:!0,value:!1,stageId:this.stage.id,alwaysHidden:!1})}setFieldValues(){const section=ORIGIN_TRIAL_CREATION_FIELDS.sections[0];this.fieldValues=section.fields.map(field=>{const featureJSONKey=ALL_FIELDS[field].name||field;let value=getStageValue(this.stage,featureJSONKey);return"ot_owner_email"!==featureJSONKey||value?"ot_require_approvals"===featureJSONKey&&(this.showApprovalsFields=!!value):value=[this.userEmail],{name:featureJSONKey,touched:!0,value,stageId:this.stage.id}}),this.addOptionalApprovalsFields(),this.addAdditionalFields()}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerHandlers(el){if(el){await el.updateComplete;const submitButton=this.renderRoot.querySelector("input[id=submit-button]");submitButton?.form?.addEventListener("submit",event=>{this.handleFormSubmit(event)}),setupScrollToHash(this)}}checkWebfeatureUseCounter(field,errors){field.checkMessage=errors.ot_webfeature_use_counter?x$1` <span class="check-error"> + <b>Error</b>: ${errors.ot_webfeature_use_counter} + </span>`:E$1}checkChromiumTrialName(field,errors){field.checkMessage=errors.ot_chromium_trial_name?x$1` <span class="check-error"> + <b>Error</b>: ${errors.ot_chromium_trial_name} + </span>`:E$1}checkThirdPartySupport(field,errors){field.checkMessage=errors.ot_has_third_party_support?x$1` <br /> + <span class="check-error"> + <b>Error</b>: ${errors.ot_has_third_party_support} + </span>`:E$1}checkCriticalTrial(field,errors){field.checkMessage=errors.ot_is_critical_trial?x$1` <br /> + <span class="check-error"> + <b>Error</b>: ${errors.ot_is_critical_trial} + </span>`:E$1}handleChromiumChecks(errors){for(const field of this.fieldValues)"ot_webfeature_use_counter"===field.name?this.checkWebfeatureUseCounter(field,errors):"ot_chromium_trial_name"===field.name?this.checkChromiumTrialName(field,errors):"ot_has_third_party_support"===field.name?this.checkThirdPartySupport(field,errors):"ot_is_critical_trial"===field.name&&this.checkCriticalTrial(field,errors)}async handleFormSubmit(e){e.preventDefault(),this.showApprovalsFields||this.fieldValues.forEach(fieldInfo=>{fieldInfo.isApprovalsField&&(fieldInfo.touched=!1)});const useCounterField=this.fieldValues.find(fv=>"ot_webfeature_use_counter"===fv.name);this.isDeprecationTrial&&(useCounterField.touched=!1);const featureSubmitBody=formatFeatureChanges(this.fieldValues,this.featureId),stageSubmitBody=featureSubmitBody.stages[0];if("ot_webfeature_use_counter"in stageSubmitBody){let useCounterPrefix="";this.webfeatureUseCounterType===USE_COUNTER_TYPE_WEBDXFEATURE?useCounterPrefix="WebDXFeature::":this.webfeatureUseCounterType===USE_COUNTER_TYPE_CSS_PROPERTY_ID&&(useCounterPrefix="CSSSampleId::"),stageSubmitBody.ot_webfeature_use_counter.value=`${useCounterPrefix}${stageSubmitBody.ot_webfeature_use_counter.value}`}this.submitting=!0,window.csClient.createOriginTrial(this.featureId,this.stageId,stageSubmitBody).then(resp=>{resp.errors?(this.handleChromiumChecks(resp.errors),showToastMessage("Some issues were found with the given inputs. Check input errors and try again."),this.submitting=!1,this.requestUpdate()):(showToastMessage("Creation request submitted!"),setTimeout(()=>{window.location.href=`/feature/${this.featureId}`},1e3))})}handleCancelClick(){window.location.href=`/feature/${this.featureId}`}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}getNextPage(){return`/feature/${this.featureId}`}renderSubheader(){const link=this.loading?E$1:x$1` + <a href=${this.getNextPage()}> + <sl-icon name="arrow-left"></sl-icon> + Request origin trial creation: ${this.feature.name} + </a> + `;return x$1` + <div id="subheader"> + <h2 id="breadcrumbs">${link}</h2> + </div> + `}renderFields(){const fields=this.fieldValues.map((fieldInfo,i)=>{if(fieldInfo.alwaysHidden||fieldInfo.isApprovalsField&&!this.showApprovalsFields||"ot_webfeature_use_counter"===fieldInfo.name&&this.isDeprecationTrial)return E$1;const shouldFadeIn=fieldInfo.isApprovalsField||"ot_webfeature_use_counter"===fieldInfo.name;let additionalInfo=E$1;return"ot_webfeature_use_counter"==fieldInfo.name&&(additionalInfo=x$1` + <chromedash-form-field + name="ot_webfeature_use_counter__type" + index=${i} + .value=${this.webfeatureUseCounterType} + .fieldValues=${this.fieldValues} + ?shouldFadeIn=${shouldFadeIn} + @form-field-update="${this.handleUseCounterTypeUpdate}" + class="choices" + > + </chromedash-form-field> + `),x$1` + ${additionalInfo} + <chromedash-form-field + name=${fieldInfo.name} + index=${i} + value=${fieldInfo.value} + disabledReason="${getDisabledHelpText(fieldInfo.name,this.stage)}" + .checkMessage=${fieldInfo.checkMessage} + .fieldValues=${this.fieldValues} + ?shouldFadeIn=${shouldFadeIn} + @form-field-update="${this.handleFormFieldUpdate}" + > + </chromedash-form-field> + `});return fields}renderForm(){this.fieldValues.feature=this.feature;const submitButtonTitle=this.submitting?"Submitting...":"Submit";return x$1` + <form name="feature_form"> + ${this.submitting?x$1`<div id="overlay"> + <div class="loading"> + <div id="spinner"> + <img class="submission-spinner" src="/static/img/ring.svg" /> + </div> + </div> + </div>`:E$1} + <chromedash-form-table ${n$2(this.registerHandlers)}> + <section class="stage_form"> + <div class="warning warning-div"> + <h3> + Please make sure this data is correct before submission! If you + are not sure about any information on this form, contact + <strong>origin-trials-support@google.com</strong> + </h3> + </div> + ${this.renderFields()} + </section> + </chromedash-form-table> + <div class="final_buttons"> + <input + id="submit-button" + class="button" + type="submit" + value=${submitButtonTitle} + ?disabled=${this.submitting} + /> + <button + id="cancel-button" + type="reset" + @click=${this.handleCancelClick} + > + Cancel + </button> + </div> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}};__decorate$p([n$5({type:Number})],ChromedashOTCreationPage.prototype,"stageId",void 0),__decorate$p([n$5({type:Number})],ChromedashOTCreationPage.prototype,"featureId",void 0),__decorate$p([n$5({attribute:!1})],ChromedashOTCreationPage.prototype,"feature",void 0),__decorate$p([n$5({type:String})],ChromedashOTCreationPage.prototype,"appTitle",void 0),__decorate$p([n$5({type:String})],ChromedashOTCreationPage.prototype,"userEmail",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"loading",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"submitting",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"fieldValues",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"showApprovalsFields",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"isDeprecationTrial",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"webfeatureUseCounterType",void 0),__decorate$p([r$6()],ChromedashOTCreationPage.prototype,"stage",void 0),ChromedashOTCreationPage=__decorate$p([t$3("chromedash-ot-creation-page")],ChromedashOTCreationPage);var __decorate$o=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashOTExtensionPage extends i$4{constructor(){super(...arguments),this.stageId=0,this.featureId=0,this.appTitle="",this.loading=!0,this.fieldValues=[],this.currentMilestone=123,this.endMilestoneDateValues={}}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7``]}static get properties(){return{stageId:{type:Number},featureId:{type:Number},userEmail:{type:String},feature:{type:Object},loading:{type:Boolean},appTitle:{type:String},fieldValues:{type:Array},currentMilestone:{type:Number},endMilestoneDateValues:{type:Object}}}connectedCallback(){super.connectedCallback(),this.fetchData()}handleFormFieldUpdate(event){const value=event.detail.value,index=event.detail.index;if(index>=this.fieldValues.length)throw new Error("Out of bounds index when updating field values.");this.fieldValues[index].touched=!0,this.fieldValues[index].value=value,"ot_extension__milestone_desktop_last"==this.fieldValues[index].name&&this.getChromeScheduleDate(event.detail.value)}openMilestoneExplanationDialog(){openInfoDialog(dialogTypes.END_MILESTONE_EXPLANATION)}updateMilestoneDate(milestone){const milestoneDiv=this.renderRoot.querySelector("#milestone-date"),milestoneTextEl=this.renderRoot.querySelector("#milestone-date-text"),date=new Date(this.endMilestoneDateValues[milestone]);milestoneDiv&&milestoneTextEl&&(milestoneDiv.style.display="block",milestoneTextEl.innerHTML=`For milestone ${milestone}, this trial will end on ${date.toLocaleDateString()}.`)}async getChromeScheduleDate(milestone){const milestoneDiv=this.renderRoot.querySelector("#milestone-date");if(milestoneDiv&&(milestoneDiv.style.display="none",!!extensionMilestoneIsValid(milestone,this.currentMilestone))){if(!(milestone in this.endMilestoneDateValues)){const milestonePlusTwo=parseInt(milestone)+2,resp=await fetch(`https://chromiumdash.appspot.com/fetch_milestone_schedule?mstone=${milestonePlusTwo}`),respJson=await resp.json();this.endMilestoneDateValues[milestone]=respJson.mstones[0].late_stable_date}this.updateMilestoneDate(milestone)}}fetchData(){this.loading=!0,Promise.all([window.csClient.getFeature(this.featureId),window.csClient.getStage(this.featureId,this.stageId)]).then(([feature,stage])=>{this.feature=feature,this.stage=stage,this.feature.name&&(document.title=`${this.feature.name} - ${this.appTitle}`),this.loading=!1}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}),fetch("https://chromiumdash.appspot.com/fetch_milestone_schedule").then(resp=>resp.json()).then(scheduleInfo=>{this.currentMilestone=parseInt(scheduleInfo.mstones[0].mstone)})}disconnectedCallback(){super.disconnectedCallback(),document.title=this.appTitle}async registerHandlers(el){if(el){await el.updateComplete;const submitButton=this.renderRoot.querySelector("input[id=submit-button]");submitButton?.form?.addEventListener("submit",event=>{this.handleFormSubmit(event)}),setupScrollToHash(this)}}handleFormSubmit(e){e.preventDefault();const featureSubmitBody=formatFeatureChanges(this.fieldValues,this.featureId),stageSubmitBody=featureSubmitBody.stages[0];let newStageId=null;window.csClient.createStage(this.featureId,stageSubmitBody).then(resp=>(newStageId=resp.stage_id,window.csClient.getGates(this.featureId))).then(resp=>{const gate=resp.gates.find(gate=>gate.stage_id===newStageId);showToastMessage("Extension request started!"),newStageId&&gate?setTimeout(()=>{window.location.href=`/feature/${this.featureId}?gate=${gate.id}`},1e3):setTimeout(()=>{window.location.href=`/feature/${this.featureId}`},1e3)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleCancelClick(e){e.preventDefault(),window.location.href=`/feature/${this.featureId}`}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}getNextPage(){return`/feature/${this.featureId}`}renderSubheader(){const link=this.loading?E$1:x$1` + <a href=${this.getNextPage()}> + <sl-icon name="arrow-left"></sl-icon> + Request origin trial extension: ${this.feature.name} + </a> + `;return x$1` + <div id="subheader"> + <h2 id="breadcrumbs">${link}</h2> + </div> + `}addDefaultRequestFields(){this.fieldValues.push({name:"ot_owner_email",touched:!0,value:this.userEmail,stageId:this.stage.id}),this.fieldValues.push({name:"ot_action_requested",touched:!0,value:!0,stageId:this.stage.id});const extensionStageType=OT_EXTENSION_STAGE_MAPPING[this.stage.stage_type];this.fieldValues.push({name:"stage_type",touched:!0,value:extensionStageType,stageId:this.stage.id}),this.fieldValues.push({name:"ot_stage_id",touched:!0,value:this.stage.id,stageId:this.stage.id})}renderFields(section){const fields=section.fields.map(field=>{const featureJSONKey=ALL_FIELDS[field].name||field,index=this.fieldValues.length;this.fieldValues.push({name:featureJSONKey,touched:!0,value:null,stageId:this.stage.id});let milestoneInfoText=x$1``;return"ot_extension__milestone_desktop_last"===featureJSONKey&&(milestoneInfoText=x$1` <div + id="milestone-date" + style="display:none;" + > + <span id="milestone-date-text" class="helptext fade-in"></span> + <a class="helptext" @click=${this.openMilestoneExplanationDialog}> + Learn how this date is chosen + </a> + </div>`),x$1` + <chromedash-form-field + name=${featureJSONKey} + index=${index} + disabledReason="${getDisabledHelpText(field,this.stage)}" + .fieldValues=${this.fieldValues} + @form-field-update="${this.handleFormFieldUpdate}" + > + </chromedash-form-field> + ${milestoneInfoText} + `});return this.addDefaultRequestFields(),fields}renderForm(){this.fieldValues.feature=this.feature;const section=ORIGIN_TRIAL_EXTENSION_FIELDS.sections[0];return x$1` + <form name="feature_form"> + <chromedash-form-table ${n$2(this.registerHandlers)}> + <section class="stage_form">${this.renderFields(section)}</section> + </chromedash-form-table> + <div class="final_buttons"> + <input + id="submit-button" + class="button" + type="submit" + value="Submit" + /> + <button + id="cancel-button" + type="reset" + @click=${this.handleCancelClick} + > + Cancel + </button> + </div> + </form> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderForm()} + `}}__decorate$o([n$5({type:Number})],ChromedashOTExtensionPage.prototype,"stageId",void 0),__decorate$o([n$5({type:Number})],ChromedashOTExtensionPage.prototype,"featureId",void 0),__decorate$o([n$5({type:String})],ChromedashOTExtensionPage.prototype,"userEmail",void 0),__decorate$o([n$5({type:String})],ChromedashOTExtensionPage.prototype,"appTitle",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"feature",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"loading",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"fieldValues",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"currentMilestone",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"endMilestoneDateValues",void 0),__decorate$o([r$6()],ChromedashOTExtensionPage.prototype,"stage",void 0),customElements.define("chromedash-ot-extension-page",ChromedashOTExtensionPage);var __decorate$n=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashSettingsPage=class ChromedashSettingsPage extends i$4{constructor(){super(...arguments),this.notify_as_starrer=!1,this.submitting=!1}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + th, + td { + padding: 4px; + } + + input[type='submit'] { + margin: 20px; + } + + input[disabled] { + opacity: 0.5; + pointer-events: none; + } + + #spinner { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + height: 60%; + width: 100%; + } + + table .helptext { + display: block; + font-style: italic; + font-size: smaller; + max-width: 40em; + margin-top: 2px; + } + `]}connectedCallback(){super.connectedCallback(),window.csClient.getSettings().then(res=>{this.notify_as_starrer=res.notify_as_starrer}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleSubmit(e){e.preventDefault(),this.submitting=!0,window.csClient.setSettings(this.notify_as_starrer).then(()=>{showToastMessage("Settings saved."),handleSaveChangesResponse("")}).catch(()=>{showToastMessage("Unable to save the settings. Please try again."),handleSaveChangesResponse("Unable to save the settings. Please try again.")}).finally(()=>{this.submitting=!1})}handleChange(){this.notify_as_starrer=!this.notify_as_starrer}render(){const submitButtonTitle=this.submitting?"Submitting...":"Submit";return x$1` + <div id="subheader"> + <h2>User preferences</h2> + </div> + <section> + <form name="user_pref_form" @submit=${this.handleSubmit}> + <table cellspacing="6"> + <tbody> + <tr> + <th> + <label for="id_notify_as_starrer">Notify as starrer:</label> + </th> + <td> + <sl-checkbox + id="id_notify_as_starrer" + name="notify_as_starrer" + ?checked=${this.notify_as_starrer} + @input=${this.handleChange} + > + </sl-checkbox> + <span class="helptext"> + Send you notification emails for features that you + starred?</span + > + </td> + </tr> + </tbody> + </table> + <input + type="submit" + value=${submitButtonTitle} + ?disabled=${this.submitting} + /> + </form> + </section> + ${this.submitting?x$1` <div class="loading"> + <div id="spinner"><img src="/static/img/ring.svg" /></div> + </div>`:E$1} + `}};__decorate$n([r$6()],ChromedashSettingsPage.prototype,"notify_as_starrer",void 0),__decorate$n([r$6()],ChromedashSettingsPage.prototype,"submitting",void 0),ChromedashSettingsPage=__decorate$n([t$3("chromedash-settings-page")],ChromedashSettingsPage);var __decorate$m=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashXMeter=class ChromedashXMeter extends i$4{constructor(){super(...arguments),this.value=0,this.max=100,this.href="#"}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: grid; + grid-template-columns: 65px 1fr; + grid-column-gap: 15px; + height: 1.6em; + font-size: 14px; + } + + #percentage-number { + place-self: center; + } + + #track { + background: var(--barchart-background); + border-radius: var(--border-radius); + overflow: hidden; + height: 100%; + } + + #indicator { + background: var(--barchart-foreground); + height: 100%; + white-space: nowrap; + padding: 3px 0; + } + `]}render(){return x$1` + <p id="percentage-number"> + ${1e-4>this.value?"<0.0001%":this.value.toFixed(4)+"%"} + </p> + <a href="${this.href}"> + <div id="track"> + <div + id="indicator" + style="width: ${100*(this.value/this.max)}%" + ></div> + </div> + </a> + `}};__decorate$m([n$5({type:Number})],ChromedashXMeter.prototype,"value",void 0),__decorate$m([n$5({type:Number})],ChromedashXMeter.prototype,"max",void 0),__decorate$m([n$5({type:String})],ChromedashXMeter.prototype,"href",void 0),ChromedashXMeter=__decorate$m([t$3("chromedash-x-meter")],ChromedashXMeter);var __decorate$l=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashStackRank=class ChromedashStackRank extends i$4{constructor(){super(...arguments),this.type="",this.view="",this.viewList=[],this.tempList=[],this.maxPercentage=100,this.sortType="percentage",this.sortReverse=!1,this.shouldHideObsolete=!0,this.obsoleteCount=0}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: block; + flex: 1; + padding: 1px; + } + + .title-text { + flex: 1; + font-weight: 500; + } + + li { + padding: 5px 0; + display: flex; + align-items: center; + } + + #subheader { + font-size: 15px; + display: flex; + justify-content: space-between; + align-items: center; + } + + #dropdown-selection:hover { + background: var(--sl-color-neutral-100); + } + + sl-button::part(base) { + color: #000; + } + + li > :first-child { + flex: 1; + word-break: break-all; + } + + li > :nth-child(2) { + flex: 2; + } + + .stack-rank-header { + margin-bottom: 5px; + text-align: center; + } + + .stack-rank-item { + border-top: var(--table-divider); + } + + .stack-rank-item-hidden { + display: none; + } + + .stack-rank-item-name { + display: grid; + grid-template-columns: var(--icon-size) 1fr; + grid-column-gap: 15px; + position: relative; + left: -20px; + } + .stack-rank-item-name .hash-link { + place-self: center; + visibility: hidden; + } + .stack-rank-item-name:hover .hash-link { + visibility: visible; + } + + .stack-rank-item-result { + display: flex; + align-items: center; + gap: 15px; + margin-right: 15px; + } + + chromedash-x-meter { + flex: 1; + } + + a.icon-wrapper { + display: flex; + gap: 3px; + align-items: center; + } + a.icon-wrapper:hover { + text-decoration: none; + } + + .spacer { + visibility: hidden; + } + + sl-skeleton { + margin: 0; + padding: 5px 20px; + } + + /* On small displays, only show timeline icons (no text). */ + @media only screen and (max-width: 600px) { + .icon-text { + display: none; + } + + .stack-rank-item-name { + grid-column-gap: 5px; + } + + .stack-rank-item-result { + margin-right: 5px; + } + } + `]}willUpdate(changedProperties){var _Mathmax7=Math.max;changedProperties.has("viewList")&&this.viewList.length&&(this.maxPercentage=this.viewList.reduce((accum,currVal)=>_Mathmax7(accum,currVal.percentage),0),setTimeout(()=>{this.scrollToPosition()},300),this.obsoleteCount=this.viewList.filter(item=>item.obsolete).length)}scrollToPosition(e){let hash;if(e?hash=e.currentTarget.getAttribute("href"):location.hash&&(hash=decodeURIComponent(location.hash)),hash){const el=this.renderRoot.querySelector(".stack-rank-list "+hash);el?.scrollIntoView({behavior:"smooth"})}}sort(e){e.preventDefault();const parts=e.target.dataset.order.split("-");this.sortType=parts[0],this.sortReverse=!!parts[1];const newViewList=[...this.viewList];this.viewList=sortBy_(this.sortType,this.sortReverse,newViewList)}handleChangeHideObsolete(e){this.shouldHideObsolete=e.target.checked}renderSubHeader(){return x$1` + <div id="subheader"> + <p class="title-text"> + Showing + <span + >${this.viewList.length-(this.shouldHideObsolete?this.obsoleteCount:0)}</span + > + properties + </p> + <sl-checkbox + ?checked=${this.shouldHideObsolete} + @input=${this.handleChangeHideObsolete} + > + Hide obsolete + </sl-checkbox> + <div id="dropdown-selection"> + <sl-dropdown> + <sl-button + slot="trigger" + variant="text" + ?disabled=${!this.viewList.length} + > + <sl-icon name="filter-left"></sl-icon> + SORT BY + </sl-button> + <sl-menu @click="${this.sort}"> + <sl-menu-item + type="checkbox" + ?checked=${"percentage"==this.sortType&&!this.sortReverse} + data-order="percentage" + > + Most used + </sl-menu-item> + <sl-menu-item + type="checkbox" + ?checked=${"percentage"==this.sortType&&this.sortReverse} + data-order="percentage-reverse" + > + Least used + </sl-menu-item> + <sl-menu-item + type="checkbox" + ?checked=${"property_name"==this.sortType&&this.sortReverse} + data-order="property_name-reverse" + > + Name (A-Z) + </sl-menu-item> + <sl-menu-item + type="checkbox" + ?checked=${"property_name"==this.sortType&&!this.sortReverse} + data-order="property_name" + > + Name (Z-A) + </sl-menu-item> + </sl-menu> + </sl-dropdown> + </div> + </div> + `}renderStackRank(displayedList){return x$1` + ${displayedList.map(item=>x$1` + <li + class="stack-rank-item ${this.shouldHideObsolete&&item.obsolete?"stack-rank-item-hidden":""}" + id="${item.property_name}" + > + <div + title="${item.property_name}. Click to deep link to this property." + > + <a + class="stack-rank-item-name" + href="#${item.property_name}" + @click=${this.scrollToPosition} + > + <sl-icon + class="hash-link" + library="material" + name="link" + ></sl-icon> + <p>${item.property_name}</p> + </a> + </div> + <div class="stack-rank-item-result"> + <chromedash-x-meter + value="${item.percentage}" + max="${this.maxPercentage}" + href="/metrics/${this.type}/timeline/${this.view}/${item.bucket_id}" + title="Click to see a timeline view of this property" + > + </chromedash-x-meter> + <a + class="icon-wrapper" + href="/metrics/${this.type}/timeline/${this.view}/${item.bucket_id}" + title="Click to see a timeline view of this property" + > + <sl-icon name="graph-up"></sl-icon> + <p class="icon-text">Timeline</p> + </a> + </div> + </li> + `)} + `}renderSkeletons(){return x$1`${Array.from(Array(20)).map(()=>x$1` + <li class="stack-rank-item"> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </li> + `)}`}renderTemporaryRank(){return x$1` + ${this.tempList.length?this.renderStackRank(this.tempList):E$1} + ${this.renderSkeletons()} + `}renderStackRankList(){return x$1` + <ol class="stack-rank-list"> + <li class="stack-rank-header"> + <p class="title-text">Property name</p> + <div class="stack-rank-item-result"> + <p class="title-text">Percentage</p> + <a class="icon-wrapper spacer"> + <sl-icon name="graph-up"></sl-icon> + <p class="icon-text">Timeline</p> + </a> + </div> + </li> + ${this.viewList.length?this.renderStackRank(this.viewList):this.renderTemporaryRank()} + </ol> + `}render(){return x$1` ${this.renderSubHeader()} ${this.renderStackRankList()} `}};__decorate$l([n$5({type:String,attribute:!1})],ChromedashStackRank.prototype,"type",void 0),__decorate$l([n$5({type:String,attribute:!1})],ChromedashStackRank.prototype,"view",void 0),__decorate$l([n$5({type:Array,attribute:!1})],ChromedashStackRank.prototype,"viewList",void 0),__decorate$l([n$5({type:Array,attribute:!1})],ChromedashStackRank.prototype,"tempList",void 0),__decorate$l([r$6()],ChromedashStackRank.prototype,"maxPercentage",void 0),__decorate$l([r$6()],ChromedashStackRank.prototype,"sortType",void 0),__decorate$l([r$6()],ChromedashStackRank.prototype,"sortReverse",void 0),__decorate$l([r$6()],ChromedashStackRank.prototype,"shouldHideObsolete",void 0),__decorate$l([r$6()],ChromedashStackRank.prototype,"obsoleteCount",void 0),ChromedashStackRank=__decorate$l([t$3("chromedash-stack-rank")],ChromedashStackRank);const sortBy_=(propName,reverse,arr)=>{const compareAsNumbers="percentage"===propName;return arr.sort((a,b)=>{const propA=compareAsNumbers?+a[propName]:a[propName],propB=compareAsNumbers?+b[propName]:b[propName];return propA>propB?reverse?1:-1:propA<propB?reverse?-1:1:0}),arr};var __decorate$k=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashStackRankPage extends i$4{constructor(){super(...arguments),this.viewList=[],this.tempList=[]}static get styles(){return[...SHARED_STYLES,i$7` + h3 { + margin: var(--content-padding) 0; + font-weight: 500; + color: #000; + } + + .description { + margin-bottom: 1em; + } + .description #highlighted-text { + font-weight: 500; + } + + #datalist-input { + width: 30em; + max-width: 100%; + border-radius: 10px; + height: 25px; + margin-bottom: var(--content-padding); + padding-left: 10px; + font-size: 15px; + } + `]}connectedCallback(){super.connectedCallback(),this.loadAll()}loadAll(){let endpoint=`/data/${this.type}${this.view}`;const options={credentials:"omit"};fetch(endpoint,options).then(res=>res.json()).then(props=>{for(let i=0,item;item=props[i];++i)item.percentage=(100*item.day_percentage).toFixed(6),item.obsolete=item.property_name&&(item.property_name.startsWith("OBSOLETE_")||item.property_name.endsWith("(obsolete)"));const viewList=props.filter(item=>!["ERROR","PageVisits","PageDestruction"].includes(item.property_name));this.tempList=viewList.slice(0,30),setTimeout(()=>{this.viewList=viewList},300)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleSearchBarChange(e){const inputValue=e.currentTarget.value,property=this.viewList.find(item=>item.property_name===inputValue);window.location.href=`/metrics/${this.type}/timeline/${this.view}/${property.bucket_id}`}renderSubheader(){const subTitleText=METRICS_TYPE_AND_VIEW_TO_SUBTITLE[this.type+this.view];return x$1`<h2>${subTitleText} > stack rank</h2>`}renderSearchBar(){return x$1` + <input + id="datalist-input" + type="search" + list="features" + autocomplete="off" + placeholder=${this.viewList.length?"Select or search a property for detailed stats":"loading..."} + @change="${this.handleSearchBarChange}" + /> + <datalist id="features"> + ${this.viewList.map(item=>x$1` + <option + value="${item.property_name}" + dataset-debug-bucket-id="${item.bucket_id}" + ></option> + `)} + </datalist> + `}renderDataPanel(){return x$1` + <h3>Data from last 24 hours</h3> + <p class="description"> + The percentage numbers indicate the + <span id="highlighted-text" + >percentage of Chrome page loads (across all channels and platforms) + that use the ${"css"==this.type?"property":"feature"} at least + once</span + >. Data is collected via Chrome's + <a + href="https://cs.chromium.org/chromium/src/tools/metrics/histograms/enums.xml" + target="_blank" + rel="noopener" + >anonymous usage statistics</a + >. + </p> + <chromedash-stack-rank + .type=${this.type} + .view=${this.view} + .tempList=${this.tempList} + .viewList=${this.viewList} + > + </chromedash-stack-rank> + `}render(){return x$1` + <div id="subheader">${this.renderSubheader()}</div> + ${this.renderSearchBar()} ${this.renderDataPanel()} + `}}__decorate$k([n$5({attribute:!1})],ChromedashStackRankPage.prototype,"type",void 0),__decorate$k([n$5({attribute:!1})],ChromedashStackRankPage.prototype,"view",void 0),__decorate$k([n$5({attribute:!1})],ChromedashStackRankPage.prototype,"viewList",void 0),__decorate$k([n$5({attribute:!1})],ChromedashStackRankPage.prototype,"tempList",void 0),customElements.define("chromedash-stack-rank-page",ChromedashStackRankPage);var __decorate$j=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashStaleFeaturesPage=class ChromedashStaleFeaturesPage extends i$4{constructor(){super(...arguments),this.staleFeatures=[],this.loading=!0,this._sortColumn="name",this._sortDirection="asc"}static get styles(){return[...SHARED_STYLES,...FORM_STYLES,i$7` + :host { + display: block; + padding: 1em 2em; + max-width: 1400px; + margin: auto; + } + + #subheader { + padding: 0.5em 0; + margin-bottom: 1.5em; + border-bottom: 1px solid #e0e0e0; + } + + #breadcrumbs { + color: #333; + font-size: 1.75em; + font-weight: 600; + margin: 0; + } + + table { + width: 100%; + border-collapse: collapse; + } + + th, + td { + padding: 14px 18px; + text-align: left; + border-bottom: 1px solid #ddd; + } + + thead tr { + background-color: #f9f9f9; + } + + th { + font-weight: 600; + color: #555; + text-transform: uppercase; + font-size: 0.85em; + letter-spacing: 0.05em; + } + + th.sortable { + cursor: pointer; + user-select: none; + position: relative; + padding-right: 36px; + } + + th.sortable:hover { + background-color: #f0f0f0; + } + + .sort-indicator { + position: absolute; + top: 50%; + right: 18px; + transform: translateY(-50%); + opacity: 0.6; + transition: opacity 0.2s ease-in-out; + } + + tbody tr:nth-child(even) { + background-color: #fdfdfd; + } + + tbody tr:hover { + background-color: #f1f1f1; + transition: background-color 0.2s ease-in-out; + } + + td a { + color: var(--link-color); + text-decoration: none; + font-weight: 500; + } + + td a:hover { + text-decoration: underline; + } + + .no-features { + padding: 2em; + text-align: center; + font-style: italic; + color: #777; + background-color: #fafafa; + border: 1px solid #ddd; + border-radius: 8px; + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}async fetchData(){this.loading=!0;try{const staleFeaturesResp=await window.csClient.getStaleFeatures();this.staleFeatures=staleFeaturesResp.stale_features}catch(error){console.error(error),showToastMessage("Some errors occurred. Please refresh the page or try again later.")}finally{this.loading=!1}}_handleSort(column){this._sortColumn===column?this._sortDirection="asc"===this._sortDirection?"desc":"asc":(this._sortColumn=column,this._sortDirection="asc")}_renderSortIndicator(column){return this._sortColumn===column?"asc"===this._sortDirection?"\u25B2":"\u25BC":""}renderSkeletons(){return x$1` + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <section id="metadata"> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}renderSubheader(){return x$1` + <div id="subheader"> + <h2 id="breadcrumbs">Stale features</h2> + </div> + `}renderStaleFeatures(){if(0===this.staleFeatures.length)return x$1` + <div class="no-features"> + <p>No stale features found. Great job!</p> + </div> + `;const sortedFeatures=[...this.staleFeatures].sort((a,b)=>{const valA=a[this._sortColumn],valB=b[this._sortColumn];let comparison=0;return"string"==typeof valA&&"string"==typeof valB?comparison=valA.localeCompare(valB):"number"==typeof valA&&"number"==typeof valB?comparison=valA-valB:"accurate_as_of"===this._sortColumn&&(comparison=new Date(valA).getTime()-new Date(valB).getTime()),"asc"===this._sortDirection?comparison:-comparison});return x$1` + <div class="stale-features-table-container"> + <table> + <thead> + <tr> + <th class="sortable" @click=${()=>this._handleSort("name")}> + Name + <span class="sort-indicator" + >${this._renderSortIndicator("name")}</span + > + </th> + <th>Owner Emails</th> + <th + class="sortable" + @click=${()=>this._handleSort("milestone_field")} + > + Milestone Field + <span class="sort-indicator" + >${this._renderSortIndicator("milestone_field")}</span + > + </th> + <th + class="sortable" + @click=${()=>this._handleSort("milestone")} + > + Milestone + <span class="sort-indicator" + >${this._renderSortIndicator("milestone")}</span + > + </th> + <th + class="sortable" + @click=${()=>this._handleSort("outstanding_notifications")} + > + Notifications + <span class="sort-indicator" + >${this._renderSortIndicator("outstanding_notifications")}</span + > + </th> + <th + class="sortable" + @click=${()=>this._handleSort("accurate_as_of")} + > + Last Updated + <span class="sort-indicator" + >${this._renderSortIndicator("accurate_as_of")}</span + > + </th> + </tr> + </thead> + <tbody> + ${sortedFeatures.map(feature=>x$1` + <tr> + <td><a href="/feature/${feature.id}">${feature.name}</a></td> + <td>${feature.owner_emails.join(", ")}</td> + <td>${feature.milestone_field}</td> + <td>${feature.milestone}</td> + <td>${feature.outstanding_notifications}</td> + <td> + ${new Date(feature.accurate_as_of).toLocaleDateString()} + </td> + </tr> + `)} + </tbody> + </table> + </div> + `}render(){return x$1` + ${this.renderSubheader()} + ${this.loading?this.renderSkeletons():this.renderStaleFeatures()} + `}};__decorate$j([r$6()],ChromedashStaleFeaturesPage.prototype,"staleFeatures",void 0),__decorate$j([r$6()],ChromedashStaleFeaturesPage.prototype,"loading",void 0),__decorate$j([r$6()],ChromedashStaleFeaturesPage.prototype,"_sortColumn",void 0),__decorate$j([r$6()],ChromedashStaleFeaturesPage.prototype,"_sortDirection",void 0),ChromedashStaleFeaturesPage=__decorate$j([t$3("chromedash-stale-features-page")],ChromedashStaleFeaturesPage);var __decorate$i=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashTimeline extends i$4{constructor(){super(...arguments),this.type="",this.view="",this.props=[],this.selectedBucketId="1",this.showAllHistoricalData=!1}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: block; + flex: 1; + width: var(--max-content-width); + } + + :host label { + margin-left: 8px; + cursor: pointer; + } + + #chart { + margin-top: 15px; + width: 100%; + height: 450px; + background: var(--table-alternate-background); + border-radius: var(--border-radius); + } + + #http-archive-data { + border: 0; + width: 100%; + height: 870px; + } + + .header_title { + margin: 32px 0 15px 0; + font-weight: 500; + color: #000; + } + + .description { + margin: 15px 0; + } + + .callout { + padding: var(--content-padding); + margin-top: var(--content-padding); + background-color: var(--sl-color-warning-100); + border-color: rgba(27, 31, 35, 0.15); + line-height: 1.4; + } + + #bigquery:empty { + display: none; + } + + #bigquery { + font-family: 'Courier New', Courier, monospace; + font-weight: 600; + padding: 15px; + margin-bottom: 100px; + background: var(--table-alternate-background); + display: inline-block; + } + + #datalist-input { + width: 20em; + border-radius: 10px; + height: 25px; + padding-left: 10px; + font-size: 15px; + } + + sl-progress-bar { + --height: 4px; + --track-color: var(--barchart-foreground); + --indicator-color: var(--barchart-background); + } + `]}updated(){window.google.charts.setOnLoadCallback(this._updateTimeline.bind(this))}updateSelectedBucketId(e){const inputValue=e.currentTarget.value,feature=this.props.find(el=>el[1]===inputValue);feature?this.selectedBucketId=feature[0].toString():inputValue&&showToastMessage("No matching features. Please try again!")}toggleShowAllHistoricalData(){this.showAllHistoricalData=!this.showAllHistoricalData}firstUpdated(){window.google.charts.load("current",{packages:["corechart"]})}drawVisualization(data,bucketId,showAllHistoricalData){function aggregateByMonth(date){const month=date.getMonth(),year=date.getFullYear();return new Date(year,month)}const datatable=new google.visualization.DataTable;datatable.addColumn("date","Date"),datatable.addColumn("number","Percentage"),datatable.addColumn({type:"string",role:"annotation"}),datatable.addColumn({type:"string",role:"annotationText"});const rowArray=[];for(let i=0,item;item=data[i];++i){const dateStr=item.date.split("-"),date=new Date;date.setFullYear(parseInt(dateStr[0]),parseInt(dateStr[1])-1,parseInt(dateStr[2]));const row=[date,parseFloat((100*item.day_percentage).toFixed(6))];"2017-10-27"===item.date?row.push("A","Modernized metrics"):row.push(null,null),rowArray.push(row)}datatable.addRows(rowArray);const groupedTable=window.google.visualization.data.group(datatable,[{column:0,modifier:aggregateByMonth,type:"date"}],[{column:1,aggregation:window.google.visualization.data.avg,type:"number",label:"Monthly Average"}],[{column:2,type:"string"}]),formatter=new window.google.visualization.NumberFormat({fractionDigits:6});formatter.format(groupedTable,1);let view=groupedTable;if(!showAllHistoricalData){const startYear=new Date().getFullYear()-2;view=new window.google.visualization.DataView(groupedTable),view.setRows(view.getFilteredRows([{column:0,minValue:new Date(startYear,0,1)}]))}const chartEl=this.shadowRoot.querySelector("#chart"),chart=new window.google.visualization.LineChart(chartEl);chart.draw(view,{backgroundColor:"white",legend:{position:"none"},curveType:"function",vAxis:{title:"% page loads",minValue:0},hAxis:{title:"Date",format:"MMM d, YYYY"},width:"100%",height:"100%",pointSize:4,series:{0:{color:"#4580c0"}},trendlines:{0:{type:"linear",opacity:.5,color:"#bdd6ed",pointsVisible:!1}}})}_updateTimeline(){if("1"!==this.selectedBucketId&&this.props.length){let url="/data/timeline/"+this.type+this.view+"?bucket_id="+this.selectedBucketId;this._renderHTTPArchiveData();const chartEl=this.shadowRoot.querySelector("#chart");chartEl.innerHTML.includes("sl-progress-bar")||chartEl.insertAdjacentHTML("afterbegin","<sl-progress-bar indeterminate></sl-progress-bar>");const options={credentials:"omit"};fetch(url,options).then(res=>res.json()).then(response=>{this.drawVisualization(response,this.selectedBucketId,this.showAllHistoricalData)});const currentUrl="/metrics/"+this.type+"/timeline/"+this.view+"/"+this.selectedBucketId;history.pushState&&location.pathname!=currentUrl&&history.pushState({id:this.selectedBucketId},"",currentUrl)}}_renderHTTPArchiveData(){const feature=this.props.find(el=>el[0]===parseInt(this.selectedBucketId));if(feature){let featureName=feature[1];const inputEl=this.shadowRoot.querySelector("#datalist-input");inputEl.value=featureName,"css"==this.type&&(featureName=convertToCamelCaseFeatureName(featureName));const REPORT_ID="1M8kXOqPkwYNKjJhtag_nvDNJCpvmw_ri",dsEmbedUrl=`https://datastudio.google.com/embed/reporting/${"1M8kXOqPkwYNKjJhtag_nvDNJCpvmw_ri"}/page/tc5b?params=%7B"df3":"include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580${featureName}"%7D`,hadEl=this.shadowRoot.querySelector("#http-archive-data");hadEl.src=dsEmbedUrl;const bigqueryEl=this.shadowRoot.querySelector("#bigquery");bigqueryEl.textContent=`#standardSQL +SELECT date, client, pct_urls, sample_urls +FROM \`httparchive.blink_features.usage\` +WHERE feature = '${featureName}' +AND date = (SELECT MAX(date) FROM \`httparchive.blink_features.usage\`) +ORDER BY date DESC, client`}}render(){const note2017=x$1` + <p class="callout"> + <b>Note</b>: on 2017-10-26 the underlying metrics were switched over to + a newer collection system which is + <a + href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-api-owners-discuss/IpIkbz0qtrM/HUCfSMv2AQAJ" + target="_blank" + >more accurate</a + >. This is also the reason for the abrupt spike around 2017-10-26. + </p> + `;return x$1` + <input + id="datalist-input" + type="search" + list="features" + autocomplete="off" + placeholder="Select or search a property" + @change="${this.updateSelectedBucketId}" + /> + <datalist id="features"> + ${this.props.map(prop=>x$1` + <option + value="${prop[1]}" + dataset-debug-bucket-id="${prop[0]}" + ></option> + `)} + </datalist> + <label> + Show all historical data: + <input + type="checkbox" + ?checked="${this.showAllHistoricalData}" + @change="${this.toggleShowAllHistoricalData}" + /> + </label> + <h3 id="usage" class="header_title"> + Percentage of page loads over time + </h3> + <p class="description"> + The chart below shows the percentage of page loads (in Chrome) that use + this feature at least once. Data is across all channels and platforms. + Newly added use counters that are not on Chrome stable yet only have + data from the Chrome channels they're on. + </p> + <div id="chart"></div> + ${this.showAllHistoricalData?note2017:E$1} + <h3 id="httparchive" class="header_title"> + Adoption of the feature on top sites + </h3> + <p class="description"> + The chart below shows the adoption of the feature by the top URLs on the + internet. Data from + <a href="https://httparchive.org/" target="_blank">HTTP Archive</a>. + </p> + <iframe id="http-archive-data"></iframe> + <p class="callout"> + <b>Note</b>: The jump around July and December 2018 are because the + corpus of URLs crawled by HTTP Archive increased. These jumps have no + correlation with the jump in the top graph. See the + <a + href="https://discuss.httparchive.org/t/changes-to-the-http-archive-corpus/1539" + target="_blank" + >announcement</a + > + for more details. + </p> + <p class="description"> + Copy and run this command in + <a href="https://bigquery.cloud.google.com" target="_blank">BigQuery</a> + to produce similar results: + </p> + <pre id="bigquery"></pre> + `}}__decorate$i([n$5({type:String})],ChromedashTimeline.prototype,"type",void 0),__decorate$i([n$5({type:String})],ChromedashTimeline.prototype,"view",void 0),__decorate$i([n$5({attribute:!1})],ChromedashTimeline.prototype,"props",void 0),__decorate$i([n$5({attribute:!1})],ChromedashTimeline.prototype,"selectedBucketId",void 0),__decorate$i([n$5({attribute:!1})],ChromedashTimeline.prototype,"showAllHistoricalData",void 0);function capitalize(word){const letters=word.split("");return letters[0]=letters[0].toUpperCase(),letters.join("")}function convertToCamelCaseFeatureName(property){return"CSSProperty"+property.split("-").map(capitalize).join("")}customElements.define("chromedash-timeline",ChromedashTimeline);var __decorate$h=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};class ChromedashTimelinePage extends i$4{constructor(){super(...arguments),this.type="",this.view="",this.props=[],this.selectedBucketId="1"}static get styles(){return[...SHARED_STYLES,i$7``]}connectedCallback(){super.connectedCallback();let endpoint=`/data/blink/${this.type}props`;const options={credentials:"omit"};fetch(endpoint,options).then(res=>res.json()).then(props=>{this.props=props}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}renderSubheader(){const subTitleText=METRICS_TYPE_AND_VIEW_TO_SUBTITLE[this.type+this.view];return x$1` + <div id="subheader"> + <h2 id="breadcrumbs"> + <a href="/metrics/${this.type}/${this.view}"> + <sl-icon name="arrow-left"></sl-icon> </a + >${subTitleText} > timeline + </h2> + </div> + `}renderDataPanel(){return x$1` + <chromedash-timeline + .type=${this.type} + .view=${this.view} + .props=${this.props} + .selectedBucketId=${this.selectedBucketId} + > + </chromedash-timeline> + `}render(){return x$1` ${this.renderSubheader()} ${this.renderDataPanel()} `}}__decorate$h([n$5({type:String})],ChromedashTimelinePage.prototype,"type",void 0),__decorate$h([n$5({type:String})],ChromedashTimelinePage.prototype,"view",void 0),__decorate$h([n$5({attribute:!1})],ChromedashTimelinePage.prototype,"props",void 0),__decorate$h([n$5({attribute:!1})],ChromedashTimelinePage.prototype,"selectedBucketId",void 0),customElements.define("chromedash-timeline-page",ChromedashTimelinePage);var __decorate$g=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const DEFAULT_DURATION=7e3;let ChromedashToast=class ChromedashToast extends i$4{constructor(){super(...arguments),this.msg="",this.open=!1,this.actionLabel="",this.currentTimeout=null,this.waitingForTransition=!1}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: flex; + justify-content: space-between; + position: fixed; + background: var(--toast-background); + color: var(--toast-color); + min-height: 48px; + min-width: 288px; + padding: var(--content-padding); + box-sizing: border-box; + box-shadow: var(--card-box-shadow); + border-radius: var(--border-radius); + margin: var(--content-padding); + cursor: default; + transition: + transform 0.3s, + opacity 0.3s; + opacity: 0; + will-change: opacity, transform; + -webkit-transform: translateY(100px); + transform: translateY(100px); + z-index: 3; + bottom: 0; + } + + :host([open]) { + opacity: 1; + transform: translateY(-32px); + } + + #action { + text-transform: uppercase; + text-decoration: none; + color: var(--toast-action-color); + font-weight: bold; + } + + #msg { + margin-right: var(--content-padding); + } + `]}showMessage(msg,optAction,optTapHandler,optDuration){if(!this.waitingForTransition){if(this.msg=msg,this.actionLabel=optAction,optTapHandler){const action=this.shadowRoot.querySelector("#action");action&&action.addEventListener("click",e=>{e.preventDefault(),optTapHandler()},{once:!0})}this.open?(this.open=!1,this.waitingForTransition=!0,null!==this.currentTimeout&&clearTimeout(this.currentTimeout),this.addEventListener("transitionend",()=>{this.show(optDuration),this.waitingForTransition=!1},{once:!0})):this.show(optDuration)}}show(optDuration){const duration=optDuration||DEFAULT_DURATION;0<duration&&(this.currentTimeout=window.setTimeout(()=>{this.open=!1},duration)),this.open=!0}render(){return x$1` + <span id="msg">${this.msg}</span> + <a href="#" id="action">${this.actionLabel}</a> + `}};__decorate$g([n$5({type:String})],ChromedashToast.prototype,"msg",void 0),__decorate$g([n$5({type:Boolean,reflect:!0})],ChromedashToast.prototype,"open",void 0),__decorate$g([n$5({attribute:!1})],ChromedashToast.prototype,"actionLabel",void 0),__decorate$g([r$6()],ChromedashToast.prototype,"currentTimeout",void 0),__decorate$g([n$5({type:Boolean})],ChromedashToast.prototype,"waitingForTransition",void 0),ChromedashToast=__decorate$g([t$3("chromedash-toast")],ChromedashToast);var tree_item_styles_default=i$7` + :host { + display: block; + outline: 0; + z-index: 0; + } + + :host(:focus) { + outline: none; + } + + slot:not([name])::slotted(sl-icon) { + margin-inline-end: var(--sl-spacing-x-small); + } + + .tree-item { + position: relative; + display: flex; + align-items: stretch; + flex-direction: column; + color: var(--sl-color-neutral-700); + cursor: pointer; + user-select: none; + -webkit-user-select: none; + } + + .tree-item__checkbox { + pointer-events: none; + } + + .tree-item__expand-button, + .tree-item__checkbox, + .tree-item__label { + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + line-height: var(--sl-line-height-dense); + letter-spacing: var(--sl-letter-spacing-normal); + } + + .tree-item__checkbox::part(base) { + display: flex; + align-items: center; + } + + .tree-item__indentation { + display: block; + width: 1em; + flex-shrink: 0; + } + + .tree-item__expand-button { + display: flex; + align-items: center; + justify-content: center; + box-sizing: content-box; + color: var(--sl-color-neutral-500); + padding: var(--sl-spacing-x-small); + width: 1rem; + height: 1rem; + flex-shrink: 0; + cursor: pointer; + } + + .tree-item__expand-button { + transition: var(--sl-transition-medium) rotate ease; + } + + .tree-item--expanded .tree-item__expand-button { + rotate: 90deg; + } + + .tree-item--expanded.tree-item--rtl .tree-item__expand-button { + rotate: -90deg; + } + + .tree-item--expanded slot[name='expand-icon'], + .tree-item:not(.tree-item--expanded) slot[name='collapse-icon'] { + display: none; + } + + .tree-item:not(.tree-item--has-expand-button) .tree-item__expand-icon-slot { + display: none; + } + + .tree-item__expand-button--visible { + cursor: pointer; + } + + .tree-item__item { + display: flex; + align-items: center; + border-inline-start: solid 3px transparent; + } + + .tree-item--disabled .tree-item__item { + opacity: 0.5; + outline: none; + cursor: not-allowed; + } + + :host(:focus-visible) .tree-item__item { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + z-index: 2; + } + + :host(:not([aria-disabled='true'])) .tree-item--selected .tree-item__item { + background-color: var(--sl-color-neutral-100); + border-inline-start-color: var(--sl-color-primary-600); + } + + :host(:not([aria-disabled='true'])) .tree-item__expand-button { + color: var(--sl-color-neutral-600); + } + + .tree-item__label { + display: flex; + align-items: center; + transition: var(--sl-transition-fast) color; + } + + .tree-item__children { + display: block; + font-size: calc(1em + var(--indent-size, var(--sl-spacing-medium))); + } + + /* Indentation lines */ + .tree-item__children { + position: relative; + } + + .tree-item__children::before { + content: ''; + position: absolute; + top: var(--indent-guide-offset); + bottom: var(--indent-guide-offset); + left: calc(1em - (var(--indent-guide-width) / 2) - 1px); + border-inline-end: var(--indent-guide-width) var(--indent-guide-style) var(--indent-guide-color); + z-index: 1; + } + + .tree-item--rtl .tree-item__children::before { + left: auto; + right: 1em; + } + + @media (forced-colors: active) { + :host(:not([aria-disabled='true'])) .tree-item--selected .tree-item__item { + outline: dashed 1px SelectedItem; + } + } +`;function n(n,r,t){return n?r(n):t?.(n)}var _SlTreeItem=class _SlTreeItem extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.indeterminate=!1,this.isLeaf=!1,this.loading=!1,this.selectable=!1,this.expanded=!1,this.selected=!1,this.disabled=!1,this.lazy=!1}static isTreeItem(node){return node instanceof Element&&"treeitem"===node.getAttribute("role")}connectedCallback(){super.connectedCallback(),this.setAttribute("role","treeitem"),this.setAttribute("tabindex","-1"),this.isNestedItem()&&(this.slot="children")}firstUpdated(){this.childrenContainer.hidden=!this.expanded,this.childrenContainer.style.height=this.expanded?"auto":"0",this.isLeaf=!this.lazy&&0===this.getChildrenItems().length,this.handleExpandedChange()}async animateCollapse(){this.emit("sl-collapse"),await stopAnimations(this.childrenContainer);const{keyframes,options}=getAnimation(this,"tree-item.collapse",{dir:this.localize.dir()});await animateTo(this.childrenContainer,shimKeyframesHeightAuto(keyframes,this.childrenContainer.scrollHeight),options),this.childrenContainer.hidden=!0,this.emit("sl-after-collapse")}isNestedItem(){const parent=this.parentElement;return!!parent&&_SlTreeItem.isTreeItem(parent)}handleChildrenSlotChange(){this.loading=!1,this.isLeaf=!this.lazy&&0===this.getChildrenItems().length}willUpdate(changedProperties){changedProperties.has("selected")&&!changedProperties.has("indeterminate")&&(this.indeterminate=!1)}async animateExpand(){this.emit("sl-expand"),await stopAnimations(this.childrenContainer),this.childrenContainer.hidden=!1;const{keyframes,options}=getAnimation(this,"tree-item.expand",{dir:this.localize.dir()});await animateTo(this.childrenContainer,shimKeyframesHeightAuto(keyframes,this.childrenContainer.scrollHeight),options),this.childrenContainer.style.height="auto",this.emit("sl-after-expand")}handleLoadingChange(){this.setAttribute("aria-busy",this.loading?"true":"false"),this.loading||this.animateExpand()}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false")}handleSelectedChange(){this.setAttribute("aria-selected",this.selected?"true":"false")}handleExpandedChange(){this.isLeaf?this.removeAttribute("aria-expanded"):this.setAttribute("aria-expanded",this.expanded?"true":"false")}handleExpandAnimation(){this.expanded?this.lazy?(this.loading=!0,this.emit("sl-lazy-load")):this.animateExpand():this.animateCollapse()}handleLazyChange(){this.emit("sl-lazy-change")}getChildrenItems({includeDisabled=!0}={}){return this.childrenSlot?[...this.childrenSlot.assignedElements({flatten:!0})].filter(item=>_SlTreeItem.isTreeItem(item)&&(includeDisabled||!item.disabled)):[]}render(){const isRtl="rtl"===this.localize.dir(),showExpandButton=!this.loading&&(!this.isLeaf||this.lazy);return x$1` + <div + part="base" + class="${e$2({"tree-item":!0,"tree-item--expanded":this.expanded,"tree-item--selected":this.selected,"tree-item--disabled":this.disabled,"tree-item--leaf":this.isLeaf,"tree-item--has-expand-button":showExpandButton,"tree-item--rtl":"rtl"===this.localize.dir()})}" + > + <div + class="tree-item__item" + part=" + item + ${this.disabled?"item--disabled":""} + ${this.expanded?"item--expanded":""} + ${this.indeterminate?"item--indeterminate":""} + ${this.selected?"item--selected":""} + " + > + <div class="tree-item__indentation" part="indentation"></div> + + <div + part="expand-button" + class=${e$2({"tree-item__expand-button":!0,"tree-item__expand-button--visible":showExpandButton})} + aria-hidden="true" + > + ${n(this.loading,()=>x$1` <sl-spinner part="spinner" exportparts="base:spinner__base"></sl-spinner> `)} + <slot class="tree-item__expand-icon-slot" name="expand-icon"> + <sl-icon library="system" name=${isRtl?"chevron-left":"chevron-right"}></sl-icon> + </slot> + <slot class="tree-item__expand-icon-slot" name="collapse-icon"> + <sl-icon library="system" name=${isRtl?"chevron-left":"chevron-right"}></sl-icon> + </slot> + </div> + + ${n(this.selectable,()=>x$1` + <sl-checkbox + part="checkbox" + exportparts=" + base:checkbox__base, + control:checkbox__control, + control--checked:checkbox__control--checked, + control--indeterminate:checkbox__control--indeterminate, + checked-icon:checkbox__checked-icon, + indeterminate-icon:checkbox__indeterminate-icon, + label:checkbox__label + " + class="tree-item__checkbox" + ?disabled="${this.disabled}" + ?checked="${l(this.selected)}" + ?indeterminate="${this.indeterminate}" + tabindex="-1" + ></sl-checkbox> + `)} + + <slot class="tree-item__label" part="label"></slot> + </div> + + <div class="tree-item__children" part="children" role="group"> + <slot name="children" @slotchange="${this.handleChildrenSlotChange}"></slot> + </div> + </div> + `}};_SlTreeItem.styles=[component_styles_default,tree_item_styles_default],_SlTreeItem.dependencies={"sl-checkbox":SlCheckbox,"sl-icon":SlIcon,"sl-spinner":SlSpinner},__decorateClass([r$6()],_SlTreeItem.prototype,"indeterminate",2),__decorateClass([r$6()],_SlTreeItem.prototype,"isLeaf",2),__decorateClass([r$6()],_SlTreeItem.prototype,"loading",2),__decorateClass([r$6()],_SlTreeItem.prototype,"selectable",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlTreeItem.prototype,"expanded",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlTreeItem.prototype,"selected",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlTreeItem.prototype,"disabled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlTreeItem.prototype,"lazy",2),__decorateClass([e$6("slot:not([name])")],_SlTreeItem.prototype,"defaultSlot",2),__decorateClass([e$6("slot[name=children]")],_SlTreeItem.prototype,"childrenSlot",2),__decorateClass([e$6(".tree-item__item")],_SlTreeItem.prototype,"itemElement",2),__decorateClass([e$6(".tree-item__children")],_SlTreeItem.prototype,"childrenContainer",2),__decorateClass([e$6(".tree-item__expand-button slot")],_SlTreeItem.prototype,"expandButtonSlot",2),__decorateClass([watch("loading",{waitUntilFirstUpdate:!0})],_SlTreeItem.prototype,"handleLoadingChange",1),__decorateClass([watch("disabled")],_SlTreeItem.prototype,"handleDisabledChange",1),__decorateClass([watch("selected")],_SlTreeItem.prototype,"handleSelectedChange",1),__decorateClass([watch("expanded",{waitUntilFirstUpdate:!0})],_SlTreeItem.prototype,"handleExpandedChange",1),__decorateClass([watch("expanded",{waitUntilFirstUpdate:!0})],_SlTreeItem.prototype,"handleExpandAnimation",1),__decorateClass([watch("lazy",{waitUntilFirstUpdate:!0})],_SlTreeItem.prototype,"handleLazyChange",1);var SlTreeItem=_SlTreeItem;setDefaultAnimation("tree-item.expand",{keyframes:[{height:"0",opacity:"0",overflow:"hidden"},{height:"auto",opacity:"1",overflow:"hidden"}],options:{duration:250,easing:"cubic-bezier(0.4, 0.0, 0.2, 1)"}}),setDefaultAnimation("tree-item.collapse",{keyframes:[{height:"auto",opacity:"1",overflow:"hidden"},{height:"0",opacity:"0",overflow:"hidden"}],options:{duration:200,easing:"cubic-bezier(0.4, 0.0, 0.2, 1)"}}),SlTreeItem.define("sl-tree-item");var tree_styles_default=i$7` + :host { + /* + * These are actually used by tree item, but we define them here so they can more easily be set and all tree items + * stay consistent. + */ + --indent-guide-color: var(--sl-color-neutral-200); + --indent-guide-offset: 0; + --indent-guide-style: solid; + --indent-guide-width: 0; + --indent-size: var(--sl-spacing-large); + + display: block; + + /* + * Tree item indentation uses the "em" unit to increment its width on each level, so setting the font size to zero + * here removes the indentation for all the nodes on the first level. + */ + font-size: 0; + } +`;function clamp(value,min,max){const noNegativeZero=n=>Object.is(n,-0)?0:n;return value<min?noNegativeZero(min):value>max?noNegativeZero(max):noNegativeZero(value)}function syncCheckboxes(changedTreeItem,initialSync=!1){function syncParentItem(treeItem){const children=treeItem.getChildrenItems({includeDisabled:!1});if(children.length){const allChecked=children.every(item=>item.selected),allUnchecked=children.every(item=>!item.selected&&!item.indeterminate);treeItem.selected=allChecked,treeItem.indeterminate=!allChecked&&!allUnchecked}}function syncAncestors(treeItem){const parentItem=treeItem.parentElement;SlTreeItem.isTreeItem(parentItem)&&(syncParentItem(parentItem),syncAncestors(parentItem))}function syncDescendants(treeItem){for(const childItem of treeItem.getChildrenItems())childItem.selected=initialSync?treeItem.selected||childItem.selected:!childItem.disabled&&treeItem.selected,syncDescendants(childItem);initialSync&&syncParentItem(treeItem)}syncDescendants(changedTreeItem),syncAncestors(changedTreeItem)}var SlTree=class extends ShoelaceElement{constructor(){super(),this.selection="single",this.clickTarget=null,this.localize=new LocalizeController(this),this.initTreeItem=item=>{item.selectable="multiple"===this.selection,["expand","collapse"].filter(status=>!!this.querySelector(`[slot="${status}-icon"]`)).forEach(status=>{const existingIcon=item.querySelector(`[slot="${status}-icon"]`),expandButtonIcon=this.getExpandButtonIcon(status);if(expandButtonIcon)if(null===existingIcon)item.append(expandButtonIcon);else if(existingIcon.hasAttribute("data-default"))existingIcon.replaceWith(expandButtonIcon);else;})},this.handleTreeChanged=mutations=>{for(const mutation of mutations){const addedNodes=[...mutation.addedNodes].filter(SlTreeItem.isTreeItem),removedNodes=[...mutation.removedNodes].filter(SlTreeItem.isTreeItem);addedNodes.forEach(this.initTreeItem),this.lastFocusedItem&&removedNodes.includes(this.lastFocusedItem)&&(this.lastFocusedItem=null)}},this.handleFocusOut=event=>{const relatedTarget=event.relatedTarget;relatedTarget&&this.contains(relatedTarget)||(this.tabIndex=0)},this.handleFocusIn=event=>{const target=event.target;event.target===this&&this.focusItem(this.lastFocusedItem||this.getAllTreeItems()[0]),SlTreeItem.isTreeItem(target)&&!target.disabled&&(this.lastFocusedItem&&(this.lastFocusedItem.tabIndex=-1),this.lastFocusedItem=target,this.tabIndex=-1,target.tabIndex=0)},this.addEventListener("focusin",this.handleFocusIn),this.addEventListener("focusout",this.handleFocusOut),this.addEventListener("sl-lazy-change",this.handleSlotChange)}async connectedCallback(){super.connectedCallback(),this.setAttribute("role","tree"),this.setAttribute("tabindex","0"),await this.updateComplete,this.mutationObserver=new MutationObserver(this.handleTreeChanged),this.mutationObserver.observe(this,{childList:!0,subtree:!0})}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.mutationObserver)?void 0:_a.disconnect()}getExpandButtonIcon(status){const slot="expand"===status?this.expandedIconSlot:this.collapsedIconSlot,icon=slot.assignedElements({flatten:!0})[0];if(icon){const clone=icon.cloneNode(!0);return[clone,...clone.querySelectorAll("[id]")].forEach(el=>el.removeAttribute("id")),clone.setAttribute("data-default",""),clone.slot=`${status}-icon`,clone}return null}selectItem(selectedItem){const previousSelection=[...this.selectedItems];if("multiple"===this.selection)selectedItem.selected=!selectedItem.selected,selectedItem.lazy&&(selectedItem.expanded=!0),syncCheckboxes(selectedItem);else if("single"===this.selection||selectedItem.isLeaf){const items=this.getAllTreeItems();for(const item of items)item.selected=item===selectedItem}else"leaf"===this.selection&&(selectedItem.expanded=!selectedItem.expanded);const nextSelection=this.selectedItems;(previousSelection.length!==nextSelection.length||nextSelection.some(item=>!previousSelection.includes(item)))&&Promise.all(nextSelection.map(el=>el.updateComplete)).then(()=>{this.emit("sl-selection-change",{detail:{selection:nextSelection}})})}getAllTreeItems(){return[...this.querySelectorAll("sl-tree-item")]}focusItem(item){null==item?void 0:item.focus()}handleKeyDown(event){if(!["ArrowDown","ArrowUp","ArrowRight","ArrowLeft","Home","End","Enter"," "].includes(event.key))return;if(event.composedPath().some(el=>{var _a;return["input","textarea"].includes(null==(_a=null==el?void 0:el.tagName)?void 0:_a.toLowerCase())}))return;const items=this.getFocusableItems(),isLtr="ltr"===this.localize.dir(),isRtl="rtl"===this.localize.dir();if(0<items.length){event.preventDefault();const activeItemIndex=items.findIndex(item=>item.matches(":focus")),activeItem=items[activeItemIndex],focusItemAt=index=>{const item=items[clamp(index,0,items.length-1)];this.focusItem(item)},toggleExpand=expanded=>{activeItem.expanded=expanded};"ArrowDown"===event.key?focusItemAt(activeItemIndex+1):"ArrowUp"===event.key?focusItemAt(activeItemIndex-1):isLtr&&"ArrowRight"===event.key||isRtl&&"ArrowLeft"===event.key?!activeItem||activeItem.disabled||activeItem.expanded||activeItem.isLeaf&&!activeItem.lazy?focusItemAt(activeItemIndex+1):toggleExpand(!0):isLtr&&"ArrowLeft"===event.key||isRtl&&"ArrowRight"===event.key?!activeItem||activeItem.disabled||activeItem.isLeaf||!activeItem.expanded?focusItemAt(activeItemIndex-1):toggleExpand(!1):"Home"===event.key?focusItemAt(0):"End"===event.key?focusItemAt(items.length-1):("Enter"===event.key||" "===event.key)&&!activeItem.disabled&&this.selectItem(activeItem)}}handleClick(event){const target=event.target,treeItem=target.closest("sl-tree-item"),isExpandButton=event.composedPath().some(el=>{var _a;return null==(_a=null==el?void 0:el.classList)?void 0:_a.contains("tree-item__expand-button")});!treeItem||treeItem.disabled||target!==this.clickTarget||(isExpandButton?treeItem.expanded=!treeItem.expanded:this.selectItem(treeItem))}handleMouseDown(event){this.clickTarget=event.target}handleSlotChange(){const items=this.getAllTreeItems();items.forEach(this.initTreeItem)}async handleSelectionChange(){const isSelectionMultiple="multiple"===this.selection,items=this.getAllTreeItems();this.setAttribute("aria-multiselectable",isSelectionMultiple?"true":"false");for(const item of items)item.selectable=isSelectionMultiple;isSelectionMultiple&&(await this.updateComplete,[...this.querySelectorAll(":scope > sl-tree-item")].forEach(treeItem=>syncCheckboxes(treeItem,!0)))}get selectedItems(){const items=this.getAllTreeItems(),isSelected=item=>item.selected;return items.filter(isSelected)}getFocusableItems(){const items=this.getAllTreeItems(),collapsedItems=new Set;return items.filter(item=>{var _a;if(item.disabled)return!1;const parent=null==(_a=item.parentElement)?void 0:_a.closest("[role=treeitem]");return parent&&(!parent.expanded||parent.loading||collapsedItems.has(parent))&&collapsedItems.add(item),!collapsedItems.has(item)})}render(){return x$1` + <div + part="base" + class="tree" + @click=${this.handleClick} + @keydown=${this.handleKeyDown} + @mousedown=${this.handleMouseDown} + > + <slot @slotchange=${this.handleSlotChange}></slot> + <span hidden aria-hidden="true"><slot name="expand-icon"></slot></span> + <span hidden aria-hidden="true"><slot name="collapse-icon"></slot></span> + </div> + `}};SlTree.styles=[component_styles_default,tree_styles_default],__decorateClass([e$6("slot:not([name])")],SlTree.prototype,"defaultSlot",2),__decorateClass([e$6("slot[name=expand-icon]")],SlTree.prototype,"expandedIconSlot",2),__decorateClass([e$6("slot[name=collapse-icon]")],SlTree.prototype,"collapsedIconSlot",2),__decorateClass([n$5()],SlTree.prototype,"selection",2),__decorateClass([watch("selection")],SlTree.prototype,"handleSelectionChange",1),SlTree.define("sl-tree");var visually_hidden_styles_default=i$7` + :host(:not(:focus-within)) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + clip: rect(0 0 0 0) !important; + clip-path: inset(50%) !important; + border: none !important; + overflow: hidden !important; + white-space: nowrap !important; + padding: 0 !important; + } +`,SlVisuallyHidden=class extends ShoelaceElement{render(){return x$1` <slot></slot> `}};SlVisuallyHidden.styles=[component_styles_default,visually_hidden_styles_default],SlVisuallyHidden.define("sl-visually-hidden");var tab_panel_styles_default=i$7` + :host { + --padding: 0; + + display: none; + } + + :host([active]) { + display: block; + } + + .tab-panel { + display: block; + padding: var(--padding); + } +`,id$1=0,SlTabPanel=class extends ShoelaceElement{constructor(){super(...arguments),this.attrId=++id$1,this.componentId=`sl-tab-panel-${this.attrId}`,this.name="",this.active=!1}connectedCallback(){super.connectedCallback(),this.id=0<this.id.length?this.id:this.componentId,this.setAttribute("role","tabpanel")}handleActiveChange(){this.setAttribute("aria-hidden",this.active?"false":"true")}render(){return x$1` + <slot + part="base" + class=${e$2({"tab-panel":!0,"tab-panel--active":this.active})} + ></slot> + `}};SlTabPanel.styles=[component_styles_default,tab_panel_styles_default],__decorateClass([n$5({reflect:!0})],SlTabPanel.prototype,"name",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTabPanel.prototype,"active",2),__decorateClass([watch("active")],SlTabPanel.prototype,"handleActiveChange",1),SlTabPanel.define("sl-tab-panel");var tab_styles_default=i$7` + :host { + display: inline-block; + } + + .tab { + display: inline-flex; + align-items: center; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-small); + font-weight: var(--sl-font-weight-semibold); + border-radius: var(--sl-border-radius-medium); + color: var(--sl-color-neutral-600); + padding: var(--sl-spacing-medium) var(--sl-spacing-large); + white-space: nowrap; + user-select: none; + -webkit-user-select: none; + cursor: pointer; + transition: + var(--transition-speed) box-shadow, + var(--transition-speed) color; + } + + .tab:hover:not(.tab--disabled) { + color: var(--sl-color-primary-600); + } + + :host(:focus) { + outline: transparent; + } + + :host(:focus-visible) { + color: var(--sl-color-primary-600); + outline: var(--sl-focus-ring); + outline-offset: calc(-1 * var(--sl-focus-ring-width) - var(--sl-focus-ring-offset)); + } + + .tab.tab--active:not(.tab--disabled) { + color: var(--sl-color-primary-600); + } + + .tab.tab--closable { + padding-inline-end: var(--sl-spacing-small); + } + + .tab.tab--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .tab__close-button { + font-size: var(--sl-font-size-small); + margin-inline-start: var(--sl-spacing-small); + } + + .tab__close-button::part(base) { + padding: var(--sl-spacing-3x-small); + } + + @media (forced-colors: active) { + .tab.tab--active:not(.tab--disabled) { + outline: solid 1px transparent; + outline-offset: -3px; + } + } +`,id=0,SlTab=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.attrId=++id,this.componentId=`sl-tab-${this.attrId}`,this.panel="",this.active=!1,this.closable=!1,this.disabled=!1,this.tabIndex=0}connectedCallback(){super.connectedCallback(),this.setAttribute("role","tab")}handleCloseClick(event){event.stopPropagation(),this.emit("sl-close")}handleActiveChange(){this.setAttribute("aria-selected",this.active?"true":"false")}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false"),this.tabIndex=this.disabled&&!this.active?-1:0}render(){return this.id=0<this.id.length?this.id:this.componentId,x$1` + <div + part="base" + class=${e$2({tab:!0,"tab--active":this.active,"tab--closable":this.closable,"tab--disabled":this.disabled})} + > + <slot></slot> + ${this.closable?x$1` + <sl-icon-button + part="close-button" + exportparts="base:close-button__base" + name="x-lg" + library="system" + label=${this.localize.term("close")} + class="tab__close-button" + @click=${this.handleCloseClick} + tabindex="-1" + ></sl-icon-button> + `:""} + </div> + `}};SlTab.styles=[component_styles_default,tab_styles_default],SlTab.dependencies={"sl-icon-button":SlIconButton},__decorateClass([e$6(".tab")],SlTab.prototype,"tab",2),__decorateClass([n$5({reflect:!0})],SlTab.prototype,"panel",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTab.prototype,"active",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTab.prototype,"closable",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlTab.prototype,"disabled",2),__decorateClass([n$5({type:Number,reflect:!0})],SlTab.prototype,"tabIndex",2),__decorateClass([watch("active")],SlTab.prototype,"handleActiveChange",1),__decorateClass([watch("disabled")],SlTab.prototype,"handleDisabledChange",1),SlTab.define("sl-tab");var tab_group_styles_default=i$7` + :host { + --indicator-color: var(--sl-color-primary-600); + --track-color: var(--sl-color-neutral-200); + --track-width: 2px; + + display: block; + } + + .tab-group { + display: flex; + border-radius: 0; + } + + .tab-group__tabs { + display: flex; + position: relative; + } + + .tab-group__indicator { + position: absolute; + transition: + var(--sl-transition-fast) translate ease, + var(--sl-transition-fast) width ease; + } + + .tab-group--has-scroll-controls .tab-group__nav-container { + position: relative; + padding: 0 var(--sl-spacing-x-large); + } + + .tab-group--has-scroll-controls .tab-group__scroll-button--start--hidden, + .tab-group--has-scroll-controls .tab-group__scroll-button--end--hidden { + visibility: hidden; + } + + .tab-group__body { + display: block; + overflow: auto; + } + + .tab-group__scroll-button { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + bottom: 0; + width: var(--sl-spacing-x-large); + } + + .tab-group__scroll-button--start { + left: 0; + } + + .tab-group__scroll-button--end { + right: 0; + } + + .tab-group--rtl .tab-group__scroll-button--start { + left: auto; + right: 0; + } + + .tab-group--rtl .tab-group__scroll-button--end { + left: 0; + right: auto; + } + + /* + * Top + */ + + .tab-group--top { + flex-direction: column; + } + + .tab-group--top .tab-group__nav-container { + order: 1; + } + + .tab-group--top .tab-group__nav { + display: flex; + overflow-x: auto; + + /* Hide scrollbar in Firefox */ + scrollbar-width: none; + } + + /* Hide scrollbar in Chrome/Safari */ + .tab-group--top .tab-group__nav::-webkit-scrollbar { + width: 0; + height: 0; + } + + .tab-group--top .tab-group__tabs { + flex: 1 1 auto; + position: relative; + flex-direction: row; + border-bottom: solid var(--track-width) var(--track-color); + } + + .tab-group--top .tab-group__indicator { + bottom: calc(-1 * var(--track-width)); + border-bottom: solid var(--track-width) var(--indicator-color); + } + + .tab-group--top .tab-group__body { + order: 2; + } + + .tab-group--top ::slotted(sl-tab-panel) { + --padding: var(--sl-spacing-medium) 0; + } + + /* + * Bottom + */ + + .tab-group--bottom { + flex-direction: column; + } + + .tab-group--bottom .tab-group__nav-container { + order: 2; + } + + .tab-group--bottom .tab-group__nav { + display: flex; + overflow-x: auto; + + /* Hide scrollbar in Firefox */ + scrollbar-width: none; + } + + /* Hide scrollbar in Chrome/Safari */ + .tab-group--bottom .tab-group__nav::-webkit-scrollbar { + width: 0; + height: 0; + } + + .tab-group--bottom .tab-group__tabs { + flex: 1 1 auto; + position: relative; + flex-direction: row; + border-top: solid var(--track-width) var(--track-color); + } + + .tab-group--bottom .tab-group__indicator { + top: calc(-1 * var(--track-width)); + border-top: solid var(--track-width) var(--indicator-color); + } + + .tab-group--bottom .tab-group__body { + order: 1; + } + + .tab-group--bottom ::slotted(sl-tab-panel) { + --padding: var(--sl-spacing-medium) 0; + } + + /* + * Start + */ + + .tab-group--start { + flex-direction: row; + } + + .tab-group--start .tab-group__nav-container { + order: 1; + } + + .tab-group--start .tab-group__tabs { + flex: 0 0 auto; + flex-direction: column; + border-inline-end: solid var(--track-width) var(--track-color); + } + + .tab-group--start .tab-group__indicator { + right: calc(-1 * var(--track-width)); + border-right: solid var(--track-width) var(--indicator-color); + } + + .tab-group--start.tab-group--rtl .tab-group__indicator { + right: auto; + left: calc(-1 * var(--track-width)); + } + + .tab-group--start .tab-group__body { + flex: 1 1 auto; + order: 2; + } + + .tab-group--start ::slotted(sl-tab-panel) { + --padding: 0 var(--sl-spacing-medium); + } + + /* + * End + */ + + .tab-group--end { + flex-direction: row; + } + + .tab-group--end .tab-group__nav-container { + order: 2; + } + + .tab-group--end .tab-group__tabs { + flex: 0 0 auto; + flex-direction: column; + border-left: solid var(--track-width) var(--track-color); + } + + .tab-group--end .tab-group__indicator { + left: calc(-1 * var(--track-width)); + border-inline-start: solid var(--track-width) var(--indicator-color); + } + + .tab-group--end.tab-group--rtl .tab-group__indicator { + right: calc(-1 * var(--track-width)); + left: auto; + } + + .tab-group--end .tab-group__body { + flex: 1 1 auto; + order: 1; + } + + .tab-group--end ::slotted(sl-tab-panel) { + --padding: 0 var(--sl-spacing-medium); + } +`,resize_observer_styles_default=i$7` + :host { + display: contents; + } +`,SlResizeObserver=class extends ShoelaceElement{constructor(){super(...arguments),this.observedElements=[],this.disabled=!1}connectedCallback(){super.connectedCallback(),this.resizeObserver=new ResizeObserver(entries=>{this.emit("sl-resize",{detail:{entries}})}),this.disabled||this.startObserver()}disconnectedCallback(){super.disconnectedCallback(),this.stopObserver()}handleSlotChange(){this.disabled||this.startObserver()}startObserver(){const slot=this.shadowRoot.querySelector("slot");if(null!==slot){const elements=slot.assignedElements({flatten:!0});this.observedElements.forEach(el=>this.resizeObserver.unobserve(el)),this.observedElements=[],elements.forEach(el=>{this.resizeObserver.observe(el),this.observedElements.push(el)})}}stopObserver(){this.resizeObserver.disconnect()}handleDisabledChange(){this.disabled?this.stopObserver():this.startObserver()}render(){return x$1` <slot @slotchange=${this.handleSlotChange}></slot> `}};SlResizeObserver.styles=[component_styles_default,resize_observer_styles_default],__decorateClass([n$5({type:Boolean,reflect:!0})],SlResizeObserver.prototype,"disabled",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlResizeObserver.prototype,"handleDisabledChange",1);var SlTabGroup=class extends ShoelaceElement{constructor(){super(...arguments),this.tabs=[],this.focusableTabs=[],this.panels=[],this.localize=new LocalizeController(this),this.hasScrollControls=!1,this.shouldHideScrollStartButton=!1,this.shouldHideScrollEndButton=!1,this.placement="top",this.activation="auto",this.noScrollControls=!1,this.fixedScrollControls=!1,this.scrollOffset=1}connectedCallback(){const whenAllDefined=Promise.all([customElements.whenDefined("sl-tab"),customElements.whenDefined("sl-tab-panel")]);super.connectedCallback(),this.resizeObserver=new ResizeObserver(()=>{this.repositionIndicator(),this.updateScrollControls()}),this.mutationObserver=new MutationObserver(mutations=>{const instanceMutations=mutations.filter(({target})=>{if(target===this)return!0;if(target.closest("sl-tab-group")!==this)return!1;const tagName=target.tagName.toLowerCase();return"sl-tab"===tagName||"sl-tab-panel"===tagName});if(0!==instanceMutations.length)if(instanceMutations.some(m=>!["aria-labelledby","aria-controls"].includes(m.attributeName))&&setTimeout(()=>this.setAriaLabels()),instanceMutations.some(m=>"disabled"===m.attributeName))this.syncTabsAndPanels();else if(instanceMutations.some(m=>"active"===m.attributeName)){const tabs=instanceMutations.filter(m=>"active"===m.attributeName&&"sl-tab"===m.target.tagName.toLowerCase()).map(m=>m.target),newActiveTab=tabs.find(tab=>tab.active);newActiveTab&&this.setActiveTab(newActiveTab)}}),this.updateComplete.then(()=>{this.syncTabsAndPanels(),this.mutationObserver.observe(this,{attributes:!0,attributeFilter:["active","disabled","name","panel"],childList:!0,subtree:!0}),this.resizeObserver.observe(this.nav),whenAllDefined.then(()=>{const intersectionObserver=new IntersectionObserver((entries,observer)=>{var _a;0<entries[0].intersectionRatio&&(this.setAriaLabels(),this.setActiveTab(null==(_a=this.getActiveTab())?this.tabs[0]:_a,{emitEvents:!1}),observer.unobserve(entries[0].target))});intersectionObserver.observe(this.tabGroup)})})}disconnectedCallback(){var _a,_b;super.disconnectedCallback(),null==(_a=this.mutationObserver)?void 0:_a.disconnect(),this.nav&&(null==(_b=this.resizeObserver)?void 0:_b.unobserve(this.nav))}getAllTabs(){const slot=this.shadowRoot.querySelector("slot[name=\"nav\"]");return slot.assignedElements()}getAllPanels(){return[...this.body.assignedElements()].filter(el=>"sl-tab-panel"===el.tagName.toLowerCase())}getActiveTab(){return this.tabs.find(el=>el.active)}handleClick(event){const target=event.target,tab=target.closest("sl-tab"),tabGroup=null==tab?void 0:tab.closest("sl-tab-group");tabGroup!==this||null!==tab&&this.setActiveTab(tab,{scrollBehavior:"smooth"})}handleKeyDown(event){const target=event.target,tab=target.closest("sl-tab"),tabGroup=null==tab?void 0:tab.closest("sl-tab-group");if(tabGroup===this&&(["Enter"," "].includes(event.key)&&null!==tab&&(this.setActiveTab(tab,{scrollBehavior:"smooth"}),event.preventDefault()),["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End"].includes(event.key))){const activeEl=this.tabs.find(t=>t.matches(":focus")),isRtl="rtl"===this.localize.dir();let nextTab=null;if("sl-tab"===(null==activeEl?void 0:activeEl.tagName.toLowerCase())){if("Home"===event.key)nextTab=this.focusableTabs[0];else if("End"===event.key)nextTab=this.focusableTabs[this.focusableTabs.length-1];else if(["top","bottom"].includes(this.placement)&&event.key===(isRtl?"ArrowRight":"ArrowLeft")||["start","end"].includes(this.placement)&&"ArrowUp"===event.key){const currentIndex=this.tabs.findIndex(el=>el===activeEl);nextTab=this.findNextFocusableTab(currentIndex,"backward")}else if(["top","bottom"].includes(this.placement)&&event.key===(isRtl?"ArrowLeft":"ArrowRight")||["start","end"].includes(this.placement)&&"ArrowDown"===event.key){const currentIndex=this.tabs.findIndex(el=>el===activeEl);nextTab=this.findNextFocusableTab(currentIndex,"forward")}if(!nextTab)return;nextTab.tabIndex=0,nextTab.focus({preventScroll:!0}),"auto"===this.activation?this.setActiveTab(nextTab,{scrollBehavior:"smooth"}):this.tabs.forEach(tabEl=>{tabEl.tabIndex=tabEl===nextTab?0:-1}),["top","bottom"].includes(this.placement)&&scrollIntoView(nextTab,this.nav,"horizontal"),event.preventDefault()}}}handleScrollToStart(){this.nav.scroll({left:"rtl"===this.localize.dir()?this.nav.scrollLeft+this.nav.clientWidth:this.nav.scrollLeft-this.nav.clientWidth,behavior:"smooth"})}handleScrollToEnd(){this.nav.scroll({left:"rtl"===this.localize.dir()?this.nav.scrollLeft-this.nav.clientWidth:this.nav.scrollLeft+this.nav.clientWidth,behavior:"smooth"})}setActiveTab(tab,options){if(options=__spreadValues({emitEvents:!0,scrollBehavior:"auto"},options),tab!==this.activeTab&&!tab.disabled){const previousTab=this.activeTab;this.activeTab=tab,this.tabs.forEach(el=>{el.active=el===this.activeTab,el.tabIndex=el===this.activeTab?0:-1}),this.panels.forEach(el=>{var _a;return el.active=el.name===(null==(_a=this.activeTab)?void 0:_a.panel)}),this.syncIndicator(),["top","bottom"].includes(this.placement)&&scrollIntoView(this.activeTab,this.nav,"horizontal",options.scrollBehavior),options.emitEvents&&(previousTab&&this.emit("sl-tab-hide",{detail:{name:previousTab.panel}}),this.emit("sl-tab-show",{detail:{name:this.activeTab.panel}}))}}setAriaLabels(){this.tabs.forEach(tab=>{const panel=this.panels.find(el=>el.name===tab.panel);panel&&(tab.setAttribute("aria-controls",panel.getAttribute("id")),panel.setAttribute("aria-labelledby",tab.getAttribute("id")))})}repositionIndicator(){const currentTab=this.getActiveTab();if(!currentTab)return;const width=currentTab.clientWidth,height=currentTab.clientHeight,isRtl="rtl"===this.localize.dir(),allTabs=this.getAllTabs(),precedingTabs=allTabs.slice(0,allTabs.indexOf(currentTab)),offset=precedingTabs.reduce((previous,current)=>({left:previous.left+current.clientWidth,top:previous.top+current.clientHeight}),{left:0,top:0});switch(this.placement){case"top":case"bottom":this.indicator.style.width=`${width}px`,this.indicator.style.height="auto",this.indicator.style.translate=isRtl?`${-1*offset.left}px`:`${offset.left}px`;break;case"start":case"end":this.indicator.style.width="auto",this.indicator.style.height=`${height}px`,this.indicator.style.translate=`0 ${offset.top}px`}}syncTabsAndPanels(){this.tabs=this.getAllTabs(),this.focusableTabs=this.tabs.filter(el=>!el.disabled),this.panels=this.getAllPanels(),this.syncIndicator(),this.updateComplete.then(()=>this.updateScrollControls())}findNextFocusableTab(currentIndex,direction){let nextTab=null;const iterator="forward"===direction?1:-1;for(let nextIndex=currentIndex+iterator;currentIndex<this.tabs.length;){if(nextTab=this.tabs[nextIndex]||null,null===nextTab){nextTab="forward"===direction?this.focusableTabs[0]:this.focusableTabs[this.focusableTabs.length-1];break}if(!nextTab.disabled)break;nextIndex+=iterator}return nextTab}updateScrollButtons(){this.hasScrollControls&&!this.fixedScrollControls&&(this.shouldHideScrollStartButton=this.scrollFromStart()<=this.scrollOffset,this.shouldHideScrollEndButton=this.isScrolledToEnd())}isScrolledToEnd(){return this.scrollFromStart()+this.nav.clientWidth>=this.nav.scrollWidth-this.scrollOffset}scrollFromStart(){return"rtl"===this.localize.dir()?-this.nav.scrollLeft:this.nav.scrollLeft}updateScrollControls(){this.hasScrollControls=!this.noScrollControls&&["top","bottom"].includes(this.placement)&&this.nav.scrollWidth>this.nav.clientWidth+1,this.updateScrollButtons()}syncIndicator(){const tab=this.getActiveTab();tab?(this.indicator.style.display="block",this.repositionIndicator()):this.indicator.style.display="none"}show(panel){const tab=this.tabs.find(el=>el.panel===panel);tab&&this.setActiveTab(tab,{scrollBehavior:"smooth"})}render(){const isRtl="rtl"===this.localize.dir();return x$1` + <div + part="base" + class=${e$2({"tab-group":!0,"tab-group--top":"top"===this.placement,"tab-group--bottom":"bottom"===this.placement,"tab-group--start":"start"===this.placement,"tab-group--end":"end"===this.placement,"tab-group--rtl":"rtl"===this.localize.dir(),"tab-group--has-scroll-controls":this.hasScrollControls})} + @click=${this.handleClick} + @keydown=${this.handleKeyDown} + > + <div class="tab-group__nav-container" part="nav"> + ${this.hasScrollControls?x$1` + <sl-icon-button + part="scroll-button scroll-button--start" + exportparts="base:scroll-button__base" + class=${e$2({"tab-group__scroll-button":!0,"tab-group__scroll-button--start":!0,"tab-group__scroll-button--start--hidden":this.shouldHideScrollStartButton})} + name=${isRtl?"chevron-right":"chevron-left"} + library="system" + tabindex="-1" + aria-hidden="true" + label=${this.localize.term("scrollToStart")} + @click=${this.handleScrollToStart} + ></sl-icon-button> + `:""} + + <div class="tab-group__nav" @scrollend=${this.updateScrollButtons}> + <div part="tabs" class="tab-group__tabs" role="tablist"> + <div part="active-tab-indicator" class="tab-group__indicator"></div> + <sl-resize-observer @sl-resize=${this.syncIndicator}> + <slot name="nav" @slotchange=${this.syncTabsAndPanels}></slot> + </sl-resize-observer> + </div> + </div> + + ${this.hasScrollControls?x$1` + <sl-icon-button + part="scroll-button scroll-button--end" + exportparts="base:scroll-button__base" + class=${e$2({"tab-group__scroll-button":!0,"tab-group__scroll-button--end":!0,"tab-group__scroll-button--end--hidden":this.shouldHideScrollEndButton})} + name=${isRtl?"chevron-left":"chevron-right"} + library="system" + tabindex="-1" + aria-hidden="true" + label=${this.localize.term("scrollToEnd")} + @click=${this.handleScrollToEnd} + ></sl-icon-button> + `:""} + </div> + + <slot part="body" class="tab-group__body" @slotchange=${this.syncTabsAndPanels}></slot> + </div> + `}};SlTabGroup.styles=[component_styles_default,tab_group_styles_default],SlTabGroup.dependencies={"sl-icon-button":SlIconButton,"sl-resize-observer":SlResizeObserver},__decorateClass([e$6(".tab-group")],SlTabGroup.prototype,"tabGroup",2),__decorateClass([e$6(".tab-group__body")],SlTabGroup.prototype,"body",2),__decorateClass([e$6(".tab-group__nav")],SlTabGroup.prototype,"nav",2),__decorateClass([e$6(".tab-group__indicator")],SlTabGroup.prototype,"indicator",2),__decorateClass([r$6()],SlTabGroup.prototype,"hasScrollControls",2),__decorateClass([r$6()],SlTabGroup.prototype,"shouldHideScrollStartButton",2),__decorateClass([r$6()],SlTabGroup.prototype,"shouldHideScrollEndButton",2),__decorateClass([n$5()],SlTabGroup.prototype,"placement",2),__decorateClass([n$5()],SlTabGroup.prototype,"activation",2),__decorateClass([n$5({attribute:"no-scroll-controls",type:Boolean})],SlTabGroup.prototype,"noScrollControls",2),__decorateClass([n$5({attribute:"fixed-scroll-controls",type:Boolean})],SlTabGroup.prototype,"fixedScrollControls",2),__decorateClass([t$2({passive:!0})],SlTabGroup.prototype,"updateScrollButtons",1),__decorateClass([watch("noScrollControls",{waitUntilFirstUpdate:!0})],SlTabGroup.prototype,"updateScrollControls",1),__decorateClass([watch("placement",{waitUntilFirstUpdate:!0})],SlTabGroup.prototype,"syncIndicator",1),SlTabGroup.define("sl-tab-group");var split_panel_styles_default=i$7` + :host { + --divider-width: 4px; + --divider-hit-area: 12px; + --min: 0%; + --max: 100%; + + display: grid; + } + + .start, + .end { + overflow: hidden; + } + + .divider { + flex: 0 0 var(--divider-width); + display: flex; + position: relative; + align-items: center; + justify-content: center; + background-color: var(--sl-color-neutral-200); + color: var(--sl-color-neutral-900); + z-index: 1; + } + + .divider:focus { + outline: none; + } + + :host(:not([disabled])) .divider:focus-visible { + background-color: var(--sl-color-primary-600); + color: var(--sl-color-neutral-0); + } + + :host([disabled]) .divider { + cursor: not-allowed; + } + + /* Horizontal */ + :host(:not([vertical], [disabled])) .divider { + cursor: col-resize; + } + + :host(:not([vertical])) .divider::after { + display: flex; + content: ''; + position: absolute; + height: 100%; + left: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2); + width: var(--divider-hit-area); + } + + /* Vertical */ + :host([vertical]) { + flex-direction: column; + } + + :host([vertical]:not([disabled])) .divider { + cursor: row-resize; + } + + :host([vertical]) .divider::after { + content: ''; + position: absolute; + width: 100%; + top: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2); + height: var(--divider-hit-area); + } + + @media (forced-colors: active) { + .divider { + outline: solid 1px transparent; + } + } +`;function drag(container,options){function move(pointerEvent){const dims=container.getBoundingClientRect(),defaultView=container.ownerDocument.defaultView,offsetX=dims.left+defaultView.scrollX,offsetY=dims.top+defaultView.scrollY,x=pointerEvent.pageX-offsetX,y=pointerEvent.pageY-offsetY;(null==options?void 0:options.onMove)&&options.onMove(x,y)}function stop(){document.removeEventListener("pointermove",move),document.removeEventListener("pointerup",stop),(null==options?void 0:options.onStop)&&options.onStop()}document.addEventListener("pointermove",move,{passive:!0}),document.addEventListener("pointerup",stop),(null==options?void 0:options.initialEvent)instanceof PointerEvent&&move(options.initialEvent)}var SNAP_NONE=()=>null,SlSplitPanel=class extends ShoelaceElement{constructor(){super(...arguments),this.isCollapsed=!1,this.localize=new LocalizeController(this),this.positionBeforeCollapsing=0,this.position=50,this.vertical=!1,this.disabled=!1,this.snapValue="",this.snapFunction=SNAP_NONE,this.snapThreshold=12}toSnapFunction(snap){var _Mathabs3=Math.abs,_Mathround3=Math.round;const snapPoints=snap.split(" ");return({pos,size,snapThreshold,isRtl,vertical})=>{var _NumberPOSITIVE_INFINITY=Number.POSITIVE_INFINITY;let newPos=pos,minDistance=_NumberPOSITIVE_INFINITY;return snapPoints.forEach(value=>{var _NumberparseFloat=Number.parseFloat;let snapPoint;if(value.startsWith("repeat(")){const repeatVal=snap.substring(7,snap.length-1),isPercent=repeatVal.endsWith("%"),repeatNum=_NumberparseFloat(repeatVal),snapIntervalPx=isPercent?size*(repeatNum/100):repeatNum;snapPoint=_Mathround3((isRtl&&!vertical?size-pos:pos)/snapIntervalPx)*snapIntervalPx}else snapPoint=value.endsWith("%")?size*(_NumberparseFloat(value)/100):_NumberparseFloat(value);isRtl&&!vertical&&(snapPoint=size-snapPoint);const distance=_Mathabs3(pos-snapPoint);distance<=snapThreshold&&distance<minDistance&&(newPos=snapPoint,minDistance=distance)}),newPos}}set snap(snap){this.snapValue=null==snap?"":snap,this.snapFunction=snap?"string"==typeof snap?this.toSnapFunction(snap):snap:SNAP_NONE}get snap(){return this.snapValue}connectedCallback(){super.connectedCallback(),this.resizeObserver=new ResizeObserver(entries=>this.handleResize(entries)),this.updateComplete.then(()=>this.resizeObserver.observe(this)),this.detectSize(),this.cachedPositionInPixels=this.percentageToPixels(this.position)}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.resizeObserver)?void 0:_a.unobserve(this)}detectSize(){const{width,height}=this.getBoundingClientRect();this.size=this.vertical?height:width}percentageToPixels(value){return this.size*(value/100)}pixelsToPercentage(value){return 100*(value/this.size)}handleDrag(event){const isRtl="rtl"===this.localize.dir();this.disabled||(event.cancelable&&event.preventDefault(),drag(this,{onMove:(x,y)=>{var _a;let newPositionInPixels=this.vertical?y:x;"end"===this.primary&&(newPositionInPixels=this.size-newPositionInPixels),newPositionInPixels=null==(_a=this.snapFunction({pos:newPositionInPixels,size:this.size,snapThreshold:this.snapThreshold,isRtl,vertical:this.vertical}))?newPositionInPixels:_a,this.position=clamp(this.pixelsToPercentage(newPositionInPixels),0,100)},initialEvent:event}))}handleKeyDown(event){if(!this.disabled&&["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","Enter"].includes(event.key)){let newPosition=this.position;const incr=(event.shiftKey?10:1)*("end"===this.primary?-1:1);if(event.preventDefault(),("ArrowLeft"===event.key&&!this.vertical||"ArrowUp"===event.key&&this.vertical)&&(newPosition-=incr),("ArrowRight"===event.key&&!this.vertical||"ArrowDown"===event.key&&this.vertical)&&(newPosition+=incr),"Home"===event.key&&(newPosition="end"===this.primary?100:0),"End"===event.key&&(newPosition="end"===this.primary?0:100),"Enter"===event.key)if(this.isCollapsed)newPosition=this.positionBeforeCollapsing,this.isCollapsed=!1;else{const positionBeforeCollapsing=this.position;newPosition=0,requestAnimationFrame(()=>{this.isCollapsed=!0,this.positionBeforeCollapsing=positionBeforeCollapsing})}this.position=clamp(newPosition,0,100)}}handleResize(entries){const{width,height}=entries[0].contentRect;this.size=this.vertical?height:width,(isNaN(this.cachedPositionInPixels)||this.position===1/0)&&(this.cachedPositionInPixels=+this.getAttribute("position-in-pixels"),this.positionInPixels=+this.getAttribute("position-in-pixels"),this.position=this.pixelsToPercentage(this.positionInPixels)),this.primary&&(this.position=this.pixelsToPercentage(this.cachedPositionInPixels))}handlePositionChange(){this.cachedPositionInPixels=this.percentageToPixels(this.position),this.isCollapsed=!1,this.positionBeforeCollapsing=0,this.positionInPixels=this.percentageToPixels(this.position),this.emit("sl-reposition")}handlePositionInPixelsChange(){this.position=this.pixelsToPercentage(this.positionInPixels)}handleVerticalChange(){this.detectSize()}render(){const gridTemplate=this.vertical?"gridTemplateRows":"gridTemplateColumns",gridTemplateAlt=this.vertical?"gridTemplateColumns":"gridTemplateRows",isRtl="rtl"===this.localize.dir(),primary=` + clamp( + 0%, + clamp( + var(--min), + ${this.position}% - var(--divider-width) / 2, + var(--max) + ), + calc(100% - var(--divider-width)) + ) + `,secondary="auto";return this.style[gridTemplate]="end"===this.primary?isRtl&&!this.vertical?`${primary} var(--divider-width) ${secondary}`:`${secondary} var(--divider-width) ${primary}`:isRtl&&!this.vertical?`${secondary} var(--divider-width) ${primary}`:`${primary} var(--divider-width) ${secondary}`,this.style[gridTemplateAlt]="",x$1` + <slot name="start" part="panel start" class="start"></slot> + + <div + part="divider" + class="divider" + tabindex=${o$6(this.disabled?void 0:"0")} + role="separator" + aria-valuenow=${this.position} + aria-valuemin="0" + aria-valuemax="100" + aria-label=${this.localize.term("resize")} + @keydown=${this.handleKeyDown} + @mousedown=${this.handleDrag} + @touchstart=${this.handleDrag} + > + <slot name="divider"></slot> + </div> + + <slot name="end" part="panel end" class="end"></slot> + `}};SlSplitPanel.styles=[component_styles_default,split_panel_styles_default],__decorateClass([e$6(".divider")],SlSplitPanel.prototype,"divider",2),__decorateClass([n$5({type:Number,reflect:!0})],SlSplitPanel.prototype,"position",2),__decorateClass([n$5({attribute:"position-in-pixels",type:Number})],SlSplitPanel.prototype,"positionInPixels",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSplitPanel.prototype,"vertical",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSplitPanel.prototype,"disabled",2),__decorateClass([n$5()],SlSplitPanel.prototype,"primary",2),__decorateClass([n$5({reflect:!0})],SlSplitPanel.prototype,"snap",1),__decorateClass([n$5({type:Number,attribute:"snap-threshold"})],SlSplitPanel.prototype,"snapThreshold",2),__decorateClass([watch("position")],SlSplitPanel.prototype,"handlePositionChange",1),__decorateClass([watch("positionInPixels")],SlSplitPanel.prototype,"handlePositionInPixelsChange",1),__decorateClass([watch("vertical")],SlSplitPanel.prototype,"handleVerticalChange",1),SlSplitPanel.define("sl-split-panel");var switch_styles_default=i$7` + :host { + display: inline-block; + } + + :host([size='small']) { + --height: var(--sl-toggle-size-small); + --thumb-size: calc(var(--sl-toggle-size-small) + 4px); + --width: calc(var(--height) * 2); + + font-size: var(--sl-input-font-size-small); + } + + :host([size='medium']) { + --height: var(--sl-toggle-size-medium); + --thumb-size: calc(var(--sl-toggle-size-medium) + 4px); + --width: calc(var(--height) * 2); + + font-size: var(--sl-input-font-size-medium); + } + + :host([size='large']) { + --height: var(--sl-toggle-size-large); + --thumb-size: calc(var(--sl-toggle-size-large) + 4px); + --width: calc(var(--height) * 2); + + font-size: var(--sl-input-font-size-large); + } + + .switch { + position: relative; + display: inline-flex; + align-items: center; + font-family: var(--sl-input-font-family); + font-size: inherit; + font-weight: var(--sl-input-font-weight); + color: var(--sl-input-label-color); + vertical-align: middle; + cursor: pointer; + } + + .switch__control { + flex: 0 0 auto; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: var(--width); + height: var(--height); + background-color: var(--sl-color-neutral-400); + border: solid var(--sl-input-border-width) var(--sl-color-neutral-400); + border-radius: var(--height); + transition: + var(--sl-transition-fast) border-color, + var(--sl-transition-fast) background-color; + } + + .switch__control .switch__thumb { + width: var(--thumb-size); + height: var(--thumb-size); + background-color: var(--sl-color-neutral-0); + border-radius: 50%; + border: solid var(--sl-input-border-width) var(--sl-color-neutral-400); + translate: calc((var(--width) - var(--height)) / -2); + transition: + var(--sl-transition-fast) translate ease, + var(--sl-transition-fast) background-color, + var(--sl-transition-fast) border-color, + var(--sl-transition-fast) box-shadow; + } + + .switch__input { + position: absolute; + opacity: 0; + padding: 0; + margin: 0; + pointer-events: none; + } + + /* Hover */ + .switch:not(.switch--checked):not(.switch--disabled) .switch__control:hover { + background-color: var(--sl-color-neutral-400); + border-color: var(--sl-color-neutral-400); + } + + .switch:not(.switch--checked):not(.switch--disabled) .switch__control:hover .switch__thumb { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-color-neutral-400); + } + + /* Focus */ + .switch:not(.switch--checked):not(.switch--disabled) .switch__input:focus-visible ~ .switch__control { + background-color: var(--sl-color-neutral-400); + border-color: var(--sl-color-neutral-400); + } + + .switch:not(.switch--checked):not(.switch--disabled) .switch__input:focus-visible ~ .switch__control .switch__thumb { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-color-primary-600); + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + /* Checked */ + .switch--checked .switch__control { + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + } + + .switch--checked .switch__control .switch__thumb { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-color-primary-600); + translate: calc((var(--width) - var(--height)) / 2); + } + + /* Checked + hover */ + .switch.switch--checked:not(.switch--disabled) .switch__control:hover { + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + } + + .switch.switch--checked:not(.switch--disabled) .switch__control:hover .switch__thumb { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-color-primary-600); + } + + /* Checked + focus */ + .switch.switch--checked:not(.switch--disabled) .switch__input:focus-visible ~ .switch__control { + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + } + + .switch.switch--checked:not(.switch--disabled) .switch__input:focus-visible ~ .switch__control .switch__thumb { + background-color: var(--sl-color-neutral-0); + border-color: var(--sl-color-primary-600); + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + /* Disabled */ + .switch--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .switch__label { + display: inline-block; + line-height: var(--height); + margin-inline-start: 0.5em; + user-select: none; + -webkit-user-select: none; + } + + :host([required]) .switch__label::after { + content: var(--sl-input-required-content); + color: var(--sl-input-required-content-color); + margin-inline-start: var(--sl-input-required-content-offset); + } + + @media (forced-colors: active) { + .switch.switch--checked:not(.switch--disabled) .switch__control:hover .switch__thumb, + .switch--checked .switch__control .switch__thumb { + background-color: ButtonText; + } + } +`,SlSwitch=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this,{value:control=>control.checked?control.value||"on":void 0,defaultValue:control=>control.defaultChecked,setValue:(control,checked)=>control.checked=checked}),this.hasSlotController=new HasSlotController(this,"help-text"),this.hasFocus=!1,this.title="",this.name="",this.size="medium",this.disabled=!1,this.checked=!1,this.defaultChecked=!1,this.form="",this.required=!1,this.helpText=""}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}firstUpdated(){this.formControlController.updateValidity()}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleInput(){this.emit("sl-input")}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}handleClick(){this.checked=!this.checked,this.emit("sl-change")}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleKeyDown(event){"ArrowLeft"===event.key&&(event.preventDefault(),this.checked=!1,this.emit("sl-change"),this.emit("sl-input")),"ArrowRight"===event.key&&(event.preventDefault(),this.checked=!0,this.emit("sl-change"),this.emit("sl-input"))}handleCheckedChange(){this.input.checked=this.checked,this.formControlController.updateValidity()}handleDisabledChange(){this.formControlController.setValidity(!0)}click(){this.input.click()}focus(options){this.input.focus(options)}blur(){this.input.blur()}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.input.reportValidity()}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){const hasHelpTextSlot=this.hasSlotController.test("help-text"),hasHelpText=!!this.helpText||!!hasHelpTextSlot;return x$1` + <div + class=${e$2({"form-control":!0,"form-control--small":"small"===this.size,"form-control--medium":"medium"===this.size,"form-control--large":"large"===this.size,"form-control--has-help-text":hasHelpText})} + > + <label + part="base" + class=${e$2({switch:!0,"switch--checked":this.checked,"switch--disabled":this.disabled,"switch--focused":this.hasFocus,"switch--small":"small"===this.size,"switch--medium":"medium"===this.size,"switch--large":"large"===this.size})} + > + <input + class="switch__input" + type="checkbox" + title=${this.title} + name=${this.name} + value=${o$6(this.value)} + .checked=${l(this.checked)} + .disabled=${this.disabled} + .required=${this.required} + role="switch" + aria-checked=${this.checked?"true":"false"} + aria-describedby="help-text" + @click=${this.handleClick} + @input=${this.handleInput} + @invalid=${this.handleInvalid} + @blur=${this.handleBlur} + @focus=${this.handleFocus} + @keydown=${this.handleKeyDown} + /> + + <span part="control" class="switch__control"> + <span part="thumb" class="switch__thumb"></span> + </span> + + <div part="label" class="switch__label"> + <slot></slot> + </div> + </label> + + <div + aria-hidden=${hasHelpText?"false":"true"} + class="form-control__help-text" + id="help-text" + part="form-control-help-text" + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlSwitch.styles=[component_styles_default,form_control_styles_default,switch_styles_default],__decorateClass([e$6("input[type=\"checkbox\"]")],SlSwitch.prototype,"input",2),__decorateClass([r$6()],SlSwitch.prototype,"hasFocus",2),__decorateClass([n$5()],SlSwitch.prototype,"title",2),__decorateClass([n$5()],SlSwitch.prototype,"name",2),__decorateClass([n$5()],SlSwitch.prototype,"value",2),__decorateClass([n$5({reflect:!0})],SlSwitch.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSwitch.prototype,"disabled",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSwitch.prototype,"checked",2),__decorateClass([defaultValue("checked")],SlSwitch.prototype,"defaultChecked",2),__decorateClass([n$5({reflect:!0})],SlSwitch.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlSwitch.prototype,"required",2),__decorateClass([n$5({attribute:"help-text"})],SlSwitch.prototype,"helpText",2),__decorateClass([watch("checked",{waitUntilFirstUpdate:!0})],SlSwitch.prototype,"handleCheckedChange",1),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlSwitch.prototype,"handleDisabledChange",1),SlSwitch.define("sl-switch"),SlResizeObserver.define("sl-resize-observer"),SlSpinner.define("sl-spinner");var range_styles_default=i$7` + :host { + --thumb-size: 20px; + --tooltip-offset: 10px; + --track-color-active: var(--sl-color-neutral-200); + --track-color-inactive: var(--sl-color-neutral-200); + --track-active-offset: 0%; + --track-height: 6px; + + display: block; + } + + .range { + position: relative; + } + + .range__control { + --percent: 0%; + -webkit-appearance: none; + border-radius: 3px; + width: 100%; + height: var(--track-height); + background: transparent; + line-height: var(--sl-input-height-medium); + vertical-align: middle; + margin: 0; + + background-image: linear-gradient( + to right, + var(--track-color-inactive) 0%, + var(--track-color-inactive) min(var(--percent), var(--track-active-offset)), + var(--track-color-active) min(var(--percent), var(--track-active-offset)), + var(--track-color-active) max(var(--percent), var(--track-active-offset)), + var(--track-color-inactive) max(var(--percent), var(--track-active-offset)), + var(--track-color-inactive) 100% + ); + } + + .range--rtl .range__control { + background-image: linear-gradient( + to left, + var(--track-color-inactive) 0%, + var(--track-color-inactive) min(var(--percent), var(--track-active-offset)), + var(--track-color-active) min(var(--percent), var(--track-active-offset)), + var(--track-color-active) max(var(--percent), var(--track-active-offset)), + var(--track-color-inactive) max(var(--percent), var(--track-active-offset)), + var(--track-color-inactive) 100% + ); + } + + /* Webkit */ + .range__control::-webkit-slider-runnable-track { + width: 100%; + height: var(--track-height); + border-radius: 3px; + border: none; + } + + .range__control::-webkit-slider-thumb { + border: none; + width: var(--thumb-size); + height: var(--thumb-size); + border-radius: 50%; + background-color: var(--sl-color-primary-600); + border: solid var(--sl-input-border-width) var(--sl-color-primary-600); + -webkit-appearance: none; + margin-top: calc(var(--thumb-size) / -2 + var(--track-height) / 2); + cursor: pointer; + } + + .range__control:enabled::-webkit-slider-thumb:hover { + background-color: var(--sl-color-primary-500); + border-color: var(--sl-color-primary-500); + } + + .range__control:enabled:focus-visible::-webkit-slider-thumb { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .range__control:enabled::-webkit-slider-thumb:active { + background-color: var(--sl-color-primary-500); + border-color: var(--sl-color-primary-500); + cursor: grabbing; + } + + /* Firefox */ + .range__control::-moz-focus-outer { + border: 0; + } + + .range__control::-moz-range-progress { + background-color: var(--track-color-active); + border-radius: 3px; + height: var(--track-height); + } + + .range__control::-moz-range-track { + width: 100%; + height: var(--track-height); + background-color: var(--track-color-inactive); + border-radius: 3px; + border: none; + } + + .range__control::-moz-range-thumb { + border: none; + height: var(--thumb-size); + width: var(--thumb-size); + border-radius: 50%; + background-color: var(--sl-color-primary-600); + border-color: var(--sl-color-primary-600); + transition: + var(--sl-transition-fast) border-color, + var(--sl-transition-fast) background-color, + var(--sl-transition-fast) color, + var(--sl-transition-fast) box-shadow; + cursor: pointer; + } + + .range__control:enabled::-moz-range-thumb:hover { + background-color: var(--sl-color-primary-500); + border-color: var(--sl-color-primary-500); + } + + .range__control:enabled:focus-visible::-moz-range-thumb { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .range__control:enabled::-moz-range-thumb:active { + background-color: var(--sl-color-primary-500); + border-color: var(--sl-color-primary-500); + cursor: grabbing; + } + + /* States */ + .range__control:focus-visible { + outline: none; + } + + .range__control:disabled { + opacity: 0.5; + } + + .range__control:disabled::-webkit-slider-thumb { + cursor: not-allowed; + } + + .range__control:disabled::-moz-range-thumb { + cursor: not-allowed; + } + + /* Tooltip output */ + .range__tooltip { + position: absolute; + z-index: var(--sl-z-index-tooltip); + left: 0; + border-radius: var(--sl-tooltip-border-radius); + background-color: var(--sl-tooltip-background-color); + font-family: var(--sl-tooltip-font-family); + font-size: var(--sl-tooltip-font-size); + font-weight: var(--sl-tooltip-font-weight); + line-height: var(--sl-tooltip-line-height); + color: var(--sl-tooltip-color); + opacity: 0; + padding: var(--sl-tooltip-padding); + transition: var(--sl-transition-fast) opacity; + pointer-events: none; + } + + .range__tooltip:after { + content: ''; + position: absolute; + width: 0; + height: 0; + left: 50%; + translate: calc(-1 * var(--sl-tooltip-arrow-size)); + } + + .range--tooltip-visible .range__tooltip { + opacity: 1; + } + + /* Tooltip on top */ + .range--tooltip-top .range__tooltip { + top: calc(-1 * var(--thumb-size) - var(--tooltip-offset)); + } + + .range--tooltip-top .range__tooltip:after { + border-top: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color); + border-left: var(--sl-tooltip-arrow-size) solid transparent; + border-right: var(--sl-tooltip-arrow-size) solid transparent; + top: 100%; + } + + /* Tooltip on bottom */ + .range--tooltip-bottom .range__tooltip { + bottom: calc(-1 * var(--thumb-size) - var(--tooltip-offset)); + } + + .range--tooltip-bottom .range__tooltip:after { + border-bottom: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color); + border-left: var(--sl-tooltip-arrow-size) solid transparent; + border-right: var(--sl-tooltip-arrow-size) solid transparent; + bottom: 100%; + } + + @media (forced-colors: active) { + .range__control, + .range__tooltip { + border: solid 1px transparent; + } + + .range__control::-webkit-slider-thumb { + border: solid 1px transparent; + } + + .range__control::-moz-range-thumb { + border: solid 1px transparent; + } + + .range__tooltip:after { + display: none; + } + } +`,SlRange=class extends ShoelaceElement{constructor(){super(...arguments),this.formControlController=new FormControlController(this),this.hasSlotController=new HasSlotController(this,"help-text","label"),this.localize=new LocalizeController(this),this.hasFocus=!1,this.hasTooltip=!1,this.title="",this.name="",this.value=0,this.label="",this.helpText="",this.disabled=!1,this.min=0,this.max=100,this.step=1,this.tooltip="top",this.tooltipFormatter=value=>value.toString(),this.form="",this.defaultValue=0}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}connectedCallback(){super.connectedCallback(),this.resizeObserver=new ResizeObserver(()=>this.syncRange()),this.value<this.min&&(this.value=this.min),this.value>this.max&&(this.value=this.max),this.updateComplete.then(()=>{this.syncRange(),this.resizeObserver.observe(this.input)})}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.resizeObserver)?void 0:_a.unobserve(this.input)}handleChange(){this.emit("sl-change")}handleInput(){this.value=parseFloat(this.input.value),this.emit("sl-input"),this.syncRange()}handleBlur(){this.hasFocus=!1,this.hasTooltip=!1,this.emit("sl-blur")}handleFocus(){this.hasFocus=!0,this.hasTooltip=!0,this.emit("sl-focus")}handleThumbDragStart(){this.hasTooltip=!0}handleThumbDragEnd(){this.hasTooltip=!1}syncProgress(percent){this.input.style.setProperty("--percent",`${100*percent}%`)}syncTooltip(percent){if(null!==this.output){const inputWidth=this.input.offsetWidth,tooltipWidth=this.output.offsetWidth,thumbSize=getComputedStyle(this.input).getPropertyValue("--thumb-size"),isRtl="rtl"===this.localize.dir(),percentAsWidth=inputWidth*percent;if(isRtl){const x=`${inputWidth-percentAsWidth}px + ${percent} * ${thumbSize}`;this.output.style.translate=`calc((${x} - ${tooltipWidth/2}px - ${thumbSize} / 2))`}else{const x=`${percentAsWidth}px - ${percent} * ${thumbSize}`;this.output.style.translate=`calc(${x} - ${tooltipWidth/2}px + ${thumbSize} / 2)`}}}handleValueChange(){this.formControlController.updateValidity(),this.input.value=this.value.toString(),this.value=parseFloat(this.input.value),this.syncRange()}handleDisabledChange(){this.formControlController.setValidity(this.disabled)}syncRange(){const percent=Math.max(0,(this.value-this.min)/(this.max-this.min));this.syncProgress(percent),"none"!==this.tooltip&&this.hasTooltip&&this.updateComplete.then(()=>this.syncTooltip(percent))}handleInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}focus(options){this.input.focus(options)}blur(){this.input.blur()}stepUp(){this.input.stepUp(),this.value!==+this.input.value&&(this.value=+this.input.value)}stepDown(){this.input.stepDown(),this.value!==+this.input.value&&(this.value=+this.input.value)}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.input.reportValidity()}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){const hasLabelSlot=this.hasSlotController.test("label"),hasHelpTextSlot=this.hasSlotController.test("help-text"),hasLabel=!!this.label||!!hasLabelSlot,hasHelpText=!!this.helpText||!!hasHelpTextSlot;return x$1` + <div + part="form-control" + class=${e$2({"form-control":!0,"form-control--medium":!0,"form-control--has-label":hasLabel,"form-control--has-help-text":hasHelpText})} + > + <label + part="form-control-label" + class="form-control__label" + for="input" + aria-hidden=${hasLabel?"false":"true"} + > + <slot name="label">${this.label}</slot> + </label> + + <div part="form-control-input" class="form-control-input"> + <div + part="base" + class=${e$2({range:!0,"range--disabled":this.disabled,"range--focused":this.hasFocus,"range--rtl":"rtl"===this.localize.dir(),"range--tooltip-visible":this.hasTooltip,"range--tooltip-top":"top"===this.tooltip,"range--tooltip-bottom":"bottom"===this.tooltip})} + @mousedown=${this.handleThumbDragStart} + @mouseup=${this.handleThumbDragEnd} + @touchstart=${this.handleThumbDragStart} + @touchend=${this.handleThumbDragEnd} + > + <input + part="input" + id="input" + class="range__control" + title=${this.title} + type="range" + name=${o$6(this.name)} + ?disabled=${this.disabled} + min=${o$6(this.min)} + max=${o$6(this.max)} + step=${o$6(this.step)} + .value=${l(this.value.toString())} + aria-describedby="help-text" + @change=${this.handleChange} + @focus=${this.handleFocus} + @input=${this.handleInput} + @invalid=${this.handleInvalid} + @blur=${this.handleBlur} + /> + ${"none"===this.tooltip||this.disabled?"":x$1` + <output part="tooltip" class="range__tooltip"> + ${"function"==typeof this.tooltipFormatter?this.tooltipFormatter(this.value):this.value} + </output> + `} + </div> + </div> + + <div + part="form-control-help-text" + id="help-text" + class="form-control__help-text" + aria-hidden=${hasHelpText?"false":"true"} + > + <slot name="help-text">${this.helpText}</slot> + </div> + </div> + `}};SlRange.styles=[component_styles_default,form_control_styles_default,range_styles_default],__decorateClass([e$6(".range__control")],SlRange.prototype,"input",2),__decorateClass([e$6(".range__tooltip")],SlRange.prototype,"output",2),__decorateClass([r$6()],SlRange.prototype,"hasFocus",2),__decorateClass([r$6()],SlRange.prototype,"hasTooltip",2),__decorateClass([n$5()],SlRange.prototype,"title",2),__decorateClass([n$5()],SlRange.prototype,"name",2),__decorateClass([n$5({type:Number})],SlRange.prototype,"value",2),__decorateClass([n$5()],SlRange.prototype,"label",2),__decorateClass([n$5({attribute:"help-text"})],SlRange.prototype,"helpText",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRange.prototype,"disabled",2),__decorateClass([n$5({type:Number})],SlRange.prototype,"min",2),__decorateClass([n$5({type:Number})],SlRange.prototype,"max",2),__decorateClass([n$5({type:Number})],SlRange.prototype,"step",2),__decorateClass([n$5()],SlRange.prototype,"tooltip",2),__decorateClass([n$5({attribute:!1})],SlRange.prototype,"tooltipFormatter",2),__decorateClass([n$5({reflect:!0})],SlRange.prototype,"form",2),__decorateClass([defaultValue()],SlRange.prototype,"defaultValue",2),__decorateClass([t$2({passive:!0})],SlRange.prototype,"handleThumbDragStart",1),__decorateClass([watch("value",{waitUntilFirstUpdate:!0})],SlRange.prototype,"handleValueChange",1),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlRange.prototype,"handleDisabledChange",1),__decorateClass([watch("hasTooltip",{waitUntilFirstUpdate:!0})],SlRange.prototype,"syncRange",1),SlRange.define("sl-range");var rating_styles_default=i$7` + :host { + --symbol-color: var(--sl-color-neutral-300); + --symbol-color-active: var(--sl-color-amber-500); + --symbol-size: 1.2rem; + --symbol-spacing: var(--sl-spacing-3x-small); + + display: inline-flex; + } + + .rating { + position: relative; + display: inline-flex; + border-radius: var(--sl-border-radius-medium); + vertical-align: middle; + } + + .rating:focus { + outline: none; + } + + .rating:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .rating__symbols { + display: inline-flex; + position: relative; + font-size: var(--symbol-size); + line-height: 0; + color: var(--symbol-color); + white-space: nowrap; + cursor: pointer; + } + + .rating__symbols > * { + padding: var(--symbol-spacing); + } + + .rating__symbol--active, + .rating__partial--filled { + color: var(--symbol-color-active); + } + + .rating__partial-symbol-container { + position: relative; + } + + .rating__partial--filled { + position: absolute; + top: var(--symbol-spacing); + left: var(--symbol-spacing); + } + + .rating__symbol { + transition: var(--sl-transition-fast) scale; + pointer-events: none; + } + + .rating__symbol--hover { + scale: 1.2; + } + + .rating--disabled .rating__symbols, + .rating--readonly .rating__symbols { + cursor: default; + } + + .rating--disabled .rating__symbol--hover, + .rating--readonly .rating__symbol--hover { + scale: none; + } + + .rating--disabled { + opacity: 0.5; + } + + .rating--disabled .rating__symbols { + cursor: not-allowed; + } + + /* Forced colors mode */ + @media (forced-colors: active) { + .rating__symbol--active { + color: SelectedItem; + } + } +`,SlRating=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.hoverValue=0,this.isHovering=!1,this.label="",this.value=0,this.max=5,this.precision=1,this.readonly=!1,this.disabled=!1,this.getSymbol=()=>"<sl-icon name=\"star-fill\" library=\"system\"></sl-icon>"}getValueFromMousePosition(event){return this.getValueFromXCoordinate(event.clientX)}getValueFromTouchPosition(event){return this.getValueFromXCoordinate(event.touches[0].clientX)}getValueFromXCoordinate(coordinate){const isRtl="rtl"===this.localize.dir(),{left,right,width}=this.rating.getBoundingClientRect(),value=isRtl?this.roundToPrecision((right-coordinate)/width*this.max,this.precision):this.roundToPrecision((coordinate-left)/width*this.max,this.precision);return clamp(value,0,this.max)}handleClick(event){this.disabled||(this.setValue(this.getValueFromMousePosition(event)),this.emit("sl-change"))}setValue(newValue){this.disabled||this.readonly||(this.value=newValue===this.value?0:newValue,this.isHovering=!1)}handleKeyDown(event){var _Mathmin4=Math.min,_Mathmax8=Math.max;const isLtr="ltr"===this.localize.dir(),isRtl="rtl"===this.localize.dir(),oldValue=this.value;if(!(this.disabled||this.readonly)){if("ArrowDown"===event.key||isLtr&&"ArrowLeft"===event.key||isRtl&&"ArrowRight"===event.key){const decrement=event.shiftKey?1:this.precision;this.value=_Mathmax8(0,this.value-decrement),event.preventDefault()}if("ArrowUp"===event.key||isLtr&&"ArrowRight"===event.key||isRtl&&"ArrowLeft"===event.key){const increment=event.shiftKey?1:this.precision;this.value=_Mathmin4(this.max,this.value+increment),event.preventDefault()}"Home"===event.key&&(this.value=0,event.preventDefault()),"End"===event.key&&(this.value=this.max,event.preventDefault()),this.value!==oldValue&&this.emit("sl-change")}}handleMouseEnter(event){this.isHovering=!0,this.hoverValue=this.getValueFromMousePosition(event)}handleMouseMove(event){this.hoverValue=this.getValueFromMousePosition(event)}handleMouseLeave(){this.isHovering=!1}handleTouchStart(event){this.isHovering=!0,this.hoverValue=this.getValueFromTouchPosition(event),event.preventDefault()}handleTouchMove(event){this.hoverValue=this.getValueFromTouchPosition(event)}handleTouchEnd(event){this.isHovering=!1,this.setValue(this.hoverValue),this.emit("sl-change"),event.preventDefault()}roundToPrecision(numberToRound,precision=.5){const multiplier=1/precision;return Math.ceil(numberToRound*multiplier)/multiplier}handleHoverValueChange(){this.emit("sl-hover",{detail:{phase:"move",value:this.hoverValue}})}handleIsHoveringChange(){this.emit("sl-hover",{detail:{phase:this.isHovering?"start":"end",value:this.hoverValue}})}focus(options){this.rating.focus(options)}blur(){this.rating.blur()}render(){var _Mathceil2=Math.ceil;const isRtl="rtl"===this.localize.dir(),counter=Array.from(Array(this.max).keys());let displayValue=0;return displayValue=this.disabled||this.readonly?this.value:this.isHovering?this.hoverValue:this.value,x$1` + <div + part="base" + class=${e$2({rating:!0,"rating--readonly":this.readonly,"rating--disabled":this.disabled,"rating--rtl":isRtl})} + role="slider" + aria-label=${this.label} + aria-disabled=${this.disabled?"true":"false"} + aria-readonly=${this.readonly?"true":"false"} + aria-valuenow=${this.value} + aria-valuemin=${0} + aria-valuemax=${this.max} + tabindex=${this.disabled||this.readonly?"-1":"0"} + @click=${this.handleClick} + @keydown=${this.handleKeyDown} + @mouseenter=${this.handleMouseEnter} + @touchstart=${this.handleTouchStart} + @mouseleave=${this.handleMouseLeave} + @touchend=${this.handleTouchEnd} + @mousemove=${this.handleMouseMove} + @touchmove=${this.handleTouchMove} + > + <span class="rating__symbols"> + ${counter.map(index=>displayValue>index&&displayValue<index+1?x$1` + <span + class=${e$2({rating__symbol:!0,"rating__partial-symbol-container":!0,"rating__symbol--hover":this.isHovering&&_Mathceil2(displayValue)===index+1})} + role="presentation" + > + <div + style=${o$3({clipPath:isRtl?`inset(0 ${100*(displayValue-index)}% 0 0)`:`inset(0 0 0 ${100*(displayValue-index)}%)`})} + > + ${o$2(this.getSymbol(index+1))} + </div> + <div + class="rating__partial--filled" + style=${o$3({clipPath:isRtl?`inset(0 0 0 ${100-100*(displayValue-index)}%)`:`inset(0 ${100-100*(displayValue-index)}% 0 0)`})} + > + ${o$2(this.getSymbol(index+1))} + </div> + </span> + `:x$1` + <span + class=${e$2({rating__symbol:!0,"rating__symbol--hover":this.isHovering&&_Mathceil2(displayValue)===index+1,"rating__symbol--active":displayValue>=index+1})} + role="presentation" + > + ${o$2(this.getSymbol(index+1))} + </span> + `)} + </span> + </div> + `}};SlRating.styles=[component_styles_default,rating_styles_default],SlRating.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".rating")],SlRating.prototype,"rating",2),__decorateClass([r$6()],SlRating.prototype,"hoverValue",2),__decorateClass([r$6()],SlRating.prototype,"isHovering",2),__decorateClass([n$5()],SlRating.prototype,"label",2),__decorateClass([n$5({type:Number})],SlRating.prototype,"value",2),__decorateClass([n$5({type:Number})],SlRating.prototype,"max",2),__decorateClass([n$5({type:Number})],SlRating.prototype,"precision",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRating.prototype,"readonly",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRating.prototype,"disabled",2),__decorateClass([n$5()],SlRating.prototype,"getSymbol",2),__decorateClass([t$2({passive:!0})],SlRating.prototype,"handleTouchMove",1),__decorateClass([watch("hoverValue")],SlRating.prototype,"handleHoverValueChange",1),__decorateClass([watch("isHovering")],SlRating.prototype,"handleIsHoveringChange",1),SlRating.define("sl-rating");var radio_button_styles_default=i$7` + ${button_styles_default} + + .button__prefix, + .button__suffix, + .button__label { + display: inline-flex; + position: relative; + align-items: center; + } + + /* We use a hidden input so constraint validation errors work, since they don't appear to show when used with buttons. + We can't actually hide it, though, otherwise the messages will be suppressed by the browser. */ + .hidden-input { + all: unset; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + outline: dotted 1px red; + opacity: 0; + z-index: -1; + } +`,SlRadioButton=class extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"[default]","prefix","suffix"),this.hasFocus=!1,this.checked=!1,this.disabled=!1,this.size="medium",this.pill=!1}connectedCallback(){super.connectedCallback(),this.setAttribute("role","presentation")}handleBlur(){this.hasFocus=!1,this.emit("sl-blur")}handleClick(e){return this.disabled?(e.preventDefault(),void e.stopPropagation()):void(this.checked=!0)}handleFocus(){this.hasFocus=!0,this.emit("sl-focus")}handleDisabledChange(){this.setAttribute("aria-disabled",this.disabled?"true":"false")}focus(options){this.input.focus(options)}blur(){this.input.blur()}render(){return u$1` + <div part="base" role="presentation"> + <button + part="${`button${this.checked?" button--checked":""}`}" + role="radio" + aria-checked="${this.checked}" + class=${e$2({button:!0,"button--default":!0,"button--small":"small"===this.size,"button--medium":"medium"===this.size,"button--large":"large"===this.size,"button--checked":this.checked,"button--disabled":this.disabled,"button--focused":this.hasFocus,"button--outline":!0,"button--pill":this.pill,"button--has-label":this.hasSlotController.test("[default]"),"button--has-prefix":this.hasSlotController.test("prefix"),"button--has-suffix":this.hasSlotController.test("suffix")})} + aria-disabled=${this.disabled} + type="button" + value=${o$6(this.value)} + @blur=${this.handleBlur} + @focus=${this.handleFocus} + @click=${this.handleClick} + > + <slot name="prefix" part="prefix" class="button__prefix"></slot> + <slot part="label" class="button__label"></slot> + <slot name="suffix" part="suffix" class="button__suffix"></slot> + </button> + </div> + `}};SlRadioButton.styles=[component_styles_default,radio_button_styles_default],__decorateClass([e$6(".button")],SlRadioButton.prototype,"input",2),__decorateClass([e$6(".hidden-input")],SlRadioButton.prototype,"hiddenInput",2),__decorateClass([r$6()],SlRadioButton.prototype,"hasFocus",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRadioButton.prototype,"checked",2),__decorateClass([n$5()],SlRadioButton.prototype,"value",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRadioButton.prototype,"disabled",2),__decorateClass([n$5({reflect:!0})],SlRadioButton.prototype,"size",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlRadioButton.prototype,"pill",2),__decorateClass([watch("disabled",{waitUntilFirstUpdate:!0})],SlRadioButton.prototype,"handleDisabledChange",1),SlRadioButton.define("sl-radio-button");var progress_ring_styles_default=i$7` + :host { + --size: 128px; + --track-width: 4px; + --track-color: var(--sl-color-neutral-200); + --indicator-width: var(--track-width); + --indicator-color: var(--sl-color-primary-600); + --indicator-transition-duration: 0.35s; + + display: inline-flex; + } + + .progress-ring { + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + } + + .progress-ring__image { + width: var(--size); + height: var(--size); + rotate: -90deg; + transform-origin: 50% 50%; + } + + .progress-ring__track, + .progress-ring__indicator { + --radius: calc(var(--size) / 2 - max(var(--track-width), var(--indicator-width)) * 0.5); + --circumference: calc(var(--radius) * 2 * 3.141592654); + + fill: none; + r: var(--radius); + cx: calc(var(--size) / 2); + cy: calc(var(--size) / 2); + } + + .progress-ring__track { + stroke: var(--track-color); + stroke-width: var(--track-width); + } + + .progress-ring__indicator { + stroke: var(--indicator-color); + stroke-width: var(--indicator-width); + stroke-linecap: round; + transition-property: stroke-dashoffset; + transition-duration: var(--indicator-transition-duration); + stroke-dasharray: var(--circumference) var(--circumference); + stroke-dashoffset: calc(var(--circumference) - var(--percentage) * var(--circumference)); + } + + .progress-ring__label { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + user-select: none; + -webkit-user-select: none; + } +`,SlProgressRing=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.value=0,this.label=""}updated(changedProps){var _MathPI=Math.PI;if(super.updated(changedProps),changedProps.has("value")){const radius=parseFloat(getComputedStyle(this.indicator).getPropertyValue("r")),circumference=2*_MathPI*radius,offset=circumference-this.value/100*circumference;this.indicatorOffset=`${offset}px`}}render(){return x$1` + <div + part="base" + class="progress-ring" + role="progressbar" + aria-label=${0<this.label.length?this.label:this.localize.term("progress")} + aria-describedby="label" + aria-valuemin="0" + aria-valuemax="100" + aria-valuenow="${this.value}" + style="--percentage: ${this.value/100}" + > + <svg class="progress-ring__image"> + <circle class="progress-ring__track"></circle> + <circle class="progress-ring__indicator" style="stroke-dashoffset: ${this.indicatorOffset}"></circle> + </svg> + + <slot id="label" part="label" class="progress-ring__label"></slot> + </div> + `}};SlProgressRing.styles=[component_styles_default,progress_ring_styles_default],__decorateClass([e$6(".progress-ring__indicator")],SlProgressRing.prototype,"indicator",2),__decorateClass([r$6()],SlProgressRing.prototype,"indicatorOffset",2),__decorateClass([n$5({type:Number,reflect:!0})],SlProgressRing.prototype,"value",2),__decorateClass([n$5()],SlProgressRing.prototype,"label",2),SlProgressRing.define("sl-progress-ring");var qr_code_styles_default=i$7` + :host { + display: inline-block; + } +`;let G=null;class H{}H.render=function(w,B){G(w,B)},self.QrCreator=H,function(w){var _Mathfloor6=Math.floor,_Mathmin5=Math.min,_Mathmax9=Math.max,_Mathround4=Math.round;function B(t,c,a,e){var b={},h=w(a,c);h.u(t),h.J(),e=e||0;var r=h.h(),d=h.h()+2*e;return b.text=t,b.level=c,b.version=a,b.O=d,b.a=function(b,a){return b-=e,a-=e,!(0>b||b>=r||0>a||a>=r)&&h.a(b,a)},b}function C(t,c,a,e,b,h,r,d,g,x){function u(b,a,f,c,d,r,g){b?(t.lineTo(a+r,f+g),t.arcTo(a,f,c,d,h)):t.lineTo(a,f)}r?t.moveTo(c+h,a):t.moveTo(c,a),u(d,e,a,e,b,-h,0),u(g,e,b,c,b,0,-h),u(x,c,b,c,a,h,0),u(r,c,a,e,a,0,h)}function z(t,c,a,e,b,h,r,d,g,x){function u(b,a,c,d){t.moveTo(b+c,a),t.lineTo(b,a),t.lineTo(b,a+d),t.arcTo(b,a,b+c,a,h)}r&&u(c,a,h,h),d&&u(e,a,-h,h),g&&u(e,b,-h,-h),x&&u(c,b,h,-h)}function A(t,c){var a=c.fill;if("string"==typeof a)t.fillStyle=a;else{var e=a.type,b=a.colorStops;if(a=a.position.map(b=>_Mathround4(b*c.size)),"linear-gradient"===e)var h=t.createLinearGradient.apply(t,a);else if("radial-gradient"===e)h=t.createRadialGradient.apply(t,a);else throw Error("Unsupported fill");b.forEach(([b,a])=>{h.addColorStop(b,a)}),t.fillStyle=h}}function y(t,c){a:{var a=c.text,e=c.v,b=c.N,h=c.K,r=c.P;for(b=_Mathmax9(1,b||1),h=_Mathmin5(40,h||40);b<=h;b+=1)try{var d=B(a,e,b,r);break a}catch(J){}d=void 0}if(!d)return null;for(a=t.getContext("2d"),c.background&&(a.fillStyle=c.background,a.fillRect(c.left,c.top,c.size,c.size)),e=d.O,h=c.size/e,a.beginPath(),r=0;r<e;r+=1)for(b=0;b<e;b+=1){var g=a,x=c.left+b*h,u=c.top+r*h,p=r,q=b,f=d.a,k=x+h,m=u+h,D=p-1,E=p+1,n=q-1,l=q+1,y=_Mathfloor6(_Mathmin5(.5,_Mathmax9(0,c.R))*h),v=f(p,q),I=f(D,n),w=f(D,q);D=f(D,l);var F=f(p,l);l=f(E,l),q=f(E,q),E=f(E,n),p=f(p,n),x=_Mathround4(x),u=_Mathround4(u),k=_Mathround4(k),m=_Mathround4(m),v?C(g,x,u,k,m,y,!w&&!p,!w&&!F,!q&&!F,!q&&!p):z(g,x,u,k,m,y,w&&p&&I,w&&F&&D,q&&F&&l,q&&p&&E)}return A(a,c),a.fill(),t}var v={minVersion:1,maxVersion:40,ecLevel:"L",left:0,top:0,size:200,fill:"#000",background:null,text:"no text",radius:.5,quiet:0};G=function(t,c){var a={};Object.assign(a,v,t),a.N=a.minVersion,a.K=a.maxVersion,a.v=a.ecLevel,a.left=a.left,a.top=a.top,a.size=a.size,a.fill=a.fill,a.background=a.background,a.text=a.text,a.R=a.radius,a.P=a.quiet,c instanceof HTMLCanvasElement?((c.width!==a.size||c.height!==a.size)&&(c.width=a.size,c.height=a.size),c.getContext("2d").clearRect(0,0,c.width,c.height),y(c,a)):(t=document.createElement("canvas"),t.width=a.size,t.height=a.size,a=y(t,a),c.appendChild(a))}}(function(){var _Mathfloor7=Math.floor,_Mathmax0=Math.max;function w(c){var a=C.s(c);return{S:function(){return 4},b:function(){return a.length},write:function(c){for(var b=0;b<a.length;b+=1)c.put(a[b],8)}}}function B(){var c=[],a=0,e={B:function(){return c},c:function(b){return 1==(1&c[_Mathfloor7(b/8)]>>>7-b%8)},put:function(b,h){for(var a=0;a<h;a+=1)e.m(1==(1&b>>>h-a-1))},f:function(){return a},m:function(b){var h=_Mathfloor7(a/8);c.length<=h&&c.push(0),b&&(c[h]|=128>>>a%8),a+=1}};return e}function C(c,a){function e(b,h){for(var a=-1;7>=a;a+=1)if(!(-1>=b+a||d<=b+a))for(var c=-1;7>=c;c+=1)-1>=h+c||d<=h+c||(r[b+a][h+c]=!!(0<=a&&6>=a&&(0==c||6==c)||0<=c&&6>=c&&(0==a||6==a)||2<=a&&4>=a&&2<=c&&4>=c))}function b(b,a){for(var f=d=4*c+17,k=Array(f),m=0;m<f;m+=1){k[m]=Array(f);for(var p=0;p<f;p+=1)k[m][p]=null}for(r=k,e(0,0),e(d-7,0),e(0,d-7),f=y.G(c),k=0;k<f.length;k+=1)for(m=0;m<f.length;m+=1){p=f[k];var q=f[m];if(null==r[p][q])for(var n=-2;2>=n;n+=1)for(var l=-2;2>=l;l+=1)r[p+n][q+l]=-2==n||2==n||-2==l||2==l||0==n&&0==l}for(f=8;f<d-8;f+=1)null==r[f][6]&&(r[f][6]=0==f%2);for(f=8;f<d-8;f+=1)null==r[6][f]&&(r[6][f]=0==f%2);for(f=y.w(h<<3|a),k=0;15>k;k+=1)m=!b&&1==(1&f>>k),r[6>k?k:8>k?k+1:d-15+k][8]=m,r[8][8>k?d-k-1:9>k?15-k:14-k]=m;if(r[d-8][8]=!b,7<=c){for(f=y.A(c),k=0;18>k;k+=1)m=!b&&1==(1&f>>k),r[_Mathfloor7(k/3)][k%3+d-8-3]=m;for(k=0;18>k;k+=1)m=!b&&1==(1&f>>k),r[k%3+d-8-3][_Mathfloor7(k/3)]=m}if(null==g){for(b=t.I(c,h),f=B(),k=0;k<x.length;k+=1)m=x[k],f.put(4,4),f.put(m.b(),y.f(4,c)),m.write(f);for(k=m=0;k<b.length;k+=1)m+=b[k].j;if(f.f()>8*m)throw Error("code length overflow. ("+f.f()+">"+8*m+")");for(f.f()+4<=8*m&&f.put(0,4);0!=f.f()%8;)f.m(!1);for(;!(f.f()>=8*m)&&(f.put(236,8),!(f.f()>=8*m));)f.put(17,8);var u=0;for(m=k=0,p=Array(b.length),q=Array(b.length),n=0;n<b.length;n+=1){var v=b[n].j,w=b[n].o-v;for(k=_Mathmax0(k,v),m=_Mathmax0(m,w),p[n]=Array(v),l=0;l<p[n].length;l+=1)p[n][l]=255&f.B()[l+u];for(u+=v,l=y.C(w),v=z(p[n],l.b()-1).l(l),q[n]=Array(l.b()-1),l=0;l<q[n].length;l+=1)w=l+v.b()-q[n].length,q[n][l]=0<=w?v.c(w):0}for(l=f=0;l<b.length;l+=1)f+=b[l].o;for(f=Array(f),l=u=0;l<k;l+=1)for(n=0;n<b.length;n+=1)l<p[n].length&&(f[u]=p[n][l],u+=1);for(l=0;l<m;l+=1)for(n=0;n<b.length;n+=1)l<q[n].length&&(f[u]=q[n][l],u+=1);g=f}for(b=g,f=-1,k=d-1,m=7,p=0,a=y.F(a),q=d-1;0<q;q-=2)for(6==q&&--q;;){for(n=0;2>n;n+=1)null==r[k][q-n]&&(l=!1,p<b.length&&(l=1==(1&b[p]>>>m)),a(k,q-n)&&(l=!l),r[k][q-n]=l,--m,-1==m&&(p+=1,m=7));if(k+=f,0>k||d<=k){k-=f,f=-f;break}}}var h=A[a],r=null,d=0,g=null,x=[],u={u:function(b){b=w(b),x.push(b),g=null},a:function(b,a){if(0>b||d<=b||0>a||d<=a)throw Error(b+","+a);return r[b][a]},h:function(){return d},J:function(){for(var a=0,h=0,c=0;8>c;c+=1){b(!0,c);var d=y.D(u);(0==c||a>d)&&(a=d,h=c)}b(!1,h)}};return u}function z(c,a){if("undefined"==typeof c.length)throw Error(c.length+"/"+a);var e=function(){for(var b=0;b<c.length&&0==c[b];)b+=1;for(var r=Array(c.length-b+a),d=0;d<c.length-b;d+=1)r[d]=c[d+b];return r}(),b={c:function(b){return e[b]},b:function(){return e.length},multiply:function(a){for(var h=Array(b.b()+a.b()-1),c=0;c<b.b();c+=1)for(var g=0;g<a.b();g+=1)h[c+g]^=v.i(v.g(b.c(c))+v.g(a.c(g)));return z(h,0)},l:function(a){if(0>b.b()-a.b())return b;for(var c=v.g(b.c(0))-v.g(a.c(0)),h=Array(b.b()),g=0;g<b.b();g+=1)h[g]=b.c(g);for(g=0;g<a.b();g+=1)h[g]^=v.i(v.g(a.c(g))+c);return z(h,0).l(a)}};return b}C.s=function(c){for(var a=[],e=0,b;e<c.length;e++)b=c.charCodeAt(e),128>b?a.push(b):2048>b?a.push(192|b>>6,128|63&b):55296>b||57344<=b?a.push(224|b>>12,128|63&b>>6,128|63&b):(e++,b=65536+((1023&b)<<10|1023&c.charCodeAt(e)),a.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return a};var A={L:1,M:0,Q:3,H:2},y=function(){function c(b){for(var a=0;0!=b;)a+=1,b>>>=1;return a}var a=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],e={w:function(b){for(var a=b<<10;0<=c(a)-c(1335);)a^=1335<<c(a)-c(1335);return 21522^(b<<10|a)},A:function(b){for(var a=b<<12;0<=c(a)-c(7973);)a^=7973<<c(a)-c(7973);return b<<12|a},G:function(b){return a[b-1]},F:function(b){switch(b){case 0:return function(b,a){return 0==(b+a)%2};case 1:return function(b){return 0==b%2};case 2:return function(b,a){return 0==a%3};case 3:return function(b,a){return 0==(b+a)%3};case 4:return function(b,a){return 0==(_Mathfloor7(b/2)+_Mathfloor7(a/3))%2};case 5:return function(b,a){return 0==b*a%2+b*a%3};case 6:return function(b,a){return 0==(b*a%2+b*a%3)%2};case 7:return function(b,a){return 0==(b*a%3+(b+a)%2)%2};default:throw Error("bad maskPattern:"+b)}},C:function(b){for(var a=z([1],0),c=0;c<b;c+=1)a=a.multiply(z([1,v.i(c)],0));return a},f:function(b,a){if(4!=b||1>a||40<a)throw Error("mode: "+b+"; type: "+a);return 10>a?8:16},D:function(b){for(var a=b.h(),c=0,d=0;d<a;d+=1)for(var g=0;g<a;g+=1){for(var e=0,t=b.a(d,g),p=-1;1>=p;p+=1)if(!(0>d+p||a<=d+p))for(var q=-1;1>=q;q+=1)0>g+q||a<=g+q||(0!=p||0!=q)&&t==b.a(d+p,g+q)&&(e+=1);5<e&&(c+=3+e-5)}for(d=0;d<a-1;d+=1)for(g=0;g<a-1;g+=1)(e=0,b.a(d,g)&&(e+=1),b.a(d+1,g)&&(e+=1),b.a(d,g+1)&&(e+=1),b.a(d+1,g+1)&&(e+=1),0==e||4==e)&&(c+=3);for(d=0;d<a;d+=1)for(g=0;g<a-6;g+=1)b.a(d,g)&&!b.a(d,g+1)&&b.a(d,g+2)&&b.a(d,g+3)&&b.a(d,g+4)&&!b.a(d,g+5)&&b.a(d,g+6)&&(c+=40);for(g=0;g<a;g+=1)for(d=0;d<a-6;d+=1)b.a(d,g)&&!b.a(d+1,g)&&b.a(d+2,g)&&b.a(d+3,g)&&b.a(d+4,g)&&!b.a(d+5,g)&&b.a(d+6,g)&&(c+=40);for(g=e=0;g<a;g+=1)for(d=0;d<a;d+=1)b.a(d,g)&&(e+=1);return c+=10*(Math.abs(100*e/a/a-50)/5)}};return e}(),v=function(){for(var c=Array(256),a=Array(256),e=0;8>e;e+=1)c[e]=1<<e;for(e=8;256>e;e+=1)c[e]=c[e-4]^c[e-5]^c[e-6]^c[e-8];for(e=0;255>e;e+=1)a[c[e]]=e;return{g:function(b){if(1>b)throw Error("glog("+b+")");return a[b]},i:function(b){for(;0>b;)b+=255;for(;256<=b;)b-=255;return c[b]}}}(),t=function(){function c(b,c){return c===A.L?a[4*(b-1)]:c===A.M?a[4*(b-1)+1]:c===A.Q?a[4*(b-1)+2]:c===A.H?a[4*(b-1)+3]:void 0}var a=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12,7,37,13],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],e={I:function(b,a){var e=c(b,a);if("undefined"==typeof e)throw Error("bad rs block @ typeNumber:"+b+"/errorCorrectLevel:"+a);b=e.length/3,a=[];for(var d=0;d<b;d+=1)for(var g=e[3*d],h=e[3*d+1],t=e[3*d+2],p=0;p<g;p+=1){var q=t,f={};f.o=h,f.j=q,a.push(f)}return a}};return e}();return C}());var QrCreator$1=QrCreator,SlQrCode=class extends ShoelaceElement{constructor(){super(...arguments),this.value="",this.label="",this.size=128,this.fill="black",this.background="white",this.radius=0,this.errorCorrection="H"}firstUpdated(){this.generate()}generate(){this.hasUpdated&&QrCreator$1.render({text:this.value,radius:this.radius,ecLevel:this.errorCorrection,fill:this.fill,background:this.background,size:2*this.size},this.canvas)}render(){var _a;return x$1` + <canvas + part="base" + class="qr-code" + role="img" + aria-label=${0<(null==(_a=this.label)?void 0:_a.length)?this.label:this.value} + style=${o$3({width:`${this.size}px`,height:`${this.size}px`})} + ></canvas> + `}};SlQrCode.styles=[component_styles_default,qr_code_styles_default],__decorateClass([e$6("canvas")],SlQrCode.prototype,"canvas",2),__decorateClass([n$5()],SlQrCode.prototype,"value",2),__decorateClass([n$5()],SlQrCode.prototype,"label",2),__decorateClass([n$5({type:Number})],SlQrCode.prototype,"size",2),__decorateClass([n$5()],SlQrCode.prototype,"fill",2),__decorateClass([n$5()],SlQrCode.prototype,"background",2),__decorateClass([n$5({type:Number})],SlQrCode.prototype,"radius",2),__decorateClass([n$5({attribute:"error-correction"})],SlQrCode.prototype,"errorCorrection",2),__decorateClass([watch(["background","errorCorrection","fill","radius","size","value"])],SlQrCode.prototype,"generate",1),SlQrCode.define("sl-qr-code");var menu_label_styles_default=i$7` + :host { + display: block; + } + + .menu-label { + display: inline-block; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-small); + font-weight: var(--sl-font-weight-semibold); + line-height: var(--sl-line-height-normal); + letter-spacing: var(--sl-letter-spacing-normal); + color: var(--sl-color-neutral-500); + padding: var(--sl-spacing-2x-small) var(--sl-spacing-x-large); + user-select: none; + -webkit-user-select: none; + } +`,SlMenuLabel=class extends ShoelaceElement{render(){return x$1` <slot part="base" class="menu-label"></slot> `}};SlMenuLabel.styles=[component_styles_default,menu_label_styles_default],SlMenuLabel.define("sl-menu-label");var mutation_observer_styles_default=i$7` + :host { + display: contents; + } +`,SlMutationObserver=class extends ShoelaceElement{constructor(){super(...arguments),this.attrOldValue=!1,this.charData=!1,this.charDataOldValue=!1,this.childList=!1,this.disabled=!1,this.handleMutation=mutationList=>{this.emit("sl-mutation",{detail:{mutationList}})}}connectedCallback(){super.connectedCallback(),this.mutationObserver=new MutationObserver(this.handleMutation),this.disabled||this.startObserver()}disconnectedCallback(){super.disconnectedCallback(),this.stopObserver()}startObserver(){const observeAttributes="string"==typeof this.attr&&0<this.attr.length,attributeFilter=observeAttributes&&"*"!==this.attr?this.attr.split(" "):void 0;try{this.mutationObserver.observe(this,{subtree:!0,childList:this.childList,attributes:observeAttributes,attributeFilter,attributeOldValue:this.attrOldValue,characterData:this.charData,characterDataOldValue:this.charDataOldValue})}catch(e){}}stopObserver(){this.mutationObserver.disconnect()}handleDisabledChange(){this.disabled?this.stopObserver():this.startObserver()}handleChange(){this.stopObserver(),this.startObserver()}render(){return x$1` <slot></slot> `}};SlMutationObserver.styles=[component_styles_default,mutation_observer_styles_default],__decorateClass([n$5({reflect:!0})],SlMutationObserver.prototype,"attr",2),__decorateClass([n$5({attribute:"attr-old-value",type:Boolean,reflect:!0})],SlMutationObserver.prototype,"attrOldValue",2),__decorateClass([n$5({attribute:"char-data",type:Boolean,reflect:!0})],SlMutationObserver.prototype,"charData",2),__decorateClass([n$5({attribute:"char-data-old-value",type:Boolean,reflect:!0})],SlMutationObserver.prototype,"charDataOldValue",2),__decorateClass([n$5({attribute:"child-list",type:Boolean,reflect:!0})],SlMutationObserver.prototype,"childList",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlMutationObserver.prototype,"disabled",2),__decorateClass([watch("disabled")],SlMutationObserver.prototype,"handleDisabledChange",1),__decorateClass([watch("attr",{waitUntilFirstUpdate:!0}),watch("attr-old-value",{waitUntilFirstUpdate:!0}),watch("char-data",{waitUntilFirstUpdate:!0}),watch("char-data-old-value",{waitUntilFirstUpdate:!0}),watch("childList",{waitUntilFirstUpdate:!0})],SlMutationObserver.prototype,"handleChange",1),SlMutationObserver.define("sl-mutation-observer");var image_comparer_styles_default=i$7` + :host { + --divider-width: 2px; + --handle-size: 2.5rem; + + display: inline-block; + position: relative; + } + + .image-comparer { + max-width: 100%; + max-height: 100%; + overflow: hidden; + } + + .image-comparer__before, + .image-comparer__after { + display: block; + pointer-events: none; + } + + .image-comparer__before::slotted(img), + .image-comparer__after::slotted(img), + .image-comparer__before::slotted(svg), + .image-comparer__after::slotted(svg) { + display: block; + max-width: 100% !important; + height: auto; + } + + .image-comparer__after { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + } + + .image-comparer__divider { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + width: var(--divider-width); + height: 100%; + background-color: var(--sl-color-neutral-0); + translate: calc(var(--divider-width) / -2); + cursor: ew-resize; + } + + .image-comparer__handle { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: calc(50% - (var(--handle-size) / 2)); + width: var(--handle-size); + height: var(--handle-size); + background-color: var(--sl-color-neutral-0); + border-radius: var(--sl-border-radius-circle); + font-size: calc(var(--handle-size) * 0.5); + color: var(--sl-color-neutral-700); + cursor: inherit; + z-index: 10; + } + + .image-comparer__handle:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } +`,SlImageComparer=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.position=50}handleDrag(event){const{width}=this.base.getBoundingClientRect(),isRtl="rtl"===this.localize.dir();event.preventDefault(),drag(this.base,{onMove:x=>{this.position=parseFloat(clamp(100*(x/width),0,100).toFixed(2)),isRtl&&(this.position=100-this.position)},initialEvent:event})}handleKeyDown(event){const isLtr="ltr"===this.localize.dir(),isRtl="rtl"===this.localize.dir();if(["ArrowLeft","ArrowRight","Home","End"].includes(event.key)){const incr=event.shiftKey?10:1;let newPosition=this.position;event.preventDefault(),(isLtr&&"ArrowLeft"===event.key||isRtl&&"ArrowRight"===event.key)&&(newPosition-=incr),(isLtr&&"ArrowRight"===event.key||isRtl&&"ArrowLeft"===event.key)&&(newPosition+=incr),"Home"===event.key&&(newPosition=0),"End"===event.key&&(newPosition=100),newPosition=clamp(newPosition,0,100),this.position=newPosition}}handlePositionChange(){this.emit("sl-change")}render(){const isRtl="rtl"===this.localize.dir();return x$1` + <div + part="base" + id="image-comparer" + class=${e$2({"image-comparer":!0,"image-comparer--rtl":isRtl})} + @keydown=${this.handleKeyDown} + > + <div class="image-comparer__image"> + <div part="before" class="image-comparer__before"> + <slot name="before"></slot> + </div> + + <div + part="after" + class="image-comparer__after" + style=${o$3({clipPath:isRtl?`inset(0 0 0 ${100-this.position}%)`:`inset(0 ${100-this.position}% 0 0)`})} + > + <slot name="after"></slot> + </div> + </div> + + <div + part="divider" + class="image-comparer__divider" + style=${o$3({left:isRtl?`${100-this.position}%`:`${this.position}%`})} + @mousedown=${this.handleDrag} + @touchstart=${this.handleDrag} + > + <div + part="handle" + class="image-comparer__handle" + role="scrollbar" + aria-valuenow=${this.position} + aria-valuemin="0" + aria-valuemax="100" + aria-controls="image-comparer" + tabindex="0" + > + <slot name="handle"> + <sl-icon library="system" name="grip-vertical"></sl-icon> + </slot> + </div> + </div> + </div> + `}};SlImageComparer.styles=[component_styles_default,image_comparer_styles_default],SlImageComparer.scopedElement={"sl-icon":SlIcon},__decorateClass([e$6(".image-comparer")],SlImageComparer.prototype,"base",2),__decorateClass([e$6(".image-comparer__handle")],SlImageComparer.prototype,"handle",2),__decorateClass([n$5({type:Number,reflect:!0})],SlImageComparer.prototype,"position",2),__decorateClass([watch("position",{waitUntilFirstUpdate:!0})],SlImageComparer.prototype,"handlePositionChange",1),SlImageComparer.define("sl-image-comparer");var include_styles_default=i$7` + :host { + display: block; + } +`,includeFiles=new Map;function requestInclude(src,mode="cors"){const prev=includeFiles.get(src);if(void 0!==prev)return Promise.resolve(prev);const fileDataPromise=fetch(src,{mode}).then(async response=>{const res={ok:response.ok,status:response.status,html:await response.text()};return includeFiles.set(src,res),res});return includeFiles.set(src,fileDataPromise),fileDataPromise}var SlInclude=class extends ShoelaceElement{constructor(){super(...arguments),this.mode="cors",this.allowScripts=!1}executeScript(script){const newScript=document.createElement("script");[...script.attributes].forEach(attr=>newScript.setAttribute(attr.name,attr.value)),newScript.textContent=script.textContent,script.parentNode.replaceChild(newScript,script)}async handleSrcChange(){try{const src=this.src,file=await requestInclude(src,this.mode);if(src!==this.src)return;if(!file.ok)return void this.emit("sl-error",{detail:{status:file.status}});this.innerHTML=file.html,this.allowScripts&&[...this.querySelectorAll("script")].forEach(script=>this.executeScript(script)),this.emit("sl-load")}catch(e){this.emit("sl-error",{detail:{status:-1}})}}render(){return x$1`<slot></slot>`}};SlInclude.styles=[component_styles_default,include_styles_default],__decorateClass([n$5()],SlInclude.prototype,"src",2),__decorateClass([n$5()],SlInclude.prototype,"mode",2),__decorateClass([n$5({attribute:"allow-scripts",type:Boolean})],SlInclude.prototype,"allowScripts",2),__decorateClass([watch("src")],SlInclude.prototype,"handleSrcChange",1),SlInclude.define("sl-include");var SlFormatBytes=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.value=0,this.unit="byte",this.display="short"}render(){if(isNaN(this.value))return"";const bitPrefixes=["","kilo","mega","giga","tera"],bytePrefixes=["","kilo","mega","giga","tera","peta"],prefix="bit"===this.unit?bitPrefixes:bytePrefixes,index=Math.max(0,Math.min(Math.floor(Math.log10(this.value)/3),prefix.length-1)),unit=prefix[index]+this.unit,valueToFormat=parseFloat((this.value/Math.pow(1e3,index)).toPrecision(3));return this.localize.number(valueToFormat,{style:"unit",unit,unitDisplay:this.display})}};__decorateClass([n$5({type:Number})],SlFormatBytes.prototype,"value",2),__decorateClass([n$5()],SlFormatBytes.prototype,"unit",2),__decorateClass([n$5()],SlFormatBytes.prototype,"display",2),SlFormatBytes.define("sl-format-bytes");var SlFormatDate=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.date=new Date,this.hourFormat="auto"}render(){const date=new Date(this.date),hour12="auto"===this.hourFormat?void 0:"12"===this.hourFormat;return isNaN(date.getMilliseconds())?void 0:x$1` + <time datetime=${date.toISOString()}> + ${this.localize.date(date,{weekday:this.weekday,era:this.era,year:this.year,month:this.month,day:this.day,hour:this.hour,minute:this.minute,second:this.second,timeZoneName:this.timeZoneName,timeZone:this.timeZone,hour12})} + </time> + `}};__decorateClass([n$5()],SlFormatDate.prototype,"date",2),__decorateClass([n$5()],SlFormatDate.prototype,"weekday",2),__decorateClass([n$5()],SlFormatDate.prototype,"era",2),__decorateClass([n$5()],SlFormatDate.prototype,"year",2),__decorateClass([n$5()],SlFormatDate.prototype,"month",2),__decorateClass([n$5()],SlFormatDate.prototype,"day",2),__decorateClass([n$5()],SlFormatDate.prototype,"hour",2),__decorateClass([n$5()],SlFormatDate.prototype,"minute",2),__decorateClass([n$5()],SlFormatDate.prototype,"second",2),__decorateClass([n$5({attribute:"time-zone-name"})],SlFormatDate.prototype,"timeZoneName",2),__decorateClass([n$5({attribute:"time-zone"})],SlFormatDate.prototype,"timeZone",2),__decorateClass([n$5({attribute:"hour-format"})],SlFormatDate.prototype,"hourFormat",2),SlFormatDate.define("sl-format-date");var SlFormatNumber=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.value=0,this.type="decimal",this.noGrouping=!1,this.currency="USD",this.currencyDisplay="symbol"}render(){return isNaN(this.value)?"":this.localize.number(this.value,{style:this.type,currency:this.currency,currencyDisplay:this.currencyDisplay,useGrouping:!this.noGrouping,minimumIntegerDigits:this.minimumIntegerDigits,minimumFractionDigits:this.minimumFractionDigits,maximumFractionDigits:this.maximumFractionDigits,minimumSignificantDigits:this.minimumSignificantDigits,maximumSignificantDigits:this.maximumSignificantDigits})}};__decorateClass([n$5({type:Number})],SlFormatNumber.prototype,"value",2),__decorateClass([n$5()],SlFormatNumber.prototype,"type",2),__decorateClass([n$5({attribute:"no-grouping",type:Boolean})],SlFormatNumber.prototype,"noGrouping",2),__decorateClass([n$5()],SlFormatNumber.prototype,"currency",2),__decorateClass([n$5({attribute:"currency-display"})],SlFormatNumber.prototype,"currencyDisplay",2),__decorateClass([n$5({attribute:"minimum-integer-digits",type:Number})],SlFormatNumber.prototype,"minimumIntegerDigits",2),__decorateClass([n$5({attribute:"minimum-fraction-digits",type:Number})],SlFormatNumber.prototype,"minimumFractionDigits",2),__decorateClass([n$5({attribute:"maximum-fraction-digits",type:Number})],SlFormatNumber.prototype,"maximumFractionDigits",2),__decorateClass([n$5({attribute:"minimum-significant-digits",type:Number})],SlFormatNumber.prototype,"minimumSignificantDigits",2),__decorateClass([n$5({attribute:"maximum-significant-digits",type:Number})],SlFormatNumber.prototype,"maximumSignificantDigits",2),SlFormatNumber.define("sl-format-number");var divider_styles_default=i$7` + :host { + --color: var(--sl-panel-border-color); + --width: var(--sl-panel-border-width); + --spacing: var(--sl-spacing-medium); + } + + :host(:not([vertical])) { + display: block; + border-top: solid var(--width) var(--color); + margin: var(--spacing) 0; + } + + :host([vertical]) { + display: inline-block; + height: 100%; + border-left: solid var(--width) var(--color); + margin: 0 var(--spacing); + } +`,SlDivider=class extends ShoelaceElement{constructor(){super(...arguments),this.vertical=!1}connectedCallback(){super.connectedCallback(),this.setAttribute("role","separator")}handleVerticalChange(){this.setAttribute("aria-orientation",this.vertical?"vertical":"horizontal")}};SlDivider.styles=[component_styles_default,divider_styles_default],__decorateClass([n$5({type:Boolean,reflect:!0})],SlDivider.prototype,"vertical",2),__decorateClass([watch("vertical")],SlDivider.prototype,"handleVerticalChange",1),SlDivider.define("sl-divider");var copy_button_styles_default=i$7` + :host { + --error-color: var(--sl-color-danger-600); + --success-color: var(--sl-color-success-600); + + display: inline-block; + } + + .copy-button__button { + flex: 0 0 auto; + display: flex; + align-items: center; + background: none; + border: none; + border-radius: var(--sl-border-radius-medium); + font-size: inherit; + color: inherit; + padding: var(--sl-spacing-x-small); + cursor: pointer; + transition: var(--sl-transition-x-fast) color; + } + + .copy-button--success .copy-button__button { + color: var(--success-color); + } + + .copy-button--error .copy-button__button { + color: var(--error-color); + } + + .copy-button__button:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .copy-button__button[disabled] { + opacity: 0.5; + cursor: not-allowed !important; + } + + slot { + display: inline-flex; + } +`,SlCopyButton=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.isCopying=!1,this.status="rest",this.value="",this.from="",this.disabled=!1,this.copyLabel="",this.successLabel="",this.errorLabel="",this.feedbackDuration=1e3,this.tooltipPlacement="top",this.hoist=!1}async handleCopy(){if(this.disabled||this.isCopying)return;this.isCopying=!0;let valueToCopy=this.value;if(this.from){const root=this.getRootNode(),isProperty=this.from.includes("."),isAttribute=this.from.includes("[")&&this.from.includes("]");let id=this.from,field="";isProperty?[id,field]=this.from.trim().split("."):isAttribute&&([id,field]=this.from.trim().replace(/\]$/,"").split("["));const target="getElementById"in root?root.getElementById(id):null;target?isAttribute?valueToCopy=target.getAttribute(field)||"":isProperty?valueToCopy=target[field]||"":valueToCopy=target.textContent||"":(this.showStatus("error"),this.emit("sl-error"))}if(!valueToCopy)this.showStatus("error"),this.emit("sl-error");else try{await navigator.clipboard.writeText(valueToCopy),this.showStatus("success"),this.emit("sl-copy",{detail:{value:valueToCopy}})}catch(error){this.showStatus("error"),this.emit("sl-error")}}async showStatus(status){const copyLabel=this.copyLabel||this.localize.term("copy"),successLabel=this.successLabel||this.localize.term("copied"),errorLabel=this.errorLabel||this.localize.term("error"),iconToShow="success"===status?this.successIcon:this.errorIcon,showAnimation=getAnimation(this,"copy.in",{dir:"ltr"}),hideAnimation=getAnimation(this,"copy.out",{dir:"ltr"});this.tooltip.content="success"===status?successLabel:errorLabel,await this.copyIcon.animate(hideAnimation.keyframes,hideAnimation.options).finished,this.copyIcon.hidden=!0,this.status=status,iconToShow.hidden=!1,await iconToShow.animate(showAnimation.keyframes,showAnimation.options).finished,setTimeout(async()=>{await iconToShow.animate(hideAnimation.keyframes,hideAnimation.options).finished,iconToShow.hidden=!0,this.status="rest",this.copyIcon.hidden=!1,await this.copyIcon.animate(showAnimation.keyframes,showAnimation.options).finished,this.tooltip.content=copyLabel,this.isCopying=!1},this.feedbackDuration)}render(){const copyLabel=this.copyLabel||this.localize.term("copy");return x$1` + <sl-tooltip + class=${e$2({"copy-button":!0,"copy-button--success":"success"===this.status,"copy-button--error":"error"===this.status})} + content=${copyLabel} + placement=${this.tooltipPlacement} + ?disabled=${this.disabled} + ?hoist=${this.hoist} + exportparts=" + base:tooltip__base, + base__popup:tooltip__base__popup, + base__arrow:tooltip__base__arrow, + body:tooltip__body + " + > + <button + class="copy-button__button" + part="button" + type="button" + ?disabled=${this.disabled} + @click=${this.handleCopy} + > + <slot part="copy-icon" name="copy-icon"> + <sl-icon library="system" name="copy"></sl-icon> + </slot> + <slot part="success-icon" name="success-icon" hidden> + <sl-icon library="system" name="check"></sl-icon> + </slot> + <slot part="error-icon" name="error-icon" hidden> + <sl-icon library="system" name="x-lg"></sl-icon> + </slot> + </button> + </sl-tooltip> + `}};SlCopyButton.styles=[component_styles_default,copy_button_styles_default],SlCopyButton.dependencies={"sl-icon":SlIcon,"sl-tooltip":SlTooltip},__decorateClass([e$6("slot[name=\"copy-icon\"]")],SlCopyButton.prototype,"copyIcon",2),__decorateClass([e$6("slot[name=\"success-icon\"]")],SlCopyButton.prototype,"successIcon",2),__decorateClass([e$6("slot[name=\"error-icon\"]")],SlCopyButton.prototype,"errorIcon",2),__decorateClass([e$6("sl-tooltip")],SlCopyButton.prototype,"tooltip",2),__decorateClass([r$6()],SlCopyButton.prototype,"isCopying",2),__decorateClass([r$6()],SlCopyButton.prototype,"status",2),__decorateClass([n$5()],SlCopyButton.prototype,"value",2),__decorateClass([n$5()],SlCopyButton.prototype,"from",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCopyButton.prototype,"disabled",2),__decorateClass([n$5({attribute:"copy-label"})],SlCopyButton.prototype,"copyLabel",2),__decorateClass([n$5({attribute:"success-label"})],SlCopyButton.prototype,"successLabel",2),__decorateClass([n$5({attribute:"error-label"})],SlCopyButton.prototype,"errorLabel",2),__decorateClass([n$5({attribute:"feedback-duration",type:Number})],SlCopyButton.prototype,"feedbackDuration",2),__decorateClass([n$5({attribute:"tooltip-placement"})],SlCopyButton.prototype,"tooltipPlacement",2),__decorateClass([n$5({type:Boolean})],SlCopyButton.prototype,"hoist",2),setDefaultAnimation("copy.in",{keyframes:[{scale:".25",opacity:".25"},{scale:"1",opacity:"1"}],options:{duration:100}}),setDefaultAnimation("copy.out",{keyframes:[{scale:"1",opacity:"1"},{scale:".25",opacity:"0"}],options:{duration:100}}),SlCopyButton.define("sl-copy-button");var color_picker_styles_default=i$7` + :host { + --grid-width: 280px; + --grid-height: 200px; + --grid-handle-size: 16px; + --slider-height: 15px; + --slider-handle-size: 17px; + --swatch-size: 25px; + + display: inline-block; + } + + .color-picker { + width: var(--grid-width); + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + color: var(--color); + background-color: var(--sl-panel-background-color); + border-radius: var(--sl-border-radius-medium); + user-select: none; + -webkit-user-select: none; + } + + .color-picker--inline { + border: solid var(--sl-panel-border-width) var(--sl-panel-border-color); + } + + .color-picker--inline:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .color-picker__grid { + position: relative; + height: var(--grid-height); + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%), + linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%); + border-top-left-radius: var(--sl-border-radius-medium); + border-top-right-radius: var(--sl-border-radius-medium); + cursor: crosshair; + forced-color-adjust: none; + } + + .color-picker__grid-handle { + position: absolute; + width: var(--grid-handle-size); + height: var(--grid-handle-size); + border-radius: 50%; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); + border: solid 2px white; + margin-top: calc(var(--grid-handle-size) / -2); + margin-left: calc(var(--grid-handle-size) / -2); + transition: var(--sl-transition-fast) scale; + } + + .color-picker__grid-handle--dragging { + cursor: none; + scale: 1.5; + } + + .color-picker__grid-handle:focus-visible { + outline: var(--sl-focus-ring); + } + + .color-picker__controls { + padding: var(--sl-spacing-small); + display: flex; + align-items: center; + } + + .color-picker__sliders { + flex: 1 1 auto; + } + + .color-picker__slider { + position: relative; + height: var(--slider-height); + border-radius: var(--sl-border-radius-pill); + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + forced-color-adjust: none; + } + + .color-picker__slider:not(:last-of-type) { + margin-bottom: var(--sl-spacing-small); + } + + .color-picker__slider-handle { + position: absolute; + top: calc(50% - var(--slider-handle-size) / 2); + width: var(--slider-handle-size); + height: var(--slider-handle-size); + background-color: white; + border-radius: 50%; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); + margin-left: calc(var(--slider-handle-size) / -2); + } + + .color-picker__slider-handle:focus-visible { + outline: var(--sl-focus-ring); + } + + .color-picker__hue { + background-image: linear-gradient( + to right, + rgb(255, 0, 0) 0%, + rgb(255, 255, 0) 17%, + rgb(0, 255, 0) 33%, + rgb(0, 255, 255) 50%, + rgb(0, 0, 255) 67%, + rgb(255, 0, 255) 83%, + rgb(255, 0, 0) 100% + ); + } + + .color-picker__alpha .color-picker__alpha-gradient { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: inherit; + } + + .color-picker__preview { + flex: 0 0 auto; + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + width: 2.25rem; + height: 2.25rem; + border: none; + border-radius: var(--sl-border-radius-circle); + background: none; + margin-left: var(--sl-spacing-small); + cursor: copy; + forced-color-adjust: none; + } + + .color-picker__preview:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: inherit; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); + + /* We use a custom property in lieu of currentColor because of https://bugs.webkit.org/show_bug.cgi?id=216780 */ + background-color: var(--preview-color); + } + + .color-picker__preview:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .color-picker__preview-color { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: solid 1px rgba(0, 0, 0, 0.125); + } + + .color-picker__preview-color--copied { + animation: pulse 0.75s; + } + + @keyframes pulse { + 0% { + box-shadow: 0 0 0 0 var(--sl-color-primary-500); + } + 70% { + box-shadow: 0 0 0 0.5rem transparent; + } + 100% { + box-shadow: 0 0 0 0 transparent; + } + } + + .color-picker__user-input { + display: flex; + padding: 0 var(--sl-spacing-small) var(--sl-spacing-small) var(--sl-spacing-small); + } + + .color-picker__user-input sl-input { + min-width: 0; /* fix input width in Safari */ + flex: 1 1 auto; + } + + .color-picker__user-input sl-button-group { + margin-left: var(--sl-spacing-small); + } + + .color-picker__user-input sl-button { + min-width: 3.25rem; + max-width: 3.25rem; + font-size: 1rem; + } + + .color-picker__swatches { + display: grid; + grid-template-columns: repeat(8, 1fr); + grid-gap: 0.5rem; + justify-items: center; + border-top: solid 1px var(--sl-color-neutral-200); + padding: var(--sl-spacing-small); + forced-color-adjust: none; + } + + .color-picker__swatch { + position: relative; + width: var(--swatch-size); + height: var(--swatch-size); + border-radius: var(--sl-border-radius-small); + } + + .color-picker__swatch .color-picker__swatch-color { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: solid 1px rgba(0, 0, 0, 0.125); + border-radius: inherit; + cursor: pointer; + } + + .color-picker__swatch:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .color-picker__transparent-bg { + background-image: linear-gradient(45deg, var(--sl-color-neutral-300) 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, var(--sl-color-neutral-300) 75%), + linear-gradient(45deg, transparent 75%, var(--sl-color-neutral-300) 75%), + linear-gradient(45deg, var(--sl-color-neutral-300) 25%, transparent 25%); + background-size: 10px 10px; + background-position: + 0 0, + 0 0, + -5px -5px, + 5px 5px; + } + + .color-picker--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .color-picker--disabled .color-picker__grid, + .color-picker--disabled .color-picker__grid-handle, + .color-picker--disabled .color-picker__slider, + .color-picker--disabled .color-picker__slider-handle, + .color-picker--disabled .color-picker__preview, + .color-picker--disabled .color-picker__swatch, + .color-picker--disabled .color-picker__swatch-color { + pointer-events: none; + } + + /* + * Color dropdown + */ + + .color-dropdown::part(panel) { + max-height: none; + background-color: var(--sl-panel-background-color); + border: solid var(--sl-panel-border-width) var(--sl-panel-border-color); + border-radius: var(--sl-border-radius-medium); + overflow: visible; + } + + .color-dropdown__trigger { + display: inline-block; + position: relative; + background-color: transparent; + border: none; + cursor: pointer; + forced-color-adjust: none; + } + + .color-dropdown__trigger.color-dropdown__trigger--small { + width: var(--sl-input-height-small); + height: var(--sl-input-height-small); + border-radius: var(--sl-border-radius-circle); + } + + .color-dropdown__trigger.color-dropdown__trigger--medium { + width: var(--sl-input-height-medium); + height: var(--sl-input-height-medium); + border-radius: var(--sl-border-radius-circle); + } + + .color-dropdown__trigger.color-dropdown__trigger--large { + width: var(--sl-input-height-large); + height: var(--sl-input-height-large); + border-radius: var(--sl-border-radius-circle); + } + + .color-dropdown__trigger:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: inherit; + background-color: currentColor; + box-shadow: + inset 0 0 0 2px var(--sl-input-border-color), + inset 0 0 0 4px var(--sl-color-neutral-0); + } + + .color-dropdown__trigger--empty:before { + background-color: transparent; + } + + .color-dropdown__trigger:focus-visible { + outline: none; + } + + .color-dropdown__trigger:focus-visible:not(.color-dropdown__trigger--disabled) { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .color-dropdown__trigger.color-dropdown__trigger--disabled { + opacity: 0.5; + cursor: not-allowed; + } +`;function bound01(n,max){var _Mathmin6=Math.min,_Mathmax1=Math.max,_Mathabs4=Math.abs;isOnePointZero(n)&&(n="100%");const isPercent=isPercentage(n);return(n=360===max?n:_Mathmin6(max,_Mathmax1(0,parseFloat(n))),isPercent&&(n=parseInt(n*max+"",10)/100),1e-6>_Mathabs4(n-max))?1:(n=360===max?(0>n?n%max+max:n%max)/parseFloat(max+""):n%max/parseFloat(max+""),n)}function clamp01(val){return Math.min(1,Math.max(0,val))}function isOnePointZero(n){return"string"==typeof n&&-1!==n.indexOf(".")&&1===parseFloat(n)}function isPercentage(n){return"string"==typeof n&&-1!==n.indexOf("%")}function boundAlpha(a){return a=parseFloat(a),(isNaN(a)||0>a||1<a)&&(a=1),a}function convertToPercentage(n){return 1>=+n?`${100*+n}%`:n}function pad2(c){return 1===c.length?"0"+c:c+""}function rgbToRgb(r,g,b){return{r:255*bound01(r,255),g:255*bound01(g,255),b:255*bound01(b,255)}}function rgbToHsl(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);const max=Math.max(r,g,b),min=Math.min(r,g,b);let h=0,s=0;const l=(max+min)/2;if(max===min)s=0,h=0;else{const d=max-min;s=.5<l?d/(2-max-min):d/(max+min);max===r?h=(g-b)/d+(g<b?6:0):max===g?h=(b-r)/d+2:max===b?h=(r-g)/d+4:void 0;h/=6}return{h,s,l}}function hue2rgb(p,q,t){return 0>t&&(t+=1),1<t&&(t-=1),t<1/6?p+(q-p)*(6*t):t<1/2?q:t<2/3?p+6*((q-p)*(2/3-t)):p}function hslToRgb(h,s,l){let r,g,b;if(h=bound01(h,360),s=bound01(s,100),l=bound01(l,100),0===s)g=l,b=l,r=l;else{const q=.5>l?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}return{r:255*r,g:255*g,b:255*b}}function rgbToHsv(r,g,b){var _Mathmin7=Math.min,_Mathmax10=Math.max;r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);const max=_Mathmax10(r,g,b),min=_Mathmin7(r,g,b);let h=0;const v=max,d=max-min,s=0===max?0:d/max;return max===min?h=0:(max===r?h=(g-b)/d+(g<b?6:0):max===g?h=(b-r)/d+2:max===b?h=(r-g)/d+4:void 0,h/=6),{h,s,v}}function hsvToRgb(h,s,v){h=6*bound01(h,360),s=bound01(s,100),v=bound01(v,100);const i=Math.floor(h),f=h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),mod=i%6,r=[v,q,p,p,t,v][mod],g=[t,v,v,q,p,p][mod],b=[p,p,t,v,v,q][mod];return{r:255*r,g:255*g,b:255*b}}function rgbToHex(r,g,b,allow3Char){var _Mathround5=Math.round;const hex=[pad2(_Mathround5(r).toString(16)),pad2(_Mathround5(g).toString(16)),pad2(_Mathround5(b).toString(16))];return allow3Char&&hex[0].startsWith(hex[0].charAt(1))&&hex[1].startsWith(hex[1].charAt(1))&&hex[2].startsWith(hex[2].charAt(1))?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0):hex.join("")}function rgbaToHex(r,g,b,a,allow4Char){var _Mathround6=Math.round;const hex=[pad2(_Mathround6(r).toString(16)),pad2(_Mathround6(g).toString(16)),pad2(_Mathround6(b).toString(16)),pad2(convertDecimalToHex(a))];return allow4Char&&hex[0].startsWith(hex[0].charAt(1))&&hex[1].startsWith(hex[1].charAt(1))&&hex[2].startsWith(hex[2].charAt(1))&&hex[3].startsWith(hex[3].charAt(1))?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0)+hex[3].charAt(0):hex.join("")}function cmykToRgb(c,m,y,k){const cConv=c/100,mConv=m/100,yConv=y/100,kConv=k/100,r=255*(1-cConv)*(1-kConv),g=255*(1-mConv)*(1-kConv),b=255*(1-yConv)*(1-kConv);return{r,g,b}}function rgbToCmyk(r,g,b){var _Mathmin8=Math.min,_Mathround7=Math.round;let c=1-r/255,m=1-g/255,y=1-b/255,k=_Mathmin8(c,m,y);return 1===k?(c=0,m=0,y=0):(c=100*((c-k)/(1-k)),m=100*((m-k)/(1-k)),y=100*((y-k)/(1-k))),k*=100,{c:_Mathround7(c),m:_Mathround7(m),y:_Mathround7(y),k:_Mathround7(k)}}function convertDecimalToHex(d){return Math.round(255*parseFloat(d)).toString(16)}function convertHexToDecimal(h){return parseIntFromHex(h)/255}function parseIntFromHex(val){return parseInt(val,16)}function numberInputToObject(color){return{r:color>>16,g:(65280&color)>>8,b:255&color}}const names={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",goldenrod:"#daa520",gold:"#ffd700",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavenderblush:"#fff0f5",lavender:"#e6e6fa",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};function inputToRGB(color){var _Mathmin9=Math.min,_Mathmax11=Math.max;let rgb={r:0,g:0,b:0},a=1,s=null,v=null,l=null,ok=!1,format=!1;return"string"==typeof color&&(color=stringInputToObject(color)),"object"==typeof color&&(isValidCSSUnit(color.r)&&isValidCSSUnit(color.g)&&isValidCSSUnit(color.b)?(rgb=rgbToRgb(color.r,color.g,color.b),ok=!0,format="%"===(color.r+"").substr(-1)?"prgb":"rgb"):isValidCSSUnit(color.h)&&isValidCSSUnit(color.s)&&isValidCSSUnit(color.v)?(s=convertToPercentage(color.s),v=convertToPercentage(color.v),rgb=hsvToRgb(color.h,s,v),ok=!0,format="hsv"):isValidCSSUnit(color.h)&&isValidCSSUnit(color.s)&&isValidCSSUnit(color.l)?(s=convertToPercentage(color.s),l=convertToPercentage(color.l),rgb=hslToRgb(color.h,s,l),ok=!0,format="hsl"):isValidCSSUnit(color.c)&&isValidCSSUnit(color.m)&&isValidCSSUnit(color.y)&&isValidCSSUnit(color.k)&&(rgb=cmykToRgb(color.c,color.m,color.y,color.k),ok=!0,format="cmyk"),Object.prototype.hasOwnProperty.call(color,"a")&&(a=color.a)),a=boundAlpha(a),{ok,format:color.format||format,r:_Mathmin9(255,_Mathmax11(rgb.r,0)),g:_Mathmin9(255,_Mathmax11(rgb.g,0)),b:_Mathmin9(255,_Mathmax11(rgb.b,0)),a}}const CSS_INTEGER="[-\\+]?\\d+%?",CSS_NUMBER="[-\\+]?\\d*\\.\\d+%?",CSS_UNIT="(?:"+CSS_NUMBER+")|(?:"+"[-\\+]?\\d+%?"+")",PERMISSIVE_MATCH3="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?",PERMISSIVE_MATCH4="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?",matchers={CSS_UNIT:new RegExp(CSS_UNIT),rgb:new RegExp("rgb"+PERMISSIVE_MATCH3),rgba:new RegExp("rgba"+PERMISSIVE_MATCH4),hsl:new RegExp("hsl"+PERMISSIVE_MATCH3),hsla:new RegExp("hsla"+PERMISSIVE_MATCH4),hsv:new RegExp("hsv"+PERMISSIVE_MATCH3),hsva:new RegExp("hsva"+PERMISSIVE_MATCH4),cmyk:new RegExp("cmyk"+PERMISSIVE_MATCH4),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/};function stringInputToObject(color){if(color=color.trim().toLowerCase(),0===color.length)return!1;let named=!1;if(names[color])color=names[color],named=!0;else if("transparent"===color)return{r:0,g:0,b:0,a:0,format:"name"};let match=matchers.rgb.exec(color);return match?{r:match[1],g:match[2],b:match[3]}:(match=matchers.rgba.exec(color),match)?{r:match[1],g:match[2],b:match[3],a:match[4]}:(match=matchers.hsl.exec(color),match)?{h:match[1],s:match[2],l:match[3]}:(match=matchers.hsla.exec(color),match)?{h:match[1],s:match[2],l:match[3],a:match[4]}:(match=matchers.hsv.exec(color),match)?{h:match[1],s:match[2],v:match[3]}:(match=matchers.hsva.exec(color),match)?{h:match[1],s:match[2],v:match[3],a:match[4]}:(match=matchers.cmyk.exec(color),match)?{c:match[1],m:match[2],y:match[3],k:match[4]}:(match=matchers.hex8.exec(color),match)?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),a:convertHexToDecimal(match[4]),format:named?"name":"hex8"}:(match=matchers.hex6.exec(color),match)?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?"name":"hex"}:(match=matchers.hex4.exec(color),match)?{r:parseIntFromHex(match[1]+match[1]),g:parseIntFromHex(match[2]+match[2]),b:parseIntFromHex(match[3]+match[3]),a:convertHexToDecimal(match[4]+match[4]),format:named?"name":"hex8"}:(match=matchers.hex3.exec(color),!!match&&{r:parseIntFromHex(match[1]+match[1]),g:parseIntFromHex(match[2]+match[2]),b:parseIntFromHex(match[3]+match[3]),format:named?"name":"hex"})}function isValidCSSUnit(color){var _NumberisNaN2=Number.isNaN;return"number"==typeof color?!_NumberisNaN2(color):matchers.CSS_UNIT.test(color)}class TinyColor{constructor(color="",opts={}){var _Mathround8=Math.round;if(color instanceof TinyColor)return color;"number"==typeof color&&(color=numberInputToObject(color)),this.originalInput=color;const rgb=inputToRGB(color);this.originalInput=color,this.r=rgb.r,this.g=rgb.g,this.b=rgb.b,this.a=rgb.a,this.roundA=_Mathround8(100*this.a)/100,this.format=opts.format??rgb.format,this.gradientType=opts.gradientType,1>this.r&&(this.r=_Mathround8(this.r)),1>this.g&&(this.g=_Mathround8(this.g)),1>this.b&&(this.b=_Mathround8(this.b)),this.isValid=rgb.ok}isDark(){return 128>this.getBrightness()}isLight(){return!this.isDark()}getBrightness(){const rgb=this.toRgb();return(299*rgb.r+587*rgb.g+114*rgb.b)/1e3}getLuminance(){var _Mathpow9=Math.pow;const rgb=this.toRgb();let R,G,B;const RsRGB=rgb.r/255,GsRGB=rgb.g/255,BsRGB=rgb.b/255;return R=.03928>=RsRGB?RsRGB/12.92:_Mathpow9((RsRGB+.055)/1.055,2.4),G=.03928>=GsRGB?GsRGB/12.92:_Mathpow9((GsRGB+.055)/1.055,2.4),B=.03928>=BsRGB?BsRGB/12.92:_Mathpow9((BsRGB+.055)/1.055,2.4),.2126*R+.7152*G+.0722*B}getAlpha(){return this.a}setAlpha(alpha){var _Mathround9=Math.round;return this.a=boundAlpha(alpha),this.roundA=_Mathround9(100*this.a)/100,this}isMonochrome(){const{s}=this.toHsl();return 0===s}toHsv(){const hsv=rgbToHsv(this.r,this.g,this.b);return{h:360*hsv.h,s:hsv.s,v:hsv.v,a:this.a}}toHsvString(){var _Mathround0=Math.round;const hsv=rgbToHsv(this.r,this.g,this.b),h=_Mathround0(360*hsv.h),s=_Mathround0(100*hsv.s),v=_Mathround0(100*hsv.v);return 1===this.a?`hsv(${h}, ${s}%, ${v}%)`:`hsva(${h}, ${s}%, ${v}%, ${this.roundA})`}toHsl(){const hsl=rgbToHsl(this.r,this.g,this.b);return{h:360*hsl.h,s:hsl.s,l:hsl.l,a:this.a}}toHslString(){var _Mathround1=Math.round;const hsl=rgbToHsl(this.r,this.g,this.b),h=_Mathround1(360*hsl.h),s=_Mathround1(100*hsl.s),l=_Mathround1(100*hsl.l);return 1===this.a?`hsl(${h}, ${s}%, ${l}%)`:`hsla(${h}, ${s}%, ${l}%, ${this.roundA})`}toHex(allow3Char=!1){return rgbToHex(this.r,this.g,this.b,allow3Char)}toHexString(allow3Char=!1){return"#"+this.toHex(allow3Char)}toHex8(allow4Char=!1){return rgbaToHex(this.r,this.g,this.b,this.a,allow4Char)}toHex8String(allow4Char=!1){return"#"+this.toHex8(allow4Char)}toHexShortString(allowShortChar=!1){return 1===this.a?this.toHexString(allowShortChar):this.toHex8String(allowShortChar)}toRgb(){var _Mathround10=Math.round;return{r:_Mathround10(this.r),g:_Mathround10(this.g),b:_Mathround10(this.b),a:this.a}}toRgbString(){var _Mathround11=Math.round;const r=_Mathround11(this.r),g=_Mathround11(this.g),b=_Mathround11(this.b);return 1===this.a?`rgb(${r}, ${g}, ${b})`:`rgba(${r}, ${g}, ${b}, ${this.roundA})`}toPercentageRgb(){const fmt=x=>`${Math.round(100*bound01(x,255))}%`;return{r:fmt(this.r),g:fmt(this.g),b:fmt(this.b),a:this.a}}toPercentageRgbString(){const rnd=x=>Math.round(100*bound01(x,255));return 1===this.a?`rgb(${rnd(this.r)}%, ${rnd(this.g)}%, ${rnd(this.b)}%)`:`rgba(${rnd(this.r)}%, ${rnd(this.g)}%, ${rnd(this.b)}%, ${this.roundA})`}toCmyk(){return{...rgbToCmyk(this.r,this.g,this.b)}}toCmykString(){const{c,m,y,k}=rgbToCmyk(this.r,this.g,this.b);return`cmyk(${c}, ${m}, ${y}, ${k})`}toName(){if(0===this.a)return"transparent";if(1>this.a)return!1;const hex="#"+rgbToHex(this.r,this.g,this.b,!1);for(const[key,value]of Object.entries(names))if(hex===value)return key;return!1}toString(format){const formatSet=!!format;format=format??this.format;let formattedString=!1;const hasAlpha=1>this.a&&0<=this.a,needsAlphaFormat=!formatSet&&hasAlpha&&(format.startsWith("hex")||"name"===format);return needsAlphaFormat?"name"===format&&0===this.a?this.toName():this.toRgbString():("rgb"===format&&(formattedString=this.toRgbString()),"prgb"===format&&(formattedString=this.toPercentageRgbString()),("hex"===format||"hex6"===format)&&(formattedString=this.toHexString()),"hex3"===format&&(formattedString=this.toHexString(!0)),"hex4"===format&&(formattedString=this.toHex8String(!0)),"hex8"===format&&(formattedString=this.toHex8String()),"name"===format&&(formattedString=this.toName()),"hsl"===format&&(formattedString=this.toHslString()),"hsv"===format&&(formattedString=this.toHsvString()),"cmyk"===format&&(formattedString=this.toCmykString()),formattedString||this.toHexString())}toNumber(){var _Mathround12=Math.round;return(_Mathround12(this.r)<<16)+(_Mathround12(this.g)<<8)+_Mathround12(this.b)}clone(){return new TinyColor(this.toString())}lighten(amount=10){const hsl=this.toHsl();return hsl.l+=amount/100,hsl.l=clamp01(hsl.l),new TinyColor(hsl)}brighten(amount=10){var _Mathmin0=Math.min,_Mathmax12=Math.max,_Mathround13=Math.round;const rgb=this.toRgb();return rgb.r=_Mathmax12(0,_Mathmin0(255,rgb.r-_Mathround13(255*-(amount/100)))),rgb.g=_Mathmax12(0,_Mathmin0(255,rgb.g-_Mathround13(255*-(amount/100)))),rgb.b=_Mathmax12(0,_Mathmin0(255,rgb.b-_Mathround13(255*-(amount/100)))),new TinyColor(rgb)}darken(amount=10){const hsl=this.toHsl();return hsl.l-=amount/100,hsl.l=clamp01(hsl.l),new TinyColor(hsl)}tint(amount=10){return this.mix("white",amount)}shade(amount=10){return this.mix("black",amount)}desaturate(amount=10){const hsl=this.toHsl();return hsl.s-=amount/100,hsl.s=clamp01(hsl.s),new TinyColor(hsl)}saturate(amount=10){const hsl=this.toHsl();return hsl.s+=amount/100,hsl.s=clamp01(hsl.s),new TinyColor(hsl)}greyscale(){return this.desaturate(100)}spin(amount){const hsl=this.toHsl(),hue=(hsl.h+amount)%360;return hsl.h=0>hue?360+hue:hue,new TinyColor(hsl)}mix(color,amount=50){const rgb1=this.toRgb(),rgb2=new TinyColor(color).toRgb(),p=amount/100,rgba={r:(rgb2.r-rgb1.r)*p+rgb1.r,g:(rgb2.g-rgb1.g)*p+rgb1.g,b:(rgb2.b-rgb1.b)*p+rgb1.b,a:(rgb2.a-rgb1.a)*p+rgb1.a};return new TinyColor(rgba)}analogous(results=6,slices=30){const hsl=this.toHsl(),part=360/slices,ret=[this];for(hsl.h=(hsl.h-(part*results>>1)+720)%360;--results;)hsl.h=(hsl.h+part)%360,ret.push(new TinyColor(hsl));return ret}complement(){const hsl=this.toHsl();return hsl.h=(hsl.h+180)%360,new TinyColor(hsl)}monochromatic(results=6){const hsv=this.toHsv(),{h}=hsv,{s}=hsv;let{v}=hsv;const res=[],modification=1/results;for(;results--;)res.push(new TinyColor({h,s,v})),v=(v+modification)%1;return res}splitcomplement(){const hsl=this.toHsl(),{h}=hsl;return[this,new TinyColor({h:(h+72)%360,s:hsl.s,l:hsl.l}),new TinyColor({h:(h+216)%360,s:hsl.s,l:hsl.l})]}onBackground(background){const fg=this.toRgb(),bg=new TinyColor(background).toRgb(),alpha=fg.a+bg.a*(1-fg.a);return new TinyColor({r:(fg.r*fg.a+bg.r*bg.a*(1-fg.a))/alpha,g:(fg.g*fg.a+bg.g*bg.a*(1-fg.a))/alpha,b:(fg.b*fg.a+bg.b*bg.a*(1-fg.a))/alpha,a:alpha})}triad(){return this.polyad(3)}tetrad(){return this.polyad(4)}polyad(n){const hsl=this.toHsl(),{h}=hsl,result=[this],increment=360/n;for(let i=1;i<n;i++)result.push(new TinyColor({h:(h+i*increment)%360,s:hsl.s,l:hsl.l}));return result}equals(color){const comparedColor=new TinyColor(color);return"cmyk"===this.format||"cmyk"===comparedColor.format?this.toCmykString()===comparedColor.toCmykString():this.toRgbString()===comparedColor.toRgbString()}}var hasEyeDropper="EyeDropper"in window,SlColorPicker=class extends ShoelaceElement{constructor(){super(),this.formControlController=new FormControlController(this),this.isSafeValue=!1,this.localize=new LocalizeController(this),this.hasFocus=!1,this.isDraggingGridHandle=!1,this.isEmpty=!1,this.inputValue="",this.hue=0,this.saturation=100,this.brightness=100,this.alpha=100,this.value="",this.defaultValue="",this.label="",this.format="hex",this.inline=!1,this.size="medium",this.noFormatToggle=!1,this.name="",this.disabled=!1,this.hoist=!1,this.opacity=!1,this.uppercase=!1,this.swatches="",this.form="",this.required=!1,this.handleFocusIn=()=>{this.hasFocus=!0,this.emit("sl-focus")},this.handleFocusOut=()=>{this.hasFocus=!1,this.emit("sl-blur")},this.addEventListener("focusin",this.handleFocusIn),this.addEventListener("focusout",this.handleFocusOut)}get validity(){return this.input.validity}get validationMessage(){return this.input.validationMessage}firstUpdated(){this.input.updateComplete.then(()=>{this.formControlController.updateValidity()})}handleCopy(){this.input.select(),document.execCommand("copy"),this.previewButton.focus(),this.previewButton.classList.add("color-picker__preview-color--copied"),this.previewButton.addEventListener("animationend",()=>{this.previewButton.classList.remove("color-picker__preview-color--copied")})}handleFormatToggle(){const formats=["hex","rgb","hsl","hsv"],nextIndex=(formats.indexOf(this.format)+1)%formats.length;this.format=formats[nextIndex],this.setColor(this.value),this.emit("sl-change"),this.emit("sl-input")}handleAlphaDrag(event){const container=this.shadowRoot.querySelector(".color-picker__slider.color-picker__alpha"),handle=container.querySelector(".color-picker__slider-handle"),{width}=container.getBoundingClientRect();let initialValue=this.value,currentValue=this.value;handle.focus(),event.preventDefault(),drag(container,{onMove:x=>{this.alpha=clamp(100*(x/width),0,100),this.syncValues(),this.value!==currentValue&&(currentValue=this.value,this.emit("sl-input"))},onStop:()=>{this.value!==initialValue&&(initialValue=this.value,this.emit("sl-change"))},initialEvent:event})}handleHueDrag(event){const container=this.shadowRoot.querySelector(".color-picker__slider.color-picker__hue"),handle=container.querySelector(".color-picker__slider-handle"),{width}=container.getBoundingClientRect();let initialValue=this.value,currentValue=this.value;handle.focus(),event.preventDefault(),drag(container,{onMove:x=>{this.hue=clamp(360*(x/width),0,360),this.syncValues(),this.value!==currentValue&&(currentValue=this.value,this.emit("sl-input"))},onStop:()=>{this.value!==initialValue&&(initialValue=this.value,this.emit("sl-change"))},initialEvent:event})}handleGridDrag(event){const grid=this.shadowRoot.querySelector(".color-picker__grid"),handle=grid.querySelector(".color-picker__grid-handle"),{width,height}=grid.getBoundingClientRect();let initialValue=this.value,currentValue=this.value;handle.focus(),event.preventDefault(),this.isDraggingGridHandle=!0,drag(grid,{onMove:(x,y)=>{this.saturation=clamp(100*(x/width),0,100),this.brightness=clamp(100-100*(y/height),0,100),this.syncValues(),this.value!==currentValue&&(currentValue=this.value,this.emit("sl-input"))},onStop:()=>{this.isDraggingGridHandle=!1,this.value!==initialValue&&(initialValue=this.value,this.emit("sl-change"))},initialEvent:event})}handleAlphaKeyDown(event){const increment=event.shiftKey?10:1,oldValue=this.value;"ArrowLeft"===event.key&&(event.preventDefault(),this.alpha=clamp(this.alpha-increment,0,100),this.syncValues()),"ArrowRight"===event.key&&(event.preventDefault(),this.alpha=clamp(this.alpha+increment,0,100),this.syncValues()),"Home"===event.key&&(event.preventDefault(),this.alpha=0,this.syncValues()),"End"===event.key&&(event.preventDefault(),this.alpha=100,this.syncValues()),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input"))}handleHueKeyDown(event){const increment=event.shiftKey?10:1,oldValue=this.value;"ArrowLeft"===event.key&&(event.preventDefault(),this.hue=clamp(this.hue-increment,0,360),this.syncValues()),"ArrowRight"===event.key&&(event.preventDefault(),this.hue=clamp(this.hue+increment,0,360),this.syncValues()),"Home"===event.key&&(event.preventDefault(),this.hue=0,this.syncValues()),"End"===event.key&&(event.preventDefault(),this.hue=360,this.syncValues()),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input"))}handleGridKeyDown(event){const increment=event.shiftKey?10:1,oldValue=this.value;"ArrowLeft"===event.key&&(event.preventDefault(),this.saturation=clamp(this.saturation-increment,0,100),this.syncValues()),"ArrowRight"===event.key&&(event.preventDefault(),this.saturation=clamp(this.saturation+increment,0,100),this.syncValues()),"ArrowUp"===event.key&&(event.preventDefault(),this.brightness=clamp(this.brightness+increment,0,100),this.syncValues()),"ArrowDown"===event.key&&(event.preventDefault(),this.brightness=clamp(this.brightness-increment,0,100),this.syncValues()),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input"))}handleInputChange(event){const target=event.target,oldValue=this.value;event.stopPropagation(),this.input.value?(this.setColor(target.value),target.value=this.value):this.value="",this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input"))}handleInputInput(event){this.formControlController.updateValidity(),event.stopPropagation()}handleInputKeyDown(event){if("Enter"===event.key){const oldValue=this.value;this.input.value?(this.setColor(this.input.value),this.input.value=this.value,this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input")),setTimeout(()=>this.input.select())):this.hue=0}}handleInputInvalid(event){this.formControlController.setValidity(!1),this.formControlController.emitInvalidEvent(event)}handleTouchMove(event){event.preventDefault()}parseColor(colorString){var _Mathround14=Math.round;const color=new TinyColor(colorString);if(!color.isValid)return null;const hslColor=color.toHsl(),hsl={h:hslColor.h,s:100*hslColor.s,l:100*hslColor.l,a:hslColor.a},rgb=color.toRgb(),hex=color.toHexString(),hexa=color.toHex8String(),hsvColor=color.toHsv(),hsv={h:hsvColor.h,s:100*hsvColor.s,v:100*hsvColor.v,a:hsvColor.a};return{hsl:{h:hsl.h,s:hsl.s,l:hsl.l,string:this.setLetterCase(`hsl(${_Mathround14(hsl.h)}, ${_Mathround14(hsl.s)}%, ${_Mathround14(hsl.l)}%)`)},hsla:{h:hsl.h,s:hsl.s,l:hsl.l,a:hsl.a,string:this.setLetterCase(`hsla(${_Mathround14(hsl.h)}, ${_Mathround14(hsl.s)}%, ${_Mathround14(hsl.l)}%, ${hsl.a.toFixed(2).toString()})`)},hsv:{h:hsv.h,s:hsv.s,v:hsv.v,string:this.setLetterCase(`hsv(${_Mathround14(hsv.h)}, ${_Mathround14(hsv.s)}%, ${_Mathround14(hsv.v)}%)`)},hsva:{h:hsv.h,s:hsv.s,v:hsv.v,a:hsv.a,string:this.setLetterCase(`hsva(${_Mathround14(hsv.h)}, ${_Mathround14(hsv.s)}%, ${_Mathround14(hsv.v)}%, ${hsv.a.toFixed(2).toString()})`)},rgb:{r:rgb.r,g:rgb.g,b:rgb.b,string:this.setLetterCase(`rgb(${_Mathround14(rgb.r)}, ${_Mathround14(rgb.g)}, ${_Mathround14(rgb.b)})`)},rgba:{r:rgb.r,g:rgb.g,b:rgb.b,a:rgb.a,string:this.setLetterCase(`rgba(${_Mathround14(rgb.r)}, ${_Mathround14(rgb.g)}, ${_Mathround14(rgb.b)}, ${rgb.a.toFixed(2).toString()})`)},hex:this.setLetterCase(hex),hexa:this.setLetterCase(hexa)}}setColor(colorString){const newColor=this.parseColor(colorString);return null!==newColor&&(this.hue=newColor.hsva.h,this.saturation=newColor.hsva.s,this.brightness=newColor.hsva.v,this.alpha=this.opacity?100*newColor.hsva.a:100,this.syncValues(),!0)}setLetterCase(string){return"string"==typeof string?this.uppercase?string.toUpperCase():string.toLowerCase():""}async syncValues(){const currentColor=this.parseColor(`hsva(${this.hue}, ${this.saturation}%, ${this.brightness}%, ${this.alpha/100})`);null===currentColor||(this.inputValue="hsl"===this.format?this.opacity?currentColor.hsla.string:currentColor.hsl.string:"rgb"===this.format?this.opacity?currentColor.rgba.string:currentColor.rgb.string:"hsv"===this.format?this.opacity?currentColor.hsva.string:currentColor.hsv.string:this.opacity?currentColor.hexa:currentColor.hex,this.isSafeValue=!0,this.value=this.inputValue,await this.updateComplete,this.isSafeValue=!1)}handleAfterHide(){this.previewButton.classList.remove("color-picker__preview-color--copied")}handleEyeDropper(){if(hasEyeDropper){const eyeDropper=new EyeDropper;eyeDropper.open().then(colorSelectionResult=>{const oldValue=this.value;this.setColor(colorSelectionResult.sRGBHex),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input"))}).catch(()=>{})}}selectSwatch(color){const oldValue=this.value;this.disabled||(this.setColor(color),this.value!==oldValue&&(this.emit("sl-change"),this.emit("sl-input")))}getHexString(hue,saturation,brightness,alpha=100){const color=new TinyColor(`hsva(${hue}, ${saturation}%, ${brightness}%, ${alpha/100})`);return color.isValid?color.toHex8String():""}stopNestedEventPropagation(event){event.stopImmediatePropagation()}handleFormatChange(){this.syncValues()}handleOpacityChange(){this.alpha=100}handleValueChange(oldValue,newValue){if(this.isEmpty=!newValue,newValue||(this.hue=0,this.saturation=0,this.brightness=100,this.alpha=100),!this.isSafeValue){const newColor=this.parseColor(newValue);null===newColor?this.inputValue=null==oldValue?"":oldValue:(this.inputValue=this.value,this.hue=newColor.hsva.h,this.saturation=newColor.hsva.s,this.brightness=newColor.hsva.v,this.alpha=100*newColor.hsva.a,this.syncValues())}}focus(options){this.inline?this.base.focus(options):this.trigger.focus(options)}blur(){var _a;const elementToBlur=this.inline?this.base:this.trigger;this.hasFocus&&(elementToBlur.focus({preventScroll:!0}),elementToBlur.blur()),(null==(_a=this.dropdown)?void 0:_a.open)&&this.dropdown.hide()}getFormattedValue(format="hex"){const currentColor=this.parseColor(`hsva(${this.hue}, ${this.saturation}%, ${this.brightness}%, ${this.alpha/100})`);if(null===currentColor)return"";return"hex"===format?currentColor.hex:"hexa"===format?currentColor.hexa:"rgb"===format?currentColor.rgb.string:"rgba"===format?currentColor.rgba.string:"hsl"===format?currentColor.hsl.string:"hsla"===format?currentColor.hsla.string:"hsv"===format?currentColor.hsv.string:"hsva"===format?currentColor.hsva.string:""}checkValidity(){return this.input.checkValidity()}getForm(){return this.formControlController.getForm()}reportValidity(){return this.inline||this.validity.valid?this.input.reportValidity():(this.dropdown.show(),this.addEventListener("sl-after-show",()=>this.input.reportValidity(),{once:!0}),this.disabled||this.formControlController.emitInvalidEvent(),!1)}setCustomValidity(message){this.input.setCustomValidity(message),this.formControlController.updateValidity()}render(){var _Mathround15=Math.round;const gridHandleX=this.saturation,gridHandleY=100-this.brightness,swatches=Array.isArray(this.swatches)?this.swatches:this.swatches.split(";").filter(color=>""!==color.trim()),colorPicker=x$1` + <div + part="base" + class=${e$2({"color-picker":!0,"color-picker--inline":this.inline,"color-picker--disabled":this.disabled,"color-picker--focused":this.hasFocus})} + aria-disabled=${this.disabled?"true":"false"} + aria-labelledby="label" + tabindex=${this.inline?"0":"-1"} + > + ${this.inline?x$1` + <sl-visually-hidden id="label"> + <slot name="label">${this.label}</slot> + </sl-visually-hidden> + `:null} + + <div + part="grid" + class="color-picker__grid" + style=${o$3({backgroundColor:this.getHexString(this.hue,100,100)})} + @pointerdown=${this.handleGridDrag} + @touchmove=${this.handleTouchMove} + > + <span + part="grid-handle" + class=${e$2({"color-picker__grid-handle":!0,"color-picker__grid-handle--dragging":this.isDraggingGridHandle})} + style=${o$3({top:`${gridHandleY}%`,left:`${gridHandleX}%`,backgroundColor:this.getHexString(this.hue,this.saturation,this.brightness,this.alpha)})} + role="application" + aria-label="HSV" + tabindex=${o$6(this.disabled?void 0:"0")} + @keydown=${this.handleGridKeyDown} + ></span> + </div> + + <div class="color-picker__controls"> + <div class="color-picker__sliders"> + <div + part="slider hue-slider" + class="color-picker__hue color-picker__slider" + @pointerdown=${this.handleHueDrag} + @touchmove=${this.handleTouchMove} + > + <span + part="slider-handle hue-slider-handle" + class="color-picker__slider-handle" + style=${o$3({left:`${0===this.hue?0:100/(360/this.hue)}%`})} + role="slider" + aria-label="hue" + aria-orientation="horizontal" + aria-valuemin="0" + aria-valuemax="360" + aria-valuenow=${`${_Mathround15(this.hue)}`} + tabindex=${o$6(this.disabled?void 0:"0")} + @keydown=${this.handleHueKeyDown} + ></span> + </div> + + ${this.opacity?x$1` + <div + part="slider opacity-slider" + class="color-picker__alpha color-picker__slider color-picker__transparent-bg" + @pointerdown="${this.handleAlphaDrag}" + @touchmove=${this.handleTouchMove} + > + <div + class="color-picker__alpha-gradient" + style=${o$3({backgroundImage:`linear-gradient( + to right, + ${this.getHexString(this.hue,this.saturation,this.brightness,0)} 0%, + ${this.getHexString(this.hue,this.saturation,this.brightness,100)} 100% + )`})} + ></div> + <span + part="slider-handle opacity-slider-handle" + class="color-picker__slider-handle" + style=${o$3({left:`${this.alpha}%`})} + role="slider" + aria-label="alpha" + aria-orientation="horizontal" + aria-valuemin="0" + aria-valuemax="100" + aria-valuenow=${_Mathround15(this.alpha)} + tabindex=${o$6(this.disabled?void 0:"0")} + @keydown=${this.handleAlphaKeyDown} + ></span> + </div> + `:""} + </div> + + <button + type="button" + part="preview" + class="color-picker__preview color-picker__transparent-bg" + aria-label=${this.localize.term("copy")} + style=${o$3({"--preview-color":this.getHexString(this.hue,this.saturation,this.brightness,this.alpha)})} + @click=${this.handleCopy} + ></button> + </div> + + <div class="color-picker__user-input" aria-live="polite"> + <sl-input + part="input" + type="text" + name=${this.name} + autocomplete="off" + autocorrect="off" + autocapitalize="off" + spellcheck="false" + value=${this.isEmpty?"":this.inputValue} + ?required=${this.required} + ?disabled=${this.disabled} + aria-label=${this.localize.term("currentValue")} + @keydown=${this.handleInputKeyDown} + @sl-change=${this.handleInputChange} + @sl-input=${this.handleInputInput} + @sl-invalid=${this.handleInputInvalid} + @sl-blur=${this.stopNestedEventPropagation} + @sl-focus=${this.stopNestedEventPropagation} + ></sl-input> + + <sl-button-group> + ${this.noFormatToggle?"":x$1` + <sl-button + part="format-button" + aria-label=${this.localize.term("toggleColorFormat")} + exportparts=" + base:format-button__base, + prefix:format-button__prefix, + label:format-button__label, + suffix:format-button__suffix, + caret:format-button__caret + " + @click=${this.handleFormatToggle} + @sl-blur=${this.stopNestedEventPropagation} + @sl-focus=${this.stopNestedEventPropagation} + > + ${this.setLetterCase(this.format)} + </sl-button> + `} + ${hasEyeDropper?x$1` + <sl-button + part="eye-dropper-button" + exportparts=" + base:eye-dropper-button__base, + prefix:eye-dropper-button__prefix, + label:eye-dropper-button__label, + suffix:eye-dropper-button__suffix, + caret:eye-dropper-button__caret + " + @click=${this.handleEyeDropper} + @sl-blur=${this.stopNestedEventPropagation} + @sl-focus=${this.stopNestedEventPropagation} + > + <sl-icon + library="system" + name="eyedropper" + label=${this.localize.term("selectAColorFromTheScreen")} + ></sl-icon> + </sl-button> + `:""} + </sl-button-group> + </div> + + ${0<swatches.length?x$1` + <div part="swatches" class="color-picker__swatches"> + ${swatches.map(swatch=>{const parsedColor=this.parseColor(swatch);return parsedColor?x$1` + <div + part="swatch" + class="color-picker__swatch color-picker__transparent-bg" + tabindex=${o$6(this.disabled?void 0:"0")} + role="button" + aria-label=${swatch} + @click=${()=>this.selectSwatch(swatch)} + @keydown=${event=>!this.disabled&&"Enter"===event.key&&this.setColor(parsedColor.hexa)} + > + <div + class="color-picker__swatch-color" + style=${o$3({backgroundColor:parsedColor.hexa})} + ></div> + </div> + `:(console.error(`Unable to parse swatch color: "${swatch}"`,this),"")})} + </div> + `:""} + </div> + `;return this.inline?colorPicker:x$1` + <sl-dropdown + class="color-dropdown" + aria-disabled=${this.disabled?"true":"false"} + .containingElement=${this} + ?disabled=${this.disabled} + ?hoist=${this.hoist} + @sl-after-hide=${this.handleAfterHide} + > + <button + part="trigger" + slot="trigger" + class=${e$2({"color-dropdown__trigger":!0,"color-dropdown__trigger--disabled":this.disabled,"color-dropdown__trigger--small":"small"===this.size,"color-dropdown__trigger--medium":"medium"===this.size,"color-dropdown__trigger--large":"large"===this.size,"color-dropdown__trigger--empty":this.isEmpty,"color-dropdown__trigger--focused":this.hasFocus,"color-picker__transparent-bg":!0})} + style=${o$3({color:this.getHexString(this.hue,this.saturation,this.brightness,this.alpha)})} + type="button" + > + <sl-visually-hidden> + <slot name="label">${this.label}</slot> + </sl-visually-hidden> + </button> + ${colorPicker} + </sl-dropdown> + `}};SlColorPicker.styles=[component_styles_default,color_picker_styles_default],SlColorPicker.dependencies={"sl-button-group":SlButtonGroup,"sl-button":SlButton,"sl-dropdown":SlDropdown,"sl-icon":SlIcon,"sl-input":SlInput,"sl-visually-hidden":SlVisuallyHidden},__decorateClass([e$6("[part~=\"base\"]")],SlColorPicker.prototype,"base",2),__decorateClass([e$6("[part~=\"input\"]")],SlColorPicker.prototype,"input",2),__decorateClass([e$6(".color-dropdown")],SlColorPicker.prototype,"dropdown",2),__decorateClass([e$6("[part~=\"preview\"]")],SlColorPicker.prototype,"previewButton",2),__decorateClass([e$6("[part~=\"trigger\"]")],SlColorPicker.prototype,"trigger",2),__decorateClass([r$6()],SlColorPicker.prototype,"hasFocus",2),__decorateClass([r$6()],SlColorPicker.prototype,"isDraggingGridHandle",2),__decorateClass([r$6()],SlColorPicker.prototype,"isEmpty",2),__decorateClass([r$6()],SlColorPicker.prototype,"inputValue",2),__decorateClass([r$6()],SlColorPicker.prototype,"hue",2),__decorateClass([r$6()],SlColorPicker.prototype,"saturation",2),__decorateClass([r$6()],SlColorPicker.prototype,"brightness",2),__decorateClass([r$6()],SlColorPicker.prototype,"alpha",2),__decorateClass([n$5()],SlColorPicker.prototype,"value",2),__decorateClass([defaultValue()],SlColorPicker.prototype,"defaultValue",2),__decorateClass([n$5()],SlColorPicker.prototype,"label",2),__decorateClass([n$5()],SlColorPicker.prototype,"format",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlColorPicker.prototype,"inline",2),__decorateClass([n$5({reflect:!0})],SlColorPicker.prototype,"size",2),__decorateClass([n$5({attribute:"no-format-toggle",type:Boolean})],SlColorPicker.prototype,"noFormatToggle",2),__decorateClass([n$5()],SlColorPicker.prototype,"name",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlColorPicker.prototype,"disabled",2),__decorateClass([n$5({type:Boolean})],SlColorPicker.prototype,"hoist",2),__decorateClass([n$5({type:Boolean})],SlColorPicker.prototype,"opacity",2),__decorateClass([n$5({type:Boolean})],SlColorPicker.prototype,"uppercase",2),__decorateClass([n$5()],SlColorPicker.prototype,"swatches",2),__decorateClass([n$5({reflect:!0})],SlColorPicker.prototype,"form",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlColorPicker.prototype,"required",2),__decorateClass([t$2({passive:!1})],SlColorPicker.prototype,"handleTouchMove",1),__decorateClass([watch("format",{waitUntilFirstUpdate:!0})],SlColorPicker.prototype,"handleFormatChange",1),__decorateClass([watch("opacity",{waitUntilFirstUpdate:!0})],SlColorPicker.prototype,"handleOpacityChange",1),__decorateClass([watch("value")],SlColorPicker.prototype,"handleValueChange",1),SlColorPicker.define("sl-color-picker");var card_styles_default=i$7` + :host { + --border-color: var(--sl-color-neutral-200); + --border-radius: var(--sl-border-radius-medium); + --border-width: 1px; + --padding: var(--sl-spacing-large); + + display: inline-block; + } + + .card { + display: flex; + flex-direction: column; + background-color: var(--sl-panel-background-color); + box-shadow: var(--sl-shadow-x-small); + border: solid var(--border-width) var(--border-color); + border-radius: var(--border-radius); + } + + .card__image { + display: flex; + border-top-left-radius: var(--border-radius); + border-top-right-radius: var(--border-radius); + margin: calc(-1 * var(--border-width)); + overflow: hidden; + } + + .card__image::slotted(img) { + display: block; + width: 100%; + } + + .card:not(.card--has-image) .card__image { + display: none; + } + + .card__header { + display: block; + border-bottom: solid var(--border-width) var(--border-color); + padding: calc(var(--padding) / 2) var(--padding); + } + + .card:not(.card--has-header) .card__header { + display: none; + } + + .card:not(.card--has-image) .card__header { + border-top-left-radius: var(--border-radius); + border-top-right-radius: var(--border-radius); + } + + .card__body { + display: block; + padding: var(--padding); + } + + .card--has-footer .card__footer { + display: block; + border-top: solid var(--border-width) var(--border-color); + padding: var(--padding); + } + + .card:not(.card--has-footer) .card__footer { + display: none; + } +`,SlCard=class extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"footer","header","image")}render(){return x$1` + <div + part="base" + class=${e$2({card:!0,"card--has-footer":this.hasSlotController.test("footer"),"card--has-image":this.hasSlotController.test("image"),"card--has-header":this.hasSlotController.test("header")})} + > + <slot name="image" part="image" class="card__image"></slot> + <slot name="header" part="header" class="card__header"></slot> + <slot part="body" class="card__body"></slot> + <slot name="footer" part="footer" class="card__footer"></slot> + </div> + `}};SlCard.styles=[component_styles_default,card_styles_default],SlCard.define("sl-card");var AutoplayController=class{constructor(host,tickCallback){this.timerId=0,this.activeInteractions=0,this.paused=!1,this.stopped=!0,this.pause=()=>{this.activeInteractions++||(this.paused=!0,this.host.requestUpdate())},this.resume=()=>{--this.activeInteractions||(this.paused=!1,this.host.requestUpdate())},host.addController(this),this.host=host,this.tickCallback=tickCallback}hostConnected(){this.host.addEventListener("mouseenter",this.pause),this.host.addEventListener("mouseleave",this.resume),this.host.addEventListener("focusin",this.pause),this.host.addEventListener("focusout",this.resume),this.host.addEventListener("touchstart",this.pause,{passive:!0}),this.host.addEventListener("touchend",this.resume)}hostDisconnected(){this.stop(),this.host.removeEventListener("mouseenter",this.pause),this.host.removeEventListener("mouseleave",this.resume),this.host.removeEventListener("focusin",this.pause),this.host.removeEventListener("focusout",this.resume),this.host.removeEventListener("touchstart",this.pause),this.host.removeEventListener("touchend",this.resume)}start(interval){this.stop(),this.stopped=!1,this.timerId=window.setInterval(()=>{this.paused||this.tickCallback()},interval)}stop(){clearInterval(this.timerId),this.stopped=!0,this.host.requestUpdate()}},carousel_styles_default=i$7` + :host { + --slide-gap: var(--sl-spacing-medium, 1rem); + --aspect-ratio: 16 / 9; + --scroll-hint: 0px; + + display: flex; + } + + .carousel { + display: grid; + grid-template-columns: min-content 1fr min-content; + grid-template-rows: 1fr min-content; + grid-template-areas: + '. slides .' + '. pagination .'; + gap: var(--sl-spacing-medium); + align-items: center; + min-height: 100%; + min-width: 100%; + position: relative; + } + + .carousel__pagination { + grid-area: pagination; + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: var(--sl-spacing-small); + } + + .carousel__slides { + grid-area: slides; + + display: grid; + height: 100%; + width: 100%; + align-items: center; + justify-items: center; + overflow: auto; + overscroll-behavior-x: contain; + scrollbar-width: none; + aspect-ratio: calc(var(--aspect-ratio) * var(--slides-per-page)); + border-radius: var(--sl-border-radius-small); + + --slide-size: calc((100% - (var(--slides-per-page) - 1) * var(--slide-gap)) / var(--slides-per-page)); + } + + @media (prefers-reduced-motion) { + :where(.carousel__slides) { + scroll-behavior: auto; + } + } + + .carousel__slides--horizontal { + grid-auto-flow: column; + grid-auto-columns: var(--slide-size); + grid-auto-rows: 100%; + column-gap: var(--slide-gap); + scroll-snap-type: x mandatory; + scroll-padding-inline: var(--scroll-hint); + padding-inline: var(--scroll-hint); + overflow-y: hidden; + } + + .carousel__slides--vertical { + grid-auto-flow: row; + grid-auto-columns: 100%; + grid-auto-rows: var(--slide-size); + row-gap: var(--slide-gap); + scroll-snap-type: y mandatory; + scroll-padding-block: var(--scroll-hint); + padding-block: var(--scroll-hint); + overflow-x: hidden; + } + + .carousel__slides--dragging { + } + + :host([vertical]) ::slotted(sl-carousel-item) { + height: 100%; + } + + .carousel__slides::-webkit-scrollbar { + display: none; + } + + .carousel__navigation { + grid-area: navigation; + display: contents; + font-size: var(--sl-font-size-x-large); + } + + .carousel__navigation-button { + flex: 0 0 auto; + display: flex; + align-items: center; + background: none; + border: none; + border-radius: var(--sl-border-radius-small); + font-size: inherit; + color: var(--sl-color-neutral-600); + padding: var(--sl-spacing-x-small); + cursor: pointer; + transition: var(--sl-transition-medium) color; + appearance: none; + } + + .carousel__navigation-button--disabled { + opacity: 0.5; + cursor: not-allowed; + } + + .carousel__navigation-button--disabled::part(base) { + pointer-events: none; + } + + .carousel__navigation-button--previous { + grid-column: 1; + grid-row: 1; + } + + .carousel__navigation-button--next { + grid-column: 3; + grid-row: 1; + } + + .carousel__pagination-item { + display: block; + cursor: pointer; + background: none; + border: 0; + border-radius: var(--sl-border-radius-circle); + width: var(--sl-spacing-small); + height: var(--sl-spacing-small); + background-color: var(--sl-color-neutral-300); + padding: 0; + margin: 0; + } + + .carousel__pagination-item--active { + background-color: var(--sl-color-neutral-700); + transform: scale(1.2); + } + + /* Focus styles */ + .carousel__slides:focus-visible, + .carousel__navigation-button:focus-visible, + .carousel__pagination-item:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } +`,SlCarousel=class extends ShoelaceElement{constructor(){super(...arguments),this.loop=!1,this.navigation=!1,this.pagination=!1,this.autoplay=!1,this.autoplayInterval=3e3,this.slidesPerPage=1,this.slidesPerMove=1,this.orientation="horizontal",this.mouseDragging=!1,this.activeSlide=0,this.scrolling=!1,this.dragging=!1,this.autoplayController=new AutoplayController(this,()=>this.next()),this.dragStartPosition=[-1,-1],this.localize=new LocalizeController(this),this.pendingSlideChange=!1,this.handleMouseDrag=event=>{this.dragging||(this.scrollContainer.style.setProperty("scroll-snap-type","none"),this.dragging=!0,this.dragStartPosition=[event.clientX,event.clientY]),this.scrollContainer.scrollBy({left:-event.movementX,top:-event.movementY,behavior:"instant"})},this.handleMouseDragEnd=()=>{const scrollContainer=this.scrollContainer;document.removeEventListener("pointermove",this.handleMouseDrag,{capture:!0});const startLeft=scrollContainer.scrollLeft,startTop=scrollContainer.scrollTop;scrollContainer.style.removeProperty("scroll-snap-type"),scrollContainer.style.setProperty("overflow","hidden");const finalLeft=scrollContainer.scrollLeft,finalTop=scrollContainer.scrollTop;scrollContainer.style.removeProperty("overflow"),scrollContainer.style.setProperty("scroll-snap-type","none"),scrollContainer.scrollTo({left:startLeft,top:startTop,behavior:"instant"}),requestAnimationFrame(async()=>{(startLeft!==finalLeft||startTop!==finalTop)&&(scrollContainer.scrollTo({left:finalLeft,top:finalTop,behavior:prefersReducedMotion()?"auto":"smooth"}),await waitForEvent(scrollContainer,"scrollend")),scrollContainer.style.removeProperty("scroll-snap-type"),this.dragging=!1,this.dragStartPosition=[-1,-1],this.handleScrollEnd()})},this.handleSlotChange=mutations=>{const needsInitialization=mutations.some(mutation=>[...mutation.addedNodes,...mutation.removedNodes].some(el=>this.isCarouselItem(el)&&!el.hasAttribute("data-clone")));needsInitialization&&this.initializeSlides(),this.requestUpdate()}}connectedCallback(){super.connectedCallback(),this.setAttribute("role","region"),this.setAttribute("aria-label",this.localize.term("carousel"))}disconnectedCallback(){var _a;super.disconnectedCallback(),null==(_a=this.mutationObserver)?void 0:_a.disconnect()}firstUpdated(){this.initializeSlides(),this.mutationObserver=new MutationObserver(this.handleSlotChange),this.mutationObserver.observe(this,{childList:!0,subtree:!0})}willUpdate(changedProperties){(changedProperties.has("slidesPerMove")||changedProperties.has("slidesPerPage"))&&(this.slidesPerMove=Math.min(this.slidesPerMove,this.slidesPerPage))}getPageCount(){const slidesCount=this.getSlides().length,{slidesPerPage,slidesPerMove,loop}=this,pages=loop?slidesCount/slidesPerMove:(slidesCount-slidesPerPage)/slidesPerMove+1;return Math.ceil(pages)}getCurrentPage(){return Math.ceil(this.activeSlide/this.slidesPerMove)}canScrollNext(){return this.loop||this.getCurrentPage()<this.getPageCount()-1}canScrollPrev(){return this.loop||0<this.getCurrentPage()}getSlides({excludeClones=!0}={}){return[...this.children].filter(el=>this.isCarouselItem(el)&&(!excludeClones||!el.hasAttribute("data-clone")))}handleClick(event){var _Mathabs5=Math.abs;if(this.dragging&&0<this.dragStartPosition[0]&&0<this.dragStartPosition[1]){const deltaX=_Mathabs5(this.dragStartPosition[0]-event.clientX),deltaY=_Mathabs5(this.dragStartPosition[1]-event.clientY),delta=Math.sqrt(deltaX*deltaX+deltaY*deltaY);10<=delta&&event.preventDefault()}}handleKeyDown(event){if(["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End"].includes(event.key)){const target=event.target,isRtl="rtl"===this.localize.dir(),isFocusInPagination=null!==target.closest("[part~=\"pagination-item\"]"),isNext="ArrowDown"===event.key||!isRtl&&"ArrowRight"===event.key||isRtl&&"ArrowLeft"===event.key,isPrevious="ArrowUp"===event.key||!isRtl&&"ArrowLeft"===event.key||isRtl&&"ArrowRight"===event.key;event.preventDefault(),isPrevious&&this.previous(),isNext&&this.next(),"Home"===event.key&&this.goToSlide(0),"End"===event.key&&this.goToSlide(this.getSlides().length-1),isFocusInPagination&&this.updateComplete.then(()=>{var _a;const activePaginationItem=null==(_a=this.shadowRoot)?void 0:_a.querySelector("[part~=\"pagination-item--active\"]");activePaginationItem&&activePaginationItem.focus()})}}handleMouseDragStart(event){const canDrag=this.mouseDragging&&0===event.button;canDrag&&(event.preventDefault(),document.addEventListener("pointermove",this.handleMouseDrag,{capture:!0,passive:!0}),document.addEventListener("pointerup",this.handleMouseDragEnd,{capture:!0,once:!0}))}handleScroll(){this.scrolling=!0,this.pendingSlideChange||this.synchronizeSlides()}synchronizeSlides(){var _Mathceil3=Math.ceil;const io=new IntersectionObserver(entries=>{io.disconnect();for(const entry of entries){const slide=entry.target;slide.toggleAttribute("inert",!entry.isIntersecting),slide.classList.toggle("--in-view",entry.isIntersecting),slide.setAttribute("aria-hidden",entry.isIntersecting?"false":"true")}const firstIntersecting=entries.find(entry=>entry.isIntersecting);if(!firstIntersecting)return;const slidesWithClones=this.getSlides({excludeClones:!1}),slidesCount=this.getSlides().length,slideIndex=slidesWithClones.indexOf(firstIntersecting.target),normalizedIndex=this.loop?slideIndex-this.slidesPerPage:slideIndex;if(this.activeSlide=(_Mathceil3(normalizedIndex/this.slidesPerMove)*this.slidesPerMove+slidesCount)%slidesCount,!this.scrolling&&this.loop&&firstIntersecting.target.hasAttribute("data-clone")){const clonePosition=+firstIntersecting.target.getAttribute("data-clone");this.goToSlide(clonePosition,"instant")}},{root:this.scrollContainer,threshold:.6});this.getSlides({excludeClones:!1}).forEach(slide=>{io.observe(slide)})}handleScrollEnd(){!this.scrolling||this.dragging||(this.scrolling=!1,this.pendingSlideChange=!1,this.synchronizeSlides())}isCarouselItem(node){return node instanceof Element&&"sl-carousel-item"===node.tagName.toLowerCase()}initializeSlides(){this.getSlides({excludeClones:!1}).forEach((slide,index)=>{slide.classList.remove("--in-view"),slide.classList.remove("--is-active"),slide.setAttribute("role","group"),slide.setAttribute("aria-label",this.localize.term("slideNum",index+1)),this.pagination&&(slide.setAttribute("id",`slide-${index+1}`),slide.setAttribute("role","tabpanel"),slide.removeAttribute("aria-label"),slide.setAttribute("aria-labelledby",`tab-${index+1}`)),slide.hasAttribute("data-clone")&&slide.remove()}),this.updateSlidesSnap(),this.loop&&this.createClones(),this.goToSlide(this.activeSlide,"auto"),this.synchronizeSlides()}createClones(){const slides=this.getSlides(),slidesPerPage=this.slidesPerPage,lastSlides=slides.slice(-slidesPerPage),firstSlides=slides.slice(0,slidesPerPage);lastSlides.reverse().forEach((slide,i)=>{const clone=slide.cloneNode(!0);clone.setAttribute("data-clone",slides.length-i-1+""),this.prepend(clone)}),firstSlides.forEach((slide,i)=>{const clone=slide.cloneNode(!0);clone.setAttribute("data-clone",i+""),this.append(clone)})}handleSlideChange(){const slides=this.getSlides();slides.forEach((slide,i)=>{slide.classList.toggle("--is-active",i===this.activeSlide)}),this.hasUpdated&&this.emit("sl-slide-change",{detail:{index:this.activeSlide,slide:slides[this.activeSlide]}})}updateSlidesSnap(){const slides=this.getSlides(),slidesPerMove=this.slidesPerMove;slides.forEach((slide,i)=>{const shouldSnap=0==(i+slidesPerMove)%slidesPerMove;shouldSnap?slide.style.removeProperty("scroll-snap-align"):slide.style.setProperty("scroll-snap-align","none")})}handleAutoplayChange(){this.autoplayController.stop(),this.autoplay&&this.autoplayController.start(this.autoplayInterval)}previous(behavior="smooth"){this.goToSlide(this.activeSlide-this.slidesPerMove,behavior)}next(behavior="smooth"){this.goToSlide(this.activeSlide+this.slidesPerMove,behavior)}goToSlide(index,behavior="smooth"){const{slidesPerPage,loop}=this,slides=this.getSlides(),slidesWithClones=this.getSlides({excludeClones:!1});if(!slides.length)return;const newActiveSlide=loop?(index+slides.length)%slides.length:clamp(index,0,slides.length-slidesPerPage);this.activeSlide=newActiveSlide;const isRtl="rtl"===this.localize.dir(),nextSlideIndex=clamp(index+(loop?slidesPerPage:0)+(isRtl?slidesPerPage-1:0),0,slidesWithClones.length-1),nextSlide=slidesWithClones[nextSlideIndex];this.scrollToSlide(nextSlide,prefersReducedMotion()?"auto":behavior)}scrollToSlide(slide,behavior="smooth"){this.pendingSlideChange=!0,window.requestAnimationFrame(()=>{if(!this.scrollContainer)return;const scrollContainer=this.scrollContainer,scrollContainerRect=scrollContainer.getBoundingClientRect(),nextSlideRect=slide.getBoundingClientRect(),nextLeft=nextSlideRect.left-scrollContainerRect.left,nextTop=nextSlideRect.top-scrollContainerRect.top;nextLeft||nextTop?(this.pendingSlideChange=!0,scrollContainer.scrollTo({left:nextLeft+scrollContainer.scrollLeft,top:nextTop+scrollContainer.scrollTop,behavior})):this.pendingSlideChange=!1})}render(){const{slidesPerMove,scrolling}=this,pagesCount=this.getPageCount(),currentPage=this.getCurrentPage(),prevEnabled=this.canScrollPrev(),nextEnabled=this.canScrollNext(),isLtr="ltr"===this.localize.dir();return x$1` + <div part="base" class="carousel"> + <div + id="scroll-container" + part="scroll-container" + class="${e$2({carousel__slides:!0,"carousel__slides--horizontal":"horizontal"===this.orientation,"carousel__slides--vertical":"vertical"===this.orientation,"carousel__slides--dragging":this.dragging})}" + style="--slides-per-page: ${this.slidesPerPage};" + aria-busy="${scrolling?"true":"false"}" + aria-atomic="true" + tabindex="0" + @keydown=${this.handleKeyDown} + @mousedown="${this.handleMouseDragStart}" + @scroll="${this.handleScroll}" + @scrollend=${this.handleScrollEnd} + @click=${this.handleClick} + > + <slot></slot> + </div> + + ${this.navigation?x$1` + <div part="navigation" class="carousel__navigation"> + <button + part="navigation-button navigation-button--previous" + class="${e$2({"carousel__navigation-button":!0,"carousel__navigation-button--previous":!0,"carousel__navigation-button--disabled":!prevEnabled})}" + aria-label="${this.localize.term("previousSlide")}" + aria-controls="scroll-container" + aria-disabled="${prevEnabled?"false":"true"}" + @click=${prevEnabled?()=>this.previous():null} + > + <slot name="previous-icon"> + <sl-icon library="system" name="${isLtr?"chevron-left":"chevron-right"}"></sl-icon> + </slot> + </button> + + <button + part="navigation-button navigation-button--next" + class=${e$2({"carousel__navigation-button":!0,"carousel__navigation-button--next":!0,"carousel__navigation-button--disabled":!nextEnabled})} + aria-label="${this.localize.term("nextSlide")}" + aria-controls="scroll-container" + aria-disabled="${nextEnabled?"false":"true"}" + @click=${nextEnabled?()=>this.next():null} + > + <slot name="next-icon"> + <sl-icon library="system" name="${isLtr?"chevron-right":"chevron-left"}"></sl-icon> + </slot> + </button> + </div> + `:""} + ${this.pagination?x$1` + <div part="pagination" role="tablist" class="carousel__pagination"> + ${o(o$1(pagesCount),index=>{const isActive=index===currentPage;return x$1` + <button + part="pagination-item ${isActive?"pagination-item--active":""}" + class="${e$2({"carousel__pagination-item":!0,"carousel__pagination-item--active":isActive})}" + role="tab" + id="tab-${index+1}" + aria-controls="slide-${index+1}" + aria-selected="${isActive?"true":"false"}" + aria-label="${isActive?this.localize.term("slideNum",index+1):this.localize.term("goToSlide",index+1,pagesCount)}" + tabindex=${isActive?"0":"-1"} + @click=${()=>this.goToSlide(index*slidesPerMove)} + @keydown=${this.handleKeyDown} + ></button> + `})} + </div> + `:""} + </div> + `}};SlCarousel.styles=[component_styles_default,carousel_styles_default],SlCarousel.dependencies={"sl-icon":SlIcon},__decorateClass([n$5({type:Boolean,reflect:!0})],SlCarousel.prototype,"loop",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCarousel.prototype,"navigation",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCarousel.prototype,"pagination",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlCarousel.prototype,"autoplay",2),__decorateClass([n$5({type:Number,attribute:"autoplay-interval"})],SlCarousel.prototype,"autoplayInterval",2),__decorateClass([n$5({type:Number,attribute:"slides-per-page"})],SlCarousel.prototype,"slidesPerPage",2),__decorateClass([n$5({type:Number,attribute:"slides-per-move"})],SlCarousel.prototype,"slidesPerMove",2),__decorateClass([n$5()],SlCarousel.prototype,"orientation",2),__decorateClass([n$5({type:Boolean,reflect:!0,attribute:"mouse-dragging"})],SlCarousel.prototype,"mouseDragging",2),__decorateClass([e$6(".carousel__slides")],SlCarousel.prototype,"scrollContainer",2),__decorateClass([e$6(".carousel__pagination")],SlCarousel.prototype,"paginationContainer",2),__decorateClass([r$6()],SlCarousel.prototype,"activeSlide",2),__decorateClass([r$6()],SlCarousel.prototype,"scrolling",2),__decorateClass([r$6()],SlCarousel.prototype,"dragging",2),__decorateClass([t$2({passive:!0})],SlCarousel.prototype,"handleScroll",1),__decorateClass([watch("loop",{waitUntilFirstUpdate:!0}),watch("slidesPerPage",{waitUntilFirstUpdate:!0})],SlCarousel.prototype,"initializeSlides",1),__decorateClass([watch("activeSlide")],SlCarousel.prototype,"handleSlideChange",1),__decorateClass([watch("slidesPerMove")],SlCarousel.prototype,"updateSlidesSnap",1),__decorateClass([watch("autoplay")],SlCarousel.prototype,"handleAutoplayChange",1),SlCarousel.define("sl-carousel");var debounce=(fn,delay)=>{let timerId=0;return function(...args){window.clearTimeout(timerId),timerId=window.setTimeout(()=>{fn.call(this,...args)},delay)}},decorate=(proto,method,decorateFn)=>{const superFn=proto[method];proto[method]=function(...args){superFn.call(this,...args),decorateFn.call(this,superFn,...args)}};(()=>{if("undefined"!=typeof window){const isSupported="onscrollend"in window;if(!isSupported){const pointers=new Set,scrollHandlers=new WeakMap,handlePointerDown=event=>{for(const touch of event.changedTouches)pointers.add(touch.identifier)},handlePointerUp=event=>{for(const touch of event.changedTouches)pointers.delete(touch.identifier)};document.addEventListener("touchstart",handlePointerDown,!0),document.addEventListener("touchend",handlePointerUp,!0),document.addEventListener("touchcancel",handlePointerUp,!0),decorate(EventTarget.prototype,"addEventListener",function(addEventListener,type){if("scrollend"!==type)return;const handleScrollEnd=debounce(()=>{pointers.size?handleScrollEnd():this.dispatchEvent(new Event("scrollend"))},100);addEventListener.call(this,"scroll",handleScrollEnd,{passive:!0}),scrollHandlers.set(this,handleScrollEnd)}),decorate(EventTarget.prototype,"removeEventListener",function(removeEventListener,type){if("scrollend"===type){const scrollHandler=scrollHandlers.get(this);scrollHandler&&removeEventListener.call(this,"scroll",scrollHandler,{passive:!0})}})}}})();var carousel_item_styles_default=i$7` + :host { + --aspect-ratio: inherit; + + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 100%; + max-height: 100%; + aspect-ratio: var(--aspect-ratio); + scroll-snap-align: start; + scroll-snap-stop: always; + } + + ::slotted(img) { + width: 100% !important; + height: 100% !important; + object-fit: cover; + } +`,SlCarouselItem=class extends ShoelaceElement{connectedCallback(){super.connectedCallback()}render(){return x$1` <slot></slot> `}};SlCarouselItem.styles=[component_styles_default,carousel_item_styles_default],SlCarouselItem.define("sl-carousel-item");var breadcrumb_item_styles_default=i$7` + :host { + display: inline-flex; + } + + .breadcrumb-item { + display: inline-flex; + align-items: center; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-small); + font-weight: var(--sl-font-weight-semibold); + color: var(--sl-color-neutral-600); + line-height: var(--sl-line-height-normal); + white-space: nowrap; + } + + .breadcrumb-item__label { + display: inline-block; + font-family: inherit; + font-size: inherit; + font-weight: inherit; + line-height: inherit; + text-decoration: none; + color: inherit; + background: none; + border: none; + border-radius: var(--sl-border-radius-medium); + padding: 0; + margin: 0; + cursor: pointer; + transition: var(--sl-transition-fast) --color; + } + + :host(:not(:last-of-type)) .breadcrumb-item__label { + color: var(--sl-color-primary-600); + } + + :host(:not(:last-of-type)) .breadcrumb-item__label:hover { + color: var(--sl-color-primary-500); + } + + :host(:not(:last-of-type)) .breadcrumb-item__label:active { + color: var(--sl-color-primary-600); + } + + .breadcrumb-item__label:focus { + outline: none; + } + + .breadcrumb-item__label:focus-visible { + outline: var(--sl-focus-ring); + outline-offset: var(--sl-focus-ring-offset); + } + + .breadcrumb-item__prefix, + .breadcrumb-item__suffix { + display: none; + flex: 0 0 auto; + display: flex; + align-items: center; + } + + .breadcrumb-item--has-prefix .breadcrumb-item__prefix { + display: inline-flex; + margin-inline-end: var(--sl-spacing-x-small); + } + + .breadcrumb-item--has-suffix .breadcrumb-item__suffix { + display: inline-flex; + margin-inline-start: var(--sl-spacing-x-small); + } + + :host(:last-of-type) .breadcrumb-item__separator { + display: none; + } + + .breadcrumb-item__separator { + display: inline-flex; + align-items: center; + margin: 0 var(--sl-spacing-x-small); + user-select: none; + -webkit-user-select: none; + } +`,SlBreadcrumbItem=class extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"prefix","suffix"),this.renderType="button",this.rel="noreferrer noopener"}setRenderType(){const hasDropdown=0<this.defaultSlot.assignedElements({flatten:!0}).filter(i=>"sl-dropdown"===i.tagName.toLowerCase()).length;return this.href?void(this.renderType="link"):hasDropdown?void(this.renderType="dropdown"):void(this.renderType="button")}hrefChanged(){this.setRenderType()}handleSlotChange(){this.setRenderType()}render(){return x$1` + <div + part="base" + class=${e$2({"breadcrumb-item":!0,"breadcrumb-item--has-prefix":this.hasSlotController.test("prefix"),"breadcrumb-item--has-suffix":this.hasSlotController.test("suffix")})} + > + <span part="prefix" class="breadcrumb-item__prefix"> + <slot name="prefix"></slot> + </span> + + ${"link"===this.renderType?x$1` + <a + part="label" + class="breadcrumb-item__label breadcrumb-item__label--link" + href="${this.href}" + target="${o$6(this.target?this.target:void 0)}" + rel=${o$6(this.target?this.rel:void 0)} + > + <slot @slotchange=${this.handleSlotChange}></slot> + </a> + `:""} + ${"button"===this.renderType?x$1` + <button part="label" type="button" class="breadcrumb-item__label breadcrumb-item__label--button"> + <slot @slotchange=${this.handleSlotChange}></slot> + </button> + `:""} + ${"dropdown"===this.renderType?x$1` + <div part="label" class="breadcrumb-item__label breadcrumb-item__label--drop-down"> + <slot @slotchange=${this.handleSlotChange}></slot> + </div> + `:""} + + <span part="suffix" class="breadcrumb-item__suffix"> + <slot name="suffix"></slot> + </span> + + <span part="separator" class="breadcrumb-item__separator" aria-hidden="true"> + <slot name="separator"></slot> + </span> + </div> + `}};SlBreadcrumbItem.styles=[component_styles_default,breadcrumb_item_styles_default],__decorateClass([e$6("slot:not([name])")],SlBreadcrumbItem.prototype,"defaultSlot",2),__decorateClass([r$6()],SlBreadcrumbItem.prototype,"renderType",2),__decorateClass([n$5()],SlBreadcrumbItem.prototype,"href",2),__decorateClass([n$5()],SlBreadcrumbItem.prototype,"target",2),__decorateClass([n$5()],SlBreadcrumbItem.prototype,"rel",2),__decorateClass([watch("href",{waitUntilFirstUpdate:!0})],SlBreadcrumbItem.prototype,"hrefChanged",1),SlBreadcrumbItem.define("sl-breadcrumb-item"),SlButtonGroup.define("sl-button-group");var avatar_styles_default=i$7` + :host { + display: inline-block; + + --size: 3rem; + } + + .avatar { + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + width: var(--size); + height: var(--size); + background-color: var(--sl-color-neutral-400); + font-family: var(--sl-font-sans); + font-size: calc(var(--size) * 0.5); + font-weight: var(--sl-font-weight-normal); + color: var(--sl-color-neutral-0); + user-select: none; + -webkit-user-select: none; + vertical-align: middle; + } + + .avatar--circle, + .avatar--circle .avatar__image { + border-radius: var(--sl-border-radius-circle); + } + + .avatar--rounded, + .avatar--rounded .avatar__image { + border-radius: var(--sl-border-radius-medium); + } + + .avatar--square { + border-radius: 0; + } + + .avatar__icon { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .avatar__initials { + line-height: 1; + text-transform: uppercase; + } + + .avatar__image { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + overflow: hidden; + } +`,SlAvatar=class extends ShoelaceElement{constructor(){super(...arguments),this.hasError=!1,this.image="",this.label="",this.initials="",this.loading="eager",this.shape="circle"}handleImageChange(){this.hasError=!1}handleImageLoadError(){this.hasError=!0,this.emit("sl-error")}render(){const avatarWithImage=x$1` + <img + part="image" + class="avatar__image" + src="${this.image}" + loading="${this.loading}" + alt="" + @error="${this.handleImageLoadError}" + /> + `;let avatarWithoutImage=x$1``;return avatarWithoutImage=this.initials?x$1`<div part="initials" class="avatar__initials">${this.initials}</div>`:x$1` + <div part="icon" class="avatar__icon" aria-hidden="true"> + <slot name="icon"> + <sl-icon name="person-fill" library="system"></sl-icon> + </slot> + </div> + `,x$1` + <div + part="base" + class=${e$2({avatar:!0,"avatar--circle":"circle"===this.shape,"avatar--rounded":"rounded"===this.shape,"avatar--square":"square"===this.shape})} + role="img" + aria-label=${this.label} + > + ${this.image&&!this.hasError?avatarWithImage:avatarWithoutImage} + </div> + `}};SlAvatar.styles=[component_styles_default,avatar_styles_default],SlAvatar.dependencies={"sl-icon":SlIcon},__decorateClass([r$6()],SlAvatar.prototype,"hasError",2),__decorateClass([n$5()],SlAvatar.prototype,"image",2),__decorateClass([n$5()],SlAvatar.prototype,"label",2),__decorateClass([n$5()],SlAvatar.prototype,"initials",2),__decorateClass([n$5()],SlAvatar.prototype,"loading",2),__decorateClass([n$5({reflect:!0})],SlAvatar.prototype,"shape",2),__decorateClass([watch("image")],SlAvatar.prototype,"handleImageChange",1),SlAvatar.define("sl-avatar");var breadcrumb_styles_default=i$7` + .breadcrumb { + display: flex; + align-items: center; + flex-wrap: wrap; + } +`,SlBreadcrumb=class extends ShoelaceElement{constructor(){super(...arguments),this.localize=new LocalizeController(this),this.separatorDir=this.localize.dir(),this.label=""}getSeparator(){const separator=this.separatorSlot.assignedElements({flatten:!0})[0],clone=separator.cloneNode(!0);return[clone,...clone.querySelectorAll("[id]")].forEach(el=>el.removeAttribute("id")),clone.setAttribute("data-default",""),clone.slot="separator",clone}handleSlotChange(){const items=[...this.defaultSlot.assignedElements({flatten:!0})].filter(item=>"sl-breadcrumb-item"===item.tagName.toLowerCase());items.forEach((item,index)=>{const separator=item.querySelector("[slot=\"separator\"]");if(null===separator)item.append(this.getSeparator());else if(separator.hasAttribute("data-default"))separator.replaceWith(this.getSeparator());else;index===items.length-1?item.setAttribute("aria-current","page"):item.removeAttribute("aria-current")})}render(){return this.separatorDir!==this.localize.dir()&&(this.separatorDir=this.localize.dir(),this.updateComplete.then(()=>this.handleSlotChange())),x$1` + <nav part="base" class="breadcrumb" aria-label=${this.label}> + <slot @slotchange=${this.handleSlotChange}></slot> + </nav> + + <span hidden aria-hidden="true"> + <slot name="separator"> + <sl-icon name=${"rtl"===this.localize.dir()?"chevron-left":"chevron-right"} library="system"></sl-icon> + </slot> + </span> + `}};SlBreadcrumb.styles=[component_styles_default,breadcrumb_styles_default],SlBreadcrumb.dependencies={"sl-icon":SlIcon},__decorateClass([e$6("slot")],SlBreadcrumb.prototype,"defaultSlot",2),__decorateClass([e$6("slot[name=\"separator\"]")],SlBreadcrumb.prototype,"separatorSlot",2),__decorateClass([n$5()],SlBreadcrumb.prototype,"label",2),SlBreadcrumb.define("sl-breadcrumb");var animated_image_styles_default=i$7` + :host { + --control-box-size: 3rem; + --icon-size: calc(var(--control-box-size) * 0.625); + + display: inline-flex; + position: relative; + cursor: pointer; + } + + img { + display: block; + width: 100%; + height: 100%; + } + + img[aria-hidden='true'] { + display: none; + } + + .animated-image__control-box { + display: flex; + position: absolute; + align-items: center; + justify-content: center; + top: calc(50% - var(--control-box-size) / 2); + right: calc(50% - var(--control-box-size) / 2); + width: var(--control-box-size); + height: var(--control-box-size); + font-size: var(--icon-size); + background: none; + border: solid 2px currentColor; + background-color: rgb(0 0 0 /50%); + border-radius: var(--sl-border-radius-circle); + color: white; + pointer-events: none; + transition: var(--sl-transition-fast) opacity; + } + + :host([play]:hover) .animated-image__control-box { + opacity: 1; + } + + :host([play]:not(:hover)) .animated-image__control-box { + opacity: 0; + } + + :host([play]) slot[name='play-icon'], + :host(:not([play])) slot[name='pause-icon'] { + display: none; + } +`,SlAnimatedImage=class extends ShoelaceElement{constructor(){super(...arguments),this.isLoaded=!1}handleClick(){this.play=!this.play}handleLoad(){const canvas=document.createElement("canvas"),{width,height}=this.animatedImage;canvas.width=width,canvas.height=height,canvas.getContext("2d").drawImage(this.animatedImage,0,0,width,height),this.frozenFrame=canvas.toDataURL("image/gif"),this.isLoaded||(this.emit("sl-load"),this.isLoaded=!0)}handleError(){this.emit("sl-error")}handlePlayChange(){this.play&&(this.animatedImage.src="",this.animatedImage.src=this.src)}handleSrcChange(){this.isLoaded=!1}render(){return x$1` + <div class="animated-image"> + <img + class="animated-image__animated" + src=${this.src} + alt=${this.alt} + crossorigin="anonymous" + aria-hidden=${this.play?"false":"true"} + @click=${this.handleClick} + @load=${this.handleLoad} + @error=${this.handleError} + /> + + ${this.isLoaded?x$1` + <img + class="animated-image__frozen" + src=${this.frozenFrame} + alt=${this.alt} + aria-hidden=${this.play?"true":"false"} + @click=${this.handleClick} + /> + + <div part="control-box" class="animated-image__control-box"> + <slot name="play-icon"><sl-icon name="play-fill" library="system"></sl-icon></slot> + <slot name="pause-icon"><sl-icon name="pause-fill" library="system"></sl-icon></slot> + </div> + `:""} + </div> + `}};SlAnimatedImage.styles=[component_styles_default,animated_image_styles_default],SlAnimatedImage.dependencies={"sl-icon":SlIcon},__decorateClass([e$6(".animated-image__animated")],SlAnimatedImage.prototype,"animatedImage",2),__decorateClass([r$6()],SlAnimatedImage.prototype,"frozenFrame",2),__decorateClass([r$6()],SlAnimatedImage.prototype,"isLoaded",2),__decorateClass([n$5()],SlAnimatedImage.prototype,"src",2),__decorateClass([n$5()],SlAnimatedImage.prototype,"alt",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlAnimatedImage.prototype,"play",2),__decorateClass([watch("play",{waitUntilFirstUpdate:!0})],SlAnimatedImage.prototype,"handlePlayChange",1),__decorateClass([watch("src")],SlAnimatedImage.prototype,"handleSrcChange",1),SlAnimatedImage.define("sl-animated-image");var alert_styles_default=i$7` + :host { + display: contents; + + /* For better DX, we'll reset the margin here so the base part can inherit it */ + margin: 0; + } + + .alert { + position: relative; + display: flex; + align-items: stretch; + background-color: var(--sl-panel-background-color); + border: solid var(--sl-panel-border-width) var(--sl-panel-border-color); + border-top-width: calc(var(--sl-panel-border-width) * 3); + border-radius: var(--sl-border-radius-medium); + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-small); + font-weight: var(--sl-font-weight-normal); + line-height: 1.6; + color: var(--sl-color-neutral-700); + margin: inherit; + overflow: hidden; + } + + .alert:not(.alert--has-icon) .alert__icon, + .alert:not(.alert--closable) .alert__close-button { + display: none; + } + + .alert__icon { + flex: 0 0 auto; + display: flex; + align-items: center; + font-size: var(--sl-font-size-large); + padding-inline-start: var(--sl-spacing-large); + } + + .alert--has-countdown { + border-bottom: none; + } + + .alert--primary { + border-top-color: var(--sl-color-primary-600); + } + + .alert--primary .alert__icon { + color: var(--sl-color-primary-600); + } + + .alert--success { + border-top-color: var(--sl-color-success-600); + } + + .alert--success .alert__icon { + color: var(--sl-color-success-600); + } + + .alert--neutral { + border-top-color: var(--sl-color-neutral-600); + } + + .alert--neutral .alert__icon { + color: var(--sl-color-neutral-600); + } + + .alert--warning { + border-top-color: var(--sl-color-warning-600); + } + + .alert--warning .alert__icon { + color: var(--sl-color-warning-600); + } + + .alert--danger { + border-top-color: var(--sl-color-danger-600); + } + + .alert--danger .alert__icon { + color: var(--sl-color-danger-600); + } + + .alert__message { + flex: 1 1 auto; + display: block; + padding: var(--sl-spacing-large); + overflow: hidden; + } + + .alert__close-button { + flex: 0 0 auto; + display: flex; + align-items: center; + font-size: var(--sl-font-size-medium); + margin-inline-end: var(--sl-spacing-medium); + align-self: center; + } + + .alert__countdown { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: calc(var(--sl-panel-border-width) * 3); + background-color: var(--sl-panel-border-color); + display: flex; + } + + .alert__countdown--ltr { + justify-content: flex-end; + } + + .alert__countdown .alert__countdown-elapsed { + height: 100%; + width: 0; + } + + .alert--primary .alert__countdown-elapsed { + background-color: var(--sl-color-primary-600); + } + + .alert--success .alert__countdown-elapsed { + background-color: var(--sl-color-success-600); + } + + .alert--neutral .alert__countdown-elapsed { + background-color: var(--sl-color-neutral-600); + } + + .alert--warning .alert__countdown-elapsed { + background-color: var(--sl-color-warning-600); + } + + .alert--danger .alert__countdown-elapsed { + background-color: var(--sl-color-danger-600); + } + + .alert__timer { + display: none; + } +`,_SlAlert=class _SlAlert extends ShoelaceElement{constructor(){super(...arguments),this.hasSlotController=new HasSlotController(this,"icon","suffix"),this.localize=new LocalizeController(this),this.open=!1,this.closable=!1,this.variant="primary",this.duration=1/0,this.remainingTime=this.duration}static get toastStack(){return this.currentToastStack||(this.currentToastStack=Object.assign(document.createElement("div"),{className:"sl-toast-stack"})),this.currentToastStack}firstUpdated(){this.base.hidden=!this.open}restartAutoHide(){this.handleCountdownChange(),clearTimeout(this.autoHideTimeout),clearInterval(this.remainingTimeInterval),this.open&&this.duration<1/0&&(this.autoHideTimeout=window.setTimeout(()=>this.hide(),this.duration),this.remainingTime=this.duration,this.remainingTimeInterval=window.setInterval(()=>{this.remainingTime-=100},100))}pauseAutoHide(){var _a;null==(_a=this.countdownAnimation)?void 0:_a.pause(),clearTimeout(this.autoHideTimeout),clearInterval(this.remainingTimeInterval)}resumeAutoHide(){var _a;this.duration<1/0&&(this.autoHideTimeout=window.setTimeout(()=>this.hide(),this.remainingTime),this.remainingTimeInterval=window.setInterval(()=>{this.remainingTime-=100},100),null==(_a=this.countdownAnimation)?void 0:_a.play())}handleCountdownChange(){if(this.open&&this.duration<1/0&&this.countdown){const{countdownElement}=this,start="100%",end="0";this.countdownAnimation=countdownElement.animate([{width:start},{width:end}],{duration:this.duration,easing:"linear"})}}handleCloseClick(){this.hide()}async handleOpenChange(){if(this.open){this.emit("sl-show"),this.duration<1/0&&this.restartAutoHide(),await stopAnimations(this.base),this.base.hidden=!1;const{keyframes,options}=getAnimation(this,"alert.show",{dir:this.localize.dir()});await animateTo(this.base,keyframes,options),this.emit("sl-after-show")}else{blurActiveElement(this),this.emit("sl-hide"),clearTimeout(this.autoHideTimeout),clearInterval(this.remainingTimeInterval),await stopAnimations(this.base);const{keyframes,options}=getAnimation(this,"alert.hide",{dir:this.localize.dir()});await animateTo(this.base,keyframes,options),this.base.hidden=!0,this.emit("sl-after-hide")}}handleDurationChange(){this.restartAutoHide()}async show(){if(!this.open)return this.open=!0,waitForEvent(this,"sl-after-show")}async hide(){if(this.open)return this.open=!1,waitForEvent(this,"sl-after-hide")}async toast(){return new Promise(resolve=>{this.handleCountdownChange(),null===_SlAlert.toastStack.parentElement&&document.body.append(_SlAlert.toastStack),_SlAlert.toastStack.appendChild(this),requestAnimationFrame(()=>{this.clientWidth,this.show()}),this.addEventListener("sl-after-hide",()=>{_SlAlert.toastStack.removeChild(this),resolve(),null===_SlAlert.toastStack.querySelector("sl-alert")&&_SlAlert.toastStack.remove()},{once:!0})})}render(){return x$1` + <div + part="base" + class=${e$2({alert:!0,"alert--open":this.open,"alert--closable":this.closable,"alert--has-countdown":!!this.countdown,"alert--has-icon":this.hasSlotController.test("icon"),"alert--primary":"primary"===this.variant,"alert--success":"success"===this.variant,"alert--neutral":"neutral"===this.variant,"alert--warning":"warning"===this.variant,"alert--danger":"danger"===this.variant})} + role="alert" + aria-hidden=${this.open?"false":"true"} + @mouseenter=${this.pauseAutoHide} + @mouseleave=${this.resumeAutoHide} + > + <div part="icon" class="alert__icon"> + <slot name="icon"></slot> + </div> + + <div part="message" class="alert__message" aria-live="polite"> + <slot></slot> + </div> + + ${this.closable?x$1` + <sl-icon-button + part="close-button" + exportparts="base:close-button__base" + class="alert__close-button" + name="x-lg" + library="system" + label=${this.localize.term("close")} + @click=${this.handleCloseClick} + ></sl-icon-button> + `:""} + + <div role="timer" class="alert__timer">${this.remainingTime}</div> + + ${this.countdown?x$1` + <div + class=${e$2({alert__countdown:!0,"alert__countdown--ltr":"ltr"===this.countdown})} + > + <div class="alert__countdown-elapsed"></div> + </div> + `:""} + </div> + `}};_SlAlert.styles=[component_styles_default,alert_styles_default],_SlAlert.dependencies={"sl-icon-button":SlIconButton},__decorateClass([e$6("[part~=\"base\"]")],_SlAlert.prototype,"base",2),__decorateClass([e$6(".alert__countdown-elapsed")],_SlAlert.prototype,"countdownElement",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlAlert.prototype,"open",2),__decorateClass([n$5({type:Boolean,reflect:!0})],_SlAlert.prototype,"closable",2),__decorateClass([n$5({reflect:!0})],_SlAlert.prototype,"variant",2),__decorateClass([n$5({type:Number})],_SlAlert.prototype,"duration",2),__decorateClass([n$5({type:String,reflect:!0})],_SlAlert.prototype,"countdown",2),__decorateClass([r$6()],_SlAlert.prototype,"remainingTime",2),__decorateClass([watch("open",{waitUntilFirstUpdate:!0})],_SlAlert.prototype,"handleOpenChange",1),__decorateClass([watch("duration")],_SlAlert.prototype,"handleDurationChange",1);var SlAlert=_SlAlert;setDefaultAnimation("alert.show",{keyframes:[{opacity:0,scale:.8},{opacity:1,scale:1}],options:{duration:250,easing:"ease"}}),setDefaultAnimation("alert.hide",{keyframes:[{opacity:1,scale:1},{opacity:0,scale:.8}],options:{duration:250,easing:"ease"}}),SlAlert.define("sl-alert");const bounce=[{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)",transform:"translate3d(0, 0, 0)"},{offset:.2,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)",transform:"translate3d(0, 0, 0)"},{offset:.4,easing:"cubic-bezier(0.755, 0.05, 0.855, 0.06)",transform:"translate3d(0, -30px, 0) scaleY(1.1)"},{offset:.43,easing:"cubic-bezier(0.755, 0.05, 0.855, 0.06)",transform:"translate3d(0, -30px, 0) scaleY(1.1)"},{offset:.53,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)",transform:"translate3d(0, 0, 0)"},{offset:.7,easing:"cubic-bezier(0.755, 0.05, 0.855, 0.06)",transform:"translate3d(0, -15px, 0) scaleY(1.05)"},{offset:.8,"transition-timing-function":"cubic-bezier(0.215, 0.61, 0.355, 1)",transform:"translate3d(0, 0, 0) scaleY(0.95)"},{offset:.9,transform:"translate3d(0, -4px, 0) scaleY(1.02)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)",transform:"translate3d(0, 0, 0)"}],flash=[{offset:0,opacity:"1"},{offset:.25,opacity:"0"},{offset:.5,opacity:"1"},{offset:.75,opacity:"0"},{offset:1,opacity:"1"}],headShake=[{offset:0,transform:"translateX(0)"},{offset:.065,transform:"translateX(-6px) rotateY(-9deg)"},{offset:.185,transform:"translateX(5px) rotateY(7deg)"},{offset:.315,transform:"translateX(-3px) rotateY(-5deg)"},{offset:.435,transform:"translateX(2px) rotateY(3deg)"},{offset:.5,transform:"translateX(0)"}],heartBeat=[{offset:0,transform:"scale(1)"},{offset:.14,transform:"scale(1.3)"},{offset:.28,transform:"scale(1)"},{offset:.42,transform:"scale(1.3)"},{offset:.7,transform:"scale(1)"}],jello=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:.111,transform:"translate3d(0, 0, 0)"},{offset:.222,transform:"skewX(-12.5deg) skewY(-12.5deg)"},{offset:.33299999999999996,transform:"skewX(6.25deg) skewY(6.25deg)"},{offset:.444,transform:"skewX(-3.125deg) skewY(-3.125deg)"},{offset:.555,transform:"skewX(1.5625deg) skewY(1.5625deg)"},{offset:.6659999999999999,transform:"skewX(-0.78125deg) skewY(-0.78125deg)"},{offset:.777,transform:"skewX(0.390625deg) skewY(0.390625deg)"},{offset:.888,transform:"skewX(-0.1953125deg) skewY(-0.1953125deg)"},{offset:1,transform:"translate3d(0, 0, 0)"}],pulse=[{offset:0,transform:"scale3d(1, 1, 1)"},{offset:.5,transform:"scale3d(1.05, 1.05, 1.05)"},{offset:1,transform:"scale3d(1, 1, 1)"}],rubberBand=[{offset:0,transform:"scale3d(1, 1, 1)"},{offset:.3,transform:"scale3d(1.25, 0.75, 1)"},{offset:.4,transform:"scale3d(0.75, 1.25, 1)"},{offset:.5,transform:"scale3d(1.15, 0.85, 1)"},{offset:.65,transform:"scale3d(0.95, 1.05, 1)"},{offset:.75,transform:"scale3d(1.05, 0.95, 1)"},{offset:1,transform:"scale3d(1, 1, 1)"}],shake=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:.1,transform:"translate3d(-10px, 0, 0)"},{offset:.2,transform:"translate3d(10px, 0, 0)"},{offset:.3,transform:"translate3d(-10px, 0, 0)"},{offset:.4,transform:"translate3d(10px, 0, 0)"},{offset:.5,transform:"translate3d(-10px, 0, 0)"},{offset:.6,transform:"translate3d(10px, 0, 0)"},{offset:.7,transform:"translate3d(-10px, 0, 0)"},{offset:.8,transform:"translate3d(10px, 0, 0)"},{offset:.9,transform:"translate3d(-10px, 0, 0)"},{offset:1,transform:"translate3d(0, 0, 0)"}],shakeX=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:.1,transform:"translate3d(-10px, 0, 0)"},{offset:.2,transform:"translate3d(10px, 0, 0)"},{offset:.3,transform:"translate3d(-10px, 0, 0)"},{offset:.4,transform:"translate3d(10px, 0, 0)"},{offset:.5,transform:"translate3d(-10px, 0, 0)"},{offset:.6,transform:"translate3d(10px, 0, 0)"},{offset:.7,transform:"translate3d(-10px, 0, 0)"},{offset:.8,transform:"translate3d(10px, 0, 0)"},{offset:.9,transform:"translate3d(-10px, 0, 0)"},{offset:1,transform:"translate3d(0, 0, 0)"}],shakeY=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:.1,transform:"translate3d(0, -10px, 0)"},{offset:.2,transform:"translate3d(0, 10px, 0)"},{offset:.3,transform:"translate3d(0, -10px, 0)"},{offset:.4,transform:"translate3d(0, 10px, 0)"},{offset:.5,transform:"translate3d(0, -10px, 0)"},{offset:.6,transform:"translate3d(0, 10px, 0)"},{offset:.7,transform:"translate3d(0, -10px, 0)"},{offset:.8,transform:"translate3d(0, 10px, 0)"},{offset:.9,transform:"translate3d(0, -10px, 0)"},{offset:1,transform:"translate3d(0, 0, 0)"}],swing=[{offset:.2,transform:"rotate3d(0, 0, 1, 15deg)"},{offset:.4,transform:"rotate3d(0, 0, 1, -10deg)"},{offset:.6,transform:"rotate3d(0, 0, 1, 5deg)"},{offset:.8,transform:"rotate3d(0, 0, 1, -5deg)"},{offset:1,transform:"rotate3d(0, 0, 1, 0deg)"}],tada=[{offset:0,transform:"scale3d(1, 1, 1)"},{offset:.1,transform:"scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg)"},{offset:.2,transform:"scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg)"},{offset:.3,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)"},{offset:.4,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)"},{offset:.5,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)"},{offset:.6,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)"},{offset:.7,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)"},{offset:.8,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)"},{offset:.9,transform:"scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)"},{offset:1,transform:"scale3d(1, 1, 1)"}],wobble=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:.15,transform:"translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)"},{offset:.3,transform:"translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)"},{offset:.45,transform:"translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)"},{offset:.6,transform:"translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)"},{offset:.75,transform:"translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)"},{offset:1,transform:"translate3d(0, 0, 0)"}],backInDown=[{offset:0,transform:"translateY(-1200px) scale(0.7)",opacity:"0.7"},{offset:.8,transform:"translateY(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"scale(1)",opacity:"1"}],backInLeft=[{offset:0,transform:"translateX(-2000px) scale(0.7)",opacity:"0.7"},{offset:.8,transform:"translateX(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"scale(1)",opacity:"1"}],backInRight=[{offset:0,transform:"translateX(2000px) scale(0.7)",opacity:"0.7"},{offset:.8,transform:"translateX(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"scale(1)",opacity:"1"}],backInUp=[{offset:0,transform:"translateY(1200px) scale(0.7)",opacity:"0.7"},{offset:.8,transform:"translateY(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"scale(1)",opacity:"1"}],backOutDown=[{offset:0,transform:"scale(1)",opacity:"1"},{offset:.2,transform:"translateY(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"translateY(700px) scale(0.7)",opacity:"0.7"}],backOutLeft=[{offset:0,transform:"scale(1)",opacity:"1"},{offset:.2,transform:"translateX(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"translateX(-2000px) scale(0.7)",opacity:"0.7"}],backOutRight=[{offset:0,transform:"scale(1)",opacity:"1"},{offset:.2,transform:"translateX(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"translateX(2000px) scale(0.7)",opacity:"0.7"}],backOutUp=[{offset:0,transform:"scale(1)",opacity:"1"},{offset:.2,transform:"translateY(0px) scale(0.7)",opacity:"0.7"},{offset:1,transform:"translateY(-700px) scale(0.7)",opacity:"0.7"}],bounceIn=[{offset:0,opacity:"0",transform:"scale3d(0.3, 0.3, 0.3)"},{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.2,transform:"scale3d(1.1, 1.1, 1.1)"},{offset:.2,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.4,transform:"scale3d(0.9, 0.9, 0.9)"},{offset:.4,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.6,opacity:"1",transform:"scale3d(1.03, 1.03, 1.03)"},{offset:.6,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.8,transform:"scale3d(0.97, 0.97, 0.97)"},{offset:.8,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:1,opacity:"1",transform:"scale3d(1, 1, 1)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"}],bounceInDown=[{offset:0,opacity:"0",transform:"translate3d(0, -3000px, 0) scaleY(3)"},{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.6,opacity:"1",transform:"translate3d(0, 25px, 0) scaleY(0.9)"},{offset:.6,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.75,transform:"translate3d(0, -10px, 0) scaleY(0.95)"},{offset:.75,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.9,transform:"translate3d(0, 5px, 0) scaleY(0.985)"},{offset:.9,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:1,transform:"translate3d(0, 0, 0)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"}],bounceInLeft=[{offset:0,opacity:"0",transform:"translate3d(-3000px, 0, 0) scaleX(3)"},{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.6,opacity:"1",transform:"translate3d(25px, 0, 0) scaleX(1)"},{offset:.6,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.75,transform:"translate3d(-10px, 0, 0) scaleX(0.98)"},{offset:.75,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.9,transform:"translate3d(5px, 0, 0) scaleX(0.995)"},{offset:.9,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:1,transform:"translate3d(0, 0, 0)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"}],bounceInRight=[{offset:0,opacity:"0",transform:"translate3d(3000px, 0, 0) scaleX(3)"},{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.6,opacity:"1",transform:"translate3d(-25px, 0, 0) scaleX(1)"},{offset:.6,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.75,transform:"translate3d(10px, 0, 0) scaleX(0.98)"},{offset:.75,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.9,transform:"translate3d(-5px, 0, 0) scaleX(0.995)"},{offset:.9,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:1,transform:"translate3d(0, 0, 0)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"}],bounceInUp=[{offset:0,opacity:"0",transform:"translate3d(0, 3000px, 0) scaleY(5)"},{offset:0,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.6,opacity:"1",transform:"translate3d(0, -20px, 0) scaleY(0.9)"},{offset:.6,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.75,transform:"translate3d(0, 10px, 0) scaleY(0.95)"},{offset:.75,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:.9,transform:"translate3d(0, -5px, 0) scaleY(0.985)"},{offset:.9,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"},{offset:1,transform:"translate3d(0, 0, 0)"},{offset:1,easing:"cubic-bezier(0.215, 0.61, 0.355, 1)"}],bounceOut=[{offset:.2,transform:"scale3d(0.9, 0.9, 0.9)"},{offset:.5,opacity:"1",transform:"scale3d(1.1, 1.1, 1.1)"},{offset:.55,opacity:"1",transform:"scale3d(1.1, 1.1, 1.1)"},{offset:1,opacity:"0",transform:"scale3d(0.3, 0.3, 0.3)"}],bounceOutDown=[{offset:.2,transform:"translate3d(0, 10px, 0) scaleY(0.985)"},{offset:.4,opacity:"1",transform:"translate3d(0, -20px, 0) scaleY(0.9)"},{offset:.45,opacity:"1",transform:"translate3d(0, -20px, 0) scaleY(0.9)"},{offset:1,opacity:"0",transform:"translate3d(0, 2000px, 0) scaleY(3)"}],bounceOutLeft=[{offset:.2,opacity:"1",transform:"translate3d(20px, 0, 0) scaleX(0.9)"},{offset:1,opacity:"0",transform:"translate3d(-2000px, 0, 0) scaleX(2)"}],bounceOutRight=[{offset:.2,opacity:"1",transform:"translate3d(-20px, 0, 0) scaleX(0.9)"},{offset:1,opacity:"0",transform:"translate3d(2000px, 0, 0) scaleX(2)"}],bounceOutUp=[{offset:.2,transform:"translate3d(0, -10px, 0) scaleY(0.985)"},{offset:.4,opacity:"1",transform:"translate3d(0, 20px, 0) scaleY(0.9)"},{offset:.45,opacity:"1",transform:"translate3d(0, 20px, 0) scaleY(0.9)"},{offset:1,opacity:"0",transform:"translate3d(0, -2000px, 0) scaleY(3)"}],fadeIn=[{offset:0,opacity:"0"},{offset:1,opacity:"1"}],fadeInBottomLeft=[{offset:0,opacity:"0",transform:"translate3d(-100%, 100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInBottomRight=[{offset:0,opacity:"0",transform:"translate3d(100%, 100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInDown=[{offset:0,opacity:"0",transform:"translate3d(0, -100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInDownBig=[{offset:0,opacity:"0",transform:"translate3d(0, -2000px, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInLeft=[{offset:0,opacity:"0",transform:"translate3d(-100%, 0, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInLeftBig=[{offset:0,opacity:"0",transform:"translate3d(-2000px, 0, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInRight=[{offset:0,opacity:"0",transform:"translate3d(100%, 0, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInRightBig=[{offset:0,opacity:"0",transform:"translate3d(2000px, 0, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInTopLeft=[{offset:0,opacity:"0",transform:"translate3d(-100%, -100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInTopRight=[{offset:0,opacity:"0",transform:"translate3d(100%, -100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInUp=[{offset:0,opacity:"0",transform:"translate3d(0, 100%, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeInUpBig=[{offset:0,opacity:"0",transform:"translate3d(0, 2000px, 0)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],fadeOut=[{offset:0,opacity:"1"},{offset:1,opacity:"0"}],fadeOutBottomLeft=[{offset:0,opacity:"1",transform:"translate3d(0, 0, 0)"},{offset:1,opacity:"0",transform:"translate3d(-100%, 100%, 0)"}],fadeOutBottomRight=[{offset:0,opacity:"1",transform:"translate3d(0, 0, 0)"},{offset:1,opacity:"0",transform:"translate3d(100%, 100%, 0)"}],fadeOutDown=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(0, 100%, 0)"}],fadeOutDownBig=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(0, 2000px, 0)"}],fadeOutLeft=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(-100%, 0, 0)"}],fadeOutLeftBig=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(-2000px, 0, 0)"}],fadeOutRight=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(100%, 0, 0)"}],fadeOutRightBig=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(2000px, 0, 0)"}],fadeOutTopLeft=[{offset:0,opacity:"1",transform:"translate3d(0, 0, 0)"},{offset:1,opacity:"0",transform:"translate3d(-100%, -100%, 0)"}],fadeOutTopRight=[{offset:0,opacity:"1",transform:"translate3d(0, 0, 0)"},{offset:1,opacity:"0",transform:"translate3d(100%, -100%, 0)"}],fadeOutUp=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(0, -100%, 0)"}],fadeOutUpBig=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(0, -2000px, 0)"}],flip=[{offset:0,transform:"perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg)",easing:"ease-out"},{offset:.4,transform:"perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)\n rotate3d(0, 1, 0, -190deg)",easing:"ease-out"},{offset:.5,transform:"perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 150px)\n rotate3d(0, 1, 0, -170deg)",easing:"ease-in"},{offset:.8,transform:"perspective(400px) scale3d(0.95, 0.95, 0.95) translate3d(0, 0, 0)\n rotate3d(0, 1, 0, 0deg)",easing:"ease-in"},{offset:1,transform:"perspective(400px) scale3d(1, 1, 1) translate3d(0, 0, 0) rotate3d(0, 1, 0, 0deg)",easing:"ease-in"}],flipInX=[{offset:0,transform:"perspective(400px) rotate3d(1, 0, 0, 90deg)",easing:"ease-in",opacity:"0"},{offset:.4,transform:"perspective(400px) rotate3d(1, 0, 0, -20deg)",easing:"ease-in"},{offset:.6,transform:"perspective(400px) rotate3d(1, 0, 0, 10deg)",opacity:"1"},{offset:.8,transform:"perspective(400px) rotate3d(1, 0, 0, -5deg)"},{offset:1,transform:"perspective(400px)"}],flipInY=[{offset:0,transform:"perspective(400px) rotate3d(0, 1, 0, 90deg)",easing:"ease-in",opacity:"0"},{offset:.4,transform:"perspective(400px) rotate3d(0, 1, 0, -20deg)",easing:"ease-in"},{offset:.6,transform:"perspective(400px) rotate3d(0, 1, 0, 10deg)",opacity:"1"},{offset:.8,transform:"perspective(400px) rotate3d(0, 1, 0, -5deg)"},{offset:1,transform:"perspective(400px)"}],flipOutX=[{offset:0,transform:"perspective(400px)"},{offset:.3,transform:"perspective(400px) rotate3d(1, 0, 0, -20deg)",opacity:"1"},{offset:1,transform:"perspective(400px) rotate3d(1, 0, 0, 90deg)",opacity:"0"}],flipOutY=[{offset:0,transform:"perspective(400px)"},{offset:.3,transform:"perspective(400px) rotate3d(0, 1, 0, -15deg)",opacity:"1"},{offset:1,transform:"perspective(400px) rotate3d(0, 1, 0, 90deg)",opacity:"0"}],lightSpeedInLeft=[{offset:0,transform:"translate3d(-100%, 0, 0) skewX(30deg)",opacity:"0"},{offset:.6,transform:"skewX(-20deg)",opacity:"1"},{offset:.8,transform:"skewX(5deg)"},{offset:1,transform:"translate3d(0, 0, 0)"}],lightSpeedInRight=[{offset:0,transform:"translate3d(100%, 0, 0) skewX(-30deg)",opacity:"0"},{offset:.6,transform:"skewX(20deg)",opacity:"1"},{offset:.8,transform:"skewX(-5deg)"},{offset:1,transform:"translate3d(0, 0, 0)"}],lightSpeedOutLeft=[{offset:0,opacity:"1"},{offset:1,transform:"translate3d(-100%, 0, 0) skewX(-30deg)",opacity:"0"}],lightSpeedOutRight=[{offset:0,opacity:"1"},{offset:1,transform:"translate3d(100%, 0, 0) skewX(30deg)",opacity:"0"}],rotateIn=[{offset:0,transform:"rotate3d(0, 0, 1, -200deg)",opacity:"0"},{offset:1,transform:"translate3d(0, 0, 0)",opacity:"1"}],rotateInDownLeft=[{offset:0,transform:"rotate3d(0, 0, 1, -45deg)",opacity:"0"},{offset:1,transform:"translate3d(0, 0, 0)",opacity:"1"}],rotateInDownRight=[{offset:0,transform:"rotate3d(0, 0, 1, 45deg)",opacity:"0"},{offset:1,transform:"translate3d(0, 0, 0)",opacity:"1"}],rotateInUpLeft=[{offset:0,transform:"rotate3d(0, 0, 1, 45deg)",opacity:"0"},{offset:1,transform:"translate3d(0, 0, 0)",opacity:"1"}],rotateInUpRight=[{offset:0,transform:"rotate3d(0, 0, 1, -90deg)",opacity:"0"},{offset:1,transform:"translate3d(0, 0, 0)",opacity:"1"}],rotateOut=[{offset:0,opacity:"1"},{offset:1,transform:"rotate3d(0, 0, 1, 200deg)",opacity:"0"}],rotateOutDownLeft=[{offset:0,opacity:"1"},{offset:1,transform:"rotate3d(0, 0, 1, 45deg)",opacity:"0"}],rotateOutDownRight=[{offset:0,opacity:"1"},{offset:1,transform:"rotate3d(0, 0, 1, -45deg)",opacity:"0"}],rotateOutUpLeft=[{offset:0,opacity:"1"},{offset:1,transform:"rotate3d(0, 0, 1, -45deg)",opacity:"0"}],rotateOutUpRight=[{offset:0,opacity:"1"},{offset:1,transform:"rotate3d(0, 0, 1, 90deg)",opacity:"0"}],slideInDown=[{offset:0,transform:"translate3d(0, -100%, 0)",visibility:"visible"},{offset:1,transform:"translate3d(0, 0, 0)"}],slideInLeft=[{offset:0,transform:"translate3d(-100%, 0, 0)",visibility:"visible"},{offset:1,transform:"translate3d(0, 0, 0)"}],slideInRight=[{offset:0,transform:"translate3d(100%, 0, 0)",visibility:"visible"},{offset:1,transform:"translate3d(0, 0, 0)"}],slideInUp=[{offset:0,transform:"translate3d(0, 100%, 0)",visibility:"visible"},{offset:1,transform:"translate3d(0, 0, 0)"}],slideOutDown=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:1,visibility:"hidden",transform:"translate3d(0, 100%, 0)"}],slideOutLeft=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:1,visibility:"hidden",transform:"translate3d(-100%, 0, 0)"}],slideOutRight=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:1,visibility:"hidden",transform:"translate3d(100%, 0, 0)"}],slideOutUp=[{offset:0,transform:"translate3d(0, 0, 0)"},{offset:1,visibility:"hidden",transform:"translate3d(0, -100%, 0)"}],hinge=[{offset:0,easing:"ease-in-out"},{offset:.2,transform:"rotate3d(0, 0, 1, 80deg)",easing:"ease-in-out"},{offset:.4,transform:"rotate3d(0, 0, 1, 60deg)",easing:"ease-in-out",opacity:"1"},{offset:.6,transform:"rotate3d(0, 0, 1, 80deg)",easing:"ease-in-out"},{offset:.8,transform:"rotate3d(0, 0, 1, 60deg)",easing:"ease-in-out",opacity:"1"},{offset:1,transform:"translate3d(0, 700px, 0)",opacity:"0"}],jackInTheBox=[{offset:0,opacity:"0",transform:"scale(0.1) rotate(30deg)","transform-origin":"center bottom"},{offset:.5,transform:"rotate(-10deg)"},{offset:.7,transform:"rotate(3deg)"},{offset:1,opacity:"1",transform:"scale(1)"}],rollIn=[{offset:0,opacity:"0",transform:"translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)"},{offset:1,opacity:"1",transform:"translate3d(0, 0, 0)"}],rollOut=[{offset:0,opacity:"1"},{offset:1,opacity:"0",transform:"translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)"}],zoomIn=[{offset:0,opacity:"0",transform:"scale3d(0.3, 0.3, 0.3)"},{offset:.5,opacity:"1"}],zoomInDown=[{offset:0,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(0, -1000px, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:.6,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],zoomInLeft=[{offset:0,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(-1000px, 0, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:.6,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(10px, 0, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],zoomInRight=[{offset:0,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(1000px, 0, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:.6,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(-10px, 0, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],zoomInUp=[{offset:0,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(0, 1000px, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:.6,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],zoomOut=[{offset:0,opacity:"1"},{offset:.5,opacity:"0",transform:"scale3d(0.3, 0.3, 0.3)"},{offset:1,opacity:"0"}],zoomOutDown=[{offset:.4,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(0, -60px, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:1,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(0, 2000px, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],zoomOutLeft=[{offset:.4,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(42px, 0, 0)"},{offset:1,opacity:"0",transform:"scale(0.1) translate3d(-2000px, 0, 0)"}],zoomOutRight=[{offset:.4,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(-42px, 0, 0)"},{offset:1,opacity:"0",transform:"scale(0.1) translate3d(2000px, 0, 0)"}],zoomOutUp=[{offset:.4,opacity:"1",transform:"scale3d(0.475, 0.475, 0.475) translate3d(0, 60px, 0)",easing:"cubic-bezier(0.55, 0.055, 0.675, 0.19)"},{offset:1,opacity:"0",transform:"scale3d(0.1, 0.1, 0.1) translate3d(0, -2000px, 0)",easing:"cubic-bezier(0.175, 0.885, 0.32, 1)"}],easings={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",easeInSine:"cubic-bezier(0.47, 0, 0.745, 0.715)",easeOutSine:"cubic-bezier(0.39, 0.575, 0.565, 1)",easeInOutSine:"cubic-bezier(0.445, 0.05, 0.55, 0.95)",easeInQuad:"cubic-bezier(0.55, 0.085, 0.68, 0.53)",easeOutQuad:"cubic-bezier(0.25, 0.46, 0.45, 0.94)",easeInOutQuad:"cubic-bezier(0.455, 0.03, 0.515, 0.955)",easeInCubic:"cubic-bezier(0.55, 0.055, 0.675, 0.19)",easeOutCubic:"cubic-bezier(0.215, 0.61, 0.355, 1)",easeInOutCubic:"cubic-bezier(0.645, 0.045, 0.355, 1)",easeInQuart:"cubic-bezier(0.895, 0.03, 0.685, 0.22)",easeOutQuart:"cubic-bezier(0.165, 0.84, 0.44, 1)",easeInOutQuart:"cubic-bezier(0.77, 0, 0.175, 1)",easeInQuint:"cubic-bezier(0.755, 0.05, 0.855, 0.06)",easeOutQuint:"cubic-bezier(0.23, 1, 0.32, 1)",easeInOutQuint:"cubic-bezier(0.86, 0, 0.07, 1)",easeInExpo:"cubic-bezier(0.95, 0.05, 0.795, 0.035)",easeOutExpo:"cubic-bezier(0.19, 1, 0.22, 1)",easeInOutExpo:"cubic-bezier(1, 0, 0, 1)",easeInCirc:"cubic-bezier(0.6, 0.04, 0.98, 0.335)",easeOutCirc:"cubic-bezier(0.075, 0.82, 0.165, 1)",easeInOutCirc:"cubic-bezier(0.785, 0.135, 0.15, 0.86)",easeInBack:"cubic-bezier(0.6, -0.28, 0.735, 0.045)",easeOutBack:"cubic-bezier(0.175, 0.885, 0.32, 1.275)",easeInOutBack:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"};var animations=Object.freeze({__proto__:null,backInDown:backInDown,backInLeft:backInLeft,backInRight:backInRight,backInUp:backInUp,backOutDown:backOutDown,backOutLeft:backOutLeft,backOutRight:backOutRight,backOutUp:backOutUp,bounce:bounce,bounceIn:bounceIn,bounceInDown:bounceInDown,bounceInLeft:bounceInLeft,bounceInRight:bounceInRight,bounceInUp:bounceInUp,bounceOut:bounceOut,bounceOutDown:bounceOutDown,bounceOutLeft:bounceOutLeft,bounceOutRight:bounceOutRight,bounceOutUp:bounceOutUp,easings:easings,fadeIn:fadeIn,fadeInBottomLeft:fadeInBottomLeft,fadeInBottomRight:fadeInBottomRight,fadeInDown:fadeInDown,fadeInDownBig:fadeInDownBig,fadeInLeft:fadeInLeft,fadeInLeftBig:fadeInLeftBig,fadeInRight:fadeInRight,fadeInRightBig:fadeInRightBig,fadeInTopLeft:fadeInTopLeft,fadeInTopRight:fadeInTopRight,fadeInUp:fadeInUp,fadeInUpBig:fadeInUpBig,fadeOut:fadeOut,fadeOutBottomLeft:fadeOutBottomLeft,fadeOutBottomRight:fadeOutBottomRight,fadeOutDown:fadeOutDown,fadeOutDownBig:fadeOutDownBig,fadeOutLeft:fadeOutLeft,fadeOutLeftBig:fadeOutLeftBig,fadeOutRight:fadeOutRight,fadeOutRightBig:fadeOutRightBig,fadeOutTopLeft:fadeOutTopLeft,fadeOutTopRight:fadeOutTopRight,fadeOutUp:fadeOutUp,fadeOutUpBig:fadeOutUpBig,flash:flash,flip:flip,flipInX:flipInX,flipInY:flipInY,flipOutX:flipOutX,flipOutY:flipOutY,headShake:headShake,heartBeat:heartBeat,hinge:hinge,jackInTheBox:jackInTheBox,jello:jello,lightSpeedInLeft:lightSpeedInLeft,lightSpeedInRight:lightSpeedInRight,lightSpeedOutLeft:lightSpeedOutLeft,lightSpeedOutRight:lightSpeedOutRight,pulse:pulse,rollIn:rollIn,rollOut:rollOut,rotateIn:rotateIn,rotateInDownLeft:rotateInDownLeft,rotateInDownRight:rotateInDownRight,rotateInUpLeft:rotateInUpLeft,rotateInUpRight:rotateInUpRight,rotateOut:rotateOut,rotateOutDownLeft:rotateOutDownLeft,rotateOutDownRight:rotateOutDownRight,rotateOutUpLeft:rotateOutUpLeft,rotateOutUpRight:rotateOutUpRight,rubberBand:rubberBand,shake:shake,shakeX:shakeX,shakeY:shakeY,slideInDown:slideInDown,slideInLeft:slideInLeft,slideInRight:slideInRight,slideInUp:slideInUp,slideOutDown:slideOutDown,slideOutLeft:slideOutLeft,slideOutRight:slideOutRight,slideOutUp:slideOutUp,swing:swing,tada:tada,wobble:wobble,zoomIn:zoomIn,zoomInDown:zoomInDown,zoomInLeft:zoomInLeft,zoomInRight:zoomInRight,zoomInUp:zoomInUp,zoomOut:zoomOut,zoomOutDown:zoomOutDown,zoomOutLeft:zoomOutLeft,zoomOutRight:zoomOutRight,zoomOutUp:zoomOutUp}),animation_styles_default=i$7` + :host { + display: contents; + } +`,SlAnimation=class extends ShoelaceElement{constructor(){super(...arguments),this.hasStarted=!1,this.name="none",this.play=!1,this.delay=0,this.direction="normal",this.duration=1e3,this.easing="linear",this.endDelay=0,this.fill="auto",this.iterations=1/0,this.iterationStart=0,this.playbackRate=1,this.handleAnimationFinish=()=>{this.play=!1,this.hasStarted=!1,this.emit("sl-finish")},this.handleAnimationCancel=()=>{this.play=!1,this.hasStarted=!1,this.emit("sl-cancel")}}get currentTime(){var _a,_b;return null==(_b=null==(_a=this.animation)?void 0:_a.currentTime)?0:_b}set currentTime(time){this.animation&&(this.animation.currentTime=time)}connectedCallback(){super.connectedCallback(),this.createAnimation()}disconnectedCallback(){super.disconnectedCallback(),this.destroyAnimation()}handleSlotChange(){this.destroyAnimation(),this.createAnimation()}async createAnimation(){var _a,_b;const easing=null==(_a=easings[this.easing])?this.easing:_a,keyframes=null==(_b=this.keyframes)?animations[this.name]:_b,slot=await this.defaultSlot,element=slot.assignedElements()[0];return!!(element&&keyframes)&&(this.destroyAnimation(),this.animation=element.animate(keyframes,{delay:this.delay,direction:this.direction,duration:this.duration,easing,endDelay:this.endDelay,fill:this.fill,iterationStart:this.iterationStart,iterations:this.iterations}),this.animation.playbackRate=this.playbackRate,this.animation.addEventListener("cancel",this.handleAnimationCancel),this.animation.addEventListener("finish",this.handleAnimationFinish),this.play?(this.hasStarted=!0,this.emit("sl-start")):this.animation.pause(),!0)}destroyAnimation(){this.animation&&(this.animation.cancel(),this.animation.removeEventListener("cancel",this.handleAnimationCancel),this.animation.removeEventListener("finish",this.handleAnimationFinish),this.hasStarted=!1)}handleAnimationChange(){this.hasUpdated&&this.createAnimation()}handlePlayChange(){return!!this.animation&&(this.play&&!this.hasStarted&&(this.hasStarted=!0,this.emit("sl-start")),this.play?this.animation.play():this.animation.pause(),!0)}handlePlaybackRateChange(){this.animation&&(this.animation.playbackRate=this.playbackRate)}cancel(){var _a;null==(_a=this.animation)?void 0:_a.cancel()}finish(){var _a;null==(_a=this.animation)?void 0:_a.finish()}render(){return x$1` <slot @slotchange=${this.handleSlotChange}></slot> `}};SlAnimation.styles=[component_styles_default,animation_styles_default],__decorateClass([r$4("slot")],SlAnimation.prototype,"defaultSlot",2),__decorateClass([n$5()],SlAnimation.prototype,"name",2),__decorateClass([n$5({type:Boolean,reflect:!0})],SlAnimation.prototype,"play",2),__decorateClass([n$5({type:Number})],SlAnimation.prototype,"delay",2),__decorateClass([n$5()],SlAnimation.prototype,"direction",2),__decorateClass([n$5({type:Number})],SlAnimation.prototype,"duration",2),__decorateClass([n$5()],SlAnimation.prototype,"easing",2),__decorateClass([n$5({attribute:"end-delay",type:Number})],SlAnimation.prototype,"endDelay",2),__decorateClass([n$5()],SlAnimation.prototype,"fill",2),__decorateClass([n$5({type:Number})],SlAnimation.prototype,"iterations",2),__decorateClass([n$5({attribute:"iteration-start",type:Number})],SlAnimation.prototype,"iterationStart",2),__decorateClass([n$5({attribute:!1})],SlAnimation.prototype,"keyframes",2),__decorateClass([n$5({attribute:"playback-rate",type:Number})],SlAnimation.prototype,"playbackRate",2),__decorateClass([watch(["name","delay","direction","duration","easing","endDelay","fill","iterations","iterationsStart","keyframes"])],SlAnimation.prototype,"handleAnimationChange",1),__decorateClass([watch("play")],SlAnimation.prototype,"handlePlayChange",1),__decorateClass([watch("playbackRate")],SlAnimation.prototype,"handlePlaybackRateChange",1),SlAnimation.define("sl-animation");var __decorate$f=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashTypeahead=class ChromedashTypeahead extends i$4{constructor(){super(...arguments),this.slDropdownRef=e$1(),this.slInputRef=e$1(),this.value="",this.candidates=[],this.prefix=null,this.chunkStart=0,this.chunkEnd=0,this.wasDismissed=!1,this.termWasCompleted=!1,this.placeholder=""}static get styles(){return[...SHARED_STYLES,i$7` + chromedash-typeahead-dropdown { + width: 100%; + } + #inputfield::part(base) { + background: #eee; + border: none; + border-radius: 8px; + } + `]}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}reflectValue(event){event&&event.stopPropagation();const slInput=this.slInputRef.value;this.value=slInput.value}hide(){this.slDropdownRef.value.hide()}show(){this.slDropdownRef.value.show()}focus(){const slInput=this.slInputRef.value;slInput?.focus()}blur(){const slInput=this.slInputRef.value;slInput?.blur()}findPrefix(){const inputEl=this.slInputRef.value?.input;if(!inputEl)return;const wholeStr=inputEl.value,caret=inputEl.selectionStart||0;return caret==inputEl.selectionEnd?void(this.chunkStart=wholeStr.lastIndexOf(" ",caret-1)+1,this.chunkEnd=wholeStr.indexOf(" ",caret),-1===this.chunkEnd&&(this.chunkEnd=wholeStr.length),this.prefix=wholeStr.substring(this.chunkStart,caret)):void(this.prefix=null)}shouldShowCandidate(candidate,prefix){if(null===prefix)return!1;prefix=prefix.toLowerCase();const lowerName=candidate.name.toLowerCase(),lowerDoc=candidate.doc.toLowerCase();return lowerName.split(/\s+/).some(w=>w.startsWith(prefix))||lowerDoc.split(/\s+/).some(w=>w.startsWith(prefix))||lowerName.split(/\W+/).some(w=>w.startsWith(prefix))||lowerDoc.split(/\W+/).some(w=>w.startsWith(prefix))}shouldGroup(s){if(null===s)return!0;const COMPARE_OPS=["=",":","<",">"];return!COMPARE_OPS.some(op=>s.includes(op))}groupCandidates(candidates){const groupsSeen=new Set,groupsSeenTwice=new Set;for(const c of candidates)groupsSeen.has(c.group)?groupsSeenTwice.add(c.group):groupsSeen.add(c.group);const groupsSeenTwiceProcessed=new Set,result=[];for(const c of candidates)groupsSeenTwice.has(c.group)?groupsSeenTwiceProcessed.has(c.group)||(result.push({group:c.group,name:c.group+":",doc:c.doc}),groupsSeenTwiceProcessed.add(c.group)):result.push(c);return result}async handleCandidateSelected(e){const candidateValue=e.detail.item.value,inputEl=this.slInputRef.value?.renderRoot.querySelector("input");if(!inputEl)return;const wholeStr=inputEl.value,newWholeStr=wholeStr.substring(0,this.chunkStart)+candidateValue+wholeStr.substring(this.chunkEnd,wholeStr.length);this.slInputRef.value.value=newWholeStr,this.reflectValue(),await this.updateComplete,this.chunkStart+=candidateValue.length,this.chunkEnd=this.chunkStart,inputEl.selectionStart=this.chunkStart,inputEl.selectionEnd=this.chunkEnd;const possibleExtensions=this.vocabulary.filter(c=>c.name.startsWith(candidateValue));this.termWasCompleted=1>=possibleExtensions.length,this.calcCandidates(),inputEl.focus()}handleInputFieldKeyDown(event){if("Enter"===event.key){const slDropdown=this.slDropdownRef.value;if(!slDropdown)return;const currentItem=slDropdown.getCurrentItem();slDropdown.open&¤tItem||(this._fireEvent("sl-change",this),event.stopPropagation())}}handleInputFieldKeyUp(event){return["Escape"].includes(event.key)?void(this.wasDismissed=!0):["ArrowDown","ArrowUp","Enter"].includes(event.key)?void(this.wasDismissed=!1):void(this.termWasCompleted=!1,this.calcCandidates())}calcCandidates(event){event&&event.stopPropagation(),this.findPrefix(),this.candidates=this.vocabulary.filter(c=>this.shouldShowCandidate(c,this.prefix)),this.shouldGroup(this.prefix)&&(this.candidates=this.groupCandidates(this.candidates));const slDropdown=this.slDropdownRef.value;slDropdown&&(!(0<this.candidates.length)||this.wasDismissed||this.termWasCompleted?slDropdown.hide():slDropdown.show())}renderInputField(){return x$1` + <sl-input + id="inputfield" + slot="trigger" + placeholder=${this.placeholder} + value=${l(this.value)} + ${n$2(this.slInputRef)} + autocomplete="off" + spellcheck="false" + @keydown="${this.handleInputFieldKeyDown}" + @keyup="${this.handleInputFieldKeyUp}" + @focus="${this.calcCandidates}" + @click="${this.calcCandidates}" + @sl-change="${this.reflectValue}" + @sl-input="${this.reflectValue}" + > + <slot name="prefix" slot="prefix"></slot> + <slot name="suffix" slot="suffix"></slot> + </sl-input> + `}renderAutocompleteMenu(){const nonselectableItem=x$1` + <chromedash-typeahead-invisible-item></chromedash-typeahead-invisible-item> + `;return x$1` + <sl-menu + @click=${e=>e.preventDefault()} + @sl-select=${this.handleCandidateSelected} + > + ${nonselectableItem} + ${this.candidates.map(c=>x$1` + <chromedash-typeahead-item + value=${c.name} + doc=${c.doc} + prefix=${this.prefix??E$1} + ></chromedash-typeahead-item> + `)} + </sl-menu> + `}render(){return x$1` + <chromedash-typeahead-dropdown + stay-open-on-select + sync="width" + ${n$2(this.slDropdownRef)} + > + ${this.renderInputField()} ${this.renderAutocompleteMenu()} + </chromedash-typeahead-dropdown> + `}};__decorate$f([n$5()],ChromedashTypeahead.prototype,"value",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"candidates",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"prefix",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"chunkStart",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"chunkEnd",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"wasDismissed",void 0),__decorate$f([r$6()],ChromedashTypeahead.prototype,"termWasCompleted",void 0),__decorate$f([n$5({type:String})],ChromedashTypeahead.prototype,"placeholder",void 0),__decorate$f([n$5({type:Array,attribute:!1})],ChromedashTypeahead.prototype,"vocabulary",void 0),ChromedashTypeahead=__decorate$f([t$3("chromedash-typeahead")],ChromedashTypeahead);let ChromedashTypeaheadDropdown=class ChromedashTypeaheadDropdown extends dropdown_default{getCurrentItem(){const item=this.getMenu().getCurrentItem();return!item||item instanceof ChromedashTypeaheadInvisibleItem?void 0:item}setCurrentItem(newCurrentItem){const menu=this.getMenu();menu.setCurrentItem(newCurrentItem),newCurrentItem.scrollIntoView({block:"nearest",behavior:"smooth"})}getAllVisibleItems(menu){const items=menu.getAllItems();return items.filter(item=>!(item instanceof ChromedashTypeaheadInvisibleItem))}resetSelection(){const currentItem=this.getCurrentItem();currentItem?.setAttribute("tabindex","-1")}async handleTriggerKeyDown(event){const menu=this.getMenu();if(menu){const menuItems=this.getAllVisibleItems(menu);if(0!==menuItems.length){const currentItem=menu.getCurrentItem();if(["Enter"].includes(event.key)&&(event.preventDefault(),this.open&¤tItem&&(currentItem.click(),this.resetSelection())),["ArrowDown","ArrowUp"].includes(event.key))if(event.preventDefault(),event.stopPropagation(),this.open||this.show(),currentItem){const currentItemIndex=menuItems.indexOf(currentItem);"ArrowDown"===event.key&&menuItems[currentItemIndex+1]&&this.setCurrentItem(menuItems[currentItemIndex+1]),"ArrowUp"===event.key&&menuItems[currentItemIndex-1]&&this.setCurrentItem(menuItems[currentItemIndex-1])}else"ArrowDown"===event.key&&this.setCurrentItem(menuItems[1]),"ArrowUp"===event.key&&this.setCurrentItem(menuItems[menuItems.length-1])}}}};ChromedashTypeaheadDropdown=__decorate$f([t$3("chromedash-typeahead-dropdown")],ChromedashTypeaheadDropdown);let ChromedashTypeaheadItem=class ChromedashTypeaheadItem extends i$4{constructor(){super(...arguments),this.value="",this.doc="",this.prefix="",this.tabindex=-1,this.role="menuitem"}static get styles(){return[...SHARED_STYLES,i$7` + .menu-item { + display: flex; + flex-wrap: wrap; + font-family: var(--sl-font-sans); + font-size: var(--sl-font-size-medium); + font-weight: var(--sl-font-weight-normal); + line-height: var(--sl-line-height-normal); + letter-spacing: var(--sl-letter-spacing-normal); + color: var(--sl-color-neutral-700); + padding: var(--sl-spacing-2x-small) var(--sl-spacing-2x-small); + transition: var(--sl-transition-fast) fill; + user-select: none; + -webkit-user-select: none; + white-space: nowrap; + cursor: pointer; + } + + .active { + outline: none; + background-color: var(--sl-color-primary-200); + opacity: 1; + } + #value { + width: 24em; + overflow-x: hidden; + } + code { + font-size: 85%; + background: #eee; + padding: var(--content-padding-quarter); + } + `]}handleMouseOver(event){this.parentElement&&this.parentElement.setCurrentItem(this),event.stopPropagation()}highlight(s){const start=s.toLowerCase().indexOf(this.prefix.toLowerCase());if(-1===start)return s;const before=s.substring(0,start),matching=s.substring(start,start+this.prefix.length),after=s.substring(start+this.prefix.length);return x$1`${before}<b>${matching}</b>${after}`}render(){const highlightedValue=this.highlight(this.value),highlightedDoc=this.highlight(this.doc);return x$1` + <div + class="menu-item ${0===this.tabindex?"active":""}" + @mouseover=${this.handleMouseOver} + > + <span id="value"><code>${highlightedValue}</code></span> + <span id="doc">${highlightedDoc}</span> + </div> + `}};__decorate$f([n$5({type:String})],ChromedashTypeaheadItem.prototype,"value",void 0),__decorate$f([n$5({type:String})],ChromedashTypeaheadItem.prototype,"doc",void 0),__decorate$f([n$5({type:String})],ChromedashTypeaheadItem.prototype,"prefix",void 0),__decorate$f([n$5({type:Number})],ChromedashTypeaheadItem.prototype,"tabindex",void 0),__decorate$f([n$5({type:String,reflect:!0})],ChromedashTypeaheadItem.prototype,"role",void 0),ChromedashTypeaheadItem=__decorate$f([t$3("chromedash-typeahead-item")],ChromedashTypeaheadItem);let ChromedashTypeaheadInvisibleItem=class ChromedashTypeaheadInvisibleItem extends ChromedashTypeaheadItem{render(){return x$1`${E$1}`}};ChromedashTypeaheadInvisibleItem=__decorate$f([t$3("chromedash-typeahead-invisible-item")],ChromedashTypeaheadInvisibleItem);var __decorate$e=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashReportExternalReviewsDispatchPage=class ChromedashReportExternalReviewsDispatchPage extends i$4{static get styles(){return SHARED_STYLES}render(){return x$1` + <div id="subheader">Which group's reviews do you want to see?</div> + <ul> + <li><a href="/reports/external_reviews/tag">W3C TAG</a></li> + <li> + <a href="/reports/external_reviews/gecko" + >Gecko / Firefox / Mozilla</a + > + </li> + <li> + <a href="/reports/external_reviews/webkit">WebKit / Safari / Apple</a> + </li> + </ul> + `}};ChromedashReportExternalReviewsDispatchPage=__decorate$e([t$3("chromedash-report-external-reviews-dispatch-page")],ChromedashReportExternalReviewsDispatchPage);const i=Symbol();class h{get taskComplete(){return this.t||(1===this.i?this.t=new Promise((t,s)=>{this.o=t,this.h=s}):3===this.i?this.t=Promise.reject(this.l):this.t=Promise.resolve(this.u)),this.t}constructor(t,s,i){this.p=0,this.i=0,(this._=t).addController(this);const h="object"==typeof s?s:{task:s,args:i};this.v=h.task,this.j=h.args,this.m=h.argsEqual??r$1,this.k=h.onComplete,this.A=h.onError,this.autoRun=h.autoRun??!0,"initialValue"in h&&(this.u=h.initialValue,this.i=2,this.O=this.T?.())}hostUpdate(){!0===this.autoRun&&this.S()}hostUpdated(){"afterUpdate"===this.autoRun&&this.S()}T(){if(void 0!==this.j){const t=this.j();if(!Array.isArray(t))throw Error("The args function must return an array");return t}}async S(){const t=this.T(),s=this.O;this.O=t,t===s||void 0===t||void 0!==s&&this.m(s,t)||(await this.run(t))}async run(t){let s,h;t??=this.T(),this.O=t,1===this.i?this.q?.abort():(this.t=void 0,this.o=void 0,this.h=void 0),this.i=1,"afterUpdate"===this.autoRun?queueMicrotask(()=>this._.requestUpdate()):this._.requestUpdate();const r=++this.p;this.q=new AbortController;let e=!1;try{s=await this.v(t,{signal:this.q.signal})}catch(t){e=!0,h=t}if(this.p===r){if(s===i)this.i=0;else{if(!1===e){try{this.k?.(s)}catch{}this.i=2,this.o?.(s)}else{try{this.A?.(h)}catch{}this.i=3,this.h?.(h)}this.u=s,this.l=h}this._.requestUpdate()}}abort(t){1===this.i&&this.q?.abort(t)}get value(){return this.u}get error(){return this.l}get status(){return this.i}render(t){switch(this.i){case 0:return t.initial?.();case 1:return t.pending?.();case 2:return t.complete?.(this.value);case 3:return t.error?.(this.error);default:throw Error("Unexpected status: "+this.i)}}}const r$1=(s,i)=>s===i||s.length===i.length&&s.every((s,h)=>!f$3(s,i[h])),r=(r,o,t)=>{for(const t of o)if(t[0]===r)return(0,t[1])();return t?.()};var __decorate$d=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};function ascendingNumberUndefinedLast(a,b){return a===b?0:void 0===a?1:void 0===b?-1:a-b}function compareOutstandingReview(a,b){return console.assert(a.current_stage===b.current_stage,`Tried to compare features at stages ${a.current_stage} and `+`${b.current_stage} using a function that ignores features' stages.`),a.estimated_end_milestone===b.estimated_end_milestone?a.estimated_start_milestone===b.estimated_start_milestone?a.review_link<b.review_link?-1:a.review_link>b.review_link?1:0:ascendingNumberUndefinedLast(a.estimated_start_milestone,b.estimated_start_milestone):ascendingNumberUndefinedLast(a.estimated_end_milestone,b.estimated_end_milestone)}let ChromedashReportExternalReviewsPage=class ChromedashReportExternalReviewsPage extends i$4{constructor(){super(...arguments),this.reviewer=void 0,this._client=window.csOpenApiClient,this._reviewsTask=new h(this,{task:async([reviewer],{signal})=>{if(reviewer===void 0)throw new Error("Element must have \"reviewer\" attribute.",{cause:this});if(!["tag","gecko","webkit"].includes(reviewer))throw new Error(`Reviewer (${reviewer}) must be 'tag', 'gecko', or 'webkit'.`,{cause:this});const response=await this._client.listExternalReviews({reviewGroup:reviewer},{signal});return{reviews:this.groupReviews(response.reviews),links:response.link_previews,noOutstandingReviews:0===response.reviews.length}},args:()=>[this.reviewer]})}static get styles(){return[...SHARED_STYLES,i$7` + #subheader { + display: block; + } + h3 { + margin-top: var(--content-padding); + margin-bottom: var(--content-padding-quarter); + + sl-skeleton { + width: 30%; + height: 1lh; + } + } + td.feature, + td.review { + width: 45%; + } + td.milestones { + width: 10%; + } + `]}groupReviews(reviews){const result={incubating:[],prototyping:[],"dev-trial":[],"wide-review":[],"origin-trial":[],shipping:[],shipped:[]};for(const review of reviews)review.current_stage&&result[review.current_stage].push(review);for(const list of Object.values(result))list.sort(compareOutstandingReview);return result}headerRow(){return x$1`<tr> + <th>Feature</th> + <th>Review</th> + <th>Target Milestones</th> + </tr>`}renderOutstandingReviews(reviews,links){return[["Preparing to ship","shipping"],["In Origin Trial","origin-trial"],["Getting wide review","wide-review"],["In developer trials","dev-trial"],["Prototyping","prototyping"],["Incubating","incubating"],["Already shipped","shipped"]].map(([title,key])=>0<reviews[key].length?x$1`<section> + <h3 id=${key}>${title}</h3> + <table class="data-table"> + ${this.headerRow()} + ${reviews[key].map(review=>x$1` + <tr> + <td class="feature"> + <a href="/feature/${review.feature.id}" + >${review.feature.name}</a + > + </td> + <td class="review"> + <chromedash-link + href=${review.review_link} + .featureLinks=${links} + ></chromedash-link> + </td> + <td class="milestones"> + ${review.estimated_start_milestone?"M"+review.estimated_start_milestone:E$1}${["shipping","shipped"].includes(review.current_stage)?E$1:x$1`${review.estimated_start_milestone||review.estimated_end_milestone?"\u2013":E$1}${review.estimated_end_milestone?"M"+review.estimated_end_milestone:E$1}`} + </td> + </tr> + `)} + </table> + </section>`:E$1)}render(){return x$1` + <div id="subheader"> + <h2> + Open + ${r(this.reviewer,[["tag",()=>x$1`W3C TAG`],["webkit",()=>x$1`WebKit`],["gecko",()=>x$1`Mozilla`]])} + reviews for Chromium features + </h2> + <p> + Reviews are in rough order of urgency, from about-to-ship down to + incubations. Already-shipped features are listed at the bottom. + </p> + </div> + ${this._reviewsTask.render({pending:()=>x$1` + <section> + <h3><sl-skeleton effect="sheen"></sl-skeleton></h3> + <table class="data-table"> + ${this.headerRow()} + ${[1,2,3].map(()=>x$1` + <tr> + <td class="feature"> + <sl-skeleton effect="sheen"></sl-skeleton> + </td> + <td class="review"> + <sl-skeleton effect="sheen"></sl-skeleton> + </td> + <td class="milestones"> + <sl-skeleton effect="sheen"></sl-skeleton> + </td> + </tr> + `)} + </table> + </section> + `,complete:({reviews,links,noOutstandingReviews})=>noOutstandingReviews?x$1`No outstanding reviews. Congratulations!`:this.renderOutstandingReviews(reviews,links),error:e=>(console.error(`Couldn't fetch ${this.reviewer}'s reviews: `,e),x$1`<p> + Some errors occurred. Please refresh the page or try again later. + </p>`)})} + `}};__decorate$d([n$5({type:String})],ChromedashReportExternalReviewsPage.prototype,"reviewer",void 0),__decorate$d([n$5({type:Object})],ChromedashReportExternalReviewsPage.prototype,"_client",void 0),__decorate$d([n$5({attribute:!1})],ChromedashReportExternalReviewsPage.prototype,"_reviewsTask",void 0),ChromedashReportExternalReviewsPage=__decorate$d([t$3("chromedash-report-external-reviews-page")],ChromedashReportExternalReviewsPage);var __decorate$c=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashReportFeatureLatencyPage=class ChromedashReportFeatureLatencyPage extends i$4{constructor(){super(...arguments),this.rawQuery={},this._client=window.csOpenApiClient,this.latencyList=[],this._latencyTask=new h(this,{task:async([startAt,endAt],{signal})=>(this.latencyList=await this._client.listFeatureLatency({startAt,endAt},{signal}),this.latencyList),args:()=>[this.startAtDate,this.endAtDate]}),this.startAtDate=new Date("January 1, 2023"),this.endAtDate=new Date("January 1, 2024")}static get styles(){return[...SHARED_STYLES,i$7` + p { + margin: var(--content-padding) 0; + } + + table { + border: var(--table-divider); + } + td, + th { + padding: var(--content-padding); + border-bottom: var(--table-divider); + vertical-align: baseline; + } + th { + background: var(--table-header-background); + } + tr { + background: var(--table-row-background); + } + `]}static get properties(){return{latencyList:{type:Array},startAtDate:{state:!0},endAtDate:{state:!0}}}connectedCallback(){super.connectedCallback(),this.initializeParams()}initializeParams(){if(this.rawQuery){if(this.rawQuery.startAt){const parsed=Date.parse(this.rawQuery.startAt);isNaN(parsed)||(this.startAtDate=new Date(parsed))}if(this.rawQuery.endAt){const parsed=Date.parse(this.rawQuery.endAt);isNaN(parsed)||(this.endAtDate=new Date(parsed))}}}renderCount(){return x$1` + <p> + Launched ${this.latencyList.length} features between + ${this.startAtDate.toLocaleDateString()} and + ${this.endAtDate.toLocaleDateString()}. + </p> + <p>Latency is measured in calendar days.</p> + `}renderLatencyRow(featureLatency){const latencyMs=featureLatency.shipped_date-featureLatency.entry_created_date,latencyDays=Math.ceil(latencyMs/86400000);return x$1` + <tr> + <td> + <a href="/feature/${featureLatency.feature.id}"> + ${featureLatency.feature.name} + </a> + </td> + <td> + ${featureLatency.owner_emails.map(addr=>x$1`<div>${addr}</div>`)} + </td> + <td>${featureLatency.entry_created_date.toLocaleDateString()}</td> + <td>${featureLatency.shipped_date.toLocaleDateString()}</td> + <td>${latencyDays}</td> + </tr> + `}renderTable(){return x$1` + <table> + <tr> + <th>Feature</th> + <th>Owners</th> + <th>Created</th> + <th>Shipped</th> + <th>Latency</th> + </tr> + ${this.latencyList.map(fl=>this.renderLatencyRow(fl))} + </table> + `}renderWhenComplete(){return x$1` ${this.renderCount()} ${this.renderTable()} `}render(){return this._latencyTask.render({initial:()=>x$1`<p>Loading...</p>`,pending:()=>x$1`<p>Loading...</p>`,complete:()=>this.renderWhenComplete(),error:e=>(console.error(e),x$1`<p> + Some errors occurred. Please refresh the page or try again later. + </p>`)})}};__decorate$c([n$5({type:Object})],ChromedashReportFeatureLatencyPage.prototype,"rawQuery",void 0),__decorate$c([n$5({attribute:!1})],ChromedashReportFeatureLatencyPage.prototype,"_client",void 0),__decorate$c([n$5({attribute:!1})],ChromedashReportFeatureLatencyPage.prototype,"latencyList",void 0),__decorate$c([n$5({attribute:!1})],ChromedashReportFeatureLatencyPage.prototype,"_latencyTask",void 0),__decorate$c([r$6()],ChromedashReportFeatureLatencyPage.prototype,"startAtDate",void 0),__decorate$c([r$6()],ChromedashReportFeatureLatencyPage.prototype,"endAtDate",void 0),ChromedashReportFeatureLatencyPage=__decorate$c([t$3("chromedash-report-feature-latency-page")],ChromedashReportFeatureLatencyPage);var __decorate$b=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashReportSpecMentor=class ChromedashReportSpecMentor extends i$4{static get styles(){return[...SHARED_STYLES,i$7``]}render(){return x$1` + <sl-details summary="${this.mentor.email} has mentored:" open> + <table> + ${this.mentor.mentored_features.map(feature=>x$1` + <chromedash-feature-row + .feature="${feature}" + ></chromedash-feature-row> + `)} + </table> + </sl-details> + `}};__decorate$b([n$5({attribute:!1})],ChromedashReportSpecMentor.prototype,"mentor",void 0),ChromedashReportSpecMentor=__decorate$b([t$3("chromedash-report-spec-mentor")],ChromedashReportSpecMentor);var __decorate$a=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashReportSpecMentorsPage=class ChromedashReportSpecMentorsPage extends i$4{constructor(){super(...arguments),this.rawQuery={},this._client=window.csOpenApiClient,this._mentorsTask=new h(this,{task:async([updatedAfter],{signal})=>{const mentors=await this._client.listSpecMentors({after:updatedAfter},{signal});return mentors.sort((a,b)=>a.email.localeCompare(b.email)),mentors},args:()=>[this._updatedAfter]}),this._updatedAfter=new Date(Date.now()-31536000000)}static get styles(){return[...SHARED_STYLES,i$7``]}connectedCallback(){super.connectedCallback(),this.initializeParams()}initializeParams(){if(this.rawQuery&&this.rawQuery.after){const parsed=Date.parse(this.rawQuery.after);isNaN(parsed)||(this._updatedAfter=new Date(parsed))}}afterChanged(e){e.stopPropagation();const newDate=e.target.valueAsDate;newDate&&(this._updatedAfter=newDate,this.dispatchEvent(new CustomEvent("afterchanged",{detail:{after:this._updatedAfter},bubbles:!0,composed:!0})))}render(){return x$1` + <div id="subheader"> + <sl-input + type="date" + name="after" + value=${isoDateString(this._updatedAfter)} + label="List spec mentors who've worked on features that were updated after this date" + @sl-change=${this.afterChanged} + ></sl-input> + </div> + ${this._mentorsTask.render({pending:()=>x$1` <details open> + <summary><sl-skeleton effect="sheen"></sl-skeleton></summary> + <sl-skeleton effect="sheen"></sl-skeleton> + </details>`,complete:specMentors=>specMentors.map(mentor=>x$1`<chromedash-report-spec-mentor + .mentor=${mentor} + ></chromedash-report-spec-mentor>`),error:e=>(console.error(e),x$1`<p> + Some errors occurred. Please refresh the page or try again later. + </p>`)})} + `}};__decorate$a([n$5({type:Object})],ChromedashReportSpecMentorsPage.prototype,"rawQuery",void 0),__decorate$a([n$5({attribute:!1})],ChromedashReportSpecMentorsPage.prototype,"_client",void 0),__decorate$a([n$5({attribute:!1})],ChromedashReportSpecMentorsPage.prototype,"_mentorsTask",void 0),__decorate$a([r$6()],ChromedashReportSpecMentorsPage.prototype,"_updatedAfter",void 0),ChromedashReportSpecMentorsPage=__decorate$a([t$3("chromedash-report-spec-mentors-page")],ChromedashReportSpecMentorsPage);var __decorate$9=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashReportReviewLatencyPage=class ChromedashReportReviewLatencyPage extends i$4{constructor(){super(...arguments),this._client=window.csOpenApiClient,this.reviewLatencyList=[],this._reviewLatencyTask=new h(this,{task:async([],{signal})=>{this.reviewLatencyList=await this._client.listReviewsWithLatency({signal})},args:()=>[]})}static get styles(){return[...SHARED_STYLES,i$7` + p { + margin: var(--content-padding) 0; + } + table { + border-collapse: collapse; + border: 1px solid #888; + } + td, + th { + padding: var(--content-padding-half); + text-align: center; + } + td { + border-top: 1px solid #888; + border-bottom: 1px solid #888; + } + colgroup { + border: 1px solid #888; + } + th { + background: var(--table-header-background); + } + tr { + background: var(--table-row-background); + } + .left { + text-align: left; + min-width: 18em; + } + `]}static get properties(){return{featureReviewList:{state:!0}}}renderCount(){let count=0;for(const rl of this.reviewLatencyList)for(const gr of rl.gate_reviews)0<=gr.latency_days&&count++;return x$1` + <p> + ${count} reviews of ${this.reviewLatencyList.length} distinct features + in the past 90 days. + </p> + <p>Latency is measured in weekdays from request to initial response.</p> + `}renderFeatureReviewsRow(reviewLatency){const gateLatency={};for(const gr of reviewLatency.gate_reviews){let display=gr.latency_days;-1===gr.latency_days?display="":-2==gr.latency_days&&(display="Pending"),gateLatency[gr.gate_type]=display}return x$1` + <tr> + <td class="left"> + <a href="/feature/${reviewLatency.feature.id}"> + ${reviewLatency.feature.name} + </a> + </td> + <td>${gateLatency[GATE_TYPES.PRIVACY_ORIGIN_TRIAL]}</td> + <td>${gateLatency[GATE_TYPES.PRIVACY_SHIP]}</td> + <td>${gateLatency[GATE_TYPES.SECURITY_ORIGIN_TRIAL]}</td> + <td>${gateLatency[GATE_TYPES.SECURITY_SHIP]}</td> + <td>${gateLatency[GATE_TYPES.ENTERPRISE_SHIP]}</td> + <td>${gateLatency[GATE_TYPES.DEBUGGABILITY_ORIGIN_TRIAL]}</td> + <td>${gateLatency[GATE_TYPES.DEBUGGABILITY_SHIP]}</td> + <td>${gateLatency[GATE_TYPES.TESTING_SHIP]}</td> + <td>${gateLatency[GATE_TYPES.API_ORIGIN_TRIAL]}</td> + <td>${gateLatency[GATE_TYPES.API_SHIP]}</td> + </tr> + `}renderTable(){return x$1` + <table> + <colgroup> + <col /> + </colgroup> + <colgroup> + <col /> + <col /> + </colgroup> + <colgroup> + <col /> + <col /> + </colgroup> + <colgroup> + <col /> + </colgroup> + <colgroup> + <col /> + <col /> + </colgroup> + <colgroup> + <col /> + </colgroup> + <colgroup> + <col /> + <col /> + </colgroup> + <tr> + <th scope="col" rowspan="2" class="left">Feature</th> + <th scope="col" colspan="2">Privacy</th> + <th scope="col" colspan="2">Security</th> + <th scope="col" colspan="1">Enterprise</th> + <th scope="col" colspan="2">Debugability</th> + <th scope="col" colspan="1">Testing</th> + <th scope="col" colspan="2">API Owners</th> + </tr> + <tr> + <th>OT</th> + <th>Ship</th> + <th>OT</th> + <th>Ship</th> + <th>Ship</th> + <th>OT</th> + <th>Ship</th> + <th>Ship</th> + <th>OT</th> + <th>Ship</th> + </tr> + + ${this.reviewLatencyList.map(rl=>this.renderFeatureReviewsRow(rl))} + </table> + `}renderWhenComplete(){return x$1` ${this.renderCount()} ${this.renderTable()} `}render(){return this._reviewLatencyTask.render({initial:()=>x$1`<p>Loading...</p>`,pending:()=>x$1`<p>Loading...</p>`,complete:()=>this.renderWhenComplete(),error:e=>(console.error(e),x$1`<p> + Some errors occurred. Please refresh the page or try again later. + </p>`)})}};__decorate$9([n$5({attribute:!1})],ChromedashReportReviewLatencyPage.prototype,"_client",void 0),__decorate$9([n$5({attribute:!1})],ChromedashReportReviewLatencyPage.prototype,"reviewLatencyList",void 0),__decorate$9([n$5({attribute:!1})],ChromedashReportReviewLatencyPage.prototype,"_reviewLatencyTask",void 0),ChromedashReportReviewLatencyPage=__decorate$9([t$3("chromedash-report-review-latency-page")],ChromedashReportReviewLatencyPage);var __decorate$8=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const TEMPLATE_CONTENT={stable_minus_one:{channelLabel:"Released",h1Class:"",dateText:"was",featureHeader:"Features in this release"},stable:{channelLabel:"Stable",h1Class:"",dateText:"was",featureHeader:"Features in this release"},stable_soon:{channelLabel:"Stable soon",h1Class:"",dateText:"was",featureHeader:"Features planned in this release"},beta:{channelLabel:"Next up",h1Class:"chrome_version--beta",channelTag:"BETA",dateText:"between",featureHeader:"Features planned in this release"},dev:{channelLabel:"Dev",h1Class:"chrome_version--dev",channelTag:"DEV",dateText:"coming",featureHeader:"Features planned in this release"},dev_plus_one:{channelLabel:"Later",h1Class:"chrome_version--dev_plus_one",dateText:"coming",featureHeader:"Features planned in this release"}},DEFAULT_CHANNEL_TYPES=["stable","beta","dev"],GAPPED_CHANNEL_TYPES=["stable","stable_soon","beta","dev"],SHOW_DATES=!0,compareFeatures=(a,b)=>a.name.localeCompare(b.name,"fr",{ignorePunctuation:!0});let ChromedashRoadmap=class ChromedashRoadmap extends i$4{constructor(){super(...arguments),this.numColumns=0,this.cardWidth=0,this.channels={},this.starredFeatures=new Set,this.futureMilestoneArray=[],this.pastMilestoneArray=[],this.highlightFeature=void 0,this.cardOffset=0,this.shownChannelNames=[]}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: inline-flex; + padding: 0 0em var(--content-padding-huge); + margin-right: var(--content-padding-negative); + position: relative; + } + `]}connectedCallback(){super.connectedCallback(),Promise.all([window.csClient.getChannels(),window.csClient.getStars()]).then(([channels,starredFeatures])=>{this.fetchFirstBatch(channels),this.starredFeatures=new Set(starredFeatures)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}fetchFirstBatch(channels){this.shownChannelNames=channels.stable_soon?GAPPED_CHANNEL_TYPES:DEFAULT_CHANNEL_TYPES;const promises=this.shownChannelNames.map(channelType=>window.csClient.getFeaturesInMilestone(channels[channelType].version));Promise.all(promises).then(allRes=>{allRes.map((res,idx)=>{Object.keys(res).forEach(status=>{res[status].sort(compareFeatures)}),channels[this.shownChannelNames[idx]].features=res}),this.channels=channels,this.fetchNextBatch(channels.beta.version,!0),this.fetchPreviousBatch(channels.stable.version),this.lastMilestoneVisible=channels[this.shownChannelNames[this.numColumns-1]].version})}fetchNextBatch(nextVersion,firstTime=!1){const fetchInAdvance=3,fetchStart=firstTime?nextVersion+2:nextVersion+3+1,fetchEnd=nextVersion+3+1,versions=[...Array(fetchEnd-fetchStart+1).keys()].map(x=>x+fetchStart),milestonePromise=window.csClient.getSpecifiedChannels(fetchStart,fetchEnd),featurePromises=versions.map(ver=>window.csClient.getFeaturesInMilestone(ver));this.futureMilestoneArray=[...this.futureMilestoneArray,...versions],this.lastFutureFetchedOn=nextVersion,milestonePromise.then(newMilestonesInfo=>{Promise.all(featurePromises).then(allRes=>{allRes.map((res,idx)=>{Object.keys(res).forEach(status=>{res[status].sort(compareFeatures)});const version=versions[idx];newMilestonesInfo[version].features=res,newMilestonesInfo[version].version=version,this.milestoneInfo=Object.assign({},this.milestoneInfo,newMilestonesInfo)})})}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}fetchPreviousBatch(version){const versionToFetch=version-1;if(2>versionToFetch)return;const milestonePromise=window.csClient.getSpecifiedChannels(versionToFetch,versionToFetch),featurePromise=window.csClient.getFeaturesInMilestone(versionToFetch),margin=16;this.cardOffset-=1,this.style.left=this.cardOffset*(this.cardWidth+margin)+"px",this.pastMilestoneArray=[versionToFetch,...this.pastMilestoneArray],this.lastPastFetchedOn=version,Promise.all([milestonePromise,featurePromise]).then(([newMilestonesInfo,features])=>{Object.keys(features).forEach(status=>{features[status].sort(compareFeatures)}),newMilestonesInfo[versionToFetch].features=features,newMilestonesInfo[versionToFetch].version=versionToFetch,this.milestoneInfo=Object.assign({},this.milestoneInfo,newMilestonesInfo)}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}handleStarToggle(e){const newStarredFeatures=new Set(this.starredFeatures);window.csClient.setStar(e.detail.feature,e.detail.doStar).then(()=>{e.detail.doStar?newStarredFeatures.add(e.detail.feature):newStarredFeatures.delete(e.detail.feature),this.starredFeatures=newStarredFeatures}).catch(()=>{showToastMessage("Unable to star the Feature. Please Try Again.")})}handleHighlightEvent(e){this.highlightFeature=e.detail.feature}render(){return x$1` + ${c(this.pastMilestoneArray,milestone=>milestone,milestone=>x$1` + <chromedash-roadmap-milestone-card + style="width:${this.cardWidth}px;" + .channel=${this.milestoneInfo?.[milestone]} + .templateContent=${TEMPLATE_CONTENT.stable_minus_one} + ?showdates=${SHOW_DATES} + .starredFeatures=${this.starredFeatures} + .highlightFeature=${this.highlightFeature} + ?signedin=${this.signedIn} + @star-toggle-event=${this.handleStarToggle} + @highlight-feature-event=${this.handleHighlightEvent} + > + </chromedash-roadmap-milestone-card> + `)} + ${c(this.shownChannelNames,channelType=>channelType,channelType=>x$1` + <chromedash-roadmap-milestone-card + style="width:${this.cardWidth}px;" + .channel=${this.channels?.[channelType]} + .templateContent=${TEMPLATE_CONTENT[channelType]} + ?showdates=${SHOW_DATES} + .starredFeatures=${this.starredFeatures} + .highlightFeature=${this.highlightFeature} + ?signedin=${this.signedIn} + .stableMilestone=${this.channels?.["stable"]?.version} + @star-toggle-event=${this.handleStarToggle} + @highlight-feature-event=${this.handleHighlightEvent} + > + </chromedash-roadmap-milestone-card> + `)} + ${c(this.futureMilestoneArray,milestone=>milestone,milestone=>x$1` + <chromedash-roadmap-milestone-card + style="width:${this.cardWidth}px;" + .channel=${this.milestoneInfo?.[milestone]} + .templateContent=${TEMPLATE_CONTENT.dev_plus_one} + ?showdates=${SHOW_DATES} + .starredFeatures=${this.starredFeatures} + .highlightFeature=${this.highlightFeature} + ?signedin=${this.signedIn} + @star-toggle-event=${this.handleStarToggle} + @highlight-feature-event=${this.handleHighlightEvent} + > + </chromedash-roadmap-milestone-card> + `)} + `}};__decorate$8([n$5({type:Boolean})],ChromedashRoadmap.prototype,"signedIn",void 0),__decorate$8([n$5({type:Number,attribute:!1})],ChromedashRoadmap.prototype,"numColumns",void 0),__decorate$8([n$5({type:Number,attribute:!1})],ChromedashRoadmap.prototype,"cardWidth",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"channels",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"starredFeatures",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"lastFutureFetchedOn",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"lastPastFetchedOn",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"lastMilestoneVisible",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"futureMilestoneArray",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"pastMilestoneArray",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"milestoneInfo",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"highlightFeature",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"cardOffset",void 0),__decorate$8([r$6()],ChromedashRoadmap.prototype,"shownChannelNames",void 0),ChromedashRoadmap=__decorate$8([t$3("chromedash-roadmap")],ChromedashRoadmap);const ROADMAP_MILESTONE_CARD_CSS=[SHARED_STYLES,i$7` + .layout { + display: flex; + } + .layout.wrap { + flex-wrap: wrap; + } + .layout.center { + align-items: center; + } + .layout.center-center { + align-items: center; + justify-content: center; + } + .layout.vertical { + flex-direction: column; + } + :host { + padding: 16px; + background: #fff; + padding: 16px; + margin-bottom: 16px !important; + border-radius: 3px; + margin-right: 8px !important; + margin-left: 8px !important; + counter-reset: featurecount; + margin: 8px; + } + sl-icon { + font-size: 1.4rem; + color: #366597; + } + sl-icon:hover { + color: #248; + } + sl-icon.pushicon { + cursor: pointer; + } + sl-icon-button { + font-size: 16px; + } + .popup-content { + border: 2px solid #888; + border-radius: 8px; + background: #f8f8f8; + color: black; + font-size: 12pt; + padding: 1em; + width: 14em; + } + .chrome_version { + font-size: 45px; + margin: 8px 0 16px 0; + white-space: nowrap; + } + .channel_label { + font-weight: 600; + text-transform: uppercase; + font-size: 24px; + text-align: center; + } + .chrome_version .chrome-logo, + .chrome_version--stable .chrome-logo { + position: relative; + width: 45px; + height: 45px; + background: url(/static/img/chrome_logo.svg) no-repeat 50% 50%; + background-size: contain; + margin-right: 8px; + } + .chrome_version--beta .chrome-logo { + background-image: url(/static/img/chrome_logo.svg); + } + .chrome_version--dev .chrome-logo { + background-image: url(/static/img/chrome_logo.svg); + } + .chrome_version--canary .chrome-logo { + background-image: url(/static/img/chrome_logo_canary.svg); + background-size: 42px; + } + .chrome_version--dev_plus_one .chrome-logo { + filter: gray; + -webkit-filter: grayscale(1); + filter: grayscale(1); + } + .chrome-logo .channel-tag { + position: absolute; + right: 0; + top: 50%; + padding: 1px 2px; + font-size: 10px; + font-weight: bold; + color: white; + background: var(--sl-color-neutral-900); + } + .release { + padding: 16px; + background: #fff; + padding: 16px; + margin-bottom: 16px !important; + border-radius: 3px; + flex: 1 0 0; + min-width: 300px; + counter-reset: featurecount; + } + .release.no-components .feature_shipping_type { + display: none; + } + .release.no-components .feature_shipping_type + ul { + margin-top: 0; + } + .milestone_info { + margin-bottom: 8px; + } + .milestone_info:nth-of-type(3) { + border-bottom: 1px solid #e6e6e6; + padding-bottom: 16px; + } + .milestone_info .channel_label { + font-size: inherit; + font-weight: 500; + text-transform: none; + } + .no_feature_released { + color: #737373; + } + .features_list { + margin-top: 32px; + } + .features_list ul, + .features_list ol { + margin-top: 8px; + list-style: none; + padding: 0; + } + .features_list li { + padding: 8px; + font-weight: 500; + } + .features_list li .icon_row { + flex-shrink: 0; + } + .features_list .features_header { + font-weight: 500; + text-transform: uppercase; + margin-bottom: 16px; + } + .feature_shipping_type { + margin-top: 16px; + overflow: hidden; + text-overflow: ellipsis; + } + .highlight { + background: var(--light-accent-color); + } + #feature_link { + width: 100%; + } + .sl-skeleton-header-container { + display: flex; + width: 100%; + gap: 10px; + justify-content: center; + margin-top: 10px; + } + .sl-skeleton-header-container sl-skeleton { + width: 60%; + } + .sl-skeleton-title-container { + width: 50%; + } + .features_list sl-skeleton { + height: 20px; + margin: 8px; + } + .experiment { + font-size: 85%; + padding: 2px 8px; + background: #fea; + border-radius: 8px; + } + `];var __decorate$7=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const STATUS_TO_ICON_NAME={"Not started":"arrow_circle_right_20px","In-progress":"pending_20px","Needs work":"autorenew_20px",Approved:"check_circle_filled_20px",Denied:"block_20px"};let ChromedashReviewStatusIcon=class ChromedashReviewStatusIcon extends i$4{constructor(){super(...arguments),this.gates=[]}static get styles(){return[...SHARED_STYLES,i$7` + sl-icon { + width: 26px; + height: 18px; + } + + sl-icon.not-started { + color: var(--gate-preparing-icon-color); + } + sl-icon.in-progress { + color: var(--gate-pending-icon-color); + } + sl-icon.needs-work { + color: var(--gate-needs-work-icon-color); + } + sl-icon.approved { + color: var(--gate-approved-icon-color); + } + sl-icon.denied { + color: var(--gate-denied-icon-color); + } + `]}connectedCallback(){super.connectedCallback(),this.fetchData()}fetchData(){this.gates=[],window.csClient?.getGates(this.feature?.id).then(gatesRes=>{let featureGates=gatesRes.gates;this.gates=featureGates.filter(g=>this.feature.roadmap_stage_ids?.includes(g.stage_id))})}calcStatus(){let status="Not started",targetGateId,apiOwnersGateId;for(const g of this.gates)g.state!==GATE_PREPARING&&(status="In-progress"),g.state!==VOTE_OPTIONS.APPROVED[0]&&g.state!==VOTE_OPTIONS.NA[0]&&g.state!==VOTE_NA_SELF&&(targetGateId=g.id),"API Owners"===g.team_name&&(apiOwnersGateId=g.id);0<this.gates.length&&this.gates.every(g=>g.state===VOTE_OPTIONS.APPROVED[0]||g.state===VOTE_OPTIONS.NA[0]||g.state===VOTE_NA_SELF)&&(status="Approved",targetGateId=apiOwnersGateId),this.feature?.feature_type_int===FEATURE_TYPES.FEATURE_TYPE_CODE_CHANGE_ID[0]&&(status="Approved",targetGateId=void 0);for(const g of this.gates)g.state==VOTE_OPTIONS.NEEDS_WORK[0]&&(status="Needs work",targetGateId=g.id);for(const g of this.gates)g.state==VOTE_OPTIONS.DENIED[0]&&(status="Denied",targetGateId=g.id);return{status,targetGateId}}render(){if(0===this.gates.length)return x$1`<sl-icon></sl-icon>`;const{status,targetGateId}=this.calcStatus();let className=status.toLowerCase().replace(" ","-"),iconName=STATUS_TO_ICON_NAME[status],hoverText="Reviews: "+status;const icon=x$1` + <sl-icon + library="material" + title="${hoverText}" + class="${className}" + name="${iconName}" + ></sl-icon> + `;return targetGateId?x$1` + <a href="/feature/${this.feature.id}?gate=${targetGateId}">${icon}</a> + `:icon}};__decorate$7([n$5({type:Object})],ChromedashReviewStatusIcon.prototype,"feature",void 0),__decorate$7([r$6()],ChromedashReviewStatusIcon.prototype,"gates",void 0),ChromedashReviewStatusIcon=__decorate$7([t$3("chromedash-review-status-icon")],ChromedashReviewStatusIcon);var __decorate$6=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const REMOVED_STATUS=["Removed"],DEPRECATED_STATUS=["Deprecated","No longer pursuing"],ORIGIN_TRIAL=["Origin trial"],DEPRECATION_TRIAL=["Deprecation trial"],NO_FEATURE_STRING="NO FEATURES ARE PLANNED FOR THIS MILESTONE YET";let ChromedashRoadmapMilestoneCard=class ChromedashRoadmapMilestoneCard extends i$4{constructor(){super(...arguments),this.infoPopupRef=e$1(),this.starredFeatures=new Set,this.showDates=!1,this.signedIn=!1,this.currentDate=Date.now()}static{this.styles=ROADMAP_MILESTONE_CARD_CSS}_dateDiffInDays(a,b){const utc1=Date.UTC(a.getFullYear(),a.getMonth(),a.getDate()),utc2=Date.UTC(b.getFullYear(),b.getMonth(),b.getDate()),MS_PER_DAY=86400000,daysDiff=Math.floor((utc2-utc1)/MS_PER_DAY);return{days:Math.abs(daysDiff),future:1>daysDiff}}_computeDate(dateStr,addYear=!1){const opts={month:"short",day:"numeric"};addYear&&(opts.year="numeric");const date=new Date(dateStr);return new Intl.DateTimeFormat("en-US",opts).format(date)}_fireEvent(eventName,detail){const event=new CustomEvent(eventName,{bubbles:!0,composed:!0,detail});this.dispatchEvent(event)}_isAnyFeatureReleased(){for(const shippingType of this._objKeys(this.channel?.features))if(0!=this.channel?.features[shippingType].length)return!0;return!1}toggleStar(e){e.preventDefault(),e.stopPropagation();const iconEl=e.target,featureId=+iconEl.dataset.featureId,newStarred=!this.starredFeatures.has(featureId);this._fireEvent("star-toggle-event",{feature:featureId,doStar:newStarred})}highlight(e){e.preventDefault(),e.stopPropagation();const iconEl=e.target.parentNode.parentNode,featureId=+iconEl.dataset.featureId;this._fireEvent("highlight-feature-event",{feature:featureId})}removeHighlight(e){e.preventDefault(),e.stopPropagation(),this._fireEvent("highlight-feature-event",{feature:null})}_computeDaysUntil(dateStr){const date=new Date(dateStr);if(isNaN(date.getTime()))return E$1;const today=new Date,diff=this._dateDiffInDays(date,today);return 1>diff.days?"coming soon":x$1`<sl-relative-time + class="no-squeeze" + date="${date.toISOString()}" + > + </sl-relative-time>`}_objKeys(obj){return obj?Object.keys(obj).sort():[]}hidePopup(e){e.relatedTarget!=this.renderRoot.querySelector("#detailed-info-link")&&(this.infoPopupRef.value.active=!1)}renderInfoIcon(){return x$1` + <sl-icon-button + name="info-circle" + id="info-button" + @click=${()=>this.infoPopupRef.value.active=!this.infoPopupRef.value.active} + @focusout=${this.hidePopup} + ></sl-icon-button> + + <sl-popup + anchor="info-button" + placement="bottom" + strategy="fixed" + ${n$2(this.infoPopupRef)} + > + <div class="popup-content"> + New versions are offered to users gradually. <br /> + See + <a + @focusout=${this.hidePopup} + id="detailed-info-link" + href="https://chromiumdash.appspot.com/schedule" + target="_blank" + >detailed dates</a + >. + </div> + </sl-popup> + `}renderCardHeader(){if(!this.channel)return E$1;const stableStart=110<=this.channel.version?this.channel?.early_stable:this.channel?.stable_date,logo=x$1` + <span class="chrome-logo"> + ${this.templateContent.channelTag?x$1` + <span class="channel-tag" + >${this.templateContent.channelTag}</span + > + `:E$1} + </span> + `;return x$1` + <div class="layout vertical center"> + <h1 class="channel_label">${this.templateContent.channelLabel}</h1> + <h1 + class="chrome_version layout horizontal center ${this.templateContent.h1Class}" + > + ${logo} Chrome ${this.channel?.version} + </h1> + </div> + ${this.showDates&&this.channel?.earliest_beta?x$1` + <div class="milestone_info layout horizontal center-center"> + <h3> + <span class="channel_label">Beta</span> ${this.templateContent.dateText} + <span class="milestone_info-beta"> + ${this._computeDate(this.channel?.earliest_beta)} - + ${this._computeDate(this.channel?.latest_beta)} + </span> + </h3> + </div> + <div class="milestone_info layout horizontal center-center"> + <h3> + <span class="channel_label">Stable</span> + ${this._computeDaysUntil(stableStart)} + <span class="release-stable" + >(${this._computeDate(stableStart,!0)})</span + > + ${this.renderInfoIcon()} + </h3> + </div> + `:E$1} + `}_isFeatureOutdated(accurateAsOf,liveChromeVersion){if(0===this.stableMilestone||!liveChromeVersion)return!1;if(this.stableMilestone+1!==liveChromeVersion&&this.stableMilestone+2!==liveChromeVersion)return!1;const isVerified=isVerifiedWithinGracePeriod(accurateAsOf,this.currentDate);return!isVerified}_cardFeatureItemTemplate(f,shippingType){return x$1` + <li + data-feature-id="${f.id}" + class="hbox align-top ${f.id==this.highlightFeature?"highlight":""}" + > + <chromedash-review-status-icon + .feature=${f} + ></chromedash-review-status-icon> + <span> + <a + id="feature_link" + href="/feature/${f.id}" + @mouseenter="${this.highlight}" + @mouseleave="${this.removeHighlight}" + > + ${f.name} + </a> + ${f.finch_urls?.map(url=>x$1` + <a + target="_blank" + class="experiment" + href=${url} + title="Deploying to some users as an experiment" + >Exp</a + > + `)} + </span> + <span class="spacer"></span> + <span class="icon_row"> + ${this._isFeatureOutdated(f.accurate_as_of,this.channel?.version)?x$1` + <span + class="tooltip" + id="outdated-icon" + title="Feature outdated - last checked for overall accuracy more than four weeks ago" + > + <sl-icon + name="exclamation-circle-fill" + data-tooltip + ></sl-icon> + </span> + `:E$1} + ${ORIGIN_TRIAL.includes(shippingType)?x$1` + <span class="tooltip" title="Origin Trial"> + <sl-icon + library="material" + name="extension" + class="experimental" + data-tooltip + ></sl-icon> + </span> + `:E$1} + ${DEPRECATION_TRIAL.includes(shippingType)?x$1` + <span class="tooltip" title="Deprecation Trial"> + <sl-icon + library="material" + name="extension" + class="experimental" + data-tooltip + ></sl-icon> + </span> + `:E$1} + ${REMOVED_STATUS.includes(shippingType)?x$1` + <span class="tooltip" title="Removed"> + <sl-icon + name="x-circle-fill" + class="remove" + data-tooltip + ></sl-icon> + </span> + `:E$1} + ${DEPRECATED_STATUS.includes(shippingType)?x$1` + <span class="tooltip" title="Deprecated"> + <sl-icon + name="exclamation-triangle-fill" + class="deprecated" + data-tooltip + ></sl-icon> + </span> + `:E$1} + ${this.signedIn?x$1` + <span + class="tooltip" + title="Receive an email notification when there are updates" + > + <sl-icon + name="${this.starredFeatures.has(+f.id)?"star-fill":"star"}" + class="pushicon" + data-feature-id="${f.id}" + @click="${this.toggleStar}" + > + </sl-icon> + </span> + `:E$1} + </span> + </li> + `}renderOTFeatures(features){if(!features)return[];const display=[],otFeatures=features.filter(f=>f.feature_type_int!==FEATURE_TYPES.FEATURE_TYPE_DEPRECATION_ID[0]),deprecationFeatures=features.filter(f=>f.feature_type_int===FEATURE_TYPES.FEATURE_TYPE_DEPRECATION_ID[0]);return 0<otFeatures.length&&display.push(x$1` + <h3 class="feature_shipping_type">${ORIGIN_TRIAL[0]}</h3> + <ul> + ${otFeatures.map(f=>x$1` ${this._cardFeatureItemTemplate(f,ORIGIN_TRIAL[0])} `)} + </ul> + `),0<deprecationFeatures.length&&display.push(x$1` + <h3 class="feature_shipping_type">${DEPRECATION_TRIAL[0]}</h3> + <ul> + ${deprecationFeatures.map(f=>x$1` + ${this._cardFeatureItemTemplate(f,DEPRECATION_TRIAL[0])} + `)} + </ul> + `),display}renderCardFeatureList(){const featureListItems=this._objKeys(this.channel?.features).map(shippingType=>{if(shippingType===ORIGIN_TRIAL[0])return this.renderOTFeatures(this.channel?.features[shippingType]);return 0===this.channel?.features[shippingType].length?E$1:x$1` + <h3 class="feature_shipping_type">${shippingType}</h3> + <ul> + ${this.channel?.features[shippingType].map(f=>x$1` ${this._cardFeatureItemTemplate(f,shippingType)} `)} + </ul> + `});return x$1` + <div class="features_list"> + ${this._isAnyFeatureReleased()?x$1` + <div class="features_header">${this.templateContent.featureHeader}:</div> + ${featureListItems} + </div>`:x$1` + <div class="features_header no_feature_released"> + ${NO_FEATURE_STRING} + </div> + `} + </div> + `}renderSkeletons(){return x$1` + <div class="layout vertical center"> + <h1 class="channel_label">${this.templateContent.channelLabel}</h1> + <h1 class="chrome_version layout horizontal sl-skeleton-header-container ${this.templateContent.h1Class}"> + <span class="chrome-logo"></span> + <sl-skeleton effect="sheen"></sl-skeleton> + </h1> + </div> + <div class="milestone_info layout horizontal center-center"> + <h3 class="sl-skeleton-header-container"> + <sl-skeleton effect="sheen"></sl-skeleton> + </h3> + </div> + <div class="milestone_info layout horizontal center-center"> + <h3 class="sl-skeleton-header-container"> + <sl-skeleton effect="sheen"></sl-skeleton> + </h3> + </div> + <div class="features_list"> + <div class="sl-skeleton-title-container"> + <sl-skeleton effect="sheen"></sl-skeleton> + </div> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </div> + </div> + <div class="features_list"> + <div class="sl-skeleton-title-container"> + <sl-skeleton effect="sheen"></sl-skeleton> + </div> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </div> + </div> + `}render(){return x$1` + <section class="release"> + ${this.channel?x$1` ${this.renderCardHeader()} ${this.renderCardFeatureList()} `:x$1` ${this.renderSkeletons()} `} + </section> + `}};__decorate$6([n$5({attribute:!1})],ChromedashRoadmapMilestoneCard.prototype,"starredFeatures",void 0),__decorate$6([n$5({attribute:!1})],ChromedashRoadmapMilestoneCard.prototype,"highlightFeature",void 0),__decorate$6([n$5({attribute:!1})],ChromedashRoadmapMilestoneCard.prototype,"templateContent",void 0),__decorate$6([n$5({attribute:!1})],ChromedashRoadmapMilestoneCard.prototype,"channel",void 0),__decorate$6([n$5({type:Boolean})],ChromedashRoadmapMilestoneCard.prototype,"showDates",void 0),__decorate$6([n$5({type:Boolean})],ChromedashRoadmapMilestoneCard.prototype,"signedIn",void 0),__decorate$6([n$5({attribute:!1})],ChromedashRoadmapMilestoneCard.prototype,"stableMilestone",void 0),__decorate$6([r$6()],ChromedashRoadmapMilestoneCard.prototype,"currentDate",void 0),ChromedashRoadmapMilestoneCard=__decorate$6([t$3("chromedash-roadmap-milestone-card")],ChromedashRoadmapMilestoneCard);var __decorate$5=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let roadmapHelpDialogEl;async function openRoadmapHelpDialog(){roadmapHelpDialogEl||(roadmapHelpDialogEl=document.createElement("chromedash-roadmap-help-dialog"),document.body.appendChild(roadmapHelpDialogEl),await roadmapHelpDialogEl.updateComplete),roadmapHelpDialogEl.show()}let ChromedashRoadmapHelpDialog=class ChromedashRoadmapHelpDialog extends i$4{static get styles(){return[...SHARED_STYLES,i$7` + #dialog-content { + max-width: 60rem; + } + #legend li { + padding: var(--content-padding-quarter); + white-space: nowrap; + } + #legend span { + display: inline-block; + width: 8em; + } + + #legend sl-icon { + width: 26px; + height: 18px; + } + sl-icon.not-started { + color: var(--gate-preparing-icon-color); + } + sl-icon.in-progress { + color: var(--gate-pending-icon-color); + } + sl-icon.needs-work { + color: var(--gate-needs-work-icon-color); + } + sl-icon.approved { + color: var(--gate-approved-icon-color); + } + sl-icon.denied { + color: var(--gate-denied-icon-color); + } + `]}show(){this.renderRoot.querySelector("sl-dialog")?.show()}hide(){this.renderRoot.querySelector("sl-dialog")?.hide()}renderDialogContent(){return x$1` + <div id="dialog-content"> + <ul id="legend"> + <li> + <sl-icon + library="material" + class="approved" + name="check_circle_filled_20px" + ></sl-icon> + <span>Approved</span> + <td>Reviewers approved feature at this stage</td> + </li> + <li> + <sl-icon + library="material" + class="not-started" + name="arrow_circle_right_20px" + ></sl-icon> + <span>Not started</span> + <td>Feature owners have not requested reviews yet</td> + </li> + <li> + <sl-icon + library="material" + class="in-progress" + name="pending_20px" + ></sl-icon> + <span>In-progress</span> + <td>Not all reviews have finished</td> + </li> + <li> + <sl-icon + library="material" + class="needs-work" + name="autorenew_20px" + ></sl-icon> + <span>Needs work</span> + <td>Reviewers have asked for changes</td> + </li> + <li> + <sl-icon + library="material" + class="denied" + name="block_20px" + ></sl-icon> + <span>Denied</span> + <td>Reviewers suggested directional changes</td> + </li> + </ul> + </div> + `}render(){return x$1` + <sl-dialog label="Roadmap legend" style="--width:fit-content"> + ${this.renderDialogContent()} + </sl-dialog> + `}};ChromedashRoadmapHelpDialog=__decorate$5([t$3("chromedash-roadmap-help-dialog")],ChromedashRoadmapHelpDialog);var __decorate$4=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashRoadmapPage=class ChromedashRoadmapPage extends i$4{constructor(){super(...arguments),this.sectionRef=e$1(),this.roadmapRef=e$1(),this.cardWidth=0,this.numColumns=0,this.viewOffset=0,this.boundHandleResize=this.handleResize.bind(this)}static get styles(){return[...SHARED_STYLES,i$7` + .animate { + transition: margin 0.4s ease; + } + #help-button { + font-size: 1.4rem; + color: var(--unimportant-text-color); + float: right; + } + + #releases-section { + overflow: hidden; + } + + .timeline-controls { + text-align: center; + padding-bottom: var(--content-padding); + margin: 0 var(--content-padding-half); + } + `]}connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this.boundHandleResize)}disconnectedCallback(){window.removeEventListener("resize",this.boundHandleResize),super.disconnectedCallback()}firstUpdated(){this.handleResize()}handleResize(){const containerWidth=this.sectionRef.value.offsetWidth,margin=16;let numColumns=3;768>containerWidth?numColumns=1:1152>containerWidth&&(numColumns=2),this.numColumns=numColumns,containerWidth&&(this.cardWidth=containerWidth/numColumns-margin),this.updateRoadmapMargin(!1)}handleMove(e){const roadmap=this.roadmapRef.value;roadmap?.lastFutureFetchedOn&&("next-button"==e.target.id?(this.viewOffset-=1,roadmap.lastMilestoneVisible+=1,this.updateRoadmapMargin(!0)):(this.viewOffset+=1,roadmap.lastMilestoneVisible-=1,this.updateRoadmapMargin(!0)),1<roadmap.lastMilestoneVisible-roadmap.lastFutureFetchedOn?roadmap.fetchNextBatch(roadmap.lastFutureFetchedOn+1):0>=roadmap.lastMilestoneVisible-roadmap.lastPastFetchedOn&&roadmap.fetchPreviousBatch(roadmap.lastPastFetchedOn-1))}updateRoadmapMargin(animated){const roadmap=this.roadmapRef.value;if(!roadmap)return;animated?roadmap.classList.add("animate"):roadmap.classList.remove("animate");const margin=16;roadmap.style.marginLeft=this.viewOffset*(this.cardWidth+16)+"px",roadmap.style.left=roadmap.cardOffset*(this.cardWidth+16)+"px"}renderHelpIcon(){return x$1` + <sl-icon + id="help-button" + library="material" + name="help_20px" + @click="${openRoadmapHelpDialog}" + > + </sl-icon> + `}render(){return x$1` + <div id="subheader"> + <div> + <h3>Roadmap</h3> + </div> + </div> + <section id="releases-section" ${n$2(this.sectionRef)}> + <div class="timeline-controls"> + <button + id="previous-button" + aria-label="Button to move to previous release" + @click=${this.handleMove} + > + Previous + </button> + <button + id="next-button" + aria-label="Button to move to later release" + @click=${this.handleMove} + > + Next + </button> + ${this.renderHelpIcon()} + </div> + <chromedash-roadmap + ${n$2(this.roadmapRef)} + class="animate" + aria-label="List of milestone releases" + .numColumns=${this.numColumns} + .cardWidth=${this.cardWidth} + ?signedIn=${!!this.user} + > + </chromedash-roadmap> + </section> + `}};__decorate$4([n$5({type:Object,attribute:!1})],ChromedashRoadmapPage.prototype,"user",void 0),__decorate$4([r$6()],ChromedashRoadmapPage.prototype,"cardWidth",void 0),__decorate$4([r$6()],ChromedashRoadmapPage.prototype,"numColumns",void 0),__decorate$4([r$6()],ChromedashRoadmapPage.prototype,"viewOffset",void 0),ChromedashRoadmapPage=__decorate$4([t$3("chromedash-roadmap-page")],ChromedashRoadmapPage);var __decorate$3=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashUserlist=class ChromedashUserlist extends i$4{constructor(){super(...arguments),this.users=[]}static get styles(){return[...SHARED_STYLES,i$7` + form { + padding: var(--content-padding); + background: var(--card-background); + border: var(--card-border); + margin-bottom: var(--content-padding); + max-width: 20em; + } + form > * + * { + margin-top: var(--content-padding-half); + } + + ul { + margin-top: 10px; + } + ul li { + transition: opacity 600ms ease-in-out; + margin-bottom: 5px; + } + ul li.faded { + opacity: 0; + } + ul li a { + margin-right: 10px; + } + `]}addUser(user){this.users.splice(0,0,user),this.users=this.users.slice(0)}removeUser(idx){this.users.splice(idx,1),this.users=this.users.slice(0)}sortUsers(){this.users.sort((a,b)=>(!a.is_admin||b.is_admin)&&(!a.is_site_editor||b.is_site_editor||b.is_admin)?(!b.is_admin||a.is_admin)&&(!b.is_site_editor||a.is_site_editor||a.is_admin)?a.email.localeCompare(b.email):1:-1)}_onAdminToggle(){const formEl=this.renderRoot.querySelector("form"),adminCheckbox=formEl?.querySelector("input[name=\"is_admin\"]"),siteEditorCheckbox=formEl?.querySelector("input[name=\"is_site_editor\"]");adminCheckbox.checked?(siteEditorCheckbox.checked=!0,siteEditorCheckbox.disabled=!0):siteEditorCheckbox.disabled=!1}async ajaxSubmit(e){e.preventDefault();const formEl=this.renderRoot.querySelector("form");if(formEl.checkValidity()){const emailInput=formEl.querySelector("input[name=\"email\"]"),adminCheckbox=formEl.querySelector("input[name=\"is_admin\"]"),siteEditorCheckbox=formEl.querySelector("input[name=\"is_site_editor\"]"),email=emailInput?.value,isAdmin=adminCheckbox?.checked,isSiteEditor=siteEditorCheckbox?.checked;window.csClient.createAccount(email,isAdmin,isSiteEditor).then(json=>{json.error_message?alert(json.error_message):(this.addUser(json),formEl.reset(),formEl.querySelector("input[name=\"is_site_editor\"]").disabled=!1)})}}ajaxDelete(e){if(e.preventDefault(),!confirm("Remove user?"))return;const idx=e.target.dataset.index;window.csClient.deleteAccount(e.target.dataset.account).then(()=>{this.removeUser(idx)})}render(){return this.sortUsers(),x$1` + <form id="form" name="user_form" method="post"> + <div> + <input + type="email" + placeholder="Email address" + name="email" + required + /> + </div> + <div> + <label + ><input + type="checkbox" + name="is_admin" + @click="${this._onAdminToggle}" + /> + User is admin</label + > + </div> + <div> + <label + ><input type="checkbox" name="is_site_editor" /> User is site + editor</label + > + </div> + <div> + <input type="submit" @click="${this.ajaxSubmit}" value="Add user" /> + </div> + </form> + + <ul id="user-list"> + ${this.users.map((user,index)=>x$1` + <li> + <a + href="#" + data-index="${index}" + data-account="${user.id}" + @click="${this.ajaxDelete}" + >delete</a + > + ${user.is_admin?x$1`(admin)`:E$1} + ${!user.is_admin&&user.is_site_editor?x$1`(site editor)`:E$1} + <span>${user.email}</span> + </li> + `)} + </ul> + `}};__decorate$3([r$6()],ChromedashUserlist.prototype,"users",void 0),ChromedashUserlist=__decorate$3([t$3("chromedash-userlist")],ChromedashUserlist);var __decorate$2=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};let ChromedashEnterprisePage=class ChromedashEnterprisePage extends ChromedashAllFeaturesPage{renderBox(query){return x$1` + <chromedash-feature-table + query=${query} + ?signedIn=${!!this.user} + ?canEdit=${this.user&&this.user.can_edit_all} + .starredFeatures=${this.starredFeatures} + @star-toggle-event=${this.handleStarToggle} + num="100" + alwaysOfferPagination + columns="normal" + > + </chromedash-feature-table> + `}renderEnterpriseFeatures(){return this.renderBox("feature_type=\"New Feature or removal affecting enterprises\" OR enterprise_impact>1")}render(){return x$1` + <h2>Enterprise features and breaking changes</h2> + ${this.renderEnterpriseFeatures()} + `}};ChromedashEnterprisePage=__decorate$2([t$3("chromedash-enterprise-page")],ChromedashEnterprisePage);var __decorate$1=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const milestoneQueryParamKey="milestone";let ChromedashEnterpriseReleaseNotesPage=class ChromedashEnterpriseReleaseNotesPage extends i$4{constructor(){super(...arguments),this.currentChromeBrowserUpdates=[],this.upcomingChromeBrowserUpdates=[],this.currentChromeEnterpriseCore=[],this.upcomingChromeEnterpriseCore=[],this.currentChromeEnterprisePremium=[],this.upcomingChromeEnterprisePremium=[],this.features=[],this.editingFeatureIds=new Set,this.previewingIds=new Set}static get styles(){return[...SHARED_STYLES,i$7` + :host > * { + margin: 2rem 0; + } + + *[hidden] { + display: none; + } + h1 { + font-size: 2rem; + line-height: 2.5rem; + margin: 0 0 0.5rem; + } + + h2 { + font-size: 1.5rem; + letter-spacing: 0rem; + line-height: 2rem; + margin: 2rem 0 0.5rem; + font-weight: bold; + } + + h3 { + margin: 16px 0; + } + + table { + width: 100%; + } + + tr { + background-color: var(--table-row-background); + } + + th { + background-color: var(--table-header-background); + } + + table, + th, + td { + border: var(--table-divider); + } + + table th, + .bold { + font-weight: bold; + } + + table th, + table td { + padding: 16px 32px; + vertical-align: top; + } + + ul { + padding-inline-start: 1rem; + } + + .stage { + margin-top: 16px; + } + + .feature { + margin: 1rem 0 2rem; + background: var(--card-background); + border: var(--card-border); + border-radius: var(--default-border-radius); + box-shadow: var(--card-box-shadow); + padding: var(--content-padding); + } + + .toremove { + margin: 1rem 0; + } + + .labels { + margin-bottom: var(--content-padding-half); + } + .confidential::part(base) { + background: var(--warning-background); + font-weight: bold; + } + .reviewed::part(base) { + background: var(--sl-color-blue-100); + } + .ready::part(base) { + background: var(--success-background); + } + + .toremove { + font-style: italic; + } + + td:not(:first-child), + th:not(:first-child) { + text-align: center; + } + + .edit-button { + float: right; + } + .feature-summary { + margin-bottom: var(--content-padding); + } + .rollout-milestone { + width: 6em; + } + .rollout-platforms { + margin-left: 2em; + flex-grow: 1; + } + + .screenshots { + display: flex; + flex-wrap: wrap; + gap: 1rem; + } + + .screenshots img { + flex: 0 1 auto; + max-height: 300px; + max-width: calc(50% - 0.5rem); + } + `]}convertShippingStageToRolloutStages(stage){const milestones=[stage.desktop_first,stage.android_first,stage.ios_first,stage.webview_first,stage.desktop_last,stage.android_last,stage.ios_last,stage.webview_last],milestoneAndPlatformsMap=milestones.reduce((acc,milestone)=>({...acc,[milestone]:new Set}),{});return stage.desktop_first&&(milestoneAndPlatformsMap[stage.desktop_first].add(PLATFORM_CATEGORIES.PLATFORM_WINDOWS[0]),milestoneAndPlatformsMap[stage.desktop_first].add(PLATFORM_CATEGORIES.PLATFORM_MAC[0]),milestoneAndPlatformsMap[stage.desktop_first].add(PLATFORM_CATEGORIES.PLATFORM_LINUX[0])),stage.android_first&&milestoneAndPlatformsMap[stage.android_first].add(PLATFORM_CATEGORIES.PLATFORM_ANDROID[0]),stage.ios_first&&milestoneAndPlatformsMap[stage.ios_first].add(PLATFORM_CATEGORIES.PLATFORM_IOS[0]),stage.webview_first&&milestoneAndPlatformsMap[stage.webview_first].add(PLATFORM_CATEGORIES.PLATFORM_ANDROID[0]),stage.desktop_last&&(milestoneAndPlatformsMap[stage.desktop_last].add(PLATFORM_CATEGORIES.PLATFORM_WINDOWS[0]),milestoneAndPlatformsMap[stage.desktop_last].add(PLATFORM_CATEGORIES.PLATFORM_MAC[0]),milestoneAndPlatformsMap[stage.desktop_last].add(PLATFORM_CATEGORIES.PLATFORM_LINUX[0])),stage.android_last&&milestoneAndPlatformsMap[stage.android_last].add(PLATFORM_CATEGORIES.PLATFORM_ANDROID[0]),stage.ios_last&&milestoneAndPlatformsMap[stage.ios_last].add(PLATFORM_CATEGORIES.PLATFORM_IOS[0]),stage.webview_last&&milestoneAndPlatformsMap[stage.webview_last].add(PLATFORM_CATEGORIES.PLATFORM_ANDROID[0]),Object.entries(milestoneAndPlatformsMap).map(([milestone,platforms])=>({stage_type:STAGE_ENT_ROLLOUT,rollout_milestone:+milestone,rollout_platforms:Array.from(platforms).map(String),rollout_stage_plan:ROLLOUT_STAGE_PLAN_CATEGORIES.ROLLOUT_STAGE_PLAN_CUSTOM[0],rollout_details:"No rollout step"}))}convertFeatureShippingStagesToRolloutStages(f){const rollouts=f.stages.filter(s=>s.stage_type===STAGE_ENT_ROLLOUT),converted=f.stages.filter(s=>STAGE_TYPES_SHIPPING.has(s.stage_type)).map(s=>this.convertShippingStageToRolloutStages(s)).flatMap(x=>x);let newStages=0<rollouts.length?rollouts:converted;return newStages=newStages.filter(s=>!!s.rollout_milestone),newStages=newStages.sort((a,b)=>a.rollout_milestone-b.rollout_milestone),{...f,stages:newStages}}updateFeatures(features){features=features.map(f=>this.convertFeatureShippingStagesToRolloutStages(f)),this.features=features.filter(({stages})=>stages.some(s=>s.stage_type===STAGE_ENT_ROLLOUT)),this.categorizeFeatures()}categorizeFeatures(){var _Mathmin1=Math.min;const currentFeatures=this.features.filter(({stages})=>stages.some(s=>s.rollout_milestone===this.selectedMilestone)).sort((a,b)=>b.enterprise_impact-a.enterprise_impact);this.currentChromeBrowserUpdates=currentFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_BROWSER_UPDATE[0]),this.currentChromeEnterpriseCore=currentFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_CORE[0]),this.currentChromeEnterprisePremium=currentFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_PREMIUM[0]);const upcomingFeatures=this.features.filter(({stages})=>!stages.some(s=>s.rollout_milestone===this.selectedMilestone)&&stages.some(s=>s.rollout_milestone>this.selectedMilestone)).sort((a,b)=>{const minA=_Mathmin1(...a.stages.filter(s=>(s.rollout_milestone||0)>this.selectedMilestone).map(s=>s.rollout_milestone))||0,minB=_Mathmin1(...b.stages.filter(s=>(s.rollout_milestone||0)>this.selectedMilestone).map(s=>s.rollout_milestone))||0;return minA-minB});this.upcomingChromeBrowserUpdates=upcomingFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_BROWSER_UPDATE[0]),this.upcomingChromeEnterpriseCore=upcomingFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_CORE[0]),this.upcomingChromeEnterprisePremium=upcomingFeatures.filter(f=>f.enterprise_product_category===ENTERPRISE_PRODUCT_CATEGORY.CHROME_ENTERPRISE_PREMIUM[0])}replaceOneFeature(revisedFeature){const revisedList=this.features.map(f=>f.id===revisedFeature.id?revisedFeature:f);this.features=revisedList,this.categorizeFeatures()}connectedCallback(){window.csClient.getChannels().then(channels=>{this.channels=channels;const queryParams=parseRawQuery(window.location.search);milestoneQueryParamKey in queryParams?this.selectedMilestone=parseInt(queryParams[milestoneQueryParamKey],10):(this.selectedMilestone=this.channels.stable.version,updateURLParams(milestoneQueryParamKey,this.selectedMilestone))}).then(()=>window.csClient.getFeaturesForEnterpriseReleaseNotes(this.selectedMilestone)).then(({features})=>this.updateFeatures(features)).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}).finally(()=>super.connectedCallback())}updateSelectedMilestone(){const milestoneSelector=this.shadowRoot.querySelector("#milestone-selector");this.selectedMilestone=parseInt(milestoneSelector.value),window.csClient.getFeaturesForEnterpriseReleaseNotes(this.selectedMilestone).then(({features})=>this.updateFeatures(features)).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")})}update(changedProperties){this.selectedMilestone!==void 0&&updateURLParams(milestoneQueryParamKey,this.selectedMilestone),super.update(changedProperties)}renderMilestoneSelector(){const options=[];for(let i=0;i<this.selectedMilestone+20;++i)options.push(x$1`<sl-option value="${i}">Chrome ${i} release summary</sl-option>`);return x$1` <sl-select + id="milestone-selector" + placement="top" + hoist + size="small" + value=${this.selectedMilestone} + @sl-change=${this.updateSelectedMilestone} + > + ${options.map(option=>option)} + </sl-select>`}getFeatureMarkerForCategory(feature,category){return feature.enterprise_feature_categories.includes(category.toString())?"\u2713":""}renderReleaseNotesSummarySection(title,features){return x$1` + <tr> + <th>${title}</th> + <th>Security / Privacy</th> + <th>User productivity / Apps</th> + <th>Management</th> + </tr> + ${0===features.length?x$1`<tr> + <td colspan="4">Nothing</td> + </tr>`:features.map(f=>x$1` + <tr> + <td>${f.name}</td> + <td> + ${this.getFeatureMarkerForCategory(f,ENTERPRISE_FEATURE_CATEGORIES.SECURITYANDPRIVACY[0])} + </td> + <td> + ${this.getFeatureMarkerForCategory(f,ENTERPRISE_FEATURE_CATEGORIES.USERPRODUCTIVITYANDAPPS[0])} + </td> + <td> + ${this.getFeatureMarkerForCategory(f,ENTERPRISE_FEATURE_CATEGORIES.MANAGEMENT[0])} + </td> + </tr> + `)} + `}renderReleaseNotesSummary(){return x$1` <table id="release-notes-summary"> + ${this.renderReleaseNotesSummarySection("Chrome Browser updates",this.currentChromeBrowserUpdates)} + ${this.renderReleaseNotesSummarySection("Chrome Enterprise Core (CEC)",this.currentChromeEnterpriseCore)} + ${this.renderReleaseNotesSummarySection("Chrome Enterprise Premium (CEP, paid SKU)",this.currentChromeEnterprisePremium)} + ${this.renderReleaseNotesSummarySection("Upcoming Chrome Browser updates",this.upcomingChromeBrowserUpdates)} + ${this.renderReleaseNotesSummarySection("Upcoming Chrome Enterprise Core (CEC)",this.upcomingChromeEnterpriseCore)} + ${this.renderReleaseNotesSummarySection("Upcoming Chrome Enterprise Premium (CEP, paid SKU)",this.upcomingChromeEnterprisePremium)} + </table>`}getStageTitle(stage){if(0===stage.rollout_platforms.length||stage.rollout_platforms.length===Object.values(PLATFORMS_DISPLAYNAME).length)return`Chrome ${stage.rollout_milestone}`;const rollout_staqe_plan_display=stage.rollout_stage_plan===ROLLOUT_STAGE_PLAN_CATEGORIES.ROLLOUT_STAGE_PLAN_CUSTOM[0]?"":ROLLOUT_STAGE_PLAN_DISPLAYNAME[stage.rollout_stage_plan];return`Chrome ${stage.rollout_milestone} on `+`${stage.rollout_platforms.map(p=>PLATFORMS_DISPLAYNAME[p]).join(", ")}`+` ${rollout_staqe_plan_display?"- "+rollout_staqe_plan_display:""}`}userCanEdit(f){return this.user&&(this.user.can_edit_all||this.user.editable_features.includes(f.id))}userCanReview(){return this.user&&(this.user.is_admin||this.user.can_review_release_notes)}startEditing(featureId){const newEditing=new Set(this.editingFeatureIds);newEditing.add(featureId),this.editingFeatureIds=newEditing}cancel(featureId){const newEditing=new Set(this.editingFeatureIds);newEditing.delete(featureId),this.editingFeatureIds=newEditing}nowString(){const now=new Date,formatter=new Intl.DateTimeFormat("en-CA",{year:"numeric",month:"2-digit",day:"2-digit",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1,timeZone:"UTC"});let nowStr=formatter.format(now);return nowStr=nowStr.replace(",",""),nowStr}save(f){const fieldValues=[],addFieldValue=(name,el,originalValue,stage)=>{const value="SL-CHECKBOX"===el?.tagName?el?.checked:el?.value;value!==void 0&&""+value!=""+originalValue&&fieldValues.push({name,value,touched:!0,stageId:stage?.id})};let nameEl=this.shadowRoot?.querySelector("#edit-name-"+f.id);addFieldValue("name",nameEl,f.name);let confidentialEl=this.shadowRoot?.querySelector("#edit-confidential-"+f.id);addFieldValue("confidential",confidentialEl,f.confidential);let reviewedEl=this.shadowRoot?.querySelector("#edit-reviewed-"+f.id);addFieldValue("is_releasenotes_content_reviewed",reviewedEl,f.is_releasenotes_content_reviewed);let readyEl=this.shadowRoot?.querySelector("#edit-ready-"+f.id);addFieldValue("is_releasenotes_publish_ready",readyEl,f.is_releasenotes_publish_ready);let summaryEl=this.shadowRoot?.querySelector("#edit-summary-"+f.id);addFieldValue("summary",summaryEl,f.summary);const isMarkdown=(f.markdown_fields||[]).includes("summary");let markdownEl=this.shadowRoot?.querySelector("#summary-is-markdown-"+f.id);addFieldValue("summary_is_markdown",markdownEl,isMarkdown);for(const s of f.stages)if(s.id){const milestoneEl=this.shadowRoot?.querySelector("#edit-rollout-milestone-"+s.id);addFieldValue("rollout_milestone",milestoneEl,s.rollout_milestone,s);const platformsEl=this.shadowRoot?.querySelector("#edit-rollout-platforms-"+s.id);addFieldValue("rollout_platforms",platformsEl,s.rollout_platforms,s);const rolloutStagePlanEl=this.shadowRoot?.querySelector("#edit-rollout-stage-plan-"+s.id);addFieldValue("rollout_stage_plan",rolloutStagePlanEl,s.rollout_stage_plan,s);const detailsEl=this.shadowRoot?.querySelector("#edit-rollout-details-"+s.id);addFieldValue("rollout_details",detailsEl,s.rollout_details,s)}const submitBody=formatFeatureChanges(fieldValues,f.id);window.csClient.updateFeature(submitBody).then(resp=>{window.csClient.getFeature(f.id).then(resp2=>{this.replaceOneFeature(this.convertFeatureShippingStagesToRolloutStages(resp2))})}).catch(()=>{showToastMessage("Some errors occurred. Please refresh the page or try again later.")}).finally(()=>{this.cancel(f.id)})}renderToRemoveParagraph(f){return x$1` + <p class="toremove"> + <b>< To remove</b> + - <a target="_blank" href="/feature/${f.id}">Feature details</a> - + <b>Owners:</b> ${f.browsers.chrome.owners?.join(", ")} - + <b>Editors:</b> ${(f.editors||[]).join(", ")} - + <b>Enterprise impact:</b> ${ENTERPRISE_IMPACT_DISPLAYNAME[f.enterprise_impact]} + - <b>First notice:</b> ${f.first_enterprise_notification_milestone} - + <b>Last updated:</b> + <a + href="/feature/${f.id}/activity" + target="_blank" + title=${o$6(f.updated.when)} + > + ${renderRelativeDate(f.updated.when)} + </a> + by ${f.updated.by} + <b>></b> + </p> + `}renderEditButton(f){return this.userCanEdit(f)&&!this.editingFeatureIds.has(f.id)?x$1` + <sl-button + @click=${()=>{this.startEditing(f.id)}} + class="edit-button" + size="small" + >Edit</sl-button + > + `:x$1``}renderLabels(f){let confidentialLabel=x$1``;f.confidential&&(confidentialLabel=x$1`<sl-tag pill size="small" class="confidential" + >CONFIDENTIAL</sl-tag + >`);let reviewedLabel=x$1``;f.is_releasenotes_content_reviewed&&(reviewedLabel=x$1`<sl-tag pill size="small" class="reviewed" + >Release Notes Content Finalized</sl-tag + >`);let readyLabel=x$1``;return f.is_releasenotes_publish_ready&&(readyLabel=x$1`<sl-tag pill size="small" class="ready" + >Ready for Publishing</sl-tag + >`),x$1`<div class="labels"> + ${confidentialLabel} ${reviewedLabel} ${readyLabel} + </div>`}renderEditableLabels(f){let confidentialBox=x$1` + <div> + <sl-checkbox + class="feature-confidential" + id="edit-confidential-${f.id}" + ?checked=${f.confidential} + size="small" + > + Confidential + </sl-checkbox> + </div> + `,reviewedBox=x$1``;this.userCanReview()&&(reviewedBox=x$1` + <div> + <sl-checkbox + class="feature-reviewed" + id="edit-reviewed-${f.id}" + ?checked=${f.is_releasenotes_content_reviewed} + size="small" + > + Release Notes Content Finalized + </sl-checkbox> + </div> + `);let readyBox=x$1``;return this.userCanReview()&&(readyBox=x$1`<div> + <sl-checkbox + class="feature-ready" + id="edit-ready-${f.id}" + ?checked=${f.is_releasenotes_publish_ready} + size="small" + > + Ready for Publishing + </sl-checkbox> + </div> `),x$1`${confidentialBox} ${reviewedBox} ${readyBox}`}renderFeatureName(f){return x$1`<strong>${f.name}</strong>`}renderEditableFeatureName(f){return x$1` + <sl-input + class="feature-name" + id="edit-name-${f.id}" + value=${f.name} + size="small" + > + </sl-input> + `}renderFeatureSummary(f){const isMarkdown=(f.markdown_fields||[]).includes("summary"),markup=autolink(f.summary,[],isMarkdown);return isMarkdown?x$1`${markup}`:x$1`<p class="summary preformatted">${markup}</p>`}handlePreviewChecked(e,featureOrStageId){const newPreviewing=new Set(this.previewingIds);e.target.checked?newPreviewing.add(featureOrStageId):newPreviewing.delete(featureOrStageId),this.previewingIds=newPreviewing}renderEditableFeatureSummary(f){const isMarkdown=(f.markdown_fields||[]).includes("summary"),isPreviewing=this.previewingIds.has(f.id),editor=x$1` <sl-textarea + ?hidden=${isPreviewing} + class="feature-summary" + id="edit-summary-${f.id}" + value=${f.summary} + size="small" + resize="auto" + > + </sl-textarea>`,previewText=this.shadowRoot?.querySelector("#edit-summary-"+f.id)?.value??f.summary,markdownChecked=this.shadowRoot?.querySelector("#summary-is-markdown-"+f.id)?.checked??isMarkdown,preview=x$1` + <div + id="preview" + ?hidden=${!isPreviewing} + style="border:var(--card-border); padding:0 var(--content-padding); min-height:14em; background:var(--table-alternate-background)" + > + ${autolink(previewText,[],markdownChecked)} + </div> + `,controls=x$1` + <sl-checkbox + class="markdown-checkbox" + id="summary-is-markdown-${f.id}" + size="small" + ?checked=${isMarkdown} + >Use markdown</sl-checkbox + > + <sl-icon-button + name="info-circle" + id="info-button" + title="GitHub flavored markdown docs" + href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" + target="_blank" + ></sl-icon-button> + <sl-checkbox + id="show-preview-${f.id}" + size="small" + ?checked=${isPreviewing} + @sl-change=${e=>this.handlePreviewChecked(e,f.id)} + > + Preview + </sl-checkbox> + `;return x$1` ${preview} ${editor} ${controls} `}renderEditableStageItem(f,s,shouldDisplayStageTitleInBold){const platforms=s.rollout_platforms,choices=PLATFORM_CATEGORIES,availableOptions=Object.values(choices).filter(([value,label,obsolete])=>!obsolete||platforms.includes(""+value)),isPreviewing=this.previewingIds.has(s.id),editor=x$1` <sl-textarea + ?hidden=${isPreviewing} + class="rollout-details" + id="edit-rollout-details-${s.id}" + value=${s.rollout_details} + size="small" + rows="1" + resize="auto" + > + </sl-textarea>`,previewText=this.shadowRoot?.querySelector("#edit-rollout-details-"+s.id)?.value??s.rollout_details,preview=x$1` + <div + ?hidden=${!isPreviewing} + id="preview" + style="border:var(--card-border); padding:0 var(--content-padding); min-height:14em; background:var(--table-alternate-background)" + > + ${autolink(previewText,[],!0)} + </div> + `,controls=x$1` + <sl-checkbox class="markdown-checkbox" size="small" checked disabled + >Use markdown</sl-checkbox + > + <sl-icon-button + name="info-circle" + id="info-button" + title="GitHub flavored markdown docs" + href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" + target="_blank" + ></sl-icon-button> + <sl-checkbox + id="show-preview-${s.id}" + size="small" + ?checked=${isPreviewing} + @sl-change=${e=>this.handlePreviewChecked(e,s.id)} + > + Preview + </sl-checkbox> + `;return x$1` + <li class="stage"> + <div class="hbox"> + <sl-input + class="rollout-milestone" + id="edit-rollout-milestone-${s.id}" + type="number" + value=${s.rollout_milestone} + ></sl-input> + + <sl-select + class="rollout-platforms" + multiple + clearable + id="edit-rollout-platforms-${s.id}" + .value=${platforms} + > + ${availableOptions.map(([value,label])=>x$1` + <sl-option value="${value}"> ${label} </sl-option> + `)} + </sl-select> + </div> + <sl-select + class="rollout-stage-plan" + id="edit-rollout-stage-plan-${s.id}" + value=${s.rollout_stage_plan} + > + ${Object.values(ROLLOUT_STAGE_PLAN_CATEGORIES).map(([value,label])=>x$1`<sl-option value=${value}>${label}</sl-option>`)} + </sl-select> + ${preview} ${editor} ${controls} + </li> + `}renderStageItem(f,s,shouldDisplayStageTitleInBold){let details=x$1``;if(s.rollout_details){const markup=autolink(s.rollout_details,[],!0);details=x$1`${markup}`}return x$1` + <li class="stage"> + <span + class="${shouldDisplayStageTitleInBold(s.rollout_milestone,f.stages.map(s=>s.rollout_milestone).sort())?"bold":""}" + > + ${this.getStageTitle(s)} + </span> + ${details} + </li> + `}renderSaveAndCancel(f){return this.editingFeatureIds.has(f.id)?x$1` + <sl-button + class="save-button" + @click=${()=>{this.save(f)}} + size="small" + variant="primary" + >Save</sl-button + > + <sl-button + class="cancel-button" + @click=${()=>{this.cancel(f.id)}} + size="small" + >Cancel</sl-button + > + `:x$1``}renderFeatureReleaseNote(f,shouldDisplayStageTitleInBold){const isEditing=this.editingFeatureIds.has(f.id);return x$1` <section class="feature"> + ${this.renderEditButton(f)} + ${isEditing?this.renderEditableLabels(f):this.renderLabels(f)} + ${isEditing?this.renderEditableFeatureName(f):this.renderFeatureName(f)} + ${this.renderToRemoveParagraph(f)} + ${isEditing?this.renderEditableFeatureSummary(f):this.renderFeatureSummary(f)} + <ul class="stages"> + ${f.stages.map(s=>isEditing&&s.id?this.renderEditableStageItem(f,s,shouldDisplayStageTitleInBold):this.renderStageItem(f,s,shouldDisplayStageTitleInBold))} + </ul> + ${this.renderSaveAndCancel(f)} + + <div class="screenshots"> + ${f.screenshot_links.map((url,i)=>x$1`<img src="${url}" alt="Feature screenshot ${i+1}" />`)} + </div> + </section>`}renderReleaseNotesDetailsSection(title,features,shouldDisplayStageTitleInBold){return x$1` <div class="note-section"> + <h2>${title}</h2> + ${features.map(f=>this.renderFeatureReleaseNote(f,shouldDisplayStageTitleInBold))} + </div>`}renderReleaseNotesDetails(){return x$1` ${this.renderReleaseNotesDetailsSection("Chrome Browser updates",this.currentChromeBrowserUpdates,m=>m===this.selectedMilestone)} + ${this.renderReleaseNotesDetailsSection("Chrome Enterprise Core (CEC)",this.currentChromeEnterpriseCore,m=>m===this.selectedMilestone)} + ${this.renderReleaseNotesDetailsSection("Chrome Enterprise Premium (CEP, paid SKU)",this.currentChromeEnterprisePremium,m=>m===this.selectedMilestone)} + ${this.renderReleaseNotesDetailsSection("Upcoming Chrome Browser updates",this.upcomingChromeBrowserUpdates,(m,milestones)=>milestones.find(x=>parseInt(x)>this.selectedMilestone)===m)} + ${this.renderReleaseNotesDetailsSection("Upcoming Chrome Enterprise Core (CEC)",this.upcomingChromeEnterpriseCore,(m,milestones)=>milestones.find(x=>parseInt(x)>this.selectedMilestone)===m)} + ${this.renderReleaseNotesDetailsSection("Upcoming Chrome Enterprise Premium (CEP, paid SKU)",this.upcomingChromeEnterprisePremium,(m,milestones)=>milestones.find(x=>parseInt(x)>this.selectedMilestone)===m)}`}render(){return x$1` + <h1>Chrome Enterprise and Education release notes</h1> + ${this.renderMilestoneSelector()} ${this.renderReleaseNotesSummary()} + ${this.renderReleaseNotesDetails()} + `}};__decorate$1([n$5({attribute:!1})],ChromedashEnterpriseReleaseNotesPage.prototype,"user",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"currentChromeBrowserUpdates",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"upcomingChromeBrowserUpdates",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"currentChromeEnterpriseCore",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"upcomingChromeEnterpriseCore",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"currentChromeEnterprisePremium",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"upcomingChromeEnterprisePremium",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"features",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"channels",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"selectedMilestone",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"editingFeatureIds",void 0),__decorate$1([r$6()],ChromedashEnterpriseReleaseNotesPage.prototype,"previewingIds",void 0),ChromedashEnterpriseReleaseNotesPage=__decorate$1([t$3("chromedash-enterprise-release-notes-page")],ChromedashEnterpriseReleaseNotesPage);var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=3>c?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;0<=i;i--)(d=decorators[i])&&(r=(3>c?d(r):3<c?d(target,key,r):d(target,key))||r);return 3<c&&r&&Object.defineProperty(target,key,r),r};const WPT_RESULTS_REGEX=/(https?:\/\/wpt\.fyi\/results[^\s?]+)/g,COOLDOWN_MS=1800000,HANGING_TIMEOUT_MS=3600000;let ChromedashWPTEvalPage=class ChromedashWPTEvalPage extends i$4{constructor(){super(...arguments),this.featureId=0,this.feature=null,this.loading=!1,this.isRequirementsFulfilled=!1,this.completedInThisSession=!1,this._cooldownRemaining=0,this._reportContentChanged=!1,this._pollIntervalId=null,this._cooldownIntervalId=null,this._previousReportContent=null}static get styles(){return[...SHARED_STYLES,i$7` + :host { + display: block; + min-height: 100vh; + background: var(--sl-color-neutral-50); + padding: 2em; + } + + h1 { + font-size: 2rem; + font-weight: 300; + margin-bottom: 1.5rem; + padding-bottom: 0.5rem; + } + + h2 { + font-size: 1.5rem; + font-weight: 400; + margin-top: 0; + margin-bottom: 1rem; + } + + h3 { + margin-top: 1.5em; + } + + .experimental-tag { + font-size: 0.6em; + font-weight: normal; + vertical-align: middle; + background: var(--sl-color-neutral-200); + padding: 2px 8px; + border-radius: 12px; + margin-left: 8px; + } + + .card { + background: var(--sl-color-neutral-0); + border: 1px solid var(--sl-color-neutral-200); + border-radius: var(--sl-border-radius-medium); + padding: var(--sl-spacing-x-large); + box-shadow: var(--sl-shadow-x-small); + margin-bottom: var(--sl-spacing-large); + } + + .description ul { + line-height: 1.6; + } + .description li { + margin-bottom: 0.5em; + } + + .requirements-list { + display: flex; + flex-direction: column; + gap: 12px; + } + + .requirement-item { + display: flex; + align-items: center; + gap: 12px; + font-size: 16px; + padding: 8px; + border-radius: var(--sl-border-radius-medium); + transition: background 0.2s ease; + } + .requirement-item:hover { + background: var(--sl-color-neutral-50); + } + + .requirement-item sl-icon { + font-size: 1.4em; + flex-shrink: 0; + } + .requirement-item .success { + color: var(--sl-color-success-600); + } + .requirement-item .danger { + color: var(--sl-color-danger-600); + } + + .edit-link { + font-size: 0.9em; + margin-left: auto; + padding: 4px 12px; + background: var(--sl-color-primary-50); + border-radius: 12px; + text-decoration: none; + font-weight: 600; + } + .edit-link:hover { + background: var(--sl-color-primary-100); + } + + .url-list-container { + margin-left: 44px; + } + .url-list { + list-style: none; + margin: 0; + padding: 12px; + font-size: 0.85em; + background: var(--sl-color-neutral-100); + border-radius: 4px; + border: 1px solid var(--sl-color-neutral-200); + max-height: 150px; + overflow-y: auto; + } + .url-list li { + margin-bottom: 4px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .url-list a { + text-decoration: none; + } + .url-list a:hover { + text-decoration: underline; + } + + .action-section { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + min-height: 120px; + } + + .generate-button { + font-size: 1.1rem; + padding-left: 2rem; + padding-right: 2rem; + } + .generate-button sl-icon { + font-size: 1.3em; + } + + .cooldown-message { + margin-top: 12px; + color: var(--sl-color-neutral-600); + font-size: 0.9em; + display: flex; + align-items: center; + gap: 6px; + } + + .help-text { + margin-top: 8px; + color: var(--sl-color-neutral-600); + font-size: 0.9rem; + max-width: 400px; + line-height: 1.4; + } + + .status-in-progress, + .status-complete { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + font-size: 1.1rem; + } + .status-in-progress { + color: var(--sl-color-primary-600); + } + .status-in-progress sl-spinner { + font-size: 3rem; + --track-width: 4px; + } + .status-complete { + color: var(--sl-color-success-700); + } + .status-complete sl-icon { + font-size: 3rem; + color: var(--sl-color-success-600); + } + + .report-content { + overflow-wrap: break-word; + line-height: 1.6; + } + .report-content h1, + .report-content h2, + .report-content h3 { + margin-top: 1.5em; + margin-bottom: 0.75em; + color: var(--sl-color-neutral-1000); + } + .report-content *:first-child { + margin-top: 0; + } + .report-content pre { + background: var(--sl-color-neutral-900); + padding: 16px; + border-radius: 6px; + overflow-x: auto; + } + .report-content code { + background: var(--sl-color-neutral-200); + padding: 2px 4px; + border-radius: 4px; + font-size: 0.9em; + font-family: monospace; + } + .report-content pre code { + background: transparent; + padding: 0; + color: inherit; + } + + .prewrap { + white-space: pre-wrap; + } + + @keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .fade-in { + animation: fadeIn 0.8s ease-out forwards; + } + .delay-title { + animation-delay: 0.1s; + } + .delay-content { + animation-delay: 0.4s; + } + + sl-alert { + margin-bottom: var(--sl-spacing-large); + } + `]}async fetchData(){this.feature||(this.loading=!0);try{this.feature=await window.csClient.getFeature(this.featureId),this.checkRequirements(),this.managePolling(),this.updateCooldown()}catch(error){showToastMessage("Some errors occurred. Please refresh the page or try again later.")}finally{this.loading=!1}}updated(changedProperties){if(changedProperties.has("feature")&&this.feature){const currentReport=this.feature.ai_test_eval_report||null;currentReport&¤tReport!==this._previousReportContent&&(this._reportContentChanged=!0,setTimeout(()=>{this._reportContentChanged=!1},100)),this._previousReportContent=currentReport}}connectedCallback(){super.connectedCallback(),this.fetchData()}disconnectedCallback(){super.disconnectedCallback(),this.stopPolling(),this.stopCooldownTimer()}checkRequirements(){if(!this.feature)return void(this.isRequirementsFulfilled=!1);const hasSpecLink=!!this.feature.spec_link,hasWptDescr=!!this.feature.wpt_descr,hasValidUrls=null!==(this.feature.wpt_descr||"").match(WPT_RESULTS_REGEX);this.isRequirementsFulfilled=hasSpecLink&&hasWptDescr&&hasValidUrls}updateCooldown(){if(this.feature?.ai_test_eval_run_status===AITestEvaluationStatus.COMPLETE&&this.feature.ai_test_eval_status_timestamp){const completedAt=new Date(this.feature.ai_test_eval_status_timestamp).getTime(),now=Date.now(),elapsed=now-completedAt;elapsed<COOLDOWN_MS?(this._cooldownRemaining=COOLDOWN_MS-elapsed,this.startCooldownTimer()):(this._cooldownRemaining=0,this.stopCooldownTimer())}else this._cooldownRemaining=0,this.stopCooldownTimer()}startCooldownTimer(){this._cooldownIntervalId||(this._cooldownIntervalId=window.setInterval(()=>{this.updateCooldown()},6e4))}stopCooldownTimer(){this._cooldownIntervalId&&(window.clearInterval(this._cooldownIntervalId),this._cooldownIntervalId=null)}managePolling(){const status=this.feature?.ai_test_eval_run_status;status===AITestEvaluationStatus.IN_PROGRESS?this.startPolling():(this._pollIntervalId&&status===AITestEvaluationStatus.COMPLETE&&(this.completedInThisSession=!0),this.stopPolling())}startPolling(){this._pollIntervalId||(this._pollIntervalId=window.setInterval(()=>{this.fetchData()},5e3))}stopPolling(){this._pollIntervalId&&(window.clearInterval(this._pollIntervalId),this._pollIntervalId=null)}async handleGenerateClick(){if(this.isRequirementsFulfilled&&this.feature&&!(0<this._cooldownRemaining))try{this.feature={...this.feature,ai_test_eval_run_status:AITestEvaluationStatus.IN_PROGRESS,ai_test_eval_status_timestamp:new Date().toString()},this.completedInThisSession=!1,this.managePolling(),await window.csClient.generateWPTCoverageEvaluation(this.featureId)}catch(e){showToastMessage("Failed to start evaluation. Please try again later."),this.fetchData()}}renderRequirementItem(isFulfilled,label,urlHash){const icon=isFulfilled?x$1`<sl-icon + class="success" + library="material" + name="check_circle_20px" + ></sl-icon>`:x$1`<sl-icon name="x-circle-fill" class="danger"></sl-icon>`,text=isFulfilled?`${label} provided`:`Missing ${label}`;return x$1` + <div class="requirement-item"> + ${icon} + <span>${text}</span> + <a class="edit-link" href="/guide/editall/${this.featureId}#${urlHash}"> + Edit + </a> + </div> + `}_renderPreformattedText(content){return content?x$1`<div class="url-list prewrap">${content}</div>`:E$1}renderRequirementsChecks(){if(!this.feature)return x$1`${E$1}`;const hasSpecLink=!!this.feature.spec_link,hasWptDescr=!!this.feature.wpt_descr,wptUrls=(this.feature.wpt_descr||"").match(WPT_RESULTS_REGEX)||[],hasValidUrls=0<wptUrls.length;return x$1` + <section class="card"> + <h2>Prerequisites Checklist</h2> + <div class="requirements-list"> + <!-- Name and summary are assumed to always be filled --> + ${this.renderRequirementItem(!0,"Feature name","id_name")} + <div class="url-list-container"> + <div class="url-list">${this.feature.name}</div> + </div> + ${this.renderRequirementItem(!0,"Feature summary","id_summary")} + <div class="url-list-container"> + ${this._renderPreformattedText(this.feature.summary)} + </div> + ${this.renderRequirementItem(hasSpecLink,"Spec URL","id_spec_link")} + ${hasSpecLink?x$1` + <div class="url-list-container"> + <div class="url-list"> + <a + href="${o$6(this.feature.spec_link)}" + target="_blank" + >${this.feature.spec_link}</a + > + </div> + </div> + `:E$1} + ${this.renderRequirementItem(hasWptDescr,"WPT description","id_wpt_descr")} + ${hasWptDescr?x$1` + <div class="url-list-container"> + ${this._renderPreformattedText(this.feature.wpt_descr)} + </div> + `:E$1} + ${this.renderRequirementItem(hasValidUrls,"Valid wpt.fyi results URLs","id_wpt_descr")} + ${hasValidUrls?x$1` + <div class="url-list-container"> + <ul class="url-list"> + ${wptUrls.map(url=>x$1` + <li> + <a href="${url}" target="_blank" title="${url}" + >${url}</a + > + </li> + `)} + </ul> + </div> + `:E$1} + </div> + </section> + `}renderActionSection(){var _Mathceil4=Math.ceil;if(!this.feature)return x$1`${E$1}`;const status=this.feature.ai_test_eval_run_status;let isHanging=!1;if(status===AITestEvaluationStatus.IN_PROGRESS&&this.feature.ai_test_eval_status_timestamp){const startedAt=new Date(this.feature.ai_test_eval_status_timestamp).getTime(),now=Date.now();now-startedAt>HANGING_TIMEOUT_MS&&(isHanging=!0)}if(status===AITestEvaluationStatus.IN_PROGRESS&&!isHanging)return x$1` + <section class="card action-section"> + <div class="status-in-progress"> + <sl-spinner></sl-spinner> + <span>Evaluation in progress... This may take a few minutes.</span> + </div> + </section> + `;if(this.completedInThisSession&&status!==AITestEvaluationStatus.IN_PROGRESS)return x$1` + <section class="card action-section"> + <div class="status-complete fade-in"> + <sl-icon library="material" name="check_circle_20px"></sl-icon> + <span>Evaluation complete! The report is available above.</span> + </div> + </section> + `;const isCooldownActive=0<this._cooldownRemaining,minutesRemaining=_Mathceil4(this._cooldownRemaining/6e4);let buttonLabel="Evaluate test coverage";return isHanging?buttonLabel="Retry evaluation (Process timed out)":this.feature.ai_test_eval_report&&(buttonLabel="Discard this report and reevaluate test coverage"),x$1` + <section class="card action-section"> + ${status===AITestEvaluationStatus.FAILED?x$1` + <sl-alert variant="danger" open> + The previous evaluation run failed. Please try again. + </sl-alert> + `:E$1} + + <sl-button + variant="${this.feature.ai_test_eval_report?"danger":"primary"}" + size="large" + class="generate-button" + ?disabled=${!this.isRequirementsFulfilled||isCooldownActive} + @click=${this.handleGenerateClick} + > + ${buttonLabel} + </sl-button> + + ${isHanging?x$1` + <div class="help-text"> + The previous evaluation seems to be stuck. You can try starting + a new one. + </div> + `:E$1} + ${isCooldownActive?x$1` + <div class="cooldown-message"> + <sl-icon name="hourglass-split"></sl-icon> + Available in ${minutesRemaining} + minute${1===minutesRemaining?"":"s"} + </div> + `:E$1} + </section> + `}renderReport(){if(!this.feature?.ai_test_eval_report)return x$1`${E$1}`;const rawHtml=d.parse(this.feature.ai_test_eval_report),titleClass=this._reportContentChanged?"fade-in delay-title":"",contentClass=this._reportContentChanged?"fade-in delay-content":"";return x$1` + <section class="card report-section"> + <h2 class="${titleClass}">Evaluation Report</h2> + <div class="report-content ${contentClass}">${o$2(rawHtml)}</div> + </section> + `}renderSkeletonSection(){return x$1` + <section class="card"> + <h3><sl-skeleton effect="sheen" style="width: 50%"></sl-skeleton></h3> + <p> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + <sl-skeleton effect="sheen"></sl-skeleton> + </p> + </section> + `}renderSkeletons(){return x$1` + <div style="margin-top: 2em;"> + ${this.renderSkeletonSection()} ${this.renderSkeletonSection()} + </div> + `}render(){return x$1` + <div> + <h1> + AI-powered WPT coverage evaluation + <span class="experimental-tag">Experimental</span> + </h1> + + <sl-alert variant="primary" open> + <sl-icon slot="icon" name="info-circle"></sl-icon> + This feature is experimental and reports may be inaccurate. Please + <a + href="https://github.com/GoogleChrome/chromium-dashboard/issues/new?labels=Feedback,WPT-AI" + target="_blank" + >file an issue</a + > + if you have feedback or suggestions. + </sl-alert> + + <section class="card description"> + <h2>About</h2> + <p> + Here you can generate an AI-powered test coverage report for your + feature using Gemini. Gemini will analyze your feature's details, + specification, and listed Web Platform Tests to evaluate if it meets + standard minimum test coverage criteria. + </p> + + <h3>Before you begin</h3> + <p> + To ensure an accurate report, please verify the following feature + details: + </p> + <ul> + <li> + <strong>Metadata:</strong> Ensure the feature name and summary are + accurate. + </li> + <li> + <strong>Specification:</strong> A valid Spec URL must be provided. + </li> + <li> + <strong>Test Results:</strong> Add relevant + <code>wpt.fyi</code> URLs to the + <i>Web Platform Tests</i> description field. + <ul> + <li> + URLs must begin with <code>https://wpt.fyi/results/</code>. + </li> + <li> + Individual test file URLs are accepted (e.g., + <code>dom/historical.html</code>). + </li> + <li> + Directory URLs are accepted, but <strong>only</strong> if + every test in that directory is relevant to your feature. + </li> + <li> + There is a limit of <strong>50 individual test files</strong> + In the Web Platform Tests repository. If more than 50 relevant + test files are found via the listed URLs, the test suite size + is too big for automated test coverage evaluation. + </li> + <li> + <em + >Note: Subdirectories within listed directories are not + scanned.</em + > + </li> + </ul> + </li> + </ul> + </section> + + ${this.loading?this.renderSkeletons():x$1` + ${this.renderRequirementsChecks()} ${this.renderReport()} + ${this.renderActionSection()} + `} + </div> + `}};__decorate([n$5({type:Number})],ChromedashWPTEvalPage.prototype,"featureId",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"feature",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"loading",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"isRequirementsFulfilled",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"completedInThisSession",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"_cooldownRemaining",void 0),__decorate([r$6()],ChromedashWPTEvalPage.prototype,"_reportContentChanged",void 0),ChromedashWPTEvalPage=__decorate([t$3("chromedash-wpt-eval-page")],ChromedashWPTEvalPage),setBasePath("/static/shoelace"),registerIconLibrary("material",{resolver:name=>`/static/shoelace/assets/material-icons/${name}.svg`,mutator:svg=>svg.setAttribute("fill","currentColor")});//# sourceMappingURL=components.js.map From b0ee3d3c918a2ac17fd52ed3c66b3759bdff4022 Mon Sep 17 00:00:00 2001 From: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:10:37 -0700 Subject: [PATCH 3/4] Add files via upload Signed-off-by: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> --- aboutaddons.html | 876 + live-metrics.j.js | 2 + pdf.mjs | 24923 +++++++ pdf.worker.mjs | 60412 ++++++++++++++++ popup.txt | 299 + react/reactdomclient.js | 38 + .../_class_extract_field_descriptor.js | 6 + socketworker/_class_private_field_get.js | 8 + socketworker/_class_private_field_init.js | 7 + socketworker/alive-session.js | 289 + socketworker/compat | 45 + socketworker/eventloop-tasks.js | 49 + socketworker/multimapindex.js | 64 + socketworker/presence-metadata.js | 81 + socketworker/presence.js | 78 + socketworker/session.ts | 45 + socketworker/socket-worker-15d0549033ee.js | 3 + socketworker/socket-worker.ts | 93 + socketworker/stablesocketindex.js | 231 + socketworker/subscription-set.js | 49 + suiteux..js | 69 + utils.js | 292 +- viewer.mjs | 16934 +++++ web-vitals/base/metric.ts | 11 + web-vitals/base/observer.ts | 66 + web-vitals/base/processor.ts | 6 + web-vitals/cls/layout-shift-processor.ts | 65 + web-vitals/cls/metric.ts | 40 + web-vitals/cls/observer.ts | 34 + web-vitals/dom-nodes.ts | 21 + web-vitals/element-timing/metric.ts | 20 + web-vitals/element-timing/observer.ts | 69 + web-vitals/get-selector.ts | 32 + web-vitals/hpc-events.ts | 84 + web-vitals/hpc-events1.ts | 84 + web-vitals/hpc.ts | 293 + web-vitals/hydro-stats.ts | 198 + web-vitals/hydro-stats1.ts | 198 + web-vitals/inp/interaction-count.ts | 63 + web-vitals/inp/interaction-list.ts | 77 + web-vitals/inp/interaction-processor.ts | 124 + web-vitals/inp/metric.ts | 187 + web-vitals/inp/observer.ts | 80 + web-vitals/long-animation-frames.ts | 28 + web-vitals/utils/when-idle-or-hidden.ts | 24 + web-vitals/web-vitals.ts | 69 + 46 files changed, 106488 insertions(+), 278 deletions(-) create mode 100644 aboutaddons.html create mode 100644 live-metrics.j.js create mode 100644 pdf.mjs create mode 100644 pdf.worker.mjs create mode 100644 popup.txt create mode 100644 react/reactdomclient.js create mode 100644 socketworker/_class_extract_field_descriptor.js create mode 100644 socketworker/_class_private_field_get.js create mode 100644 socketworker/_class_private_field_init.js create mode 100644 socketworker/alive-session.js create mode 100644 socketworker/compat create mode 100644 socketworker/eventloop-tasks.js create mode 100644 socketworker/multimapindex.js create mode 100644 socketworker/presence-metadata.js create mode 100644 socketworker/presence.js create mode 100644 socketworker/session.ts create mode 100644 socketworker/socket-worker-15d0549033ee.js create mode 100644 socketworker/socket-worker.ts create mode 100644 socketworker/stablesocketindex.js create mode 100644 socketworker/subscription-set.js create mode 100644 suiteux..js create mode 100644 viewer.mjs create mode 100644 web-vitals/base/metric.ts create mode 100644 web-vitals/base/observer.ts create mode 100644 web-vitals/base/processor.ts create mode 100644 web-vitals/cls/layout-shift-processor.ts create mode 100644 web-vitals/cls/metric.ts create mode 100644 web-vitals/cls/observer.ts create mode 100644 web-vitals/dom-nodes.ts create mode 100644 web-vitals/element-timing/metric.ts create mode 100644 web-vitals/element-timing/observer.ts create mode 100644 web-vitals/get-selector.ts create mode 100644 web-vitals/hpc-events.ts create mode 100644 web-vitals/hpc-events1.ts create mode 100644 web-vitals/hpc.ts create mode 100644 web-vitals/hydro-stats.ts create mode 100644 web-vitals/hydro-stats1.ts create mode 100644 web-vitals/inp/interaction-count.ts create mode 100644 web-vitals/inp/interaction-list.ts create mode 100644 web-vitals/inp/interaction-processor.ts create mode 100644 web-vitals/inp/metric.ts create mode 100644 web-vitals/inp/observer.ts create mode 100644 web-vitals/long-animation-frames.ts create mode 100644 web-vitals/utils/when-idle-or-hidden.ts create mode 100644 web-vitals/web-vitals.ts diff --git a/aboutaddons.html b/aboutaddons.html new file mode 100644 index 0000000..d37bf54 --- /dev/null +++ b/aboutaddons.html @@ -0,0 +1,876 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!doctype html> +<html> + <head> + <title data-l10n-id="addons-page-title"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      + + + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/live-metrics.j.js b/live-metrics.j.js new file mode 100644 index 0000000..0b52972 --- /dev/null +++ b/live-metrics.j.js @@ -0,0 +1,2 @@ +import*as t from"../../core/common/common.js";import*as e from"../../core/host/host.js";import*as i from"../../core/i18n/i18n.js";import*as n from"../../core/platform/platform.js";import*as a from"../../core/sdk/sdk.js";import*as s from"../emulation/emulation.js";import*as o from"./web-vitals-injected/spec/spec.js";const r={lcpEmulationWarning:"Simulating a new device after the page loads can affect LCP. Reload the page after simulating a new device for accurate LCP data.",lcpVisibilityWarning:"LCP value may be inflated because the page started loading in the background."},l=i.i18n.registerUIStrings("models/live-metrics/LiveMetrics.ts",r),c=i.i18n.getLocalizedString.bind(void 0,l),d="DevTools Performance Metrics";let u;class h{static#t;static async get(){if(!this.#t){const t=new URL("./web-vitals-injected/web-vitals-injected.generated.js",import.meta.url),e=await fetch(t);this.#t=await e.text()}return this.#t}}class m extends t.ObjectWrapper.ObjectWrapper{#e=!1;#i;#n;#a;#s;#o;#r;#l=new Map;#c=new Map;#d=[];#u;#h=new t.Mutex.Mutex;#m=s.DeviceModeModel.DeviceModeModel.tryInstance();constructor(){super(),this.#g()||a.TargetManager.TargetManager.instance().observeTargets(this)}#g(){try{return t.Settings.Settings.instance().moduleSetting("x-msedge-disable-live-metrics-temp-2025").get()}catch{return!1}}static instance(t={forceNew:!1}){const{forceNew:e}=t;return u&&!e||(u=new m),u}get lcpValue(){return this.#s}get clsValue(){return this.#o}get inpValue(){return this.#r}get interactions(){return this.#l}get layoutShifts(){return this.#d}async logInteractionScripts(t){if(!this.#i)return!1;const e=this.#a;if(!e)return!1;const i=[];for(const e of t.longAnimationFrameTimings)for(const n of e.scripts){const e=n.startTime+n.duration;if(et.nodeRef),...this.#d.flatMap(t=>t.affectedNodeRefs)].filter(t=>!!t),n=new Set(i.map(t=>t.backendNodeId())),a=await e.pushNodesByBackendIdsToFrontend(n);if(a){for(let t=0;t[]);let a=i.find(e=>Math.abs(e.nextPaintTime-t.nextPaintTime)<8);if(a||(a={interactionId:`interaction-${t.entryGroupId}-${t.startTime}`,interactionType:t.interactionType,duration:t.duration,eventNames:[],phases:t.phases,startTime:t.startTime,nextPaintTime:t.nextPaintTime,longAnimationFrameTimings:t.longAnimationFrameEntries},i.push(a),this.#l.set(a.interactionId,a)),a.eventNames.includes(t.eventName)||a.eventNames.push(t.eventName),void 0!==t.nodeIndex){const i=await this.#f(t.nodeIndex,e);i&&(a.nodeRef=i)}break}case"LayoutShift":{const i=t.affectedNodeIndices.map(t=>this.#f(t,e)),n=(await Promise.all(i)).filter(t=>!!t),a={score:t.score,uniqueLayoutShiftId:t.uniqueLayoutShiftId,affectedNodeRefs:n};this.#d.push(a);break}case"reset":this.#s=void 0,this.#o=void 0,this.#r=void 0,this.#l.clear(),this.#d=[]}this.#v()}async#y(t){if(!this.#i)return null;const e=this.#i.model(a.RuntimeModel.RuntimeModel);if(!e)return null;const i=e.executionContext(t);if(!i)return null;const n=i.frameId;if(!n)return null;const s=a.FrameManager.FrameManager.instance();return await s.getOrWaitForFrame(n)}async#T(t){const{data:e}=t;e.name===o.EVENT_BINDING_NAME&&await this.#h.run(async()=>{const t=JSON.parse(e.payload);if(this.#a!==e.executionContextId){if("reset"!==t.name)return;const i=await this.#y(e.executionContextId);if(!i?.isPrimaryFrame())return;this.#a=e.executionContextId}await this.#M(t,e.executionContextId)})}async#x(){const t=this.#i;if(!t)return;const e=t.model(a.RuntimeModel.RuntimeModel);if(!e)return;const i=e.executionContexts().filter(t=>t.name===d&&!t.isDefault).map(e=>t.runtimeAgent().invoke_evaluate({expression:`window?.${o.INTERNAL_KILL_SWITCH}?.()`,contextId:e.id}));await Promise.all(i)}clearInteractions(){this.#l.clear(),this.#v()}clearLayoutShifts(){this.#d=[],this.#v()}async targetAdded(t){t===a.TargetManager.TargetManager.instance().primaryPageTarget()&&(this.#i=t,await this.enable())}async targetRemoved(t){if(t!==this.#i)return;await this.disable(),this.#i=void 0;const e=a.TargetManager.TargetManager.instance().primaryPageTarget();e&&(this.#i=e,await this.enable())}async enable(){if(e.InspectorFrontendHost.isUnderTest())return;if(!this.#i||this.#e)return;if(this.#g())return;if(this.#i.type()!==a.Target.Type.FRAME)return;const t=this.#i.model(a.DOMModel.DOMModel);if(!t)return;t.addEventListener(a.DOMModel.Events.DocumentUpdated,this.#I,this);const i=this.#i.model(a.RuntimeModel.RuntimeModel);if(!i)return;i.addEventListener(a.RuntimeModel.Events.BindingCalled,this.#T,this),await i.addBinding({name:o.EVENT_BINDING_NAME,executionContextName:d}),await this.#x();const n=await h.get();if(!this.#i)return;const{identifier:s}=await(this.#i?.pageAgent().invoke_addScriptToEvaluateOnNewDocument({source:n,worldName:d,runImmediately:!0}));this.#n=s,this.#m?.addEventListener("Updated",this.#p,this),this.#e=!0}async disable(){if(!this.#i||!this.#e)return;await this.#x();const t=this.#i.model(a.RuntimeModel.RuntimeModel);t&&(await t.removeBinding({name:o.EVENT_BINDING_NAME}),t.removeEventListener(a.RuntimeModel.Events.BindingCalled,this.#T,this));const e=this.#i.model(a.DOMModel.DOMModel);e&&e.removeEventListener(a.DOMModel.Events.DocumentUpdated,this.#I,this),this.#n&&await this.#i.pageAgent().invoke_removeScriptToEvaluateOnNewDocument({identifier:this.#n}),this.#n=void 0,this.#m?.removeEventListener("Updated",this.#p,this),this.#e=!1}}export{m as LiveMetrics}; +//# sourceMappingURL=live-metrics.js.map diff --git a/pdf.mjs b/pdf.mjs new file mode 100644 index 0000000..c3ae9d7 --- /dev/null +++ b/pdf.mjs @@ -0,0 +1,24923 @@ +/** + * @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.445 + * pdfjsBuild = ec5330f78 + */ +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; + +;// ./src/shared/util.js +const isNodeJS = false; +const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; +const LINE_FACTOR = 1.35; +const LINE_DESCENT_FACTOR = 0.35; +const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR; +const RenderingIntentFlag = { + ANY: 0x01, + DISPLAY: 0x02, + PRINT: 0x04, + SAVE: 0x08, + ANNOTATIONS_FORMS: 0x10, + ANNOTATIONS_STORAGE: 0x20, + ANNOTATIONS_DISABLE: 0x40, + IS_EDITING: 0x80, + OPLIST: 0x100 +}; +const AnnotationMode = { + DISABLE: 0, + ENABLE: 1, + ENABLE_FORMS: 2, + ENABLE_STORAGE: 3 +}; +const AnnotationEditorPrefix = "pdfjs_internal_editor_"; +const AnnotationEditorType = { + DISABLE: -1, + NONE: 0, + FREETEXT: 3, + HIGHLIGHT: 9, + STAMP: 13, + INK: 15, + POPUP: 16, + SIGNATURE: 101, + COMMENT: 102 +}; +const AnnotationEditorParamsType = { + RESIZE: 1, + CREATE: 2, + FREETEXT_SIZE: 11, + FREETEXT_COLOR: 12, + FREETEXT_OPACITY: 13, + INK_COLOR: 21, + INK_THICKNESS: 22, + INK_OPACITY: 23, + HIGHLIGHT_COLOR: 31, + HIGHLIGHT_THICKNESS: 32, + HIGHLIGHT_FREE: 33, + HIGHLIGHT_SHOW_ALL: 34, + DRAW_STEP: 41 +}; +const PermissionFlag = { + PRINT: 0x04, + MODIFY_CONTENTS: 0x08, + COPY: 0x10, + MODIFY_ANNOTATIONS: 0x20, + FILL_INTERACTIVE_FORMS: 0x100, + COPY_FOR_ACCESSIBILITY: 0x200, + ASSEMBLE: 0x400, + PRINT_HIGH_QUALITY: 0x800 +}; +const MeshFigureType = { + TRIANGLES: 1, + LATTICE: 2, + PATCH: 3 +}; +const TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; +const util_ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; +const AnnotationType = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 +}; +const AnnotationReplyType = { + GROUP: "Group", + REPLY: "R" +}; +const AnnotationFlag = { + INVISIBLE: 0x01, + HIDDEN: 0x02, + PRINT: 0x04, + NOZOOM: 0x08, + NOROTATE: 0x10, + NOVIEW: 0x20, + READONLY: 0x40, + LOCKED: 0x80, + TOGGLENOVIEW: 0x100, + LOCKEDCONTENTS: 0x200 +}; +const AnnotationFieldFlag = { + READONLY: 0x0000001, + REQUIRED: 0x0000002, + NOEXPORT: 0x0000004, + MULTILINE: 0x0001000, + PASSWORD: 0x0002000, + NOTOGGLETOOFF: 0x0004000, + RADIO: 0x0008000, + PUSHBUTTON: 0x0010000, + COMBO: 0x0020000, + EDIT: 0x0040000, + SORT: 0x0080000, + FILESELECT: 0x0100000, + MULTISELECT: 0x0200000, + DONOTSPELLCHECK: 0x0400000, + DONOTSCROLL: 0x0800000, + COMB: 0x1000000, + RICHTEXT: 0x2000000, + RADIOSINUNISON: 0x2000000, + COMMITONSELCHANGE: 0x4000000 +}; +const AnnotationBorderStyleType = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 +}; +const AnnotationActionEventType = { + E: "Mouse Enter", + X: "Mouse Exit", + D: "Mouse Down", + U: "Mouse Up", + Fo: "Focus", + Bl: "Blur", + PO: "PageOpen", + PC: "PageClose", + PV: "PageVisible", + PI: "PageInvisible", + K: "Keystroke", + F: "Format", + V: "Validate", + C: "Calculate" +}; +const DocumentActionEventType = { + WC: "WillClose", + WS: "WillSave", + DS: "DidSave", + WP: "WillPrint", + DP: "DidPrint" +}; +const PageActionEventType = { + O: "PageOpen", + C: "PageClose" +}; +const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 +}; +const OPS = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotation: 80, + endAnnotation: 81, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91, + setStrokeTransparent: 92, + setFillTransparent: 93, + rawFillPath: 94 +}; +const DrawOPS = { + moveTo: 0, + lineTo: 1, + curveTo: 2, + quadraticCurveTo: 3, + closePath: 4 +}; +const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; +let verbosity = VerbosityLevel.WARNINGS; +function setVerbosityLevel(level) { + if (Number.isInteger(level)) { + verbosity = level; + } +} +function getVerbosityLevel() { + return verbosity; +} +function info(msg) { + if (verbosity >= VerbosityLevel.INFOS) { + console.info(`Info: ${msg}`); + } +} +function warn(msg) { + if (verbosity >= VerbosityLevel.WARNINGS) { + console.warn(`Warning: ${msg}`); + } +} +function unreachable(msg) { + throw new Error(msg); +} +function assert(cond, msg) { + if (!cond) { + unreachable(msg); + } +} +function _isValidProtocol(url) { + switch (url?.protocol) { + case "http:": + case "https:": + case "ftp:": + case "mailto:": + case "tel:": + return true; + default: + return false; + } +} +function createValidAbsoluteUrl(url, baseUrl = null, options = null) { + if (!url) { + return null; + } + if (options && typeof url === "string") { + if (options.addDefaultProtocol && url.startsWith("www.")) { + const dots = url.match(/\./g); + if (dots?.length >= 2) { + url = `http://${url}`; + } + } + if (options.tryConvertEncoding) { + try { + url = stringToUTF8String(url); + } catch {} + } + } + const absoluteUrl = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url); + return _isValidProtocol(absoluteUrl) ? absoluteUrl : null; +} +function updateUrlHash(url, hash, allowRel = false) { + const res = URL.parse(url); + if (res) { + res.hash = hash; + return res.href; + } + if (allowRel && createValidAbsoluteUrl(url, "http://example.com")) { + return url.split("#", 1)[0] + `${hash ? `#${hash}` : ""}`; + } + return ""; +} +function shadow(obj, prop, value, nonSerializable = false) { + Object.defineProperty(obj, prop, { + value, + enumerable: !nonSerializable, + configurable: true, + writable: false + }); + return value; +} +const BaseException = function BaseExceptionClosure() { + function BaseException(message, name) { + this.message = message; + this.name = name; + } + BaseException.prototype = new Error(); + BaseException.constructor = BaseException; + return BaseException; +}(); +class PasswordException extends BaseException { + constructor(msg, code) { + super(msg, "PasswordException"); + this.code = code; + } +} +class UnknownErrorException extends BaseException { + constructor(msg, details) { + super(msg, "UnknownErrorException"); + this.details = details; + } +} +class InvalidPDFException extends BaseException { + constructor(msg) { + super(msg, "InvalidPDFException"); + } +} +class ResponseException extends BaseException { + constructor(msg, status, missing) { + super(msg, "ResponseException"); + this.status = status; + this.missing = missing; + } +} +class FormatError extends BaseException { + constructor(msg) { + super(msg, "FormatError"); + } +} +class AbortException extends BaseException { + constructor(msg) { + super(msg, "AbortException"); + } +} +function bytesToString(bytes) { + if (typeof bytes !== "object" || bytes?.length === undefined) { + unreachable("Invalid argument for bytesToString"); + } + const length = bytes.length; + const MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + const strBuf = []; + for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + const chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(""); +} +function stringToBytes(str) { + if (typeof str !== "string") { + unreachable("Invalid argument for stringToBytes"); + } + const length = str.length; + const bytes = new Uint8Array(length); + for (let i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xff; + } + return bytes; +} +function string32(value) { + return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); +} +function objectSize(obj) { + return Object.keys(obj).length; +} +function isLittleEndian() { + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + return view32[0] === 1; +} +function isEvalSupported() { + try { + new Function(""); + return true; + } catch { + return false; + } +} +class util_FeatureTest { + static get isLittleEndian() { + return shadow(this, "isLittleEndian", isLittleEndian()); + } + static get isEvalSupported() { + return shadow(this, "isEvalSupported", isEvalSupported()); + } + static get isOffscreenCanvasSupported() { + return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); + } + static get isImageDecoderSupported() { + return shadow(this, "isImageDecoderSupported", typeof ImageDecoder !== "undefined"); + } + static get isFloat16ArraySupported() { + return shadow(this, "isFloat16ArraySupported", typeof Float16Array !== "undefined"); + } + static get isSanitizerSupported() { + return shadow(this, "isSanitizerSupported", typeof Sanitizer !== "undefined"); + } + static get platform() { + const { + platform, + userAgent + } = navigator; + return shadow(this, "platform", { + isAndroid: userAgent.includes("Android"), + isLinux: platform.includes("Linux"), + isMac: platform.includes("Mac"), + isWindows: platform.includes("Win"), + isFirefox: true + }); + } + static get isCSSRoundSupported() { + return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)")); + } +} +const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0")); +class Util { + static makeHexColor(r, g, b) { + return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; + } + static domMatrixToTransform(dm) { + return [dm.a, dm.b, dm.c, dm.d, dm.e, dm.f]; + } + static scaleMinMax(transform, minMax) { + let temp; + if (transform[0]) { + if (transform[0] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[0]; + minMax[2] *= transform[0]; + if (transform[3] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[3]; + minMax[3] *= transform[3]; + } else { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + if (transform[1] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[1]; + minMax[3] *= transform[1]; + if (transform[2] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[2]; + minMax[2] *= transform[2]; + } + minMax[0] += transform[4]; + minMax[1] += transform[5]; + minMax[2] += transform[4]; + minMax[3] += transform[5]; + } + static transform(m1, m2) { + return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; + } + static multiplyByDOMMatrix(m, md) { + return [m[0] * md.a + m[2] * md.b, m[1] * md.a + m[3] * md.b, m[0] * md.c + m[2] * md.d, m[1] * md.c + m[3] * md.d, m[0] * md.e + m[2] * md.f + m[4], m[1] * md.e + m[3] * md.f + m[5]]; + } + static applyTransform(p, m, pos = 0) { + const p0 = p[pos]; + const p1 = p[pos + 1]; + p[pos] = p0 * m[0] + p1 * m[2] + m[4]; + p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5]; + } + static applyTransformToBezier(p, transform, pos = 0) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + for (let i = 0; i < 6; i += 2) { + const pI = p[pos + i]; + const pI1 = p[pos + i + 1]; + p[pos + i] = pI * m0 + pI1 * m2 + m4; + p[pos + i + 1] = pI * m1 + pI1 * m3 + m5; + } + } + static applyInverseTransform(p, m) { + const p0 = p[0]; + const p1 = p[1]; + const d = m[0] * m[3] - m[1] * m[2]; + p[0] = (p0 * m[3] - p1 * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + p[1] = (-p0 * m[1] + p1 * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + } + static axialAlignedBoundingBox(rect, transform, output) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + const r0 = rect[0]; + const r1 = rect[1]; + const r2 = rect[2]; + const r3 = rect[3]; + let a0 = m0 * r0 + m4; + let a2 = a0; + let a1 = m0 * r2 + m4; + let a3 = a1; + let b0 = m3 * r1 + m5; + let b2 = b0; + let b1 = m3 * r3 + m5; + let b3 = b1; + if (m1 !== 0 || m2 !== 0) { + const m1r0 = m1 * r0; + const m1r2 = m1 * r2; + const m2r1 = m2 * r1; + const m2r3 = m2 * r3; + a0 += m2r1; + a3 += m2r1; + a1 += m2r3; + a2 += m2r3; + b0 += m1r0; + b3 += m1r0; + b1 += m1r2; + b2 += m1r2; + } + output[0] = Math.min(output[0], a0, a1, a2, a3); + output[1] = Math.min(output[1], b0, b1, b2, b3); + output[2] = Math.max(output[2], a0, a1, a2, a3); + output[3] = Math.max(output[3], b0, b1, b2, b3); + } + static inverseTransform(m) { + const d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + } + static singularValueDecompose2dScale(matrix, output) { + const m0 = matrix[0]; + const m1 = matrix[1]; + const m2 = matrix[2]; + const m3 = matrix[3]; + const a = m0 ** 2 + m1 ** 2; + const b = m0 * m2 + m1 * m3; + const c = m2 ** 2 + m3 ** 2; + const first = (a + c) / 2; + const second = Math.sqrt(first ** 2 - (a * c - b ** 2)); + output[0] = Math.sqrt(first + second || 1); + output[1] = Math.sqrt(first - second || 1); + } + static normalizeRect(rect) { + const r = rect.slice(0); + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + } + static intersect(rect1, rect2) { + const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); + const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); + if (xLow > xHigh) { + return null; + } + const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); + const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); + if (yLow > yHigh) { + return null; + } + return [xLow, yLow, xHigh, yHigh]; + } + static pointBoundingBox(x, y, minMax) { + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static rectBoundingBox(x0, y0, x1, y1, minMax) { + minMax[0] = Math.min(minMax[0], x0, x1); + minMax[1] = Math.min(minMax[1], y0, y1); + minMax[2] = Math.max(minMax[2], x0, x1); + minMax[3] = Math.max(minMax[3], y0, y1); + } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; + } + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); + } + return; + } + const delta = b ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + } +} +const PDFStringTranslateTable = (/* unused pure expression or super */ null && ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac])); +function stringToPDFString(str, keepEscapeSequence = false) { + if (str[0] >= "\xEF") { + let encoding; + if (str[0] === "\xFE" && str[1] === "\xFF") { + encoding = "utf-16be"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xFF" && str[1] === "\xFE") { + encoding = "utf-16le"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") { + encoding = "utf-8"; + } + if (encoding) { + try { + const decoder = new TextDecoder(encoding, { + fatal: true + }); + const buffer = stringToBytes(str); + const decoded = decoder.decode(buffer); + if (keepEscapeSequence || !decoded.includes("\x1b")) { + return decoded; + } + return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, ""); + } catch (ex) { + warn(`stringToPDFString: "${ex}".`); + } + } + } + const strBuf = []; + for (let i = 0, ii = str.length; i < ii; i++) { + const charCode = str.charCodeAt(i); + if (!keepEscapeSequence && charCode === 0x1b) { + while (++i < ii && str.charCodeAt(i) !== 0x1b) {} + continue; + } + const code = PDFStringTranslateTable[charCode]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + return strBuf.join(""); +} +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} +function isArrayEqual(arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + for (let i = 0, ii = arr1.length; i < ii; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + return true; +} +function getModificationDate(date = new Date()) { + if (!(date instanceof Date)) { + date = new Date(date); + } + const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")]; + return buffer.join(""); +} +let NormalizeRegex = null; +let NormalizationMap = null; +function normalizeUnicode(str) { + if (!NormalizeRegex) { + NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; + NormalizationMap = new Map([["ſt", "ſt"]]); + } + return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); +} +function getUuid() { + return crypto.randomUUID(); +} +const AnnotationPrefix = "pdfjs_internal_id_"; +function _isValidExplicitDest(validRef, validName, dest) { + if (!Array.isArray(dest) || dest.length < 2) { + return false; + } + const [page, zoom, ...args] = dest; + if (!validRef(page) && !Number.isInteger(page)) { + return false; + } + if (!validName(zoom)) { + return false; + } + const argsLen = args.length; + let allowNull = true; + switch (zoom.name) { + case "XYZ": + if (argsLen < 2 || argsLen > 3) { + return false; + } + break; + case "Fit": + case "FitB": + return argsLen === 0; + case "FitH": + case "FitBH": + case "FitV": + case "FitBV": + if (argsLen > 1) { + return false; + } + break; + case "FitR": + if (argsLen !== 4) { + return false; + } + allowNull = false; + break; + default: + return false; + } + for (const arg of args) { + if (typeof arg === "number" || allowNull && arg === null) { + continue; + } + return false; + } + return true; +} +function MathClamp(v, min, max) { + return Math.min(Math.max(v, min), max); +} +function toHexUtil(arr) { + if (Uint8Array.prototype.toHex) { + return arr.toHex(); + } + return Array.from(arr, num => hexNumbers[num]).join(""); +} +function toBase64Util(arr) { + if (Uint8Array.prototype.toBase64) { + return arr.toBase64(); + } + return btoa(bytesToString(arr)); +} +function fromBase64Util(str) { + if (Uint8Array.fromBase64) { + return Uint8Array.fromBase64(str); + } + return stringToBytes(atob(str)); +} +if (typeof Promise.try !== "function") { + Promise.try = function (fn, ...args) { + return new Promise(resolve => { + resolve(fn(...args)); + }); + }; +} +if (typeof Math.sumPrecise !== "function") { + Math.sumPrecise = function (numbers) { + return numbers.reduce((a, b) => a + b, 0); + }; +} + +;// ./src/display/xfa_text.js +class XfaText { + static textContent(xfa) { + const items = []; + const output = { + items, + styles: Object.create(null) + }; + function walk(node) { + if (!node) { + return; + } + let str = null; + const name = node.name; + if (name === "#text") { + str = node.value; + } else if (!XfaText.shouldBuildText(name)) { + return; + } else if (node?.attributes?.textContent) { + str = node.attributes.textContent; + } else if (node.value) { + str = node.value; + } + if (str !== null) { + items.push({ + str + }); + } + if (!node.children) { + return; + } + for (const child of node.children) { + walk(child); + } + } + walk(xfa); + return output; + } + static shouldBuildText(name) { + return !(name === "textarea" || name === "input" || name === "option" || name === "select"); + } +} + +;// ./src/display/xfa_layer.js + +class XfaLayer { + static setupStorage(html, id, element, storage, intent) { + const storedData = storage.getValue(id, { + value: null + }); + switch (element.name) { + case "textarea": + if (storedData.value !== null) { + html.textContent = storedData.value; + } + if (intent === "print") { + break; + } + html.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + }); + break; + case "input": + if (element.attributes.type === "radio" || element.attributes.type === "checkbox") { + if (storedData.value === element.attributes.xfaOn) { + html.setAttribute("checked", true); + } else if (storedData.value === element.attributes.xfaOff) { + html.removeAttribute("checked"); + } + if (intent === "print") { + break; + } + html.addEventListener("change", event => { + storage.setValue(id, { + value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff") + }); + }); + } else { + if (storedData.value !== null) { + html.setAttribute("value", storedData.value); + } + if (intent === "print") { + break; + } + html.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + }); + } + break; + case "select": + if (storedData.value !== null) { + html.setAttribute("value", storedData.value); + for (const option of element.children) { + if (option.attributes.value === storedData.value) { + option.attributes.selected = true; + } else if (option.attributes.hasOwnProperty("selected")) { + delete option.attributes.selected; + } + } + } + html.addEventListener("input", event => { + const options = event.target.options; + const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value; + storage.setValue(id, { + value + }); + }); + break; + } + } + static setAttributes({ + html, + element, + storage = null, + intent, + linkService + }) { + const { + attributes + } = element; + const isHTMLAnchorElement = html instanceof HTMLAnchorElement; + if (attributes.type === "radio") { + attributes.name = `${attributes.name}-${intent}`; + } + for (const [key, value] of Object.entries(attributes)) { + if (value === null || value === undefined) { + continue; + } + switch (key) { + case "class": + if (value.length) { + html.setAttribute(key, value.join(" ")); + } + break; + case "dataId": + break; + case "id": + html.setAttribute("data-element-id", value); + break; + case "style": + Object.assign(html.style, value); + break; + case "textContent": + html.textContent = value; + break; + default: + if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") { + html.setAttribute(key, value); + } + } + } + if (isHTMLAnchorElement) { + linkService.addLinkAttributes(html, attributes.href, attributes.newWindow); + } + if (storage && attributes.dataId) { + this.setupStorage(html, attributes.dataId, element, storage); + } + } + static render(parameters) { + const storage = parameters.annotationStorage; + const linkService = parameters.linkService; + const root = parameters.xfaHtml; + const intent = parameters.intent || "display"; + const rootHtml = document.createElement(root.name); + if (root.attributes) { + this.setAttributes({ + html: rootHtml, + element: root, + intent, + linkService + }); + } + const isNotForRichText = intent !== "richText"; + const rootDiv = parameters.div; + rootDiv.append(rootHtml); + if (parameters.viewport) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + rootDiv.style.transform = transform; + } + if (isNotForRichText) { + rootDiv.setAttribute("class", "xfaLayer xfaFont"); + } + const textDivs = []; + if (root.children.length === 0) { + if (root.value) { + const node = document.createTextNode(root.value); + rootHtml.append(node); + if (isNotForRichText && XfaText.shouldBuildText(root.name)) { + textDivs.push(node); + } + } + return { + textDivs + }; + } + const stack = [[root, -1, rootHtml]]; + while (stack.length > 0) { + const [parent, i, html] = stack.at(-1); + if (i + 1 === parent.children.length) { + stack.pop(); + continue; + } + const child = parent.children[++stack.at(-1)[1]]; + if (child === null) { + continue; + } + const { + name + } = child; + if (name === "#text") { + const node = document.createTextNode(child.value); + textDivs.push(node); + html.append(node); + continue; + } + const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name); + html.append(childHtml); + if (child.attributes) { + this.setAttributes({ + html: childHtml, + element: child, + storage, + intent, + linkService + }); + } + if (child.children?.length > 0) { + stack.push([child, -1, childHtml]); + } else if (child.value) { + const node = document.createTextNode(child.value); + if (isNotForRichText && XfaText.shouldBuildText(name)) { + textDivs.push(node); + } + childHtml.append(node); + } + } + for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) { + el.setAttribute("readOnly", true); + } + return { + textDivs + }; + } + static update(parameters) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + parameters.div.style.transform = transform; + parameters.div.hidden = false; + } +} + +;// ./src/display/display_utils.js + + +const SVG_NS = "http://www.w3.org/2000/svg"; +class PixelsPerInch { + static CSS = 96.0; + static PDF = 72.0; + static PDF_TO_CSS_UNITS = this.CSS / this.PDF; +} +async function fetchData(url, type = "text") { + const response = await fetch(url); + if (!response.ok) { + throw new Error(response.statusText); + } + switch (type) { + case "arraybuffer": + return response.arrayBuffer(); + case "blob": + return response.blob(); + case "json": + return response.json(); + } + return response.text(); +} +class PageViewport { + constructor({ + viewBox, + userUnit, + scale, + rotation, + offsetX = 0, + offsetY = 0, + dontFlip = false + }) { + this.viewBox = viewBox; + this.userUnit = userUnit; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + scale *= userUnit; + const centerX = (viewBox[2] + viewBox[0]) / 2; + const centerY = (viewBox[3] + viewBox[1]) / 2; + let rotateA, rotateB, rotateC, rotateD; + rotation %= 360; + if (rotation < 0) { + rotation += 360; + } + switch (rotation) { + case 180: + rotateA = -1; + rotateB = 0; + rotateC = 0; + rotateD = 1; + break; + case 90: + rotateA = 0; + rotateB = 1; + rotateC = 1; + rotateD = 0; + break; + case 270: + rotateA = 0; + rotateB = -1; + rotateC = -1; + rotateD = 0; + break; + case 0: + rotateA = 1; + rotateB = 0; + rotateC = 0; + rotateD = -1; + break; + default: + throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."); + } + if (dontFlip) { + rotateC = -rotateC; + rotateD = -rotateD; + } + let offsetCanvasX, offsetCanvasY; + let width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = (viewBox[3] - viewBox[1]) * scale; + height = (viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = (viewBox[2] - viewBox[0]) * scale; + height = (viewBox[3] - viewBox[1]) * scale; + } + this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY]; + this.width = width; + this.height = height; + } + get rawDims() { + const dims = this.viewBox; + return shadow(this, "rawDims", { + pageWidth: dims[2] - dims[0], + pageHeight: dims[3] - dims[1], + pageX: dims[0], + pageY: dims[1] + }); + } + clone({ + scale = this.scale, + rotation = this.rotation, + offsetX = this.offsetX, + offsetY = this.offsetY, + dontFlip = false + } = {}) { + return new PageViewport({ + viewBox: this.viewBox.slice(), + userUnit: this.userUnit, + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + convertToViewportPoint(x, y) { + const p = [x, y]; + Util.applyTransform(p, this.transform); + return p; + } + convertToViewportRectangle(rect) { + const topLeft = [rect[0], rect[1]]; + Util.applyTransform(topLeft, this.transform); + const bottomRight = [rect[2], rect[3]]; + Util.applyTransform(bottomRight, this.transform); + return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]]; + } + convertToPdfPoint(x, y) { + const p = [x, y]; + Util.applyInverseTransform(p, this.transform); + return p; + } +} +class RenderingCancelledException extends BaseException { + constructor(msg, extraDelay = 0) { + super(msg, "RenderingCancelledException"); + this.extraDelay = extraDelay; + } +} +function isDataScheme(url) { + const ii = url.length; + let i = 0; + while (i < ii && url[i].trim() === "") { + i++; + } + return url.substring(i, i + 5).toLowerCase() === "data:"; +} +function isPdfFile(filename) { + return typeof filename === "string" && /\.pdf$/i.test(filename); +} +function getFilenameFromUrl(url) { + [url] = url.split(/[#?]/, 1); + return url.substring(url.lastIndexOf("/") + 1); +} +function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") { + if (typeof url !== "string") { + return defaultFilename; + } + if (isDataScheme(url)) { + warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.'); + return defaultFilename; + } + const getURL = urlString => { + try { + return new URL(urlString); + } catch { + try { + return new URL(decodeURIComponent(urlString)); + } catch { + try { + return new URL(urlString, "https://foo.bar"); + } catch { + try { + return new URL(decodeURIComponent(urlString), "https://foo.bar"); + } catch { + return null; + } + } + } + } + }; + const newURL = getURL(url); + if (!newURL) { + return defaultFilename; + } + const decode = name => { + try { + let decoded = decodeURIComponent(name); + if (decoded.includes("/")) { + decoded = decoded.split("/").at(-1); + if (decoded.test(/^\.pdf$/i)) { + return decoded; + } + return name; + } + return decoded; + } catch { + return name; + } + }; + const pdfRegex = /\.pdf$/i; + const filename = newURL.pathname.split("/").at(-1); + if (pdfRegex.test(filename)) { + return decode(filename); + } + if (newURL.searchParams.size > 0) { + const values = Array.from(newURL.searchParams.values()).reverse(); + for (const value of values) { + if (pdfRegex.test(value)) { + return decode(value); + } + } + const keys = Array.from(newURL.searchParams.keys()).reverse(); + for (const key of keys) { + if (pdfRegex.test(key)) { + return decode(key); + } + } + } + if (newURL.hash) { + const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + const hashFilename = reFilename.exec(newURL.hash); + if (hashFilename) { + return decode(hashFilename[0]); + } + } + return defaultFilename; +} +class StatTimer { + started = Object.create(null); + times = []; + time(name) { + if (name in this.started) { + warn(`Timer is already running for ${name}`); + } + this.started[name] = Date.now(); + } + timeEnd(name) { + if (!(name in this.started)) { + warn(`Timer has not been started for ${name}`); + } + this.times.push({ + name, + start: this.started[name], + end: Date.now() + }); + delete this.started[name]; + } + toString() { + const outBuf = []; + let longest = 0; + for (const { + name + } of this.times) { + longest = Math.max(name.length, longest); + } + for (const { + name, + start, + end + } of this.times) { + outBuf.push(`${name.padEnd(longest)} ${end - start}ms\n`); + } + return outBuf.join(""); + } +} +function isValidFetchUrl(url, baseUrl) { + throw new Error("Not implemented: isValidFetchUrl"); +} +function noContextMenu(e) { + e.preventDefault(); +} +function stopEvent(e) { + e.preventDefault(); + e.stopPropagation(); +} +function deprecated(details) { + console.log("Deprecated API usage: " + details); +} +class PDFDateString { + static #regex; + static toDateObject(input) { + if (input instanceof Date) { + return input; + } + if (!input || typeof input !== "string") { + return null; + } + this.#regex ||= new RegExp("^D:" + "(\\d{4})" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "(\\d{2})?" + "([Z|+|-])?" + "(\\d{2})?" + "'?" + "(\\d{2})?" + "'?"); + const matches = this.#regex.exec(input); + if (!matches) { + return null; + } + const year = parseInt(matches[1], 10); + let month = parseInt(matches[2], 10); + month = month >= 1 && month <= 12 ? month - 1 : 0; + let day = parseInt(matches[3], 10); + day = day >= 1 && day <= 31 ? day : 1; + let hour = parseInt(matches[4], 10); + hour = hour >= 0 && hour <= 23 ? hour : 0; + let minute = parseInt(matches[5], 10); + minute = minute >= 0 && minute <= 59 ? minute : 0; + let second = parseInt(matches[6], 10); + second = second >= 0 && second <= 59 ? second : 0; + const universalTimeRelation = matches[7] || "Z"; + let offsetHour = parseInt(matches[8], 10); + offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0; + let offsetMinute = parseInt(matches[9], 10) || 0; + offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0; + if (universalTimeRelation === "-") { + hour += offsetHour; + minute += offsetMinute; + } else if (universalTimeRelation === "+") { + hour -= offsetHour; + minute -= offsetMinute; + } + return new Date(Date.UTC(year, month, day, hour, minute, second)); + } +} +function getXfaPageViewport(xfaPage, { + scale = 1, + rotation = 0 +}) { + const { + width, + height + } = xfaPage.attributes.style; + const viewBox = [0, 0, parseInt(width), parseInt(height)]; + return new PageViewport({ + viewBox, + userUnit: 1, + scale, + rotation + }); +} +function getRGB(color) { + if (color.startsWith("#")) { + const colorRGB = parseInt(color.slice(1), 16); + return [(colorRGB & 0xff0000) >> 16, (colorRGB & 0x00ff00) >> 8, colorRGB & 0x0000ff]; + } + if (color.startsWith("rgb(")) { + return color.slice(4, -1).split(",").map(x => parseInt(x)); + } + if (color.startsWith("rgba(")) { + return color.slice(5, -1).split(",").map(x => parseInt(x)).slice(0, 3); + } + warn(`Not a valid color format: "${color}"`); + return [0, 0, 0]; +} +function getColorValues(colors) { + const span = document.createElement("span"); + span.style.visibility = "hidden"; + span.style.colorScheme = "only light"; + document.body.append(span); + for (const name of colors.keys()) { + span.style.color = name; + const computedColor = window.getComputedStyle(span).color; + colors.set(name, getRGB(computedColor)); + } + span.remove(); +} +function getCurrentTransform(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform(); + return [a, b, c, d, e, f]; +} +function getCurrentTransformInverse(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform().invertSelf(); + return [a, b, c, d, e, f]; +} +function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) { + if (viewport instanceof PageViewport) { + const { + pageWidth, + pageHeight + } = viewport.rawDims; + const { + style + } = div; + const useRound = util_FeatureTest.isCSSRoundSupported; + const w = `var(--total-scale-factor) * ${pageWidth}px`, + h = `var(--total-scale-factor) * ${pageHeight}px`; + const widthStr = useRound ? `round(down, ${w}, var(--scale-round-x))` : `calc(${w})`, + heightStr = useRound ? `round(down, ${h}, var(--scale-round-y))` : `calc(${h})`; + if (!mustFlip || viewport.rotation % 180 === 0) { + style.width = widthStr; + style.height = heightStr; + } else { + style.width = heightStr; + style.height = widthStr; + } + } + if (mustRotate) { + div.setAttribute("data-main-rotation", viewport.rotation); + } +} +class OutputScale { + constructor() { + const { + pixelRatio + } = OutputScale; + this.sx = pixelRatio; + this.sy = pixelRatio; + } + get scaled() { + return this.sx !== 1 || this.sy !== 1; + } + get symmetric() { + return this.sx === this.sy; + } + limitCanvas(width, height, maxPixels, maxDim, capAreaFactor = -1) { + let maxAreaScale = Infinity, + maxWidthScale = Infinity, + maxHeightScale = Infinity; + maxPixels = OutputScale.capPixels(maxPixels, capAreaFactor); + if (maxPixels > 0) { + maxAreaScale = Math.sqrt(maxPixels / (width * height)); + } + if (maxDim !== -1) { + maxWidthScale = maxDim / width; + maxHeightScale = maxDim / height; + } + const maxScale = Math.min(maxAreaScale, maxWidthScale, maxHeightScale); + if (this.sx > maxScale || this.sy > maxScale) { + this.sx = maxScale; + this.sy = maxScale; + return true; + } + return false; + } + static get pixelRatio() { + return globalThis.devicePixelRatio || 1; + } + static capPixels(maxPixels, capAreaFactor) { + if (capAreaFactor >= 0) { + const winPixels = Math.ceil(window.screen.availWidth * window.screen.availHeight * this.pixelRatio ** 2 * (1 + capAreaFactor / 100)); + return maxPixels > 0 ? Math.min(maxPixels, winPixels) : winPixels; + } + return maxPixels; + } +} +const SupportedImageMimeTypes = ["image/apng", "image/avif", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/webp", "image/x-icon"]; +class ColorScheme { + static get isDarkMode() { + return shadow(this, "isDarkMode", !!window?.matchMedia?.("(prefers-color-scheme: dark)").matches); + } +} +class CSSConstants { + static get commentForegroundColor() { + const element = document.createElement("span"); + element.classList.add("comment", "sidebar"); + const { + style + } = element; + style.width = style.height = "0"; + style.display = "none"; + style.color = "var(--comment-fg-color)"; + document.body.append(element); + const { + color + } = window.getComputedStyle(element); + element.remove(); + return shadow(this, "commentForegroundColor", getRGB(color)); + } +} +function applyOpacity(r, g, b, opacity) { + opacity = Math.min(Math.max(opacity ?? 1, 0), 1); + const white = 255 * (1 - opacity); + r = Math.round(r * opacity + white); + g = Math.round(g * opacity + white); + b = Math.round(b * opacity + white); + return [r, g, b]; +} +function RGBToHSL(rgb, output) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const l = (max + min) / 2; + if (max === min) { + output[0] = output[1] = 0; + } else { + const d = max - min; + output[1] = l < 0.5 ? d / (max + min) : d / (2 - max - min); + switch (max) { + case r: + output[0] = ((g - b) / d + (g < b ? 6 : 0)) * 60; + break; + case g: + output[0] = ((b - r) / d + 2) * 60; + break; + case b: + output[0] = ((r - g) / d + 4) * 60; + break; + } + } + output[2] = l; +} +function HSLToRGB(hsl, output) { + const h = hsl[0]; + const s = hsl[1]; + const l = hsl[2]; + const c = (1 - Math.abs(2 * l - 1)) * s; + const x = c * (1 - Math.abs(h / 60 % 2 - 1)); + const m = l - c / 2; + switch (Math.floor(h / 60)) { + case 0: + output[0] = c + m; + output[1] = x + m; + output[2] = m; + break; + case 1: + output[0] = x + m; + output[1] = c + m; + output[2] = m; + break; + case 2: + output[0] = m; + output[1] = c + m; + output[2] = x + m; + break; + case 3: + output[0] = m; + output[1] = x + m; + output[2] = c + m; + break; + case 4: + output[0] = x + m; + output[1] = m; + output[2] = c + m; + break; + case 5: + case 6: + output[0] = c + m; + output[1] = m; + output[2] = x + m; + break; + } +} +function computeLuminance(x) { + return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; +} +function contrastRatio(hsl1, hsl2, output) { + HSLToRGB(hsl1, output); + output.map(computeLuminance); + const lum1 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2]; + HSLToRGB(hsl2, output); + output.map(computeLuminance); + const lum2 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2]; + return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05); +} +const contrastCache = new Map(); +function findContrastColor(baseColor, fixedColor) { + const key = baseColor[0] + baseColor[1] * 0x100 + baseColor[2] * 0x10000 + fixedColor[0] * 0x1000000 + fixedColor[1] * 0x100000000 + fixedColor[2] * 0x10000000000; + let cachedValue = contrastCache.get(key); + if (cachedValue) { + return cachedValue; + } + const array = new Float32Array(9); + const output = array.subarray(0, 3); + const baseHSL = array.subarray(3, 6); + RGBToHSL(baseColor, baseHSL); + const fixedHSL = array.subarray(6, 9); + RGBToHSL(fixedColor, fixedHSL); + const isFixedColorDark = fixedHSL[2] < 0.5; + const minContrast = isFixedColorDark ? 12 : 4.5; + baseHSL[2] = isFixedColorDark ? Math.sqrt(baseHSL[2]) : 1 - Math.sqrt(1 - baseHSL[2]); + if (contrastRatio(baseHSL, fixedHSL, output) < minContrast) { + let start, end; + if (isFixedColorDark) { + start = baseHSL[2]; + end = 1; + } else { + start = 0; + end = baseHSL[2]; + } + const PRECISION = 0.005; + while (end - start > PRECISION) { + const mid = baseHSL[2] = (start + end) / 2; + if (isFixedColorDark === contrastRatio(baseHSL, fixedHSL, output) < minContrast) { + start = mid; + } else { + end = mid; + } + } + baseHSL[2] = isFixedColorDark ? end : start; + } + HSLToRGB(baseHSL, output); + cachedValue = Util.makeHexColor(Math.round(output[0] * 255), Math.round(output[1] * 255), Math.round(output[2] * 255)); + contrastCache.set(key, cachedValue); + return cachedValue; +} +function renderRichText({ + html, + dir, + className +}, container) { + const fragment = document.createDocumentFragment(); + if (typeof html === "string") { + const p = document.createElement("p"); + p.dir = dir || "auto"; + const lines = html.split(/(?:\r\n?|\n)/); + for (let i = 0, ii = lines.length; i < ii; ++i) { + const line = lines[i]; + p.append(document.createTextNode(line)); + if (i < ii - 1) { + p.append(document.createElement("br")); + } + } + fragment.append(p); + } else { + XfaLayer.render({ + xfaHtml: html, + div: fragment, + intent: "richText" + }); + } + fragment.firstElementChild.classList.add("richText", className); + container.append(fragment); +} +function makePathFromDrawOPS(data) { + const path = new Path2D(); + if (!data) { + return path; + } + for (let i = 0, ii = data.length; i < ii;) { + switch (data[i++]) { + case DrawOPS.moveTo: + path.moveTo(data[i++], data[i++]); + break; + case DrawOPS.lineTo: + path.lineTo(data[i++], data[i++]); + break; + case DrawOPS.curveTo: + path.bezierCurveTo(data[i++], data[i++], data[i++], data[i++], data[i++], data[i++]); + break; + case DrawOPS.quadraticCurveTo: + path.quadraticCurveTo(data[i++], data[i++], data[i++], data[i++]); + break; + case DrawOPS.closePath: + path.closePath(); + break; + default: + warn(`Unrecognized drawing path operator: ${data[i - 1]}`); + break; + } + } + return path; +} + +;// ./src/display/editor/toolbar.js + +class EditorToolbar { + #toolbar = null; + #colorPicker = null; + #editor; + #buttons = null; + #altText = null; + #comment = null; + #commentButtonDivider = null; + #signatureDescriptionButton = null; + static #l10nRemove = null; + constructor(editor) { + this.#editor = editor; + EditorToolbar.#l10nRemove ||= Object.freeze({ + freetext: "pdfjs-editor-remove-freetext-button", + highlight: "pdfjs-editor-remove-highlight-button", + ink: "pdfjs-editor-remove-ink-button", + stamp: "pdfjs-editor-remove-stamp-button", + signature: "pdfjs-editor-remove-signature-button" + }); + } + render() { + const editToolbar = this.#toolbar = document.createElement("div"); + editToolbar.classList.add("editToolbar", "hidden"); + editToolbar.setAttribute("role", "toolbar"); + const signal = this.#editor._uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + editToolbar.addEventListener("contextmenu", noContextMenu, { + signal + }); + editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown, { + signal + }); + } + const buttons = this.#buttons = document.createElement("div"); + buttons.className = "buttons"; + editToolbar.append(buttons); + const position = this.#editor.toolbarPosition; + if (position) { + const { + style + } = editToolbar; + const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0]; + style.insetInlineEnd = `${100 * x}%`; + style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`; + } + return editToolbar; + } + get div() { + return this.#toolbar; + } + static #pointerDown(e) { + e.stopPropagation(); + } + #focusIn(e) { + this.#editor._focusEventsAllowed = false; + stopEvent(e); + } + #focusOut(e) { + this.#editor._focusEventsAllowed = true; + stopEvent(e); + } + #addListenersToElement(element) { + const signal = this.#editor._uiManager._signal; + if (!(signal instanceof AbortSignal) || signal.aborted) { + return false; + } + element.addEventListener("focusin", this.#focusIn.bind(this), { + capture: true, + signal + }); + element.addEventListener("focusout", this.#focusOut.bind(this), { + capture: true, + signal + }); + element.addEventListener("contextmenu", noContextMenu, { + signal + }); + return true; + } + hide() { + this.#toolbar.classList.add("hidden"); + this.#colorPicker?.hideDropdown(); + } + show() { + this.#toolbar.classList.remove("hidden"); + this.#altText?.shown(); + this.#comment?.shown(); + } + addDeleteButton() { + const { + editorType, + _uiManager + } = this.#editor; + const button = document.createElement("button"); + button.classList.add("basic", "deleteButton"); + button.tabIndex = 0; + button.setAttribute("data-l10n-id", EditorToolbar.#l10nRemove[editorType]); + if (this.#addListenersToElement(button)) { + button.addEventListener("click", e => { + _uiManager.delete(); + }, { + signal: _uiManager._signal + }); + } + this.#buttons.append(button); + } + get #divider() { + const divider = document.createElement("div"); + divider.className = "divider"; + return divider; + } + async addAltText(altText) { + const button = await altText.render(); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + this.#altText = altText; + } + addComment(comment, beforeElement = null) { + if (this.#comment) { + return; + } + const button = comment.renderForToolbar(); + if (!button) { + return; + } + this.#addListenersToElement(button); + const divider = this.#commentButtonDivider = this.#divider; + if (!beforeElement) { + this.#buttons.append(button, divider); + } else { + this.#buttons.insertBefore(button, beforeElement); + this.#buttons.insertBefore(divider, beforeElement); + } + this.#comment = comment; + comment.toolbar = this; + } + addColorPicker(colorPicker) { + if (this.#colorPicker) { + return; + } + this.#colorPicker = colorPicker; + const button = colorPicker.renderButton(); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + } + async addEditSignatureButton(signatureManager) { + const button = this.#signatureDescriptionButton = await signatureManager.renderEditButton(this.#editor); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + } + removeButton(name) { + switch (name) { + case "comment": + this.#comment?.removeToolbarCommentButton(); + this.#comment = null; + this.#commentButtonDivider?.remove(); + this.#commentButtonDivider = null; + break; + } + } + async addButton(name, tool) { + switch (name) { + case "colorPicker": + if (tool) { + this.addColorPicker(tool); + } + break; + case "altText": + if (tool) { + await this.addAltText(tool); + } + break; + case "editSignature": + if (tool) { + await this.addEditSignatureButton(tool); + } + break; + case "delete": + this.addDeleteButton(); + break; + case "comment": + if (tool) { + this.addComment(tool); + } + break; + } + } + async addButtonBefore(name, tool, beforeSelector) { + if (!tool && name === "comment") { + return; + } + const beforeElement = this.#buttons.querySelector(beforeSelector); + if (!beforeElement) { + return; + } + if (name === "comment") { + this.addComment(tool, beforeElement); + } + } + updateEditSignatureButton(description) { + if (this.#signatureDescriptionButton) { + this.#signatureDescriptionButton.title = description; + } + } + remove() { + this.#toolbar.remove(); + this.#colorPicker?.destroy(); + this.#colorPicker = null; + } +} +class FloatingToolbar { + #buttons = null; + #toolbar = null; + #uiManager; + constructor(uiManager) { + this.#uiManager = uiManager; + } + #render() { + const editToolbar = this.#toolbar = document.createElement("div"); + editToolbar.className = "editToolbar"; + editToolbar.setAttribute("role", "toolbar"); + const signal = this.#uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + editToolbar.addEventListener("contextmenu", noContextMenu, { + signal + }); + } + const buttons = this.#buttons = document.createElement("div"); + buttons.className = "buttons"; + editToolbar.append(buttons); + if (this.#uiManager.hasCommentManager()) { + this.#makeButton("commentButton", `pdfjs-comment-floating-button`, "pdfjs-comment-floating-button-label", () => { + this.#uiManager.commentSelection("floating_button"); + }); + } + this.#makeButton("highlightButton", `pdfjs-highlight-floating-button1`, "pdfjs-highlight-floating-button-label", () => { + this.#uiManager.highlightSelection("floating_button"); + }); + return editToolbar; + } + #getLastPoint(boxes, isLTR) { + let lastY = 0; + let lastX = 0; + for (const box of boxes) { + const y = box.y + box.height; + if (y < lastY) { + continue; + } + const x = box.x + (isLTR ? box.width : 0); + if (y > lastY) { + lastX = x; + lastY = y; + continue; + } + if (isLTR) { + if (x > lastX) { + lastX = x; + } + } else if (x < lastX) { + lastX = x; + } + } + return [isLTR ? 1 - lastX : lastX, lastY]; + } + show(parent, boxes, isLTR) { + const [x, y] = this.#getLastPoint(boxes, isLTR); + const { + style + } = this.#toolbar ||= this.#render(); + parent.append(this.#toolbar); + style.insetInlineEnd = `${100 * x}%`; + style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`; + } + hide() { + this.#toolbar.remove(); + } + #makeButton(buttonClass, l10nId, labelL10nId, clickHandler) { + const button = document.createElement("button"); + button.classList.add("basic", buttonClass); + button.tabIndex = 0; + button.setAttribute("data-l10n-id", l10nId); + const span = document.createElement("span"); + button.append(span); + span.className = "visuallyHidden"; + span.setAttribute("data-l10n-id", labelL10nId); + const signal = this.#uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + button.addEventListener("contextmenu", noContextMenu, { + signal + }); + button.addEventListener("click", clickHandler, { + signal + }); + } + this.#buttons.append(button); + } +} + +;// ./src/display/editor/tools.js + + + +function bindEvents(obj, element, names) { + for (const name of names) { + element.addEventListener(name, obj[name].bind(obj)); + } +} +class CurrentPointers { + static #pointerId = NaN; + static #pointerIds = null; + static #moveTimestamp = NaN; + static #pointerType = null; + static initializeAndAddPointerId(pointerId) { + (CurrentPointers.#pointerIds ||= new Set()).add(pointerId); + } + static setPointer(pointerType, pointerId) { + CurrentPointers.#pointerId ||= pointerId; + CurrentPointers.#pointerType ??= pointerType; + } + static setTimeStamp(timeStamp) { + CurrentPointers.#moveTimestamp = timeStamp; + } + static isSamePointerId(pointerId) { + return CurrentPointers.#pointerId === pointerId; + } + static isSamePointerIdOrRemove(pointerId) { + if (CurrentPointers.#pointerId === pointerId) { + return true; + } + CurrentPointers.#pointerIds?.delete(pointerId); + return false; + } + static isSamePointerType(pointerType) { + return CurrentPointers.#pointerType === pointerType; + } + static isInitializedAndDifferentPointerType(pointerType) { + return CurrentPointers.#pointerType !== null && !CurrentPointers.isSamePointerType(pointerType); + } + static isSameTimeStamp(timeStamp) { + return CurrentPointers.#moveTimestamp === timeStamp; + } + static isUsingMultiplePointers() { + return CurrentPointers.#pointerIds?.size >= 1; + } + static clearPointerType() { + CurrentPointers.#pointerType = null; + } + static clearPointerIds() { + CurrentPointers.#pointerId = NaN; + CurrentPointers.#pointerIds = null; + } + static clearTimeStamp() { + CurrentPointers.#moveTimestamp = NaN; + } +} +class IdManager { + #id = 0; + get id() { + return `${AnnotationEditorPrefix}${this.#id++}`; + } +} +class ImageManager { + #baseId = getUuid(); + #id = 0; + #cache = null; + static get _isSVGFittingCanvas() { + const svg = `data:image/svg+xml;charset=UTF-8,`; + const canvas = new OffscreenCanvas(1, 3); + const ctx = canvas.getContext("2d", { + willReadFrequently: true + }); + const image = new Image(); + image.src = svg; + const promise = image.decode().then(() => { + ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3); + return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0; + }); + return shadow(this, "_isSVGFittingCanvas", promise); + } + async #get(key, rawData) { + this.#cache ||= new Map(); + let data = this.#cache.get(key); + if (data === null) { + return null; + } + if (data?.bitmap) { + data.refCounter += 1; + return data; + } + try { + data ||= { + bitmap: null, + id: `image_${this.#baseId}_${this.#id++}`, + refCounter: 0, + isSvg: false + }; + let image; + if (typeof rawData === "string") { + data.url = rawData; + image = await fetchData(rawData, "blob"); + } else if (rawData instanceof File) { + image = data.file = rawData; + } else if (rawData instanceof Blob) { + image = rawData; + } + if (image.type === "image/svg+xml") { + const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas; + const fileReader = new FileReader(); + const imageElement = new Image(); + const imagePromise = new Promise((resolve, reject) => { + imageElement.onload = () => { + data.bitmap = imageElement; + data.isSvg = true; + resolve(); + }; + fileReader.onload = async () => { + const url = data.svgUrl = fileReader.result; + imageElement.src = (await mustRemoveAspectRatioPromise) ? `${url}#svgView(preserveAspectRatio(none))` : url; + }; + imageElement.onerror = fileReader.onerror = reject; + }); + fileReader.readAsDataURL(image); + await imagePromise; + } else { + data.bitmap = await createImageBitmap(image); + } + data.refCounter = 1; + } catch (e) { + warn(e); + data = null; + } + this.#cache.set(key, data); + if (data) { + this.#cache.set(data.id, data); + } + return data; + } + async getFromFile(file) { + const { + lastModified, + name, + size, + type + } = file; + return this.#get(`${lastModified}_${name}_${size}_${type}`, file); + } + async getFromUrl(url) { + return this.#get(url, url); + } + async getFromBlob(id, blobPromise) { + const blob = await blobPromise; + return this.#get(id, blob); + } + async getFromId(id) { + this.#cache ||= new Map(); + const data = this.#cache.get(id); + if (!data) { + return null; + } + if (data.bitmap) { + data.refCounter += 1; + return data; + } + if (data.file) { + return this.getFromFile(data.file); + } + if (data.blobPromise) { + const { + blobPromise + } = data; + delete data.blobPromise; + return this.getFromBlob(data.id, blobPromise); + } + return this.getFromUrl(data.url); + } + getFromCanvas(id, canvas) { + this.#cache ||= new Map(); + let data = this.#cache.get(id); + if (data?.bitmap) { + data.refCounter += 1; + return data; + } + const offscreen = new OffscreenCanvas(canvas.width, canvas.height); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(canvas, 0, 0); + data = { + bitmap: offscreen.transferToImageBitmap(), + id: `image_${this.#baseId}_${this.#id++}`, + refCounter: 1, + isSvg: false + }; + this.#cache.set(id, data); + this.#cache.set(data.id, data); + return data; + } + getSvgUrl(id) { + const data = this.#cache.get(id); + if (!data?.isSvg) { + return null; + } + return data.svgUrl; + } + deleteId(id) { + this.#cache ||= new Map(); + const data = this.#cache.get(id); + if (!data) { + return; + } + data.refCounter -= 1; + if (data.refCounter !== 0) { + return; + } + const { + bitmap + } = data; + if (!data.url && !data.file) { + const canvas = new OffscreenCanvas(bitmap.width, bitmap.height); + const ctx = canvas.getContext("bitmaprenderer"); + ctx.transferFromImageBitmap(bitmap); + data.blobPromise = canvas.convertToBlob(); + } + bitmap.close?.(); + data.bitmap = null; + } + isValidId(id) { + return id.startsWith(`image_${this.#baseId}_`); + } +} +class CommandManager { + #commands = []; + #locked = false; + #maxSize; + #position = -1; + constructor(maxSize = 128) { + this.#maxSize = maxSize; + } + add({ + cmd, + undo, + post, + mustExec, + type = NaN, + overwriteIfSameType = false, + keepUndo = false + }) { + if (mustExec) { + cmd(); + } + if (this.#locked) { + return; + } + const save = { + cmd, + undo, + post, + type + }; + if (this.#position === -1) { + if (this.#commands.length > 0) { + this.#commands.length = 0; + } + this.#position = 0; + this.#commands.push(save); + return; + } + if (overwriteIfSameType && this.#commands[this.#position].type === type) { + if (keepUndo) { + save.undo = this.#commands[this.#position].undo; + } + this.#commands[this.#position] = save; + return; + } + const next = this.#position + 1; + if (next === this.#maxSize) { + this.#commands.splice(0, 1); + } else { + this.#position = next; + if (next < this.#commands.length) { + this.#commands.splice(next); + } + } + this.#commands.push(save); + } + undo() { + if (this.#position === -1) { + return; + } + this.#locked = true; + const { + undo, + post + } = this.#commands[this.#position]; + undo(); + post?.(); + this.#locked = false; + this.#position -= 1; + } + redo() { + if (this.#position < this.#commands.length - 1) { + this.#position += 1; + this.#locked = true; + const { + cmd, + post + } = this.#commands[this.#position]; + cmd(); + post?.(); + this.#locked = false; + } + } + hasSomethingToUndo() { + return this.#position !== -1; + } + hasSomethingToRedo() { + return this.#position < this.#commands.length - 1; + } + cleanType(type) { + if (this.#position === -1) { + return; + } + for (let i = this.#position; i >= 0; i--) { + if (this.#commands[i].type !== type) { + this.#commands.splice(i + 1, this.#position - i); + this.#position = i; + return; + } + } + this.#commands.length = 0; + this.#position = -1; + } + destroy() { + this.#commands = null; + } +} +class KeyboardManager { + constructor(callbacks) { + this.buffer = []; + this.callbacks = new Map(); + this.allKeys = new Set(); + const { + isMac + } = util_FeatureTest.platform; + for (const [keys, callback, options = {}] of callbacks) { + for (const key of keys) { + const isMacKey = key.startsWith("mac+"); + if (isMac && isMacKey) { + this.callbacks.set(key.slice(4), { + callback, + options + }); + this.allKeys.add(key.split("+").at(-1)); + } else if (!isMac && !isMacKey) { + this.callbacks.set(key, { + callback, + options + }); + this.allKeys.add(key.split("+").at(-1)); + } + } + } + } + #serialize(event) { + if (event.altKey) { + this.buffer.push("alt"); + } + if (event.ctrlKey) { + this.buffer.push("ctrl"); + } + if (event.metaKey) { + this.buffer.push("meta"); + } + if (event.shiftKey) { + this.buffer.push("shift"); + } + this.buffer.push(event.key); + const str = this.buffer.join("+"); + this.buffer.length = 0; + return str; + } + exec(self, event) { + if (!this.allKeys.has(event.key)) { + return; + } + const info = this.callbacks.get(this.#serialize(event)); + if (!info) { + return; + } + const { + callback, + options: { + bubbles = false, + args = [], + checker = null + } + } = info; + if (checker && !checker(self, event)) { + return; + } + callback.bind(self, ...args, event)(); + if (!bubbles) { + stopEvent(event); + } + } +} +class ColorManager { + static _colorsMapping = new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]); + get _colors() { + const colors = new Map([["CanvasText", null], ["Canvas", null]]); + getColorValues(colors); + return shadow(this, "_colors", colors); + } + convert(color) { + const rgb = getRGB(color); + if (!window.matchMedia("(forced-colors: active)").matches) { + return rgb; + } + for (const [name, RGB] of this._colors) { + if (RGB.every((x, i) => x === rgb[i])) { + return ColorManager._colorsMapping.get(name); + } + } + return rgb; + } + getHexCode(name) { + const rgb = this._colors.get(name); + if (!rgb) { + return name; + } + return Util.makeHexColor(...rgb); + } +} +class AnnotationEditorUIManager { + #abortController = new AbortController(); + #activeEditor = null; + #allEditableAnnotations = null; + #allEditors = new Map(); + #allLayers = new Map(); + #altTextManager = null; + #annotationStorage = null; + #changedExistingAnnotations = null; + #commandManager = new CommandManager(); + #commentManager = null; + #copyPasteAC = null; + #currentDrawingSession = null; + #currentPageIndex = 0; + #deletedAnnotationsElementIds = new Set(); + #draggingEditors = null; + #editorTypes = null; + #editorsToRescale = new Set(); + _editorUndoBar = null; + #enableHighlightFloatingButton = false; + #enableUpdatedAddImage = false; + #enableNewAltTextWhenAddingImage = false; + #filterFactory = null; + #focusMainContainerTimeoutId = null; + #focusManagerAC = null; + #highlightColors = null; + #highlightWhenShiftUp = false; + #floatingToolbar = null; + #idManager = new IdManager(); + #isEnabled = false; + #isPointerDown = false; + #isWaiting = false; + #keyboardManagerAC = null; + #lastActiveElement = null; + #mainHighlightColorPicker = null; + #missingCanvases = null; + #mlManager = null; + #mode = AnnotationEditorType.NONE; + #selectedEditors = new Set(); + #selectedTextNode = null; + #signatureManager = null; + #pageColors = null; + #showAllStates = null; + #pdfDocument = null; + #previousStates = { + isEditing: false, + isEmpty: true, + hasSomethingToUndo: false, + hasSomethingToRedo: false, + hasSelectedEditor: false, + hasSelectedText: false + }; + #translation = [0, 0]; + #translationTimeoutId = null; + #container = null; + #viewer = null; + #viewerAlert = null; + #updateModeCapability = null; + static TRANSLATE_SMALL = 1; + static TRANSLATE_BIG = 10; + static get _keyboardManager() { + const proto = AnnotationEditorUIManager.prototype; + const arrowChecker = self => self.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self.hasSomethingToControl(); + const textInputChecker = (_self, { + target: el + }) => { + if (el instanceof HTMLInputElement) { + const { + type + } = el; + return type !== "text" && type !== "number"; + } + return true; + }; + const small = this.TRANSLATE_SMALL; + const big = this.TRANSLATE_BIG; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+a", "mac+meta+a"], proto.selectAll, { + checker: textInputChecker + }], [["ctrl+z", "mac+meta+z"], proto.undo, { + checker: textInputChecker + }], [["ctrl+y", "ctrl+shift+z", "mac+meta+shift+z", "ctrl+shift+Z", "mac+meta+shift+Z"], proto.redo, { + checker: textInputChecker + }], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete", "mac+Delete"], proto.delete, { + checker: textInputChecker + }], [["Enter", "mac+Enter"], proto.addNewEditorFromKeyboard, { + checker: (self, { + target: el + }) => !(el instanceof HTMLButtonElement) && self.#container.contains(el) && !self.isEnterHandled + }], [[" ", "mac+ "], proto.addNewEditorFromKeyboard, { + checker: (self, { + target: el + }) => !(el instanceof HTMLButtonElement) && self.#container.contains(document.activeElement) + }], [["Escape", "mac+Escape"], proto.unselectAll], [["ArrowLeft", "mac+ArrowLeft"], proto.translateSelectedEditors, { + args: [-small, 0], + checker: arrowChecker + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto.translateSelectedEditors, { + args: [-big, 0], + checker: arrowChecker + }], [["ArrowRight", "mac+ArrowRight"], proto.translateSelectedEditors, { + args: [small, 0], + checker: arrowChecker + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto.translateSelectedEditors, { + args: [big, 0], + checker: arrowChecker + }], [["ArrowUp", "mac+ArrowUp"], proto.translateSelectedEditors, { + args: [0, -small], + checker: arrowChecker + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto.translateSelectedEditors, { + args: [0, -big], + checker: arrowChecker + }], [["ArrowDown", "mac+ArrowDown"], proto.translateSelectedEditors, { + args: [0, small], + checker: arrowChecker + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto.translateSelectedEditors, { + args: [0, big], + checker: arrowChecker + }]])); + } + constructor(container, viewer, viewerAlert, altTextManager, commentManager, signatureManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, enableUpdatedAddImage, enableNewAltTextWhenAddingImage, mlManager, editorUndoBar, supportsPinchToZoom) { + const signal = this._signal = this.#abortController.signal; + this.#container = container; + this.#viewer = viewer; + this.#viewerAlert = viewerAlert; + this.#altTextManager = altTextManager; + this.#commentManager = commentManager; + this.#signatureManager = signatureManager; + this.#pdfDocument = pdfDocument; + this._eventBus = eventBus; + eventBus._on("editingaction", this.onEditingAction.bind(this), { + signal + }); + eventBus._on("pagechanging", this.onPageChanging.bind(this), { + signal + }); + eventBus._on("scalechanging", this.onScaleChanging.bind(this), { + signal + }); + eventBus._on("rotationchanging", this.onRotationChanging.bind(this), { + signal + }); + eventBus._on("setpreference", this.onSetPreference.bind(this), { + signal + }); + eventBus._on("switchannotationeditorparams", evt => this.updateParams(evt.type, evt.value), { + signal + }); + window.addEventListener("pointerdown", () => { + this.#isPointerDown = true; + }, { + capture: true, + signal + }); + window.addEventListener("pointerup", () => { + this.#isPointerDown = false; + }, { + capture: true, + signal + }); + this.#addSelectionListener(); + this.#addDragAndDropListeners(); + this.#addKeyboardManager(); + this.#annotationStorage = pdfDocument.annotationStorage; + this.#filterFactory = pdfDocument.filterFactory; + this.#pageColors = pageColors; + this.#highlightColors = highlightColors || null; + this.#enableHighlightFloatingButton = enableHighlightFloatingButton; + this.#enableUpdatedAddImage = enableUpdatedAddImage; + this.#enableNewAltTextWhenAddingImage = enableNewAltTextWhenAddingImage; + this.#mlManager = mlManager || null; + this.viewParameters = { + realScale: PixelsPerInch.PDF_TO_CSS_UNITS, + rotation: 0 + }; + this.isShiftKeyDown = false; + this._editorUndoBar = editorUndoBar || null; + this._supportsPinchToZoom = supportsPinchToZoom !== false; + commentManager?.setSidebarUiManager(this); + } + destroy() { + this.#updateModeCapability?.resolve(); + this.#updateModeCapability = null; + this.#abortController?.abort(); + this.#abortController = null; + this._signal = null; + for (const layer of this.#allLayers.values()) { + layer.destroy(); + } + this.#allLayers.clear(); + this.#allEditors.clear(); + this.#editorsToRescale.clear(); + this.#missingCanvases?.clear(); + this.#activeEditor = null; + this.#selectedEditors.clear(); + this.#commandManager.destroy(); + this.#altTextManager?.destroy(); + this.#commentManager?.destroy(); + this.#signatureManager?.destroy(); + this.#floatingToolbar?.hide(); + this.#floatingToolbar = null; + this.#mainHighlightColorPicker?.destroy(); + this.#mainHighlightColorPicker = null; + this.#allEditableAnnotations = null; + if (this.#focusMainContainerTimeoutId) { + clearTimeout(this.#focusMainContainerTimeoutId); + this.#focusMainContainerTimeoutId = null; + } + if (this.#translationTimeoutId) { + clearTimeout(this.#translationTimeoutId); + this.#translationTimeoutId = null; + } + this._editorUndoBar?.destroy(); + this.#pdfDocument = null; + } + combinedSignal(ac) { + return AbortSignal.any([this._signal, ac.signal]); + } + get mlManager() { + return this.#mlManager; + } + get useNewAltTextFlow() { + return this.#enableUpdatedAddImage; + } + get useNewAltTextWhenAddingImage() { + return this.#enableNewAltTextWhenAddingImage; + } + get hcmFilter() { + return shadow(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none"); + } + get direction() { + return shadow(this, "direction", getComputedStyle(this.#container).direction); + } + get _highlightColors() { + return shadow(this, "_highlightColors", this.#highlightColors ? new Map(this.#highlightColors.split(",").map(pair => { + pair = pair.split("=").map(x => x.trim()); + pair[1] = pair[1].toUpperCase(); + return pair; + })) : null); + } + get highlightColors() { + const { + _highlightColors + } = this; + if (!_highlightColors) { + return shadow(this, "highlightColors", null); + } + const map = new Map(); + const hasHCM = !!this.#pageColors; + for (const [name, color] of _highlightColors) { + const isNameForHCM = name.endsWith("_HCM"); + if (hasHCM && isNameForHCM) { + map.set(name.replace("_HCM", ""), color); + continue; + } + if (!hasHCM && !isNameForHCM) { + map.set(name, color); + } + } + return shadow(this, "highlightColors", map); + } + get highlightColorNames() { + return shadow(this, "highlightColorNames", this.highlightColors ? new Map(Array.from(this.highlightColors, e => e.reverse())) : null); + } + getNonHCMColor(color) { + if (!this._highlightColors) { + return color; + } + const colorName = this.highlightColorNames.get(color); + return this._highlightColors.get(colorName) || color; + } + getNonHCMColorName(color) { + return this.highlightColorNames.get(color) || color; + } + setCurrentDrawingSession(layer) { + if (layer) { + this.unselectAll(); + this.disableUserSelect(true); + } else { + this.disableUserSelect(false); + } + this.#currentDrawingSession = layer; + } + setMainHighlightColorPicker(colorPicker) { + this.#mainHighlightColorPicker = colorPicker; + } + editAltText(editor, firstTime = false) { + this.#altTextManager?.editAltText(this, editor, firstTime); + } + hasCommentManager() { + return !!this.#commentManager; + } + editComment(editor, posX, posY, options) { + this.#commentManager?.showDialog(this, editor, posX, posY, options); + } + selectComment(pageIndex, uid) { + const layer = this.#allLayers.get(pageIndex); + const editor = layer?.getEditorByUID(uid); + editor?.toggleComment(true, true); + } + updateComment(editor) { + this.#commentManager?.updateComment(editor.getData()); + } + updatePopupColor(editor) { + this.#commentManager?.updatePopupColor(editor); + } + removeComment(editor) { + this.#commentManager?.removeComments([editor.uid]); + } + toggleComment(editor, isSelected, visibility = undefined) { + this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility); + } + makeCommentColor(color, opacity) { + return color && this.#commentManager?.makeCommentColor(color, opacity) || null; + } + getCommentDialogElement() { + return this.#commentManager?.dialogElement || null; + } + async waitForEditorsRendered(pageNumber) { + if (this.#allLayers.has(pageNumber - 1)) { + return; + } + const { + resolve, + promise + } = Promise.withResolvers(); + const onEditorsRendered = evt => { + if (evt.pageNumber === pageNumber) { + this._eventBus._off("editorsrendered", onEditorsRendered); + resolve(); + } + }; + this._eventBus.on("editorsrendered", onEditorsRendered); + await promise; + } + getSignature(editor) { + this.#signatureManager?.getSignature({ + uiManager: this, + editor + }); + } + get signatureManager() { + return this.#signatureManager; + } + switchToMode(mode, callback) { + this._eventBus.on("annotationeditormodechanged", callback, { + once: true, + signal: this._signal + }); + this._eventBus.dispatch("showannotationeditorui", { + source: this, + mode + }); + } + setPreference(name, value) { + this._eventBus.dispatch("setpreference", { + source: this, + name, + value + }); + } + onSetPreference({ + name, + value + }) { + switch (name) { + case "enableNewAltTextWhenAddingImage": + this.#enableNewAltTextWhenAddingImage = value; + break; + } + } + onPageChanging({ + pageNumber + }) { + this.#currentPageIndex = pageNumber - 1; + } + focusMainContainer() { + this.#container.focus(); + } + findParent(x, y) { + for (const layer of this.#allLayers.values()) { + const { + x: layerX, + y: layerY, + width, + height + } = layer.div.getBoundingClientRect(); + if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) { + return layer; + } + } + return null; + } + disableUserSelect(value = false) { + this.#viewer.classList.toggle("noUserSelect", value); + } + addShouldRescale(editor) { + this.#editorsToRescale.add(editor); + } + removeShouldRescale(editor) { + this.#editorsToRescale.delete(editor); + } + onScaleChanging({ + scale + }) { + this.commitOrRemove(); + this.viewParameters.realScale = scale * PixelsPerInch.PDF_TO_CSS_UNITS; + for (const editor of this.#editorsToRescale) { + editor.onScaleChanging(); + } + this.#currentDrawingSession?.onScaleChanging(); + } + onRotationChanging({ + pagesRotation + }) { + this.commitOrRemove(); + this.viewParameters.rotation = pagesRotation; + } + #getAnchorElementForSelection({ + anchorNode + }) { + return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode; + } + #getLayerForTextLayer(textLayer) { + const { + currentLayer + } = this; + if (currentLayer.hasTextLayer(textLayer)) { + return currentLayer; + } + for (const layer of this.#allLayers.values()) { + if (layer.hasTextLayer(textLayer)) { + return layer; + } + } + return null; + } + highlightSelection(methodOfCreation = "", comment = false) { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + return; + } + const { + anchorNode, + anchorOffset, + focusNode, + focusOffset + } = selection; + const text = selection.toString(); + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + const boxes = this.getSelectionBoxes(textLayer); + if (!boxes) { + return; + } + selection.empty(); + const layer = this.#getLayerForTextLayer(textLayer); + const isNoneMode = this.#mode === AnnotationEditorType.NONE; + const callback = () => { + const editor = layer?.createAndAddNewEditor({ + x: 0, + y: 0 + }, false, { + methodOfCreation, + boxes, + anchorNode, + anchorOffset, + focusNode, + focusOffset, + text + }); + if (isNoneMode) { + this.showAllEditors("highlight", true, true); + } + if (comment) { + editor?.editComment(); + } + }; + if (isNoneMode) { + this.switchToMode(AnnotationEditorType.HIGHLIGHT, callback); + return; + } + callback(); + } + commentSelection(methodOfCreation = "") { + this.highlightSelection(methodOfCreation, true); + } + #displayFloatingToolbar() { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + return; + } + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + const boxes = this.getSelectionBoxes(textLayer); + if (!boxes) { + return; + } + this.#floatingToolbar ||= new FloatingToolbar(this); + this.#floatingToolbar.show(textLayer, boxes, this.direction === "ltr"); + } + getAndRemoveDataFromAnnotationStorage(annotationId) { + if (!this.#annotationStorage) { + return null; + } + const key = `${AnnotationEditorPrefix}${annotationId}`; + const storedValue = this.#annotationStorage.getRawValue(key); + if (storedValue) { + this.#annotationStorage.remove(key); + } + return storedValue; + } + addToAnnotationStorage(editor) { + if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) { + this.#annotationStorage.setValue(editor.id, editor); + } + } + a11yAlert(messageId, args = null) { + const viewerAlert = this.#viewerAlert; + if (!viewerAlert) { + return; + } + viewerAlert.setAttribute("data-l10n-id", messageId); + if (args) { + viewerAlert.setAttribute("data-l10n-args", JSON.stringify(args)); + } else { + viewerAlert.removeAttribute("data-l10n-args"); + } + } + #selectionChange() { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + if (this.#selectedTextNode) { + this.#floatingToolbar?.hide(); + this.#selectedTextNode = null; + this.#dispatchUpdateStates({ + hasSelectedText: false + }); + } + return; + } + const { + anchorNode + } = selection; + if (anchorNode === this.#selectedTextNode) { + return; + } + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + if (!textLayer) { + if (this.#selectedTextNode) { + this.#floatingToolbar?.hide(); + this.#selectedTextNode = null; + this.#dispatchUpdateStates({ + hasSelectedText: false + }); + } + return; + } + this.#floatingToolbar?.hide(); + this.#selectedTextNode = anchorNode; + this.#dispatchUpdateStates({ + hasSelectedText: true + }); + if (this.#mode !== AnnotationEditorType.HIGHLIGHT && this.#mode !== AnnotationEditorType.NONE) { + return; + } + if (this.#mode === AnnotationEditorType.HIGHLIGHT) { + this.showAllEditors("highlight", true, true); + } + this.#highlightWhenShiftUp = this.isShiftKeyDown; + if (!this.isShiftKeyDown) { + const activeLayer = this.#mode === AnnotationEditorType.HIGHLIGHT ? this.#getLayerForTextLayer(textLayer) : null; + activeLayer?.toggleDrawing(); + if (this.#isPointerDown) { + const ac = new AbortController(); + const signal = this.combinedSignal(ac); + const pointerup = e => { + if (e.type === "pointerup" && e.button !== 0) { + return; + } + ac.abort(); + activeLayer?.toggleDrawing(true); + if (e.type === "pointerup") { + this.#onSelectEnd("main_toolbar"); + } + }; + window.addEventListener("pointerup", pointerup, { + signal + }); + window.addEventListener("blur", pointerup, { + signal + }); + } else { + activeLayer?.toggleDrawing(true); + this.#onSelectEnd("main_toolbar"); + } + } + } + #onSelectEnd(methodOfCreation = "") { + if (this.#mode === AnnotationEditorType.HIGHLIGHT) { + this.highlightSelection(methodOfCreation); + } else if (this.#enableHighlightFloatingButton) { + this.#displayFloatingToolbar(); + } + } + #addSelectionListener() { + document.addEventListener("selectionchange", this.#selectionChange.bind(this), { + signal: this._signal + }); + } + #addFocusManager() { + if (this.#focusManagerAC) { + return; + } + this.#focusManagerAC = new AbortController(); + const signal = this.combinedSignal(this.#focusManagerAC); + window.addEventListener("focus", this.focus.bind(this), { + signal + }); + window.addEventListener("blur", this.blur.bind(this), { + signal + }); + } + #removeFocusManager() { + this.#focusManagerAC?.abort(); + this.#focusManagerAC = null; + } + blur() { + this.isShiftKeyDown = false; + if (this.#highlightWhenShiftUp) { + this.#highlightWhenShiftUp = false; + this.#onSelectEnd("main_toolbar"); + } + if (!this.hasSelection) { + return; + } + const { + activeElement + } = document; + for (const editor of this.#selectedEditors) { + if (editor.div.contains(activeElement)) { + this.#lastActiveElement = [editor, activeElement]; + editor._focusEventsAllowed = false; + break; + } + } + } + focus() { + if (!this.#lastActiveElement) { + return; + } + const [lastEditor, lastActiveElement] = this.#lastActiveElement; + this.#lastActiveElement = null; + lastActiveElement.addEventListener("focusin", () => { + lastEditor._focusEventsAllowed = true; + }, { + once: true, + signal: this._signal + }); + lastActiveElement.focus(); + } + #addKeyboardManager() { + if (this.#keyboardManagerAC) { + return; + } + this.#keyboardManagerAC = new AbortController(); + const signal = this.combinedSignal(this.#keyboardManagerAC); + window.addEventListener("keydown", this.keydown.bind(this), { + signal + }); + window.addEventListener("keyup", this.keyup.bind(this), { + signal + }); + } + #removeKeyboardManager() { + this.#keyboardManagerAC?.abort(); + this.#keyboardManagerAC = null; + } + #addCopyPasteListeners() { + if (this.#copyPasteAC) { + return; + } + this.#copyPasteAC = new AbortController(); + const signal = this.combinedSignal(this.#copyPasteAC); + document.addEventListener("copy", this.copy.bind(this), { + signal + }); + document.addEventListener("cut", this.cut.bind(this), { + signal + }); + document.addEventListener("paste", this.paste.bind(this), { + signal + }); + } + #removeCopyPasteListeners() { + this.#copyPasteAC?.abort(); + this.#copyPasteAC = null; + } + #addDragAndDropListeners() { + const signal = this._signal; + document.addEventListener("dragover", this.dragOver.bind(this), { + signal + }); + document.addEventListener("drop", this.drop.bind(this), { + signal + }); + } + addEditListeners() { + this.#addKeyboardManager(); + this.setEditingState(true); + } + removeEditListeners() { + this.#removeKeyboardManager(); + this.setEditingState(false); + } + dragOver(event) { + for (const { + type + } of event.dataTransfer.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(type)) { + event.dataTransfer.dropEffect = "copy"; + event.preventDefault(); + return; + } + } + } + } + drop(event) { + for (const item of event.dataTransfer.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(item.type)) { + editorType.paste(item, this.currentLayer); + event.preventDefault(); + return; + } + } + } + } + copy(event) { + event.preventDefault(); + this.#activeEditor?.commitOrRemove(); + if (!this.hasSelection) { + return; + } + const editors = []; + for (const editor of this.#selectedEditors) { + const serialized = editor.serialize(true); + if (serialized) { + editors.push(serialized); + } + } + if (editors.length === 0) { + return; + } + event.clipboardData.setData("application/pdfjs", JSON.stringify(editors)); + } + cut(event) { + this.copy(event); + this.delete(); + } + async paste(event) { + event.preventDefault(); + const { + clipboardData + } = event; + for (const item of clipboardData.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(item.type)) { + editorType.paste(item, this.currentLayer); + return; + } + } + } + let data = clipboardData.getData("application/pdfjs"); + if (!data) { + return; + } + try { + data = JSON.parse(data); + } catch (ex) { + warn(`paste: "${ex.message}".`); + return; + } + if (!Array.isArray(data)) { + return; + } + this.unselectAll(); + const layer = this.currentLayer; + try { + const newEditors = []; + for (const editor of data) { + const deserializedEditor = await layer.deserialize(editor); + if (!deserializedEditor) { + return; + } + newEditors.push(deserializedEditor); + } + const cmd = () => { + for (const editor of newEditors) { + this.#addEditorToLayer(editor); + } + this.#selectEditors(newEditors); + }; + const undo = () => { + for (const editor of newEditors) { + editor.remove(); + } + }; + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } catch (ex) { + warn(`paste: "${ex.message}".`); + } + } + keydown(event) { + if (!this.isShiftKeyDown && event.key === "Shift") { + this.isShiftKeyDown = true; + } + if (this.#mode !== AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) { + AnnotationEditorUIManager._keyboardManager.exec(this, event); + } + } + keyup(event) { + if (this.isShiftKeyDown && event.key === "Shift") { + this.isShiftKeyDown = false; + if (this.#highlightWhenShiftUp) { + this.#highlightWhenShiftUp = false; + this.#onSelectEnd("main_toolbar"); + } + } + } + onEditingAction({ + name + }) { + switch (name) { + case "undo": + case "redo": + case "delete": + case "selectAll": + this[name](); + break; + case "highlightSelection": + this.highlightSelection("context_menu"); + break; + case "commentSelection": + this.commentSelection("context_menu"); + break; + } + } + #dispatchUpdateStates(details) { + const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value); + if (hasChanged) { + this._eventBus.dispatch("annotationeditorstateschanged", { + source: this, + details: Object.assign(this.#previousStates, details) + }); + if (this.#mode === AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) { + this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]); + } + } + } + #dispatchUpdateUI(details) { + this._eventBus.dispatch("annotationeditorparamschanged", { + source: this, + details + }); + } + setEditingState(isEditing) { + if (isEditing) { + this.#addFocusManager(); + this.#addCopyPasteListeners(); + this.#dispatchUpdateStates({ + isEditing: this.#mode !== AnnotationEditorType.NONE, + isEmpty: this.#isEmpty(), + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + hasSelectedEditor: false + }); + } else { + this.#removeFocusManager(); + this.#removeCopyPasteListeners(); + this.#dispatchUpdateStates({ + isEditing: false + }); + this.disableUserSelect(false); + } + } + registerEditorTypes(types) { + if (this.#editorTypes) { + return; + } + this.#editorTypes = types; + for (const editorType of this.#editorTypes) { + this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); + } + } + getId() { + return this.#idManager.id; + } + get currentLayer() { + return this.#allLayers.get(this.#currentPageIndex); + } + getLayer(pageIndex) { + return this.#allLayers.get(pageIndex); + } + get currentPageIndex() { + return this.#currentPageIndex; + } + addLayer(layer) { + this.#allLayers.set(layer.pageIndex, layer); + if (this.#isEnabled) { + layer.enable(); + } else { + layer.disable(); + } + } + removeLayer(layer) { + this.#allLayers.delete(layer.pageIndex); + } + async updateMode(mode, editId = null, isFromKeyboard = false, mustEnterInEditMode = false, editComment = false) { + if (this.#mode === mode) { + return; + } + if (this.#updateModeCapability) { + await this.#updateModeCapability.promise; + if (!this.#updateModeCapability) { + return; + } + } + this.#updateModeCapability = Promise.withResolvers(); + this.#currentDrawingSession?.commitOrRemove(); + if (this.#mode === AnnotationEditorType.POPUP) { + this.#commentManager?.hideSidebar(); + } + this.#commentManager?.destroyPopup(); + this.#mode = mode; + if (mode === AnnotationEditorType.NONE) { + this.setEditingState(false); + this.#disableAll(); + for (const editor of this.#allEditors.values()) { + editor.hideStandaloneCommentButton(); + } + this._editorUndoBar?.hide(); + this.toggleComment(null); + this.#updateModeCapability.resolve(); + return; + } + for (const editor of this.#allEditors.values()) { + editor.addStandaloneCommentButton(); + } + if (mode === AnnotationEditorType.SIGNATURE) { + await this.#signatureManager?.loadSignatures(); + } + this.setEditingState(true); + await this.#enableAll(); + this.unselectAll(); + for (const layer of this.#allLayers.values()) { + layer.updateMode(mode); + } + if (mode === AnnotationEditorType.POPUP) { + this.#allEditableAnnotations ||= await this.#pdfDocument.getAnnotationsByType(new Set(this.#editorTypes.map(editorClass => editorClass._editorType))); + const elementIds = new Set(); + const allComments = []; + for (const editor of this.#allEditors.values()) { + const { + annotationElementId, + hasComment, + deleted + } = editor; + if (annotationElementId) { + elementIds.add(annotationElementId); + } + if (hasComment && !deleted) { + allComments.push(editor.getData()); + } + } + for (const annotation of this.#allEditableAnnotations) { + const { + id, + popupRef, + contentsObj + } = annotation; + if (popupRef && contentsObj?.str && !elementIds.has(id) && !this.#deletedAnnotationsElementIds.has(id)) { + allComments.push(annotation); + } + } + this.#commentManager?.showSidebar(allComments); + } + if (!editId) { + if (isFromKeyboard) { + this.addNewEditorFromKeyboard(); + } + this.#updateModeCapability.resolve(); + return; + } + for (const editor of this.#allEditors.values()) { + if (editor.uid === editId) { + this.setSelected(editor); + if (editComment) { + editor.editComment(); + } else if (mustEnterInEditMode) { + editor.enterInEditMode(); + } else { + editor.focus(); + } + } else { + editor.unselect(); + } + } + this.#updateModeCapability.resolve(); + } + addNewEditorFromKeyboard() { + if (this.currentLayer.canCreateNewEmptyEditor()) { + this.currentLayer.addNewEditor(); + } + } + updateToolbar(options) { + if (options.mode === this.#mode) { + return; + } + this._eventBus.dispatch("switchannotationeditormode", { + source: this, + ...options + }); + } + updateParams(type, value) { + if (!this.#editorTypes) { + return; + } + switch (type) { + case AnnotationEditorParamsType.CREATE: + this.currentLayer.addNewEditor(value); + return; + case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL: + this._eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data: { + type: "highlight", + action: "toggle_visibility" + } + } + }); + (this.#showAllStates ||= new Map()).set(type, value); + this.showAllEditors("highlight", value); + break; + } + if (this.hasSelection) { + for (const editor of this.#selectedEditors) { + editor.updateParams(type, value); + } + } else { + for (const editorType of this.#editorTypes) { + editorType.updateDefaultParams(type, value); + } + } + } + showAllEditors(type, visible, updateButton = false) { + for (const editor of this.#allEditors.values()) { + if (editor.editorType === type) { + editor.show(visible); + } + } + const state = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true; + if (state !== visible) { + this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]); + } + } + enableWaiting(mustWait = false) { + if (this.#isWaiting === mustWait) { + return; + } + this.#isWaiting = mustWait; + for (const layer of this.#allLayers.values()) { + if (mustWait) { + layer.disableClick(); + } else { + layer.enableClick(); + } + layer.div.classList.toggle("waiting", mustWait); + } + } + async #enableAll() { + if (!this.#isEnabled) { + this.#isEnabled = true; + const promises = []; + for (const layer of this.#allLayers.values()) { + promises.push(layer.enable()); + } + await Promise.all(promises); + for (const editor of this.#allEditors.values()) { + editor.enable(); + } + } + } + #disableAll() { + this.unselectAll(); + if (this.#isEnabled) { + this.#isEnabled = false; + for (const layer of this.#allLayers.values()) { + layer.disable(); + } + for (const editor of this.#allEditors.values()) { + editor.disable(); + } + } + } + *getEditors(pageIndex) { + for (const editor of this.#allEditors.values()) { + if (editor.pageIndex === pageIndex) { + yield editor; + } + } + } + getEditor(id) { + return this.#allEditors.get(id); + } + addEditor(editor) { + this.#allEditors.set(editor.id, editor); + } + removeEditor(editor) { + if (editor.div.contains(document.activeElement)) { + if (this.#focusMainContainerTimeoutId) { + clearTimeout(this.#focusMainContainerTimeoutId); + } + this.#focusMainContainerTimeoutId = setTimeout(() => { + this.focusMainContainer(); + this.#focusMainContainerTimeoutId = null; + }, 0); + } + this.#allEditors.delete(editor.id); + if (editor.annotationElementId) { + this.#missingCanvases?.delete(editor.annotationElementId); + } + this.unselect(editor); + if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) { + this.#annotationStorage?.remove(editor.id); + } + } + addDeletedAnnotationElement(editor) { + this.#deletedAnnotationsElementIds.add(editor.annotationElementId); + this.addChangedExistingAnnotation(editor); + editor.deleted = true; + } + isDeletedAnnotationElement(annotationElementId) { + return this.#deletedAnnotationsElementIds.has(annotationElementId); + } + removeDeletedAnnotationElement(editor) { + this.#deletedAnnotationsElementIds.delete(editor.annotationElementId); + this.removeChangedExistingAnnotation(editor); + editor.deleted = false; + } + #addEditorToLayer(editor) { + const layer = this.#allLayers.get(editor.pageIndex); + if (layer) { + layer.addOrRebuild(editor); + } else { + this.addEditor(editor); + this.addToAnnotationStorage(editor); + } + } + setActiveEditor(editor) { + if (this.#activeEditor === editor) { + return; + } + this.#activeEditor = editor; + if (editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } + get #lastSelectedEditor() { + let ed = null; + for (ed of this.#selectedEditors) {} + return ed; + } + updateUI(editor) { + if (this.#lastSelectedEditor === editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } + updateUIForDefaultProperties(editorType) { + this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); + } + toggleSelected(editor) { + if (this.#selectedEditors.has(editor)) { + this.#selectedEditors.delete(editor); + editor.unselect(); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + return; + } + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + setSelected(editor) { + this.updateToolbar({ + mode: editor.mode, + editId: editor.uid + }); + this.#currentDrawingSession?.commitOrRemove(); + for (const ed of this.#selectedEditors) { + if (ed !== editor) { + ed.unselect(); + } + } + this.#selectedEditors.clear(); + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + isSelected(editor) { + return this.#selectedEditors.has(editor); + } + get firstSelectedEditor() { + return this.#selectedEditors.values().next().value; + } + unselect(editor) { + editor.unselect(); + this.#selectedEditors.delete(editor); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + } + get hasSelection() { + return this.#selectedEditors.size !== 0; + } + get isEnterHandled() { + return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled; + } + undo() { + this.#commandManager.undo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: true, + isEmpty: this.#isEmpty() + }); + this._editorUndoBar?.hide(); + } + redo() { + this.#commandManager.redo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + isEmpty: this.#isEmpty() + }); + } + addCommands(params) { + this.#commandManager.add(params); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: false, + isEmpty: this.#isEmpty() + }); + } + cleanUndoStack(type) { + this.#commandManager.cleanType(type); + } + #isEmpty() { + if (this.#allEditors.size === 0) { + return true; + } + if (this.#allEditors.size === 1) { + for (const editor of this.#allEditors.values()) { + return editor.isEmpty(); + } + } + return false; + } + delete() { + this.commitOrRemove(); + const drawingEditor = this.currentLayer?.endDrawingSession(true); + if (!this.hasSelection && !drawingEditor) { + return; + } + const editors = drawingEditor ? [drawingEditor] : [...this.#selectedEditors]; + const cmd = () => { + this._editorUndoBar?.show(undo, editors.length === 1 ? editors[0].editorType : editors.length); + for (const editor of editors) { + editor.remove(); + } + }; + const undo = () => { + for (const editor of editors) { + this.#addEditorToLayer(editor); + } + }; + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } + commitOrRemove() { + this.#activeEditor?.commitOrRemove(); + } + hasSomethingToControl() { + return this.#activeEditor || this.hasSelection; + } + #selectEditors(editors) { + for (const editor of this.#selectedEditors) { + editor.unselect(); + } + this.#selectedEditors.clear(); + for (const editor of editors) { + if (editor.isEmpty()) { + continue; + } + this.#selectedEditors.add(editor); + editor.select(); + } + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + } + selectAll() { + for (const editor of this.#selectedEditors) { + editor.commit(); + } + this.#selectEditors(this.#allEditors.values()); + } + unselectAll() { + if (this.#activeEditor) { + this.#activeEditor.commitOrRemove(); + if (this.#mode !== AnnotationEditorType.NONE) { + return; + } + } + if (this.#currentDrawingSession?.commitOrRemove()) { + return; + } + if (!this.hasSelection) { + return; + } + for (const editor of this.#selectedEditors) { + editor.unselect(); + } + this.#selectedEditors.clear(); + this.#dispatchUpdateStates({ + hasSelectedEditor: false + }); + } + translateSelectedEditors(x, y, noCommit = false) { + if (!noCommit) { + this.commitOrRemove(); + } + if (!this.hasSelection) { + return; + } + this.#translation[0] += x; + this.#translation[1] += y; + const [totalX, totalY] = this.#translation; + const editors = [...this.#selectedEditors]; + const TIME_TO_WAIT = 1000; + if (this.#translationTimeoutId) { + clearTimeout(this.#translationTimeoutId); + } + this.#translationTimeoutId = setTimeout(() => { + this.#translationTimeoutId = null; + this.#translation[0] = this.#translation[1] = 0; + this.addCommands({ + cmd: () => { + for (const editor of editors) { + if (this.#allEditors.has(editor.id)) { + editor.translateInPage(totalX, totalY); + editor.translationDone(); + } + } + }, + undo: () => { + for (const editor of editors) { + if (this.#allEditors.has(editor.id)) { + editor.translateInPage(-totalX, -totalY); + editor.translationDone(); + } + } + }, + mustExec: false + }); + }, TIME_TO_WAIT); + for (const editor of editors) { + editor.translateInPage(x, y); + editor.translationDone(); + } + } + setUpDragSession() { + if (!this.hasSelection) { + return; + } + this.disableUserSelect(true); + this.#draggingEditors = new Map(); + for (const editor of this.#selectedEditors) { + this.#draggingEditors.set(editor, { + savedX: editor.x, + savedY: editor.y, + savedPageIndex: editor.pageIndex, + newX: 0, + newY: 0, + newPageIndex: -1 + }); + } + } + endDragSession() { + if (!this.#draggingEditors) { + return false; + } + this.disableUserSelect(false); + const map = this.#draggingEditors; + this.#draggingEditors = null; + let mustBeAddedInUndoStack = false; + for (const [{ + x, + y, + pageIndex + }, value] of map) { + value.newX = x; + value.newY = y; + value.newPageIndex = pageIndex; + mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex; + } + if (!mustBeAddedInUndoStack) { + return false; + } + const move = (editor, x, y, pageIndex) => { + if (this.#allEditors.has(editor.id)) { + const parent = this.#allLayers.get(pageIndex); + if (parent) { + editor._setParentAndPosition(parent, x, y); + } else { + editor.pageIndex = pageIndex; + editor.x = x; + editor.y = y; + } + } + }; + this.addCommands({ + cmd: () => { + for (const [editor, { + newX, + newY, + newPageIndex + }] of map) { + move(editor, newX, newY, newPageIndex); + } + }, + undo: () => { + for (const [editor, { + savedX, + savedY, + savedPageIndex + }] of map) { + move(editor, savedX, savedY, savedPageIndex); + } + }, + mustExec: true + }); + return true; + } + dragSelectedEditors(tx, ty) { + if (!this.#draggingEditors) { + return; + } + for (const editor of this.#draggingEditors.keys()) { + editor.drag(tx, ty); + } + } + rebuild(editor) { + if (editor.parent === null) { + const parent = this.getLayer(editor.pageIndex); + if (parent) { + parent.changeParent(editor); + parent.addOrRebuild(editor); + } else { + this.addEditor(editor); + this.addToAnnotationStorage(editor); + editor.rebuild(); + } + } else { + editor.parent.addOrRebuild(editor); + } + } + get isEditorHandlingKeyboard() { + return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents(); + } + isActive(editor) { + return this.#activeEditor === editor; + } + getActive() { + return this.#activeEditor; + } + getMode() { + return this.#mode; + } + isEditingMode() { + return this.#mode !== AnnotationEditorType.NONE; + } + get imageManager() { + return shadow(this, "imageManager", new ImageManager()); + } + getSelectionBoxes(textLayer) { + if (!textLayer) { + return null; + } + const selection = document.getSelection(); + for (let i = 0, ii = selection.rangeCount; i < ii; i++) { + if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) { + return null; + } + } + const { + x: layerX, + y: layerY, + width: parentWidth, + height: parentHeight + } = textLayer.getBoundingClientRect(); + let rotator; + switch (textLayer.getAttribute("data-main-rotation")) { + case "90": + rotator = (x, y, w, h) => ({ + x: (y - layerY) / parentHeight, + y: 1 - (x + w - layerX) / parentWidth, + width: h / parentHeight, + height: w / parentWidth + }); + break; + case "180": + rotator = (x, y, w, h) => ({ + x: 1 - (x + w - layerX) / parentWidth, + y: 1 - (y + h - layerY) / parentHeight, + width: w / parentWidth, + height: h / parentHeight + }); + break; + case "270": + rotator = (x, y, w, h) => ({ + x: 1 - (y + h - layerY) / parentHeight, + y: (x - layerX) / parentWidth, + width: h / parentHeight, + height: w / parentWidth + }); + break; + default: + rotator = (x, y, w, h) => ({ + x: (x - layerX) / parentWidth, + y: (y - layerY) / parentHeight, + width: w / parentWidth, + height: h / parentHeight + }); + break; + } + const boxes = []; + for (let i = 0, ii = selection.rangeCount; i < ii; i++) { + const range = selection.getRangeAt(i); + if (range.collapsed) { + continue; + } + for (const { + x, + y, + width, + height + } of range.getClientRects()) { + if (width === 0 || height === 0) { + continue; + } + boxes.push(rotator(x, y, width, height)); + } + } + return boxes.length === 0 ? null : boxes; + } + addChangedExistingAnnotation({ + annotationElementId, + id + }) { + (this.#changedExistingAnnotations ||= new Map()).set(annotationElementId, id); + } + removeChangedExistingAnnotation({ + annotationElementId + }) { + this.#changedExistingAnnotations?.delete(annotationElementId); + } + renderAnnotationElement(annotation) { + const editorId = this.#changedExistingAnnotations?.get(annotation.data.id); + if (!editorId) { + return; + } + const editor = this.#annotationStorage.getRawValue(editorId); + if (!editor) { + return; + } + if (this.#mode === AnnotationEditorType.NONE && !editor.hasBeenModified) { + return; + } + editor.renderAnnotationElement(annotation); + } + setMissingCanvas(annotationId, annotationElementId, canvas) { + const editor = this.#missingCanvases?.get(annotationId); + if (!editor) { + return; + } + editor.setCanvas(annotationElementId, canvas); + this.#missingCanvases.delete(annotationId); + } + addMissingCanvas(annotationId, editor) { + (this.#missingCanvases ||= new Map()).set(annotationId, editor); + } +} + +;// ./src/display/editor/alt_text.js + +class AltText { + #altText = null; + #altTextDecorative = false; + #altTextButton = null; + #altTextButtonLabel = null; + #altTextTooltip = null; + #altTextTooltipTimeout = null; + #altTextWasFromKeyBoard = false; + #badge = null; + #editor = null; + #guessedText = null; + #textWithDisclaimer = null; + #useNewAltTextFlow = false; + static #l10nNewButton = null; + static _l10n = null; + constructor(editor) { + this.#editor = editor; + this.#useNewAltTextFlow = editor._uiManager.useNewAltTextFlow; + AltText.#l10nNewButton ||= Object.freeze({ + added: "pdfjs-editor-new-alt-text-added-button", + "added-label": "pdfjs-editor-new-alt-text-added-button-label", + missing: "pdfjs-editor-new-alt-text-missing-button", + "missing-label": "pdfjs-editor-new-alt-text-missing-button-label", + review: "pdfjs-editor-new-alt-text-to-review-button", + "review-label": "pdfjs-editor-new-alt-text-to-review-button-label" + }); + } + static initialize(l10n) { + AltText._l10n ??= l10n; + } + async render() { + const altText = this.#altTextButton = document.createElement("button"); + altText.className = "altText"; + altText.tabIndex = "0"; + const label = this.#altTextButtonLabel = document.createElement("span"); + altText.append(label); + if (this.#useNewAltTextFlow) { + altText.classList.add("new"); + altText.setAttribute("data-l10n-id", AltText.#l10nNewButton.missing); + label.setAttribute("data-l10n-id", AltText.#l10nNewButton["missing-label"]); + } else { + altText.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button"); + label.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button-label"); + } + const signal = this.#editor._uiManager._signal; + altText.addEventListener("contextmenu", noContextMenu, { + signal + }); + altText.addEventListener("pointerdown", event => event.stopPropagation(), { + signal + }); + const onClick = event => { + event.preventDefault(); + this.#editor._uiManager.editAltText(this.#editor); + if (this.#useNewAltTextFlow) { + this.#editor._reportTelemetry({ + action: "pdfjs.image.alt_text.image_status_label_clicked", + data: { + label: this.#label + } + }); + } + }; + altText.addEventListener("click", onClick, { + capture: true, + signal + }); + altText.addEventListener("keydown", event => { + if (event.target === altText && event.key === "Enter") { + this.#altTextWasFromKeyBoard = true; + onClick(event); + } + }, { + signal + }); + await this.#setState(); + return altText; + } + get #label() { + return this.#altText && "added" || this.#altText === null && this.guessedText && "review" || "missing"; + } + finish() { + if (!this.#altTextButton) { + return; + } + this.#altTextButton.focus({ + focusVisible: this.#altTextWasFromKeyBoard + }); + this.#altTextWasFromKeyBoard = false; + } + isEmpty() { + if (this.#useNewAltTextFlow) { + return this.#altText === null; + } + return !this.#altText && !this.#altTextDecorative; + } + hasData() { + if (this.#useNewAltTextFlow) { + return this.#altText !== null || !!this.#guessedText; + } + return this.isEmpty(); + } + get guessedText() { + return this.#guessedText; + } + async setGuessedText(guessedText) { + if (this.#altText !== null) { + return; + } + this.#guessedText = guessedText; + this.#textWithDisclaimer = await AltText._l10n.get("pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer", { + generatedAltText: guessedText + }); + this.#setState(); + } + toggleAltTextBadge(visibility = false) { + if (!this.#useNewAltTextFlow || this.#altText) { + this.#badge?.remove(); + this.#badge = null; + return; + } + if (!this.#badge) { + const badge = this.#badge = document.createElement("div"); + badge.className = "noAltTextBadge"; + this.#editor.div.append(badge); + } + this.#badge.classList.toggle("hidden", !visibility); + } + serialize(isForCopying) { + let altText = this.#altText; + if (!isForCopying && this.#guessedText === altText) { + altText = this.#textWithDisclaimer; + } + return { + altText, + decorative: this.#altTextDecorative, + guessedText: this.#guessedText, + textWithDisclaimer: this.#textWithDisclaimer + }; + } + get data() { + return { + altText: this.#altText, + decorative: this.#altTextDecorative + }; + } + set data({ + altText, + decorative, + guessedText, + textWithDisclaimer, + cancel = false + }) { + if (guessedText) { + this.#guessedText = guessedText; + this.#textWithDisclaimer = textWithDisclaimer; + } + if (this.#altText === altText && this.#altTextDecorative === decorative) { + return; + } + if (!cancel) { + this.#altText = altText; + this.#altTextDecorative = decorative; + } + this.#setState(); + } + toggle(enabled = false) { + if (!this.#altTextButton) { + return; + } + if (!enabled && this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextButton.disabled = !enabled; + } + shown() { + this.#editor._reportTelemetry({ + action: "pdfjs.image.alt_text.image_status_label_displayed", + data: { + label: this.#label + } + }); + } + destroy() { + this.#altTextButton?.remove(); + this.#altTextButton = null; + this.#altTextButtonLabel = null; + this.#altTextTooltip = null; + this.#badge?.remove(); + this.#badge = null; + } + async #setState() { + const button = this.#altTextButton; + if (!button) { + return; + } + if (this.#useNewAltTextFlow) { + button.classList.toggle("done", !!this.#altText); + button.setAttribute("data-l10n-id", AltText.#l10nNewButton[this.#label]); + this.#altTextButtonLabel?.setAttribute("data-l10n-id", AltText.#l10nNewButton[`${this.#label}-label`]); + if (!this.#altText) { + this.#altTextTooltip?.remove(); + return; + } + } else { + if (!this.#altText && !this.#altTextDecorative) { + button.classList.remove("done"); + this.#altTextTooltip?.remove(); + return; + } + button.classList.add("done"); + button.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-edit-button"); + } + let tooltip = this.#altTextTooltip; + if (!tooltip) { + this.#altTextTooltip = tooltip = document.createElement("span"); + tooltip.className = "tooltip"; + tooltip.setAttribute("role", "tooltip"); + tooltip.id = `alt-text-tooltip-${this.#editor.id}`; + const DELAY_TO_SHOW_TOOLTIP = 100; + const signal = this.#editor._uiManager._signal; + signal.addEventListener("abort", () => { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + }, { + once: true + }); + button.addEventListener("mouseenter", () => { + this.#altTextTooltipTimeout = setTimeout(() => { + this.#altTextTooltipTimeout = null; + this.#altTextTooltip.classList.add("show"); + this.#editor._reportTelemetry({ + action: "alt_text_tooltip" + }); + }, DELAY_TO_SHOW_TOOLTIP); + }, { + signal + }); + button.addEventListener("mouseleave", () => { + if (this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextTooltip?.classList.remove("show"); + }, { + signal + }); + } + if (this.#altTextDecorative) { + tooltip.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-decorative-tooltip"); + } else { + tooltip.removeAttribute("data-l10n-id"); + tooltip.textContent = this.#altText; + } + if (!tooltip.parentNode) { + button.append(tooltip); + } + const element = this.#editor.getElementForAltText(); + element?.setAttribute("aria-describedby", tooltip.id); + } +} + +;// ./src/display/editor/comment.js + +class Comment { + #commentStandaloneButton = null; + #commentToolbarButton = null; + #commentWasFromKeyBoard = false; + #editor = null; + #initialText = null; + #richText = null; + #text = null; + #date = null; + #deleted = false; + #popupPosition = null; + constructor(editor) { + this.#editor = editor; + } + renderForToolbar() { + const button = this.#commentToolbarButton = document.createElement("button"); + button.className = "comment"; + return this.#render(button, false); + } + renderForStandalone() { + const button = this.#commentStandaloneButton = document.createElement("button"); + button.className = "annotationCommentButton"; + const position = this.#editor.commentButtonPosition; + if (position) { + const { + style + } = button; + style.insetInlineEnd = `calc(${100 * (this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0])}% - var(--comment-button-dim))`; + style.top = `calc(${100 * position[1]}% - var(--comment-button-dim))`; + const color = this.#editor.commentButtonColor; + if (color) { + style.backgroundColor = color; + } + } + return this.#render(button, true); + } + focusButton() { + setTimeout(() => { + (this.#commentStandaloneButton ?? this.#commentToolbarButton)?.focus(); + }, 0); + } + onUpdatedColor() { + if (!this.#commentStandaloneButton) { + return; + } + const color = this.#editor.commentButtonColor; + if (color) { + this.#commentStandaloneButton.style.backgroundColor = color; + } + this.#editor._uiManager.updatePopupColor(this.#editor); + } + get commentButtonWidth() { + return (this.#commentStandaloneButton?.getBoundingClientRect().width ?? 0) / this.#editor.parent.boundingClientRect.width; + } + get commentPopupPositionInLayer() { + if (this.#popupPosition) { + return this.#popupPosition; + } + if (!this.#commentStandaloneButton) { + return null; + } + const { + x, + y, + height + } = this.#commentStandaloneButton.getBoundingClientRect(); + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = this.#editor.parent.boundingClientRect; + return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight]; + } + set commentPopupPositionInLayer(pos) { + this.#popupPosition = pos; + } + hasDefaultPopupPosition() { + return this.#popupPosition === null; + } + removeStandaloneCommentButton() { + this.#commentStandaloneButton?.remove(); + this.#commentStandaloneButton = null; + } + removeToolbarCommentButton() { + this.#commentToolbarButton?.remove(); + this.#commentToolbarButton = null; + } + setCommentButtonStates({ + selected, + hasPopup + }) { + if (!this.#commentStandaloneButton) { + return; + } + this.#commentStandaloneButton.classList.toggle("selected", selected); + this.#commentStandaloneButton.ariaExpanded = hasPopup; + } + #render(comment, isStandalone) { + if (!this.#editor._uiManager.hasCommentManager()) { + return null; + } + comment.tabIndex = "0"; + comment.ariaHasPopup = "dialog"; + if (isStandalone) { + comment.ariaControls = "commentPopup"; + comment.setAttribute("data-l10n-id", "pdfjs-show-comment-button"); + } else { + comment.ariaControlsElements = [this.#editor._uiManager.getCommentDialogElement()]; + comment.setAttribute("data-l10n-id", "pdfjs-editor-add-comment-button"); + } + const signal = this.#editor._uiManager._signal; + if (!(signal instanceof AbortSignal) || signal.aborted) { + return comment; + } + comment.addEventListener("contextmenu", noContextMenu, { + signal + }); + if (isStandalone) { + comment.addEventListener("focusin", e => { + this.#editor._focusEventsAllowed = false; + stopEvent(e); + }, { + capture: true, + signal + }); + comment.addEventListener("focusout", e => { + this.#editor._focusEventsAllowed = true; + stopEvent(e); + }, { + capture: true, + signal + }); + } + comment.addEventListener("pointerdown", event => event.stopPropagation(), { + signal + }); + const onClick = event => { + event.preventDefault(); + if (comment === this.#commentToolbarButton) { + this.edit(); + } else { + this.#editor.toggleComment(true); + } + }; + comment.addEventListener("click", onClick, { + capture: true, + signal + }); + comment.addEventListener("keydown", event => { + if (event.target === comment && event.key === "Enter") { + this.#commentWasFromKeyBoard = true; + onClick(event); + } + }, { + signal + }); + comment.addEventListener("pointerenter", () => { + this.#editor.toggleComment(false, true); + }, { + signal + }); + comment.addEventListener("pointerleave", () => { + this.#editor.toggleComment(false, false); + }, { + signal + }); + return comment; + } + edit(options) { + const position = this.commentPopupPositionInLayer; + let posX, posY; + if (position) { + [posX, posY] = position; + } else { + [posX, posY] = this.#editor.commentButtonPosition; + const { + width, + height, + x, + y + } = this.#editor; + posX = x + posX * width; + posY = y + posY * height; + } + const parentDimensions = this.#editor.parent.boundingClientRect; + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = parentDimensions; + this.#editor._uiManager.editComment(this.#editor, parentX + posX * parentWidth, parentY + posY * parentHeight, { + ...options, + parentDimensions + }); + } + finish() { + if (!this.#commentToolbarButton) { + return; + } + this.#commentToolbarButton.focus({ + focusVisible: this.#commentWasFromKeyBoard + }); + this.#commentWasFromKeyBoard = false; + } + isDeleted() { + return this.#deleted || this.#text === ""; + } + isEmpty() { + return this.#text === null; + } + hasBeenEdited() { + return this.isDeleted() || this.#text !== this.#initialText; + } + serialize() { + return this.data; + } + get data() { + return { + text: this.#text, + richText: this.#richText, + date: this.#date, + deleted: this.isDeleted() + }; + } + set data(text) { + if (text !== this.#text) { + this.#richText = null; + } + if (text === null) { + this.#text = ""; + this.#deleted = true; + return; + } + this.#text = text; + this.#date = new Date(); + this.#deleted = false; + } + setInitialText(text, richText = null) { + this.#initialText = text; + this.data = text; + this.#date = null; + this.#richText = richText; + } + shown() {} + destroy() { + this.#commentToolbarButton?.remove(); + this.#commentToolbarButton = null; + this.#commentStandaloneButton?.remove(); + this.#commentStandaloneButton = null; + this.#text = ""; + this.#richText = null; + this.#date = null; + this.#editor = null; + this.#commentWasFromKeyBoard = false; + this.#deleted = false; + } +} + +;// ./src/display/touch_manager.js + +class TouchManager { + #container; + #isPinching = false; + #isPinchingStopped = null; + #isPinchingDisabled; + #onPinchStart; + #onPinching; + #onPinchEnd; + #pointerDownAC = null; + #signal; + #touchInfo = null; + #touchManagerAC; + #touchMoveAC = null; + constructor({ + container, + isPinchingDisabled = null, + isPinchingStopped = null, + onPinchStart = null, + onPinching = null, + onPinchEnd = null, + signal + }) { + this.#container = container; + this.#isPinchingStopped = isPinchingStopped; + this.#isPinchingDisabled = isPinchingDisabled; + this.#onPinchStart = onPinchStart; + this.#onPinching = onPinching; + this.#onPinchEnd = onPinchEnd; + this.#touchManagerAC = new AbortController(); + this.#signal = AbortSignal.any([signal, this.#touchManagerAC.signal]); + container.addEventListener("touchstart", this.#onTouchStart.bind(this), { + passive: false, + signal: this.#signal + }); + } + get MIN_TOUCH_DISTANCE_TO_PINCH() { + return 35 / OutputScale.pixelRatio; + } + #onTouchStart(evt) { + if (this.#isPinchingDisabled?.()) { + return; + } + if (evt.touches.length === 1) { + if (this.#pointerDownAC) { + return; + } + const pointerDownAC = this.#pointerDownAC = new AbortController(); + const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]); + const container = this.#container; + const opts = { + capture: true, + signal, + passive: false + }; + const cancelPointerDown = e => { + if (e.pointerType === "touch") { + this.#pointerDownAC?.abort(); + this.#pointerDownAC = null; + } + }; + container.addEventListener("pointerdown", e => { + if (e.pointerType === "touch") { + stopEvent(e); + cancelPointerDown(e); + } + }, opts); + container.addEventListener("pointerup", cancelPointerDown, opts); + container.addEventListener("pointercancel", cancelPointerDown, opts); + return; + } + if (!this.#touchMoveAC) { + this.#touchMoveAC = new AbortController(); + const signal = AbortSignal.any([this.#signal, this.#touchMoveAC.signal]); + const container = this.#container; + const opt = { + signal, + capture: false, + passive: false + }; + container.addEventListener("touchmove", this.#onTouchMove.bind(this), opt); + const onTouchEnd = this.#onTouchEnd.bind(this); + container.addEventListener("touchend", onTouchEnd, opt); + container.addEventListener("touchcancel", onTouchEnd, opt); + opt.capture = true; + container.addEventListener("pointerdown", stopEvent, opt); + container.addEventListener("pointermove", stopEvent, opt); + container.addEventListener("pointercancel", stopEvent, opt); + container.addEventListener("pointerup", stopEvent, opt); + this.#onPinchStart?.(); + } + stopEvent(evt); + if (evt.touches.length !== 2 || this.#isPinchingStopped?.()) { + this.#touchInfo = null; + return; + } + let [touch0, touch1] = evt.touches; + if (touch0.identifier > touch1.identifier) { + [touch0, touch1] = [touch1, touch0]; + } + this.#touchInfo = { + touch0X: touch0.screenX, + touch0Y: touch0.screenY, + touch1X: touch1.screenX, + touch1Y: touch1.screenY + }; + } + #onTouchMove(evt) { + if (!this.#touchInfo || evt.touches.length !== 2) { + return; + } + stopEvent(evt); + let [touch0, touch1] = evt.touches; + if (touch0.identifier > touch1.identifier) { + [touch0, touch1] = [touch1, touch0]; + } + const { + screenX: screen0X, + screenY: screen0Y + } = touch0; + const { + screenX: screen1X, + screenY: screen1Y + } = touch1; + const touchInfo = this.#touchInfo; + const { + touch0X: pTouch0X, + touch0Y: pTouch0Y, + touch1X: pTouch1X, + touch1Y: pTouch1Y + } = touchInfo; + const prevGapX = pTouch1X - pTouch0X; + const prevGapY = pTouch1Y - pTouch0Y; + const currGapX = screen1X - screen0X; + const currGapY = screen1Y - screen0Y; + const distance = Math.hypot(currGapX, currGapY) || 1; + const pDistance = Math.hypot(prevGapX, prevGapY) || 1; + if (!this.#isPinching && Math.abs(pDistance - distance) <= TouchManager.MIN_TOUCH_DISTANCE_TO_PINCH) { + return; + } + touchInfo.touch0X = screen0X; + touchInfo.touch0Y = screen0Y; + touchInfo.touch1X = screen1X; + touchInfo.touch1Y = screen1Y; + if (!this.#isPinching) { + this.#isPinching = true; + return; + } + const origin = [(screen0X + screen1X) / 2, (screen0Y + screen1Y) / 2]; + this.#onPinching?.(origin, pDistance, distance); + } + #onTouchEnd(evt) { + if (evt.touches.length >= 2) { + return; + } + if (this.#touchMoveAC) { + this.#touchMoveAC.abort(); + this.#touchMoveAC = null; + this.#onPinchEnd?.(); + } + if (!this.#touchInfo) { + return; + } + stopEvent(evt); + this.#touchInfo = null; + this.#isPinching = false; + } + destroy() { + this.#touchManagerAC?.abort(); + this.#touchManagerAC = null; + this.#pointerDownAC?.abort(); + this.#pointerDownAC = null; + } +} + +;// ./src/display/editor/editor.js + + + + + + + +class AnnotationEditor { + #accessibilityData = null; + #allResizerDivs = null; + #altText = null; + #comment = null; + #commentStandaloneButton = null; + #disabled = false; + #dragPointerId = null; + #dragPointerType = ""; + #resizersDiv = null; + #lastPointerCoords = null; + #savedDimensions = null; + #fakeAnnotation = null; + #focusAC = null; + #focusedResizerName = ""; + #hasBeenClicked = false; + #initialRect = null; + #isEditing = false; + #isInEditMode = false; + #isResizerEnabledForKeyboard = false; + #moveInDOMTimeout = null; + #prevDragX = 0; + #prevDragY = 0; + #telemetryTimeouts = null; + #touchManager = null; + isSelected = false; + _isCopy = false; + _editToolbar = null; + _initialOptions = Object.create(null); + _initialData = null; + _isVisible = true; + _uiManager = null; + _focusEventsAllowed = true; + static _l10n = null; + static _l10nResizer = null; + #isDraggable = false; + #zIndex = AnnotationEditor._zIndex++; + static _borderLineWidth = -1; + static _colorManager = new ColorManager(); + static _zIndex = 1; + static _telemetryTimeout = 1000; + static get _resizerKeyboardManager() { + const resize = AnnotationEditor.prototype._resizeWithKeyboard; + const small = AnnotationEditorUIManager.TRANSLATE_SMALL; + const big = AnnotationEditorUIManager.TRANSLATE_BIG; + return shadow(this, "_resizerKeyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], resize, { + args: [-small, 0] + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], resize, { + args: [-big, 0] + }], [["ArrowRight", "mac+ArrowRight"], resize, { + args: [small, 0] + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], resize, { + args: [big, 0] + }], [["ArrowUp", "mac+ArrowUp"], resize, { + args: [0, -small] + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], resize, { + args: [0, -big] + }], [["ArrowDown", "mac+ArrowDown"], resize, { + args: [0, small] + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], resize, { + args: [0, big] + }], [["Escape", "mac+Escape"], AnnotationEditor.prototype._stopResizingWithKeyboard]])); + } + constructor(parameters) { + this.parent = parameters.parent; + this.id = parameters.id; + this.width = this.height = null; + this.pageIndex = parameters.parent.pageIndex; + this.name = parameters.name; + this.div = null; + this._uiManager = parameters.uiManager; + this.annotationElementId = null; + this._willKeepAspectRatio = false; + this._initialOptions.isCentered = parameters.isCentered; + this._structTreeParentId = null; + this.annotationElementId = parameters.annotationElementId || null; + this.creationDate = parameters.creationDate || new Date(); + this.modificationDate = parameters.modificationDate || null; + this.canAddComment = true; + const { + rotation, + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } = this.parent.viewport; + this.rotation = rotation; + this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360; + this.pageDimensions = [pageWidth, pageHeight]; + this.pageTranslation = [pageX, pageY]; + const [width, height] = this.parentDimensions; + this.x = parameters.x / width; + this.y = parameters.y / height; + this.isAttachedToDOM = false; + this.deleted = false; + } + get editorType() { + return Object.getPrototypeOf(this).constructor._type; + } + get mode() { + return Object.getPrototypeOf(this).constructor._editorType; + } + static get isDrawer() { + return false; + } + static get _defaultLineColor() { + return shadow(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText")); + } + static deleteAnnotationElement(editor) { + const fakeEditor = new FakeEditor({ + id: editor.parent.getNextId(), + parent: editor.parent, + uiManager: editor._uiManager + }); + fakeEditor.annotationElementId = editor.annotationElementId; + fakeEditor.deleted = true; + fakeEditor._uiManager.addToAnnotationStorage(fakeEditor); + } + static initialize(l10n, _uiManager) { + AnnotationEditor._l10n ??= l10n; + AnnotationEditor._l10nResizer ||= Object.freeze({ + topLeft: "pdfjs-editor-resizer-top-left", + topMiddle: "pdfjs-editor-resizer-top-middle", + topRight: "pdfjs-editor-resizer-top-right", + middleRight: "pdfjs-editor-resizer-middle-right", + bottomRight: "pdfjs-editor-resizer-bottom-right", + bottomMiddle: "pdfjs-editor-resizer-bottom-middle", + bottomLeft: "pdfjs-editor-resizer-bottom-left", + middleLeft: "pdfjs-editor-resizer-middle-left" + }); + if (AnnotationEditor._borderLineWidth !== -1) { + return; + } + const style = getComputedStyle(document.documentElement); + AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue("--outline-width")) || 0; + } + static updateDefaultParams(_type, _value) {} + static get defaultPropertiesToUpdate() { + return []; + } + static isHandlingMimeForPasting(mime) { + return false; + } + static paste(item, parent) { + unreachable("Not implemented"); + } + get propertiesToUpdate() { + return []; + } + get _isDraggable() { + return this.#isDraggable; + } + set _isDraggable(value) { + this.#isDraggable = value; + this.div?.classList.toggle("draggable", value); + } + get uid() { + return this.annotationElementId || this.id; + } + get isEnterHandled() { + return true; + } + center() { + const [pageWidth, pageHeight] = this.pageDimensions; + switch (this.parentRotation) { + case 90: + this.x -= this.height * pageHeight / (pageWidth * 2); + this.y += this.width * pageWidth / (pageHeight * 2); + break; + case 180: + this.x += this.width / 2; + this.y += this.height / 2; + break; + case 270: + this.x += this.height * pageHeight / (pageWidth * 2); + this.y -= this.width * pageWidth / (pageHeight * 2); + break; + default: + this.x -= this.width / 2; + this.y -= this.height / 2; + break; + } + this.fixAndSetPosition(); + } + addCommands(params) { + this._uiManager.addCommands(params); + } + get currentLayer() { + return this._uiManager.currentLayer; + } + setInBackground() { + this.div.style.zIndex = 0; + } + setInForeground() { + this.div.style.zIndex = this.#zIndex; + } + setParent(parent) { + if (parent !== null) { + this.pageIndex = parent.pageIndex; + this.pageDimensions = parent.pageDimensions; + } else { + this.#stopResizing(); + this.#fakeAnnotation?.remove(); + this.#fakeAnnotation = null; + } + this.parent = parent; + } + focusin(event) { + if (!this._focusEventsAllowed) { + return; + } + if (!this.#hasBeenClicked) { + this.parent.setSelected(this); + } else { + this.#hasBeenClicked = false; + } + } + focusout(event) { + if (!this._focusEventsAllowed) { + return; + } + if (!this.isAttachedToDOM) { + return; + } + const target = event.relatedTarget; + if (target?.closest(`#${this.id}`)) { + return; + } + event.preventDefault(); + if (!this.parent?.isMultipleSelection) { + this.commitOrRemove(); + } + } + commitOrRemove() { + if (this.isEmpty()) { + this.remove(); + } else { + this.commit(); + } + } + commit() { + if (!this.isInEditMode()) { + return; + } + this.addToAnnotationStorage(); + } + addToAnnotationStorage() { + this._uiManager.addToAnnotationStorage(this); + } + setAt(x, y, tx, ty) { + const [width, height] = this.parentDimensions; + [tx, ty] = this.screenToPageTranslation(tx, ty); + this.x = (x + tx) / width; + this.y = (y + ty) / height; + this.fixAndSetPosition(); + } + _moveAfterPaste(baseX, baseY) { + const [parentWidth, parentHeight] = this.parentDimensions; + this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); + this._onTranslated(); + } + #translate([width, height], x, y) { + [x, y] = this.screenToPageTranslation(x, y); + this.x += x / width; + this.y += y / height; + this._onTranslating(this.x, this.y); + this.fixAndSetPosition(); + } + translate(x, y) { + this.#translate(this.parentDimensions, x, y); + } + translateInPage(x, y) { + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + this.#translate(this.pageDimensions, x, y); + this.div.scrollIntoView({ + block: "nearest" + }); + } + translationDone() { + this._onTranslated(this.x, this.y); + } + drag(tx, ty) { + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + const { + div, + parentDimensions: [parentWidth, parentHeight] + } = this; + this.x += tx / parentWidth; + this.y += ty / parentHeight; + if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) { + const { + x, + y + } = this.div.getBoundingClientRect(); + if (this.parent.findNewParent(this, x, y)) { + this.x -= Math.floor(this.x); + this.y -= Math.floor(this.y); + } + } + let { + x, + y + } = this; + const [bx, by] = this.getBaseTranslation(); + x += bx; + y += by; + const { + style + } = div; + style.left = `${(100 * x).toFixed(2)}%`; + style.top = `${(100 * y).toFixed(2)}%`; + this._onTranslating(x, y); + div.scrollIntoView({ + block: "nearest" + }); + } + _onTranslating(x, y) {} + _onTranslated(x, y) {} + get _hasBeenMoved() { + return !!this.#initialRect && (this.#initialRect[0] !== this.x || this.#initialRect[1] !== this.y); + } + get _hasBeenResized() { + return !!this.#initialRect && (this.#initialRect[2] !== this.width || this.#initialRect[3] !== this.height); + } + getBaseTranslation() { + const [parentWidth, parentHeight] = this.parentDimensions; + const { + _borderLineWidth + } = AnnotationEditor; + const x = _borderLineWidth / parentWidth; + const y = _borderLineWidth / parentHeight; + switch (this.rotation) { + case 90: + return [-x, y]; + case 180: + return [x, y]; + case 270: + return [x, -y]; + default: + return [-x, -y]; + } + } + get _mustFixPosition() { + return true; + } + fixAndSetPosition(rotation = this.rotation) { + const { + div: { + style + }, + pageDimensions: [pageWidth, pageHeight] + } = this; + let { + x, + y, + width, + height + } = this; + width *= pageWidth; + height *= pageHeight; + x *= pageWidth; + y *= pageHeight; + if (this._mustFixPosition) { + switch (rotation) { + case 0: + x = MathClamp(x, 0, pageWidth - width); + y = MathClamp(y, 0, pageHeight - height); + break; + case 90: + x = MathClamp(x, 0, pageWidth - height); + y = MathClamp(y, width, pageHeight); + break; + case 180: + x = MathClamp(x, width, pageWidth); + y = MathClamp(y, height, pageHeight); + break; + case 270: + x = MathClamp(x, height, pageWidth); + y = MathClamp(y, 0, pageHeight - width); + break; + } + } + this.x = x /= pageWidth; + this.y = y /= pageHeight; + const [bx, by] = this.getBaseTranslation(); + x += bx; + y += by; + style.left = `${(100 * x).toFixed(2)}%`; + style.top = `${(100 * y).toFixed(2)}%`; + this.moveInDOM(); + } + static #rotatePoint(x, y, angle) { + switch (angle) { + case 90: + return [y, -x]; + case 180: + return [-x, -y]; + case 270: + return [-y, x]; + default: + return [x, y]; + } + } + screenToPageTranslation(x, y) { + return AnnotationEditor.#rotatePoint(x, y, this.parentRotation); + } + pageTranslationToScreen(x, y) { + return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation); + } + #getRotationMatrix(rotation) { + switch (rotation) { + case 90: + { + const [pageWidth, pageHeight] = this.pageDimensions; + return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0]; + } + case 180: + return [-1, 0, 0, -1]; + case 270: + { + const [pageWidth, pageHeight] = this.pageDimensions; + return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0]; + } + default: + return [1, 0, 0, 1]; + } + } + get parentScale() { + return this._uiManager.viewParameters.realScale; + } + get parentRotation() { + return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360; + } + get parentDimensions() { + const { + parentScale, + pageDimensions: [pageWidth, pageHeight] + } = this; + return [pageWidth * parentScale, pageHeight * parentScale]; + } + setDims() { + const { + div: { + style + }, + width, + height + } = this; + style.width = `${(100 * width).toFixed(2)}%`; + style.height = `${(100 * height).toFixed(2)}%`; + } + getInitialTranslation() { + return [0, 0]; + } + #createResizers() { + if (this.#resizersDiv) { + return; + } + this.#resizersDiv = document.createElement("div"); + this.#resizersDiv.classList.add("resizers"); + const classes = this._willKeepAspectRatio ? ["topLeft", "topRight", "bottomRight", "bottomLeft"] : ["topLeft", "topMiddle", "topRight", "middleRight", "bottomRight", "bottomMiddle", "bottomLeft", "middleLeft"]; + const signal = this._uiManager._signal; + for (const name of classes) { + const div = document.createElement("div"); + this.#resizersDiv.append(div); + div.classList.add("resizer", name); + div.setAttribute("data-resizer-name", name); + div.addEventListener("pointerdown", this.#resizerPointerdown.bind(this, name), { + signal + }); + div.addEventListener("contextmenu", noContextMenu, { + signal + }); + div.tabIndex = -1; + } + this.div.prepend(this.#resizersDiv); + } + #resizerPointerdown(name, event) { + event.preventDefault(); + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + this.#altText?.toggle(false); + const savedDraggable = this._isDraggable; + this._isDraggable = false; + this.#lastPointerCoords = [event.screenX, event.screenY]; + const ac = new AbortController(); + const signal = this._uiManager.combinedSignal(ac); + this.parent.togglePointerEvents(false); + window.addEventListener("pointermove", this.#resizerPointermove.bind(this, name), { + passive: true, + capture: true, + signal + }); + window.addEventListener("touchmove", stopEvent, { + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + const savedParentCursor = this.parent.div.style.cursor; + const savedCursor = this.div.style.cursor; + this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor; + const pointerUpCallback = () => { + ac.abort(); + this.parent.togglePointerEvents(true); + this.#altText?.toggle(true); + this._isDraggable = savedDraggable; + this.parent.div.style.cursor = savedParentCursor; + this.div.style.cursor = savedCursor; + this.#addResizeToUndoStack(); + }; + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("blur", pointerUpCallback, { + signal + }); + } + #resize(x, y, width, height) { + this.width = width; + this.height = height; + this.x = x; + this.y = y; + this.setDims(); + this.fixAndSetPosition(); + this._onResized(); + } + _onResized() {} + #addResizeToUndoStack() { + if (!this.#savedDimensions) { + return; + } + const { + savedX, + savedY, + savedWidth, + savedHeight + } = this.#savedDimensions; + this.#savedDimensions = null; + const newX = this.x; + const newY = this.y; + const newWidth = this.width; + const newHeight = this.height; + if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) { + return; + } + this.addCommands({ + cmd: this.#resize.bind(this, newX, newY, newWidth, newHeight), + undo: this.#resize.bind(this, savedX, savedY, savedWidth, savedHeight), + mustExec: true + }); + } + static _round(x) { + return Math.round(x * 10000) / 10000; + } + #resizerPointermove(name, event) { + const [parentWidth, parentHeight] = this.parentDimensions; + const savedX = this.x; + const savedY = this.y; + const savedWidth = this.width; + const savedHeight = this.height; + const minWidth = AnnotationEditor.MIN_SIZE / parentWidth; + const minHeight = AnnotationEditor.MIN_SIZE / parentHeight; + const rotationMatrix = this.#getRotationMatrix(this.rotation); + const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y]; + const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation); + const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y]; + let getPoint; + let getOpposite; + let isDiagonal = false; + let isHorizontal = false; + switch (name) { + case "topLeft": + isDiagonal = true; + getPoint = (w, h) => [0, 0]; + getOpposite = (w, h) => [w, h]; + break; + case "topMiddle": + getPoint = (w, h) => [w / 2, 0]; + getOpposite = (w, h) => [w / 2, h]; + break; + case "topRight": + isDiagonal = true; + getPoint = (w, h) => [w, 0]; + getOpposite = (w, h) => [0, h]; + break; + case "middleRight": + isHorizontal = true; + getPoint = (w, h) => [w, h / 2]; + getOpposite = (w, h) => [0, h / 2]; + break; + case "bottomRight": + isDiagonal = true; + getPoint = (w, h) => [w, h]; + getOpposite = (w, h) => [0, 0]; + break; + case "bottomMiddle": + getPoint = (w, h) => [w / 2, h]; + getOpposite = (w, h) => [w / 2, 0]; + break; + case "bottomLeft": + isDiagonal = true; + getPoint = (w, h) => [0, h]; + getOpposite = (w, h) => [w, 0]; + break; + case "middleLeft": + isHorizontal = true; + getPoint = (w, h) => [0, h / 2]; + getOpposite = (w, h) => [w, h / 2]; + break; + } + const point = getPoint(savedWidth, savedHeight); + const oppositePoint = getOpposite(savedWidth, savedHeight); + let transfOppositePoint = transf(...oppositePoint); + const oppositeX = AnnotationEditor._round(savedX + transfOppositePoint[0]); + const oppositeY = AnnotationEditor._round(savedY + transfOppositePoint[1]); + let ratioX = 1; + let ratioY = 1; + let deltaX, deltaY; + if (!event.fromKeyboard) { + const { + screenX, + screenY + } = event; + const [lastScreenX, lastScreenY] = this.#lastPointerCoords; + [deltaX, deltaY] = this.screenToPageTranslation(screenX - lastScreenX, screenY - lastScreenY); + this.#lastPointerCoords[0] = screenX; + this.#lastPointerCoords[1] = screenY; + } else { + ({ + deltaX, + deltaY + } = event); + } + [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight); + if (isDiagonal) { + const oldDiag = Math.hypot(savedWidth, savedHeight); + ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight); + } else if (isHorizontal) { + ratioX = MathClamp(Math.abs(oppositePoint[0] - point[0] - deltaX), minWidth, 1) / savedWidth; + } else { + ratioY = MathClamp(Math.abs(oppositePoint[1] - point[1] - deltaY), minHeight, 1) / savedHeight; + } + const newWidth = AnnotationEditor._round(savedWidth * ratioX); + const newHeight = AnnotationEditor._round(savedHeight * ratioY); + transfOppositePoint = transf(...getOpposite(newWidth, newHeight)); + const newX = oppositeX - transfOppositePoint[0]; + const newY = oppositeY - transfOppositePoint[1]; + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + this.width = newWidth; + this.height = newHeight; + this.x = newX; + this.y = newY; + this.setDims(); + this.fixAndSetPosition(); + this._onResizing(); + } + _onResizing() {} + altTextFinish() { + this.#altText?.finish(); + } + get toolbarButtons() { + return null; + } + async addEditToolbar() { + if (this._editToolbar || this.#isInEditMode) { + return this._editToolbar; + } + this._editToolbar = new EditorToolbar(this); + this.div.append(this._editToolbar.render()); + const { + toolbarButtons + } = this; + if (toolbarButtons) { + for (const [name, tool] of toolbarButtons) { + await this._editToolbar.addButton(name, tool); + } + } + if (!this.hasComment) { + this._editToolbar.addButton("comment", this.addCommentButton()); + } + this._editToolbar.addButton("delete"); + return this._editToolbar; + } + addCommentButtonInToolbar() { + this._editToolbar?.addButtonBefore("comment", this.addCommentButton(), ".deleteButton"); + } + removeCommentButtonFromToolbar() { + this._editToolbar?.removeButton("comment"); + } + removeEditToolbar() { + this._editToolbar?.remove(); + this._editToolbar = null; + this.#altText?.destroy(); + } + addContainer(container) { + const editToolbarDiv = this._editToolbar?.div; + if (editToolbarDiv) { + editToolbarDiv.before(container); + } else { + this.div.append(container); + } + } + getClientDimensions() { + return this.div.getBoundingClientRect(); + } + createAltText() { + if (!this.#altText) { + AltText.initialize(AnnotationEditor._l10n); + this.#altText = new AltText(this); + if (this.#accessibilityData) { + this.#altText.data = this.#accessibilityData; + this.#accessibilityData = null; + } + } + return this.#altText; + } + get altTextData() { + return this.#altText?.data; + } + set altTextData(data) { + if (!this.#altText) { + return; + } + this.#altText.data = data; + } + get guessedAltText() { + return this.#altText?.guessedText; + } + async setGuessedAltText(text) { + await this.#altText?.setGuessedText(text); + } + serializeAltText(isForCopying) { + return this.#altText?.serialize(isForCopying); + } + hasAltText() { + return !!this.#altText && !this.#altText.isEmpty(); + } + hasAltTextData() { + return this.#altText?.hasData() ?? false; + } + focusCommentButton() { + this.#comment?.focusButton(); + } + addCommentButton() { + return this.canAddComment ? this.#comment ||= new Comment(this) : null; + } + addStandaloneCommentButton() { + if (!this._uiManager.hasCommentManager()) { + return; + } + if (this.#commentStandaloneButton) { + if (this._uiManager.isEditingMode()) { + this.#commentStandaloneButton.classList.remove("hidden"); + } + return; + } + if (!this.hasComment) { + return; + } + this.#commentStandaloneButton = this.#comment.renderForStandalone(); + this.div.append(this.#commentStandaloneButton); + } + removeStandaloneCommentButton() { + this.#comment.removeStandaloneCommentButton(); + this.#commentStandaloneButton = null; + } + hideStandaloneCommentButton() { + this.#commentStandaloneButton?.classList.add("hidden"); + } + get comment() { + const { + data: { + richText, + text, + date, + deleted + } + } = this.#comment; + return { + text, + richText, + date, + deleted, + color: this.getNonHCMColor(), + opacity: this.opacity ?? 1 + }; + } + set comment(text) { + this.#comment ||= new Comment(this); + this.#comment.data = text; + if (this.hasComment) { + this.removeCommentButtonFromToolbar(); + this.addStandaloneCommentButton(); + this._uiManager.updateComment(this); + } else { + this.addCommentButtonInToolbar(); + this.removeStandaloneCommentButton(); + this._uiManager.removeComment(this); + } + } + setCommentData({ + comment, + popupRef, + richText + }) { + if (!popupRef) { + return; + } + this.#comment ||= new Comment(this); + this.#comment.setInitialText(comment, richText); + if (!this.annotationElementId) { + return; + } + const storedData = this._uiManager.getAndRemoveDataFromAnnotationStorage(this.annotationElementId); + if (storedData) { + this.updateFromAnnotationLayer(storedData); + } + } + get hasEditedComment() { + return this.#comment?.hasBeenEdited(); + } + get hasDeletedComment() { + return this.#comment?.isDeleted(); + } + get hasComment() { + return !!this.#comment && !this.#comment.isEmpty() && !this.#comment.isDeleted(); + } + async editComment(options) { + this.#comment ||= new Comment(this); + this.#comment.edit(options); + } + toggleComment(isSelected, visibility = undefined) { + if (this.hasComment) { + this._uiManager.toggleComment(this, isSelected, visibility); + } + } + setSelectedCommentButton(selected) { + this.#comment.setSelectedButton(selected); + } + addComment(serialized) { + if (this.hasEditedComment) { + const DEFAULT_POPUP_WIDTH = 180; + const DEFAULT_POPUP_HEIGHT = 100; + const [,,, trY] = serialized.rect; + const [pageWidth] = this.pageDimensions; + const [pageX] = this.pageTranslation; + const blX = pageX + pageWidth + 1; + const blY = trY - DEFAULT_POPUP_HEIGHT; + const trX = blX + DEFAULT_POPUP_WIDTH; + serialized.popup = { + contents: this.comment.text, + deleted: this.comment.deleted, + rect: [blX, blY, trX, trY] + }; + } + } + updateFromAnnotationLayer({ + popup: { + contents, + deleted + } + }) { + this.#comment.data = deleted ? null : contents; + } + get parentBoundingClientRect() { + return this.parent.boundingClientRect; + } + render() { + const div = this.div = document.createElement("div"); + div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360); + div.className = this.name; + div.setAttribute("id", this.id); + div.tabIndex = this.#disabled ? -1 : 0; + div.setAttribute("role", "application"); + if (this.defaultL10nId) { + div.setAttribute("data-l10n-id", this.defaultL10nId); + } + if (!this._isVisible) { + div.classList.add("hidden"); + } + this.setInForeground(); + this.#addFocusListeners(); + const [parentWidth, parentHeight] = this.parentDimensions; + if (this.parentRotation % 180 !== 0) { + div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`; + div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`; + } + const [tx, ty] = this.getInitialTranslation(); + this.translate(tx, ty); + bindEvents(this, div, ["keydown", "pointerdown", "dblclick"]); + if (this.isResizable && this._uiManager._supportsPinchToZoom) { + this.#touchManager ||= new TouchManager({ + container: div, + isPinchingDisabled: () => !this.isSelected, + onPinchStart: this.#touchPinchStartCallback.bind(this), + onPinching: this.#touchPinchCallback.bind(this), + onPinchEnd: this.#touchPinchEndCallback.bind(this), + signal: this._uiManager._signal + }); + } + this.addStandaloneCommentButton(); + this._uiManager._editorUndoBar?.hide(); + return div; + } + #touchPinchStartCallback() { + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + this.#altText?.toggle(false); + this.parent.togglePointerEvents(false); + } + #touchPinchCallback(_origin, prevDistance, distance) { + const slowDownFactor = 0.7; + let factor = slowDownFactor * (distance / prevDistance) + 1 - slowDownFactor; + if (factor === 1) { + return; + } + const rotationMatrix = this.#getRotationMatrix(this.rotation); + const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y]; + const [parentWidth, parentHeight] = this.parentDimensions; + const savedX = this.x; + const savedY = this.y; + const savedWidth = this.width; + const savedHeight = this.height; + const minWidth = AnnotationEditor.MIN_SIZE / parentWidth; + const minHeight = AnnotationEditor.MIN_SIZE / parentHeight; + factor = Math.max(Math.min(factor, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight); + const newWidth = AnnotationEditor._round(savedWidth * factor); + const newHeight = AnnotationEditor._round(savedHeight * factor); + if (newWidth === savedWidth && newHeight === savedHeight) { + return; + } + this.#initialRect ||= [savedX, savedY, savedWidth, savedHeight]; + const transfCenterPoint = transf(savedWidth / 2, savedHeight / 2); + const centerX = AnnotationEditor._round(savedX + transfCenterPoint[0]); + const centerY = AnnotationEditor._round(savedY + transfCenterPoint[1]); + const newTransfCenterPoint = transf(newWidth / 2, newHeight / 2); + this.x = centerX - newTransfCenterPoint[0]; + this.y = centerY - newTransfCenterPoint[1]; + this.width = newWidth; + this.height = newHeight; + this.setDims(); + this.fixAndSetPosition(); + this._onResizing(); + } + #touchPinchEndCallback() { + this.#altText?.toggle(true); + this.parent.togglePointerEvents(true); + this.#addResizeToUndoStack(); + } + pointerdown(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + event.preventDefault(); + return; + } + this.#hasBeenClicked = true; + if (this._isDraggable) { + this.#setUpDragSession(event); + return; + } + this.#selectOnPointerEvent(event); + } + #selectOnPointerEvent(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) { + this.parent.toggleSelected(this); + } else { + this.parent.setSelected(this); + } + } + #setUpDragSession(event) { + const { + isSelected + } = this; + this._uiManager.setUpDragSession(); + let hasDraggingStarted = false; + const ac = new AbortController(); + const signal = this._uiManager.combinedSignal(ac); + const opts = { + capture: true, + passive: false, + signal + }; + const cancelDrag = e => { + ac.abort(); + this.#dragPointerId = null; + this.#hasBeenClicked = false; + if (!this._uiManager.endDragSession()) { + this.#selectOnPointerEvent(e); + } + if (hasDraggingStarted) { + this._onStopDragging(); + } + }; + if (isSelected) { + this.#prevDragX = event.clientX; + this.#prevDragY = event.clientY; + this.#dragPointerId = event.pointerId; + this.#dragPointerType = event.pointerType; + window.addEventListener("pointermove", e => { + if (!hasDraggingStarted) { + hasDraggingStarted = true; + this._uiManager.toggleComment(this, true, false); + this._onStartDragging(); + } + const { + clientX: x, + clientY: y, + pointerId + } = e; + if (pointerId !== this.#dragPointerId) { + stopEvent(e); + return; + } + const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY); + this.#prevDragX = x; + this.#prevDragY = y; + this._uiManager.dragSelectedEditors(tx, ty); + }, opts); + window.addEventListener("touchmove", stopEvent, opts); + window.addEventListener("pointerdown", e => { + if (e.pointerType === this.#dragPointerType) { + if (this.#touchManager || e.isPrimary) { + cancelDrag(e); + } + } + stopEvent(e); + }, opts); + } + const pointerUpCallback = e => { + if (!this.#dragPointerId || this.#dragPointerId === e.pointerId) { + cancelDrag(e); + return; + } + stopEvent(e); + }; + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("blur", pointerUpCallback, { + signal + }); + } + _onStartDragging() {} + _onStopDragging() {} + moveInDOM() { + if (this.#moveInDOMTimeout) { + clearTimeout(this.#moveInDOMTimeout); + } + this.#moveInDOMTimeout = setTimeout(() => { + this.#moveInDOMTimeout = null; + this.parent?.moveEditorInDOM(this); + }, 0); + } + _setParentAndPosition(parent, x, y) { + parent.changeParent(this); + this.x = x; + this.y = y; + this.fixAndSetPosition(); + this._onTranslated(); + } + getRect(tx, ty, rotation = this.rotation) { + const scale = this.parentScale; + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + const shiftX = tx / scale; + const shiftY = ty / scale; + const x = this.x * pageWidth; + const y = this.y * pageHeight; + const width = this.width * pageWidth; + const height = this.height * pageHeight; + switch (rotation) { + case 0: + return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY]; + case 90: + return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY]; + case 180: + return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY]; + case 270: + return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY]; + default: + throw new Error("Invalid rotation"); + } + } + getRectInCurrentCoords(rect, pageHeight) { + const [x1, y1, x2, y2] = rect; + const width = x2 - x1; + const height = y2 - y1; + switch (this.rotation) { + case 0: + return [x1, pageHeight - y2, width, height]; + case 90: + return [x1, pageHeight - y1, height, width]; + case 180: + return [x2, pageHeight - y1, width, height]; + case 270: + return [x2, pageHeight - y2, height, width]; + default: + throw new Error("Invalid rotation"); + } + } + getPDFRect() { + return this.getRect(0, 0); + } + getNonHCMColor() { + return this.color && AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color)); + } + onUpdatedColor() { + this.#comment?.onUpdatedColor(); + } + getData() { + const { + comment: { + text: str, + color, + date, + opacity, + deleted, + richText + }, + uid: id, + pageIndex, + creationDate, + modificationDate + } = this; + return { + id, + pageIndex, + rect: this.getPDFRect(), + richText, + contentsObj: { + str + }, + creationDate, + modificationDate: date || modificationDate, + popupRef: !deleted, + color, + opacity + }; + } + onceAdded(focus) {} + isEmpty() { + return false; + } + enableEditMode() { + if (this.isInEditMode()) { + return false; + } + this.parent.setEditingState(false); + this.#isInEditMode = true; + return true; + } + disableEditMode() { + if (!this.isInEditMode()) { + return false; + } + this.parent.setEditingState(true); + this.#isInEditMode = false; + return true; + } + isInEditMode() { + return this.#isInEditMode; + } + shouldGetKeyboardEvents() { + return this.#isResizerEnabledForKeyboard; + } + needsToBeRebuilt() { + return this.div && !this.isAttachedToDOM; + } + get isOnScreen() { + const { + top, + left, + bottom, + right + } = this.getClientDimensions(); + const { + innerHeight, + innerWidth + } = window; + return left < innerWidth && right > 0 && top < innerHeight && bottom > 0; + } + #addFocusListeners() { + if (this.#focusAC || !this.div) { + return; + } + this.#focusAC = new AbortController(); + const signal = this._uiManager.combinedSignal(this.#focusAC); + this.div.addEventListener("focusin", this.focusin.bind(this), { + signal + }); + this.div.addEventListener("focusout", this.focusout.bind(this), { + signal + }); + } + rebuild() { + this.#addFocusListeners(); + } + rotate(_angle) {} + resize() {} + serializeDeleted() { + return { + id: this.annotationElementId, + deleted: true, + pageIndex: this.pageIndex, + popupRef: this._initialData?.popupRef || "" + }; + } + serialize(isForCopying = false, context = null) { + return { + annotationType: this.mode, + pageIndex: this.pageIndex, + rect: this.getPDFRect(), + rotation: this.rotation, + structTreeParentId: this._structTreeParentId, + popupRef: this._initialData?.popupRef || "" + }; + } + static async deserialize(data, parent, uiManager) { + const editor = new this.prototype.constructor({ + parent, + id: parent.getNextId(), + uiManager, + annotationElementId: data.annotationElementId, + creationDate: data.creationDate, + modificationDate: data.modificationDate + }); + editor.rotation = data.rotation; + editor.#accessibilityData = data.accessibilityData; + editor._isCopy = data.isCopy || false; + const [pageWidth, pageHeight] = editor.pageDimensions; + const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight); + editor.x = x / pageWidth; + editor.y = y / pageHeight; + editor.width = width / pageWidth; + editor.height = height / pageHeight; + return editor; + } + get hasBeenModified() { + return !!this.annotationElementId && (this.deleted || this.serialize() !== null); + } + remove() { + this.#focusAC?.abort(); + this.#focusAC = null; + if (!this.isEmpty()) { + this.commit(); + } + if (this.parent) { + this.parent.remove(this); + } else { + this._uiManager.removeEditor(this); + } + this.hideCommentPopup(); + if (this.#moveInDOMTimeout) { + clearTimeout(this.#moveInDOMTimeout); + this.#moveInDOMTimeout = null; + } + this.#stopResizing(); + this.removeEditToolbar(); + if (this.#telemetryTimeouts) { + for (const timeout of this.#telemetryTimeouts.values()) { + clearTimeout(timeout); + } + this.#telemetryTimeouts = null; + } + this.parent = null; + this.#touchManager?.destroy(); + this.#touchManager = null; + this.#fakeAnnotation?.remove(); + this.#fakeAnnotation = null; + } + get isResizable() { + return false; + } + makeResizable() { + if (this.isResizable) { + this.#createResizers(); + this.#resizersDiv.classList.remove("hidden"); + } + } + get toolbarPosition() { + return null; + } + get commentButtonPosition() { + return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0]; + } + get commentButtonPositionInPage() { + const { + commentButtonPosition: [posX, posY] + } = this; + const [blX, blY, trX, trY] = this.getPDFRect(); + return [AnnotationEditor._round(blX + (trX - blX) * posX), AnnotationEditor._round(blY + (trY - blY) * (1 - posY))]; + } + get commentButtonColor() { + return this._uiManager.makeCommentColor(this.getNonHCMColor(), this.opacity); + } + get commentPopupPosition() { + return this.#comment.commentPopupPositionInLayer; + } + set commentPopupPosition(pos) { + this.#comment.commentPopupPositionInLayer = pos; + } + hasDefaultPopupPosition() { + return this.#comment.hasDefaultPopupPosition(); + } + get commentButtonWidth() { + return this.#comment.commentButtonWidth; + } + get elementBeforePopup() { + return this.div; + } + setCommentButtonStates(options) { + this.#comment?.setCommentButtonStates(options); + } + keydown(event) { + if (!this.isResizable || event.target !== this.div || event.key !== "Enter") { + return; + } + this._uiManager.setSelected(this); + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + const children = this.#resizersDiv.children; + if (!this.#allResizerDivs) { + this.#allResizerDivs = Array.from(children); + const boundResizerKeydown = this.#resizerKeydown.bind(this); + const boundResizerBlur = this.#resizerBlur.bind(this); + const signal = this._uiManager._signal; + for (const div of this.#allResizerDivs) { + const name = div.getAttribute("data-resizer-name"); + div.setAttribute("role", "spinbutton"); + div.addEventListener("keydown", boundResizerKeydown, { + signal + }); + div.addEventListener("blur", boundResizerBlur, { + signal + }); + div.addEventListener("focus", this.#resizerFocus.bind(this, name), { + signal + }); + div.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]); + } + } + const first = this.#allResizerDivs[0]; + let firstPosition = 0; + for (const div of children) { + if (div === first) { + break; + } + firstPosition++; + } + const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4); + if (nextFirstPosition !== firstPosition) { + if (nextFirstPosition < firstPosition) { + for (let i = 0; i < firstPosition - nextFirstPosition; i++) { + this.#resizersDiv.append(this.#resizersDiv.firstElementChild); + } + } else if (nextFirstPosition > firstPosition) { + for (let i = 0; i < nextFirstPosition - firstPosition; i++) { + this.#resizersDiv.firstElementChild.before(this.#resizersDiv.lastElementChild); + } + } + let i = 0; + for (const child of children) { + const div = this.#allResizerDivs[i++]; + const name = div.getAttribute("data-resizer-name"); + child.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]); + } + } + this.#setResizerTabIndex(0); + this.#isResizerEnabledForKeyboard = true; + this.#resizersDiv.firstElementChild.focus({ + focusVisible: true + }); + event.preventDefault(); + event.stopImmediatePropagation(); + } + #resizerKeydown(event) { + AnnotationEditor._resizerKeyboardManager.exec(this, event); + } + #resizerBlur(event) { + if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) { + this.#stopResizing(); + } + } + #resizerFocus(name) { + this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : ""; + } + #setResizerTabIndex(value) { + if (!this.#allResizerDivs) { + return; + } + for (const div of this.#allResizerDivs) { + div.tabIndex = value; + } + } + _resizeWithKeyboard(x, y) { + if (!this.#isResizerEnabledForKeyboard) { + return; + } + this.#resizerPointermove(this.#focusedResizerName, { + deltaX: x, + deltaY: y, + fromKeyboard: true + }); + } + #stopResizing() { + this.#isResizerEnabledForKeyboard = false; + this.#setResizerTabIndex(-1); + this.#addResizeToUndoStack(); + } + _stopResizingWithKeyboard() { + this.#stopResizing(); + this.div.focus(); + } + select() { + if (this.isSelected && this._editToolbar) { + this._editToolbar.show(); + return; + } + this.isSelected = true; + this.makeResizable(); + this.div?.classList.add("selectedEditor"); + if (!this._editToolbar) { + this.addEditToolbar().then(() => { + if (this.div?.classList.contains("selectedEditor")) { + this._editToolbar?.show(); + } + }); + return; + } + this._editToolbar?.show(); + this.#altText?.toggleAltTextBadge(false); + } + focus() { + if (this.div && !this.div.contains(document.activeElement)) { + setTimeout(() => this.div?.focus({ + preventScroll: true + }), 0); + } + } + unselect() { + if (!this.isSelected) { + return; + } + this.isSelected = false; + this.#resizersDiv?.classList.add("hidden"); + this.div?.classList.remove("selectedEditor"); + if (this.div?.contains(document.activeElement)) { + this._uiManager.currentLayer.div.focus({ + preventScroll: true + }); + } + this._editToolbar?.hide(); + this.#altText?.toggleAltTextBadge(true); + this.hideCommentPopup(); + } + hideCommentPopup() { + if (this.hasComment) { + this._uiManager.toggleComment(null); + } + } + updateParams(type, value) {} + disableEditing() {} + enableEditing() {} + get canChangeContent() { + return false; + } + enterInEditMode() { + if (!this.canChangeContent) { + return; + } + this.enableEditMode(); + this.div.focus(); + } + dblclick(event) { + if (event.target.nodeName === "BUTTON") { + return; + } + this.enterInEditMode(); + this.parent.updateToolbar({ + mode: this.constructor._editorType, + editId: this.uid + }); + } + getElementForAltText() { + return this.div; + } + get contentDiv() { + return this.div; + } + get isEditing() { + return this.#isEditing; + } + set isEditing(value) { + this.#isEditing = value; + if (!this.parent) { + return; + } + if (value) { + this.parent.setSelected(this); + this.parent.setActiveEditor(this); + } else { + this.parent.setActiveEditor(null); + } + } + static get MIN_SIZE() { + return 16; + } + static canCreateNewEmptyEditor() { + return true; + } + get telemetryInitialData() { + return { + action: "added" + }; + } + get telemetryFinalData() { + return null; + } + _reportTelemetry(data, mustWait = false) { + if (mustWait) { + this.#telemetryTimeouts ||= new Map(); + const { + action + } = data; + let timeout = this.#telemetryTimeouts.get(action); + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(() => { + this._reportTelemetry(data); + this.#telemetryTimeouts.delete(action); + if (this.#telemetryTimeouts.size === 0) { + this.#telemetryTimeouts = null; + } + }, AnnotationEditor._telemetryTimeout); + this.#telemetryTimeouts.set(action, timeout); + return; + } + data.type ||= this.editorType; + this._uiManager._eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data + } + }); + } + show(visible = this._isVisible) { + this.div.classList.toggle("hidden", !visible); + this._isVisible = visible; + } + enable() { + if (this.div) { + this.div.tabIndex = 0; + } + this.#disabled = false; + } + disable() { + if (this.div) { + this.div.tabIndex = -1; + } + this.#disabled = true; + } + updateFakeAnnotationElement(annotationLayer) { + if (!this.#fakeAnnotation && !this.deleted) { + this.#fakeAnnotation = annotationLayer.addFakeAnnotation(this); + return; + } + if (this.deleted) { + this.#fakeAnnotation.remove(); + this.#fakeAnnotation = null; + return; + } + if (this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized) { + this.#fakeAnnotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + } + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + let content = annotation.container.querySelector(".annotationContent"); + if (!content) { + content = document.createElement("div"); + content.classList.add("annotationContent", this.editorType); + annotation.container.prepend(content); + } else if (content.nodeName === "CANVAS") { + const canvas = content; + content = document.createElement("div"); + content.classList.add("annotationContent", this.editorType); + canvas.before(content); + } + return content; + } + resetAnnotationElement(annotation) { + const { + firstElementChild + } = annotation.container; + if (firstElementChild?.nodeName === "DIV" && firstElementChild.classList.contains("annotationContent")) { + firstElementChild.remove(); + } + } +} +class FakeEditor extends AnnotationEditor { + constructor(params) { + super(params); + this.annotationElementId = params.annotationElementId; + this.deleted = true; + } + serialize() { + return this.serializeDeleted(); + } +} + +;// ./src/shared/murmurhash3.js +const SEED = 0xc3d2e1f0; +const MASK_HIGH = 0xffff0000; +const MASK_LOW = 0xffff; +class MurmurHash3_64 { + constructor(seed) { + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + update(input) { + let data, length; + if (typeof input === "string") { + data = new Uint8Array(input.length * 2); + length = 0; + for (let i = 0, ii = input.length; i < ii; i++) { + const code = input.charCodeAt(i); + if (code <= 0xff) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if (ArrayBuffer.isView(input)) { + data = input.slice(); + length = data.byteLength; + } else { + throw new Error("Invalid data format, must be a string or TypedArray."); + } + const blockCounts = length >> 2; + const tailLength = length - blockCounts * 4; + const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); + let k1 = 0, + k2 = 0; + let h1 = this.h1, + h2 = this.h2; + const C1 = 0xcc9e2d51, + C2 = 0x1b873593; + const C1_LOW = C1 & MASK_LOW, + C2_LOW = C2 & MASK_LOW; + for (let i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + k1 = 0; + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + this.h1 = h1; + this.h2 = h2; + } + hexdigest() { + let h1 = this.h1, + h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; + h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; + h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0"); + } +} + +;// ./src/display/annotation_storage.js + + + +const SerializableEmpty = Object.freeze({ + map: null, + hash: "", + transfer: undefined +}); +class AnnotationStorage { + #modified = false; + #modifiedIds = null; + #editorsMap = null; + #storage = new Map(); + constructor() { + this.onSetModified = null; + this.onResetModified = null; + this.onAnnotationEditor = null; + } + getValue(key, defaultValue) { + const value = this.#storage.get(key); + if (value === undefined) { + return defaultValue; + } + return Object.assign(defaultValue, value); + } + getRawValue(key) { + return this.#storage.get(key); + } + remove(key) { + const storedValue = this.#storage.get(key); + if (storedValue === undefined) { + return; + } + if (storedValue instanceof AnnotationEditor) { + this.#editorsMap.delete(storedValue.annotationElementId); + } + this.#storage.delete(key); + if (this.#storage.size === 0) { + this.resetModified(); + } + if (typeof this.onAnnotationEditor === "function") { + for (const value of this.#storage.values()) { + if (value instanceof AnnotationEditor) { + return; + } + } + this.onAnnotationEditor(null); + } + } + setValue(key, value) { + const obj = this.#storage.get(key); + let modified = false; + if (obj !== undefined) { + for (const [entry, val] of Object.entries(value)) { + if (obj[entry] !== val) { + modified = true; + obj[entry] = val; + } + } + } else { + modified = true; + this.#storage.set(key, value); + } + if (modified) { + this.#setModified(); + } + if (value instanceof AnnotationEditor) { + (this.#editorsMap ||= new Map()).set(value.annotationElementId, value); + if (typeof this.onAnnotationEditor === "function") { + this.onAnnotationEditor(value.constructor._type); + } + } + } + has(key) { + return this.#storage.has(key); + } + get size() { + return this.#storage.size; + } + #setModified() { + if (!this.#modified) { + this.#modified = true; + if (typeof this.onSetModified === "function") { + this.onSetModified(); + } + } + } + resetModified() { + if (this.#modified) { + this.#modified = false; + if (typeof this.onResetModified === "function") { + this.onResetModified(); + } + } + } + get print() { + return new PrintAnnotationStorage(this); + } + get serializable() { + if (this.#storage.size === 0) { + return SerializableEmpty; + } + const map = new Map(), + hash = new MurmurHash3_64(), + transfer = []; + const context = Object.create(null); + let hasBitmap = false; + for (const [key, val] of this.#storage) { + const serialized = val instanceof AnnotationEditor ? val.serialize(false, context) : val; + if (serialized) { + map.set(key, serialized); + hash.update(`${key}:${JSON.stringify(serialized)}`); + hasBitmap ||= !!serialized.bitmap; + } + } + if (hasBitmap) { + for (const value of map.values()) { + if (value.bitmap) { + transfer.push(value.bitmap); + } + } + } + return map.size > 0 ? { + map, + hash: hash.hexdigest(), + transfer + } : SerializableEmpty; + } + get editorStats() { + let stats = null; + const typeToEditor = new Map(); + let numberOfEditedComments = 0; + let numberOfDeletedComments = 0; + for (const value of this.#storage.values()) { + if (!(value instanceof AnnotationEditor)) { + if (value.popup) { + if (value.popup.deleted) { + numberOfDeletedComments += 1; + } else { + numberOfEditedComments += 1; + } + } + continue; + } + if (value.isCommentDeleted) { + numberOfDeletedComments += 1; + } else if (value.hasEditedComment) { + numberOfEditedComments += 1; + } + const editorStats = value.telemetryFinalData; + if (!editorStats) { + continue; + } + const { + type + } = editorStats; + if (!typeToEditor.has(type)) { + typeToEditor.set(type, Object.getPrototypeOf(value).constructor); + } + stats ||= Object.create(null); + const map = stats[type] ||= new Map(); + for (const [key, val] of Object.entries(editorStats)) { + if (key === "type") { + continue; + } + let counters = map.get(key); + if (!counters) { + counters = new Map(); + map.set(key, counters); + } + const count = counters.get(val) ?? 0; + counters.set(val, count + 1); + } + } + if (numberOfDeletedComments > 0 || numberOfEditedComments > 0) { + stats ||= Object.create(null); + stats.comments = { + deleted: numberOfDeletedComments, + edited: numberOfEditedComments + }; + } + if (!stats) { + return null; + } + for (const [type, editor] of typeToEditor) { + stats[type] = editor.computeTelemetryFinalData(stats[type]); + } + return stats; + } + resetModifiedIds() { + this.#modifiedIds = null; + } + updateEditor(annotationId, data) { + const value = this.#editorsMap?.get(annotationId); + if (value) { + value.updateFromAnnotationLayer(data); + return true; + } + return false; + } + getEditor(annotationId) { + return this.#editorsMap?.get(annotationId) || null; + } + get modifiedIds() { + if (this.#modifiedIds) { + return this.#modifiedIds; + } + const ids = []; + if (this.#editorsMap) { + for (const value of this.#editorsMap.values()) { + if (!value.serialize()) { + continue; + } + ids.push(value.annotationElementId); + } + } + return this.#modifiedIds = { + ids: new Set(ids), + hash: ids.join(",") + }; + } + [Symbol.iterator]() { + return this.#storage.entries(); + } +} +class PrintAnnotationStorage extends AnnotationStorage { + #serializable; + constructor(parent) { + super(); + const { + map, + hash, + transfer + } = parent.serializable; + const clone = structuredClone(map, transfer ? { + transfer + } : null); + this.#serializable = { + map: clone, + hash, + transfer + }; + } + get print() { + unreachable("Should not call PrintAnnotationStorage.print"); + } + get serializable() { + return this.#serializable; + } + get modifiedIds() { + return shadow(this, "modifiedIds", { + ids: new Set(), + hash: "" + }); + } +} + +;// ./src/display/font_loader.js + + +class FontLoader { + #systemFonts = new Set(); + constructor({ + ownerDocument = globalThis.document, + styleElement = null + }) { + this._document = ownerDocument; + this.nativeFontFaces = new Set(); + this.styleElement = null; + } + addNativeFontFace(nativeFontFace) { + this.nativeFontFaces.add(nativeFontFace); + this._document.fonts.add(nativeFontFace); + } + removeNativeFontFace(nativeFontFace) { + this.nativeFontFaces.delete(nativeFontFace); + this._document.fonts.delete(nativeFontFace); + } + insertRule(rule) { + if (!this.styleElement) { + this.styleElement = this._document.createElement("style"); + this._document.documentElement.getElementsByTagName("head")[0].append(this.styleElement); + } + const styleSheet = this.styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + } + clear() { + for (const nativeFontFace of this.nativeFontFaces) { + this._document.fonts.delete(nativeFontFace); + } + this.nativeFontFaces.clear(); + this.#systemFonts.clear(); + if (this.styleElement) { + this.styleElement.remove(); + this.styleElement = null; + } + } + async loadSystemFont({ + systemFontInfo: info, + disableFontFace, + _inspectFont + }) { + if (!info || this.#systemFonts.has(info.loadedName)) { + return; + } + assert(!disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set."); + if (this.isFontLoadingAPISupported) { + const { + loadedName, + src, + style + } = info; + const fontFace = new FontFace(loadedName, src, style); + this.addNativeFontFace(fontFace); + try { + await fontFace.load(); + this.#systemFonts.add(loadedName); + _inspectFont?.(info); + } catch { + warn(`Cannot load system font: ${info.baseFontName}, installing it could help to improve PDF rendering.`); + this.removeNativeFontFace(fontFace); + } + return; + } + unreachable("Not implemented: loadSystemFont without the Font Loading API."); + } + async bind(font) { + if (font.attached || font.missingFile && !font.systemFontInfo) { + return; + } + font.attached = true; + if (font.systemFontInfo) { + await this.loadSystemFont(font); + return; + } + if (this.isFontLoadingAPISupported) { + const nativeFontFace = font.createNativeFontFace(); + if (nativeFontFace) { + this.addNativeFontFace(nativeFontFace); + try { + await nativeFontFace.loaded; + } catch (ex) { + warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`); + font.disableFontFace = true; + throw ex; + } + } + return; + } + const rule = font.createFontFaceRule(); + if (rule) { + this.insertRule(rule); + if (this.isSyncFontLoadingSupported) { + return; + } + throw new Error("Not implemented: async font loading"); + } + } + get isFontLoadingAPISupported() { + const hasFonts = !!this._document?.fonts; + return shadow(this, "isFontLoadingAPISupported", hasFonts); + } + get isSyncFontLoadingSupported() { + return shadow(this, "isSyncFontLoadingSupported", true); + } + _queueLoadingCallback(callback) { + throw new Error("Not implemented: _queueLoadingCallback"); + } + get _loadTestFont() { + throw new Error("Not implemented: _loadTestFont"); + } + _prepareFontLoadEvent(font, request) { + throw new Error("Not implemented: _prepareFontLoadEvent"); + } +} +class FontFaceObject { + #fontData; + constructor(translatedData, inspectFont = null, extra, charProcOperatorList) { + this.compiledGlyphs = Object.create(null); + this.#fontData = translatedData; + this._inspectFont = inspectFont; + if (extra) { + Object.assign(this, extra); + } + if (charProcOperatorList) { + this.charProcOperatorList = charProcOperatorList; + } + } + createNativeFontFace() { + if (!this.data || this.disableFontFace) { + return null; + } + let nativeFontFace; + if (!this.cssFontInfo) { + nativeFontFace = new FontFace(this.loadedName, this.data, {}); + } else { + const css = { + weight: this.cssFontInfo.fontWeight + }; + if (this.cssFontInfo.italicAngle) { + css.style = `oblique ${this.cssFontInfo.italicAngle}deg`; + } + nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css); + } + this._inspectFont?.(this); + return nativeFontFace; + } + createFontFaceRule() { + if (!this.data || this.disableFontFace) { + return null; + } + const url = `url(data:${this.mimetype};base64,${toBase64Util(this.data)});`; + let rule; + if (!this.cssFontInfo) { + rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`; + } else { + let css = `font-weight: ${this.cssFontInfo.fontWeight};`; + if (this.cssFontInfo.italicAngle) { + css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`; + } + rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`; + } + this._inspectFont?.(this, url); + return rule; + } + getPathGenerator(objs, character) { + if (this.compiledGlyphs[character] !== undefined) { + return this.compiledGlyphs[character]; + } + const objId = this.loadedName + "_path_" + character; + let cmds; + try { + cmds = objs.get(objId); + } catch (ex) { + warn(`getPathGenerator - ignoring character: "${ex}".`); + } + const path = makePathFromDrawOPS(cmds); + if (!this.fontExtraProperties) { + objs.delete(objId); + } + return this.compiledGlyphs[character] = path; + } + get black() { + return this.#fontData.black; + } + get bold() { + return this.#fontData.bold; + } + get disableFontFace() { + return this.#fontData.disableFontFace ?? false; + } + set disableFontFace(value) { + shadow(this, "disableFontFace", !!value); + } + get fontExtraProperties() { + return this.#fontData.fontExtraProperties ?? false; + } + get isInvalidPDFjsFont() { + return this.#fontData.isInvalidPDFjsFont; + } + get isType3Font() { + return this.#fontData.isType3Font; + } + get italic() { + return this.#fontData.italic; + } + get missingFile() { + return this.#fontData.missingFile; + } + get remeasure() { + return this.#fontData.remeasure; + } + get vertical() { + return this.#fontData.vertical; + } + get ascent() { + return this.#fontData.ascent; + } + get defaultWidth() { + return this.#fontData.defaultWidth; + } + get descent() { + return this.#fontData.descent; + } + get bbox() { + return this.#fontData.bbox; + } + set bbox(bbox) { + shadow(this, "bbox", bbox); + } + get fontMatrix() { + return this.#fontData.fontMatrix; + } + get fallbackName() { + return this.#fontData.fallbackName; + } + get loadedName() { + return this.#fontData.loadedName; + } + get mimetype() { + return this.#fontData.mimetype; + } + get name() { + return this.#fontData.name; + } + get data() { + return this.#fontData.data; + } + clearData() { + this.#fontData.clearData(); + } + get cssFontInfo() { + return this.#fontData.cssFontInfo; + } + get systemFontInfo() { + return this.#fontData.systemFontInfo; + } + get defaultVMetrics() { + return this.#fontData.defaultVMetrics; + } +} + +;// ./src/shared/obj-bin-transform.js + +class CssFontInfo { + #buffer; + #view; + #decoder; + static strings = ["fontFamily", "fontWeight", "italicAngle"]; + static write(info) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encoder.encode(info[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + const buffer = new ArrayBuffer(stringsLength); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + assert(offset === buffer.byteLength, "CssFontInfo.write: Buffer overflow"); + return buffer; + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + #readString(index) { + assert(index < CssFontInfo.strings.length, "Invalid string index"); + let offset = 0; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get fontFamily() { + return this.#readString(0); + } + get fontWeight() { + return this.#readString(1); + } + get italicAngle() { + return this.#readString(2); + } +} +class SystemFontInfo { + #buffer; + #view; + #decoder; + static strings = ["css", "loadedName", "baseFontName", "src"]; + static write(info) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encoder.encode(info[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + stringsLength += 4; + let encodedStyleStyle, + encodedStyleWeight, + lengthEstimate = 1 + stringsLength; + if (info.style) { + encodedStyleStyle = encoder.encode(info.style.style); + encodedStyleWeight = encoder.encode(info.style.weight); + lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length; + } + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + view.setUint8(offset++, info.guessFallback ? 1 : 0); + view.setUint32(offset, 0); + offset += 4; + stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + stringsLength += 4 + length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(offset - stringsLength - 4, stringsLength); + if (info.style) { + view.setUint32(offset, encodedStyleStyle.length); + data.set(encodedStyleStyle, offset + 4); + offset += 4 + encodedStyleStyle.length; + view.setUint32(offset, encodedStyleWeight.length); + data.set(encodedStyleWeight, offset + 4); + offset += 4 + encodedStyleWeight.length; + } + assert(offset <= buffer.byteLength, "SubstitionInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + get guessFallback() { + return this.#view.getUint8(0) !== 0; + } + #readString(index) { + assert(index < SystemFontInfo.strings.length, "Invalid string index"); + let offset = 5; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get css() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get baseFontName() { + return this.#readString(2); + } + get src() { + return this.#readString(3); + } + get style() { + let offset = 1; + offset += 4 + this.#view.getUint32(offset); + const styleLength = this.#view.getUint32(offset); + const style = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, styleLength)); + offset += 4 + styleLength; + const weightLength = this.#view.getUint32(offset); + const weight = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, weightLength)); + return { + style, + weight + }; + } +} +class FontInfo { + static bools = ["black", "bold", "disableFontFace", "fontExtraProperties", "isInvalidPDFjsFont", "isType3Font", "italic", "missingFile", "remeasure", "vertical"]; + static numbers = ["ascent", "defaultWidth", "descent"]; + static strings = ["fallbackName", "loadedName", "mimetype", "name"]; + static #OFFSET_NUMBERS = Math.ceil(this.bools.length * 2 / 8); + static #OFFSET_BBOX = this.#OFFSET_NUMBERS + this.numbers.length * 8; + static #OFFSET_FONT_MATRIX = this.#OFFSET_BBOX + 1 + 2 * 4; + static #OFFSET_DEFAULT_VMETRICS = this.#OFFSET_FONT_MATRIX + 1 + 8 * 6; + static #OFFSET_STRINGS = this.#OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3; + #buffer; + #decoder; + #view; + constructor({ + data, + extra + }) { + this.#buffer = data; + this.#decoder = new TextDecoder(); + this.#view = new DataView(this.#buffer); + if (extra) { + Object.assign(this, extra); + } + } + #readBoolean(index) { + assert(index < FontInfo.bools.length, "Invalid boolean index"); + const byteOffset = Math.floor(index / 4); + const bitOffset = index * 2 % 8; + const value = this.#view.getUint8(byteOffset) >> bitOffset & 0x03; + return value === 0x00 ? undefined : value === 0x02; + } + get black() { + return this.#readBoolean(0); + } + get bold() { + return this.#readBoolean(1); + } + get disableFontFace() { + return this.#readBoolean(2); + } + get fontExtraProperties() { + return this.#readBoolean(3); + } + get isInvalidPDFjsFont() { + return this.#readBoolean(4); + } + get isType3Font() { + return this.#readBoolean(5); + } + get italic() { + return this.#readBoolean(6); + } + get missingFile() { + return this.#readBoolean(7); + } + get remeasure() { + return this.#readBoolean(8); + } + get vertical() { + return this.#readBoolean(9); + } + #readNumber(index) { + assert(index < FontInfo.numbers.length, "Invalid number index"); + return this.#view.getFloat64(FontInfo.#OFFSET_NUMBERS + index * 8); + } + get ascent() { + return this.#readNumber(0); + } + get defaultWidth() { + return this.#readNumber(1); + } + get descent() { + return this.#readNumber(2); + } + get bbox() { + let offset = FontInfo.#OFFSET_BBOX; + const numCoords = this.#view.getUint8(offset); + if (numCoords === 0) { + return undefined; + } + offset += 1; + const bbox = []; + for (let i = 0; i < 4; i++) { + bbox.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return bbox; + } + get fontMatrix() { + let offset = FontInfo.#OFFSET_FONT_MATRIX; + const numPoints = this.#view.getUint8(offset); + if (numPoints === 0) { + return undefined; + } + offset += 1; + const fontMatrix = []; + for (let i = 0; i < 6; i++) { + fontMatrix.push(this.#view.getFloat64(offset, true)); + offset += 8; + } + return fontMatrix; + } + get defaultVMetrics() { + let offset = FontInfo.#OFFSET_DEFAULT_VMETRICS; + const numMetrics = this.#view.getUint8(offset); + if (numMetrics === 0) { + return undefined; + } + offset += 1; + const defaultVMetrics = []; + for (let i = 0; i < 3; i++) { + defaultVMetrics.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return defaultVMetrics; + } + #readString(index) { + assert(index < FontInfo.strings.length, "Invalid string index"); + let offset = FontInfo.#OFFSET_STRINGS + 4; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + const stringData = new Uint8Array(length); + stringData.set(new Uint8Array(this.#buffer, offset + 4, length)); + return this.#decoder.decode(stringData); + } + get fallbackName() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get mimetype() { + return this.#readString(2); + } + get name() { + return this.#readString(3); + } + get data() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + if (length === 0) { + return undefined; + } + return new Uint8Array(this.#buffer, offset + 4, length); + } + clearData() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + const data = new Uint8Array(this.#buffer, offset + 4, length); + data.fill(0); + this.#view.setUint32(offset, 0); + } + get cssFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + if (cssFontInfoLength === 0) { + return null; + } + const cssFontInfoData = new Uint8Array(cssFontInfoLength); + cssFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength)); + return new CssFontInfo(cssFontInfoData.buffer); + } + get systemFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + if (systemFontInfoLength === 0) { + return null; + } + const systemFontInfoData = new Uint8Array(systemFontInfoLength); + systemFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength)); + return new SystemFontInfo(systemFontInfoData.buffer); + } + static write(font) { + const systemFontInfoBuffer = font.systemFontInfo ? SystemFontInfo.write(font.systemFontInfo) : null; + const cssFontInfoBuffer = font.cssFontInfo ? CssFontInfo.write(font.cssFontInfo) : null; + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of FontInfo.strings) { + encodedStrings[prop] = encoder.encode(font[prop]); + stringsLength += 4 + encodedStrings[prop].length; + } + const lengthEstimate = FontInfo.#OFFSET_STRINGS + 4 + stringsLength + 4 + (systemFontInfoBuffer ? systemFontInfoBuffer.byteLength : 0) + 4 + (cssFontInfoBuffer ? cssFontInfoBuffer.byteLength : 0) + 4 + (font.data ? font.data.length : 0); + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + const numBools = FontInfo.bools.length; + let boolByte = 0, + boolBit = 0; + for (let i = 0; i < numBools; i++) { + const value = font[FontInfo.bools[i]]; + const bits = value === undefined ? 0x00 : value ? 0x02 : 0x01; + boolByte |= bits << boolBit; + boolBit += 2; + if (boolBit === 8 || i === numBools - 1) { + view.setUint8(offset++, boolByte); + boolByte = 0; + boolBit = 0; + } + } + assert(offset === FontInfo.#OFFSET_NUMBERS, "FontInfo.write: Boolean properties offset mismatch"); + for (const prop of FontInfo.numbers) { + view.setFloat64(offset, font[prop]); + offset += 8; + } + assert(offset === FontInfo.#OFFSET_BBOX, "FontInfo.write: Number properties offset mismatch"); + if (font.bbox) { + view.setUint8(offset++, 4); + for (const coord of font.bbox) { + view.setInt16(offset, coord, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 2 * 4; + } + assert(offset === FontInfo.#OFFSET_FONT_MATRIX, "FontInfo.write: BBox properties offset mismatch"); + if (font.fontMatrix) { + view.setUint8(offset++, 6); + for (const point of font.fontMatrix) { + view.setFloat64(offset, point, true); + offset += 8; + } + } else { + view.setUint8(offset++, 0); + offset += 8 * 6; + } + assert(offset === FontInfo.#OFFSET_DEFAULT_VMETRICS, "FontInfo.write: FontMatrix properties offset mismatch"); + if (font.defaultVMetrics) { + view.setUint8(offset++, 1); + for (const metric of font.defaultVMetrics) { + view.setInt16(offset, metric, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 3 * 2; + } + assert(offset === FontInfo.#OFFSET_STRINGS, "FontInfo.write: DefaultVMetrics properties offset mismatch"); + view.setUint32(FontInfo.#OFFSET_STRINGS, 0); + offset += 4; + for (const prop of FontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(FontInfo.#OFFSET_STRINGS, offset - FontInfo.#OFFSET_STRINGS - 4); + if (!systemFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = systemFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at systemFontInfo"); + data.set(new Uint8Array(systemFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (!cssFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = cssFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at cssFontInfo"); + data.set(new Uint8Array(cssFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (font.data === undefined) { + view.setUint32(offset, 0); + offset += 4; + } else { + view.setUint32(offset, font.data.length); + data.set(font.data, offset + 4); + offset += 4 + font.data.length; + } + assert(offset <= buffer.byteLength, "FontInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } +} +class PatternInfo { + static #KIND = 0; + static #HAS_BBOX = 1; + static #HAS_BACKGROUND = 2; + static #SHADING_TYPE = 3; + static #N_COORD = 4; + static #N_COLOR = 8; + static #N_STOP = 12; + static #N_FIGURES = 16; + constructor(buffer) { + this.buffer = buffer; + this.view = new DataView(buffer); + this.data = new Uint8Array(buffer); + } + static write(ir) { + let kind, + bbox = null, + coords = [], + colors = [], + colorStops = [], + figures = [], + shadingType = null, + background = null; + switch (ir[0]) { + case "RadialAxial": + kind = ir[1] === "axial" ? 1 : 2; + bbox = ir[2]; + colorStops = ir[3]; + if (kind === 1) { + coords.push(...ir[4], ...ir[5]); + } else { + coords.push(ir[4][0], ir[4][1], ir[6], ir[5][0], ir[5][1], ir[7]); + } + break; + case "Mesh": + kind = 3; + shadingType = ir[1]; + coords = ir[2]; + colors = ir[3]; + figures = ir[4] || []; + bbox = ir[6]; + background = ir[7]; + break; + default: + throw new Error(`Unsupported pattern type: ${ir[0]}`); + } + const nCoord = Math.floor(coords.length / 2); + const nColor = Math.floor(colors.length / 3); + const nStop = colorStops.length; + const nFigures = figures.length; + let figuresSize = 0; + for (const figure of figures) { + figuresSize += 1; + figuresSize = Math.ceil(figuresSize / 4) * 4; + figuresSize += 4 + figure.coords.length * 4; + figuresSize += 4 + figure.colors.length * 4; + if (figure.verticesPerRow !== undefined) { + figuresSize += 4; + } + } + const byteLen = 20 + nCoord * 8 + nColor * 3 + nStop * 8 + (bbox ? 16 : 0) + (background ? 3 : 0) + figuresSize; + const buffer = new ArrayBuffer(byteLen); + const dataView = new DataView(buffer); + const u8data = new Uint8Array(buffer); + dataView.setUint8(PatternInfo.#KIND, kind); + dataView.setUint8(PatternInfo.#HAS_BBOX, bbox ? 1 : 0); + dataView.setUint8(PatternInfo.#HAS_BACKGROUND, background ? 1 : 0); + dataView.setUint8(PatternInfo.#SHADING_TYPE, shadingType); + dataView.setUint32(PatternInfo.#N_COORD, nCoord, true); + dataView.setUint32(PatternInfo.#N_COLOR, nColor, true); + dataView.setUint32(PatternInfo.#N_STOP, nStop, true); + dataView.setUint32(PatternInfo.#N_FIGURES, nFigures, true); + let offset = 20; + const coordsView = new Float32Array(buffer, offset, nCoord * 2); + coordsView.set(coords); + offset += nCoord * 8; + u8data.set(colors, offset); + offset += nColor * 3; + for (const [pos, hex] of colorStops) { + dataView.setFloat32(offset, pos, true); + offset += 4; + dataView.setUint32(offset, parseInt(hex.slice(1), 16), true); + offset += 4; + } + if (bbox) { + for (const v of bbox) { + dataView.setFloat32(offset, v, true); + offset += 4; + } + } + if (background) { + u8data.set(background, offset); + offset += 3; + } + for (let i = 0; i < figures.length; i++) { + const figure = figures[i]; + dataView.setUint8(offset, figure.type); + offset += 1; + offset = Math.ceil(offset / 4) * 4; + dataView.setUint32(offset, figure.coords.length, true); + offset += 4; + const figureCoordsView = new Int32Array(buffer, offset, figure.coords.length); + figureCoordsView.set(figure.coords); + offset += figure.coords.length * 4; + dataView.setUint32(offset, figure.colors.length, true); + offset += 4; + const colorsView = new Int32Array(buffer, offset, figure.colors.length); + colorsView.set(figure.colors); + offset += figure.colors.length * 4; + if (figure.verticesPerRow !== undefined) { + dataView.setUint32(offset, figure.verticesPerRow, true); + offset += 4; + } + } + return buffer; + } + getIR() { + const dataView = this.view; + const kind = this.data[PatternInfo.#KIND]; + const hasBBox = !!this.data[PatternInfo.#HAS_BBOX]; + const hasBackground = !!this.data[PatternInfo.#HAS_BACKGROUND]; + const nCoord = dataView.getUint32(PatternInfo.#N_COORD, true); + const nColor = dataView.getUint32(PatternInfo.#N_COLOR, true); + const nStop = dataView.getUint32(PatternInfo.#N_STOP, true); + const nFigures = dataView.getUint32(PatternInfo.#N_FIGURES, true); + let offset = 20; + const coords = new Float32Array(this.buffer, offset, nCoord * 2); + offset += nCoord * 8; + const colors = new Uint8Array(this.buffer, offset, nColor * 3); + offset += nColor * 3; + const stops = []; + for (let i = 0; i < nStop; ++i) { + const p = dataView.getFloat32(offset, true); + offset += 4; + const rgb = dataView.getUint32(offset, true); + offset += 4; + stops.push([p, `#${rgb.toString(16).padStart(6, "0")}`]); + } + let bbox = null; + if (hasBBox) { + bbox = []; + for (let i = 0; i < 4; ++i) { + bbox.push(dataView.getFloat32(offset, true)); + offset += 4; + } + } + let background = null; + if (hasBackground) { + background = new Uint8Array(this.buffer, offset, 3); + offset += 3; + } + const figures = []; + for (let i = 0; i < nFigures; ++i) { + const type = dataView.getUint8(offset); + offset += 1; + offset = Math.ceil(offset / 4) * 4; + const coordsLength = dataView.getUint32(offset, true); + offset += 4; + const figureCoords = new Int32Array(this.buffer, offset, coordsLength); + offset += coordsLength * 4; + const colorsLength = dataView.getUint32(offset, true); + offset += 4; + const figureColors = new Int32Array(this.buffer, offset, colorsLength); + offset += colorsLength * 4; + const figure = { + type, + coords: figureCoords, + colors: figureColors + }; + if (type === MeshFigureType.LATTICE) { + figure.verticesPerRow = dataView.getUint32(offset, true); + offset += 4; + } + figures.push(figure); + } + if (kind === 1) { + return ["RadialAxial", "axial", bbox, stops, Array.from(coords.slice(0, 2)), Array.from(coords.slice(2, 4)), null, null]; + } + if (kind === 2) { + return ["RadialAxial", "radial", bbox, stops, [coords[0], coords[1]], [coords[3], coords[4]], coords[2], coords[5]]; + } + if (kind === 3) { + const shadingType = this.data[PatternInfo.#SHADING_TYPE]; + let bounds = null; + if (coords.length > 0) { + let minX = coords[0], + maxX = coords[0]; + let minY = coords[1], + maxY = coords[1]; + for (let i = 0; i < coords.length; i += 2) { + const x = coords[i], + y = coords[i + 1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + bounds = [minX, minY, maxX, maxY]; + } + return ["Mesh", shadingType, coords, colors, figures, bounds, bbox, background]; + } + throw new Error(`Unsupported pattern kind: ${kind}`); + } +} + +;// ./src/display/api_utils.js + +function getUrlProp(val) { + return null; +} +function getDataProp(val) { + if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) { + return val; + } + if (typeof val === "string") { + return stringToBytes(val); + } + if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) { + return new Uint8Array(val); + } + throw new Error("Invalid PDF binary data: either TypedArray, " + "string, or array-like object is expected in the data property."); +} +function getFactoryUrlProp(val) { + if (typeof val !== "string") { + return null; + } + if (val.endsWith("/")) { + return val; + } + throw new Error(`Invalid factory url: "${val}" must include trailing slash.`); +} +const isRefProxy = v => typeof v === "object" && Number.isInteger(v?.num) && v.num >= 0 && Number.isInteger(v?.gen) && v.gen >= 0; +const isNameProxy = v => typeof v === "object" && typeof v?.name === "string"; +const isValidExplicitDest = _isValidExplicitDest.bind(null, isRefProxy, isNameProxy); +class LoopbackPort { + #listeners = new Map(); + #deferred = Promise.resolve(); + postMessage(obj, transfer) { + const event = { + data: structuredClone(obj, transfer ? { + transfer + } : null) + }; + this.#deferred.then(() => { + for (const [listener] of this.#listeners) { + listener.call(this, event); + } + }); + } + addEventListener(name, listener, options = null) { + let rmAbort = null; + if (options?.signal instanceof AbortSignal) { + const { + signal + } = options; + if (signal.aborted) { + warn("LoopbackPort - cannot use an `aborted` signal."); + return; + } + const onAbort = () => this.removeEventListener(name, listener); + rmAbort = () => signal.removeEventListener("abort", onAbort); + signal.addEventListener("abort", onAbort); + } + this.#listeners.set(listener, rmAbort); + } + removeEventListener(name, listener) { + const rmAbort = this.#listeners.get(listener); + rmAbort?.(); + this.#listeners.delete(listener); + } + terminate() { + for (const [, rmAbort] of this.#listeners) { + rmAbort?.(); + } + this.#listeners.clear(); + } +} + +;// ./src/shared/message_handler.js + +const CallbackKind = { + DATA: 1, + ERROR: 2 +}; +const StreamKind = { + CANCEL: 1, + CANCEL_COMPLETE: 2, + CLOSE: 3, + ENQUEUE: 4, + ERROR: 5, + PULL: 6, + PULL_COMPLETE: 7, + START_COMPLETE: 8 +}; +function onFn() {} +function wrapReason(ex) { + if (ex instanceof AbortException || ex instanceof InvalidPDFException || ex instanceof PasswordException || ex instanceof ResponseException || ex instanceof UnknownErrorException) { + return ex; + } + if (!(ex instanceof Error || typeof ex === "object" && ex !== null)) { + unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); + } + switch (ex.name) { + case "AbortException": + return new AbortException(ex.message); + case "InvalidPDFException": + return new InvalidPDFException(ex.message); + case "PasswordException": + return new PasswordException(ex.message, ex.code); + case "ResponseException": + return new ResponseException(ex.message, ex.status, ex.missing); + case "UnknownErrorException": + return new UnknownErrorException(ex.message, ex.details); + } + return new UnknownErrorException(ex.message, ex.toString()); +} +class MessageHandler { + #messageAC = new AbortController(); + constructor(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackId = 1; + this.streamId = 1; + this.streamSinks = Object.create(null); + this.streamControllers = Object.create(null); + this.callbackCapabilities = Object.create(null); + this.actionHandler = Object.create(null); + comObj.addEventListener("message", this.#onMessage.bind(this), { + signal: this.#messageAC.signal + }); + } + #onMessage({ + data + }) { + if (data.targetName !== this.sourceName) { + return; + } + if (data.stream) { + this.#processStreamMessage(data); + return; + } + if (data.callback) { + const callbackId = data.callbackId; + const capability = this.callbackCapabilities[callbackId]; + if (!capability) { + throw new Error(`Cannot resolve callback ${callbackId}`); + } + delete this.callbackCapabilities[callbackId]; + if (data.callback === CallbackKind.DATA) { + capability.resolve(data.data); + } else if (data.callback === CallbackKind.ERROR) { + capability.reject(wrapReason(data.reason)); + } else { + throw new Error("Unexpected callback case"); + } + return; + } + const action = this.actionHandler[data.action]; + if (!action) { + throw new Error(`Unknown action from worker: ${data.action}`); + } + if (data.callbackId) { + const sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + Promise.try(action, data.data).then(function (result) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.DATA, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.ERROR, + callbackId: data.callbackId, + reason: wrapReason(reason) + }); + }); + return; + } + if (data.streamId) { + this.#createStreamSink(data); + return; + } + action(data.data); + } + on(actionName, handler) { + const ah = this.actionHandler; + if (ah[actionName]) { + throw new Error(`There is already an actionName called "${actionName}"`); + } + ah[actionName] = handler; + } + send(actionName, data, transfers) { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data + }, transfers); + } + sendWithPromise(actionName, data, transfers) { + const callbackId = this.callbackId++; + const capability = Promise.withResolvers(); + this.callbackCapabilities[callbackId] = capability; + try { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + callbackId, + data + }, transfers); + } catch (ex) { + capability.reject(ex); + } + return capability.promise; + } + sendWithStream(actionName, data, queueingStrategy, transfers) { + const streamId = this.streamId++, + sourceName = this.sourceName, + targetName = this.targetName, + comObj = this.comObj; + return new ReadableStream({ + start: controller => { + const startCapability = Promise.withResolvers(); + this.streamControllers[streamId] = { + controller, + startCall: startCapability, + pullCall: null, + cancelCall: null, + isClosed: false + }; + comObj.postMessage({ + sourceName, + targetName, + action: actionName, + streamId, + data, + desiredSize: controller.desiredSize + }, transfers); + return startCapability.promise; + }, + pull: controller => { + const pullCapability = Promise.withResolvers(); + this.streamControllers[streamId].pullCall = pullCapability; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL, + streamId, + desiredSize: controller.desiredSize + }); + return pullCapability.promise; + }, + cancel: reason => { + assert(reason instanceof Error, "cancel must have a valid reason"); + const cancelCapability = Promise.withResolvers(); + this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL, + streamId, + reason: wrapReason(reason) + }); + return cancelCapability.promise; + } + }, queueingStrategy); + } + #createStreamSink(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const self = this, + action = this.actionHandler[data.action]; + const streamSink = { + enqueue(chunk, size = 1, transfers) { + if (this.isCancelled) { + return; + } + const lastDesiredSize = this.desiredSize; + this.desiredSize -= size; + if (lastDesiredSize > 0 && this.desiredSize <= 0) { + this.sinkCapability = Promise.withResolvers(); + this.ready = this.sinkCapability.promise; + } + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ENQUEUE, + streamId, + chunk + }, transfers); + }, + close() { + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CLOSE, + streamId + }); + delete self.streamSinks[streamId]; + }, + error(reason) { + assert(reason instanceof Error, "error must have a valid reason"); + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ERROR, + streamId, + reason: wrapReason(reason) + }); + }, + sinkCapability: Promise.withResolvers(), + onPull: null, + onCancel: null, + isCancelled: false, + desiredSize: data.desiredSize, + ready: null + }; + streamSink.sinkCapability.resolve(); + streamSink.ready = streamSink.sinkCapability.promise; + this.streamSinks[streamId] = streamSink; + Promise.try(action, data.data, streamSink).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + } + #processStreamMessage(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const streamController = this.streamControllers[streamId], + streamSink = this.streamSinks[streamId]; + switch (data.stream) { + case StreamKind.START_COMPLETE: + if (data.success) { + streamController.startCall.resolve(); + } else { + streamController.startCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL_COMPLETE: + if (data.success) { + streamController.pullCall.resolve(); + } else { + streamController.pullCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL: + if (!streamSink) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + break; + } + if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { + streamSink.sinkCapability.resolve(); + } + streamSink.desiredSize = data.desiredSize; + Promise.try(streamSink.onPull || onFn).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + break; + case StreamKind.ENQUEUE: + assert(streamController, "enqueue should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.controller.enqueue(data.chunk); + break; + case StreamKind.CLOSE: + assert(streamController, "close should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.isClosed = true; + streamController.controller.close(); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.ERROR: + assert(streamController, "error should have stream controller"); + streamController.controller.error(wrapReason(data.reason)); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL_COMPLETE: + if (data.success) { + streamController.cancelCall.resolve(); + } else { + streamController.cancelCall.reject(wrapReason(data.reason)); + } + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL: + if (!streamSink) { + break; + } + const dataReason = wrapReason(data.reason); + Promise.try(streamSink.onCancel || onFn, dataReason).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + streamSink.sinkCapability.reject(dataReason); + streamSink.isCancelled = true; + delete this.streamSinks[streamId]; + break; + default: + throw new Error("Unexpected stream case"); + } + } + async #deleteStreamController(streamController, streamId) { + await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]); + delete this.streamControllers[streamId]; + } + destroy() { + this.#messageAC?.abort(); + this.#messageAC = null; + } +} + +;// ./src/display/canvas_dependency_tracker.js + +const FORCED_DEPENDENCY_LABEL = "__forcedDependency"; +const { + floor, + ceil +} = Math; +function expandBBox(array, index, minX, minY, maxX, maxY) { + array[index * 4 + 0] = Math.min(array[index * 4 + 0], minX); + array[index * 4 + 1] = Math.min(array[index * 4 + 1], minY); + array[index * 4 + 2] = Math.max(array[index * 4 + 2], maxX); + array[index * 4 + 3] = Math.max(array[index * 4 + 3], maxY); +} +const EMPTY_BBOX = new Uint32Array(new Uint8Array([255, 255, 0, 0]).buffer)[0]; +class BBoxReader { + #bboxes; + #coords; + constructor(bboxes, coords) { + this.#bboxes = bboxes; + this.#coords = coords; + } + get length() { + return this.#bboxes.length; + } + isEmpty(i) { + return this.#bboxes[i] === EMPTY_BBOX; + } + minX(i) { + return this.#coords[i * 4 + 0] / 256; + } + minY(i) { + return this.#coords[i * 4 + 1] / 256; + } + maxX(i) { + return (this.#coords[i * 4 + 2] + 1) / 256; + } + maxY(i) { + return (this.#coords[i * 4 + 3] + 1) / 256; + } +} +const ensureDebugMetadata = (map, key) => { + if (!map) { + return undefined; + } + let value = map.get(key); + if (!value) { + value = { + dependencies: new Set(), + isRenderingOperation: false + }; + map.set(key, value); + } + return value; +}; +class CanvasDependencyTracker { + #simple = { + __proto__: null + }; + #incremental = { + __proto__: null, + transform: [], + moveText: [], + sameLineText: [], + [FORCED_DEPENDENCY_LABEL]: [] + }; + #namedDependencies = new Map(); + #savesStack = []; + #markedContentStack = []; + #baseTransformStack = [[1, 0, 0, 1, 0, 0]]; + #clipBox = [-Infinity, -Infinity, Infinity, Infinity]; + #pendingBBox = new Float64Array([Infinity, Infinity, -Infinity, -Infinity]); + #pendingBBoxIdx = -1; + #pendingDependencies = new Set(); + #operations = new Map(); + #fontBBoxTrustworthy = new Map(); + #canvasWidth; + #canvasHeight; + #bboxesCoords; + #bboxes; + #debugMetadata; + constructor(canvas, operationsCount, recordDebugMetadata = false) { + this.#canvasWidth = canvas.width; + this.#canvasHeight = canvas.height; + this.#initializeBBoxes(operationsCount); + if (recordDebugMetadata) { + this.#debugMetadata = new Map(); + } + } + growOperationsCount(operationsCount) { + if (operationsCount >= this.#bboxes.length) { + this.#initializeBBoxes(operationsCount, this.#bboxes); + } + } + #initializeBBoxes(operationsCount, oldBBoxes) { + const buffer = new ArrayBuffer(operationsCount * 4); + this.#bboxesCoords = new Uint8ClampedArray(buffer); + this.#bboxes = new Uint32Array(buffer); + if (oldBBoxes && oldBBoxes.length > 0) { + this.#bboxes.set(oldBBoxes); + this.#bboxes.fill(EMPTY_BBOX, oldBBoxes.length); + } else { + this.#bboxes.fill(EMPTY_BBOX); + } + } + save(opIdx) { + this.#simple = { + __proto__: this.#simple + }; + this.#incremental = { + __proto__: this.#incremental, + transform: { + __proto__: this.#incremental.transform + }, + moveText: { + __proto__: this.#incremental.moveText + }, + sameLineText: { + __proto__: this.#incremental.sameLineText + }, + [FORCED_DEPENDENCY_LABEL]: { + __proto__: this.#incremental[FORCED_DEPENDENCY_LABEL] + } + }; + this.#clipBox = { + __proto__: this.#clipBox + }; + this.#savesStack.push(opIdx); + return this; + } + restore(opIdx) { + const previous = Object.getPrototypeOf(this.#simple); + if (previous === null) { + return this; + } + this.#simple = previous; + this.#incremental = Object.getPrototypeOf(this.#incremental); + this.#clipBox = Object.getPrototypeOf(this.#clipBox); + const lastSave = this.#savesStack.pop(); + if (lastSave !== undefined) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + recordOpenMarker(idx) { + this.#savesStack.push(idx); + return this; + } + getOpenMarker() { + if (this.#savesStack.length === 0) { + return null; + } + return this.#savesStack.at(-1); + } + recordCloseMarker(opIdx) { + const lastSave = this.#savesStack.pop(); + if (lastSave !== undefined) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + beginMarkedContent(opIdx) { + this.#markedContentStack.push(opIdx); + return this; + } + endMarkedContent(opIdx) { + const lastSave = this.#markedContentStack.pop(); + if (lastSave !== undefined) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + pushBaseTransform(ctx) { + this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform())); + return this; + } + popBaseTransform() { + if (this.#baseTransformStack.length > 1) { + this.#baseTransformStack.pop(); + } + return this; + } + recordSimpleData(name, idx) { + this.#simple[name] = idx; + return this; + } + recordIncrementalData(name, idx) { + this.#incremental[name].push(idx); + return this; + } + resetIncrementalData(name, idx) { + this.#incremental[name].length = 0; + return this; + } + recordNamedData(name, idx) { + this.#namedDependencies.set(name, idx); + return this; + } + recordSimpleDataFromNamed(name, depName, fallbackIdx) { + this.#simple[name] = this.#namedDependencies.get(depName) ?? fallbackIdx; + } + recordFutureForcedDependency(name, idx) { + this.recordIncrementalData(FORCED_DEPENDENCY_LABEL, idx); + return this; + } + inheritSimpleDataAsFutureForcedDependencies(names) { + for (const name of names) { + if (name in this.#simple) { + this.recordFutureForcedDependency(name, this.#simple[name]); + } + } + return this; + } + inheritPendingDependenciesAsFutureForcedDependencies() { + for (const dep of this.#pendingDependencies) { + this.recordFutureForcedDependency(FORCED_DEPENDENCY_LABEL, dep); + } + return this; + } + resetBBox(idx) { + if (this.#pendingBBoxIdx !== idx) { + this.#pendingBBoxIdx = idx; + this.#pendingBBox[0] = Infinity; + this.#pendingBBox[1] = Infinity; + this.#pendingBBox[2] = -Infinity; + this.#pendingBBox[3] = -Infinity; + } + return this; + } + recordClipBox(idx, ctx, minX, maxX, minY, maxY) { + const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform()); + const clipBox = [Infinity, Infinity, -Infinity, -Infinity]; + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, clipBox); + const intersection = Util.intersect(this.#clipBox, clipBox); + if (intersection) { + this.#clipBox[0] = intersection[0]; + this.#clipBox[1] = intersection[1]; + this.#clipBox[2] = intersection[2]; + this.#clipBox[3] = intersection[3]; + } else { + this.#clipBox[0] = this.#clipBox[1] = Infinity; + this.#clipBox[2] = this.#clipBox[3] = -Infinity; + } + return this; + } + recordBBox(idx, ctx, minX, maxX, minY, maxY) { + const clipBox = this.#clipBox; + if (clipBox[0] === Infinity) { + return this; + } + const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform()); + if (clipBox[0] === -Infinity) { + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, this.#pendingBBox); + return this; + } + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, bbox); + this.#pendingBBox[0] = Math.min(this.#pendingBBox[0], Math.max(bbox[0], clipBox[0])); + this.#pendingBBox[1] = Math.min(this.#pendingBBox[1], Math.max(bbox[1], clipBox[1])); + this.#pendingBBox[2] = Math.max(this.#pendingBBox[2], Math.min(bbox[2], clipBox[2])); + this.#pendingBBox[3] = Math.max(this.#pendingBBox[3], Math.min(bbox[3], clipBox[3])); + return this; + } + recordCharacterBBox(idx, ctx, font, scale = 1, x = 0, y = 0, getMeasure) { + const fontBBox = font.bbox; + let isBBoxTrustworthy; + let computedBBox; + if (fontBBox) { + isBBoxTrustworthy = fontBBox[2] !== fontBBox[0] && fontBBox[3] !== fontBBox[1] && this.#fontBBoxTrustworthy.get(font); + if (isBBoxTrustworthy !== false) { + computedBBox = [0, 0, 0, 0]; + Util.axialAlignedBoundingBox(fontBBox, font.fontMatrix, computedBBox); + if (scale !== 1 || x !== 0 || y !== 0) { + Util.scaleMinMax([scale, 0, 0, -scale, x, y], computedBBox); + } + if (isBBoxTrustworthy) { + return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]); + } + } + } + if (!getMeasure) { + return this.recordFullPageBBox(idx); + } + const measure = getMeasure(); + if (fontBBox && computedBBox && isBBoxTrustworthy === undefined) { + isBBoxTrustworthy = computedBBox[0] <= x - measure.actualBoundingBoxLeft && computedBBox[2] >= x + measure.actualBoundingBoxRight && computedBBox[1] <= y - measure.actualBoundingBoxAscent && computedBBox[3] >= y + measure.actualBoundingBoxDescent; + this.#fontBBoxTrustworthy.set(font, isBBoxTrustworthy); + if (isBBoxTrustworthy) { + return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]); + } + } + return this.recordBBox(idx, ctx, x - measure.actualBoundingBoxLeft, x + measure.actualBoundingBoxRight, y - measure.actualBoundingBoxAscent, y + measure.actualBoundingBoxDescent); + } + recordFullPageBBox(idx) { + this.#pendingBBox[0] = Math.max(0, this.#clipBox[0]); + this.#pendingBBox[1] = Math.max(0, this.#clipBox[1]); + this.#pendingBBox[2] = Math.min(this.#canvasWidth, this.#clipBox[2]); + this.#pendingBBox[3] = Math.min(this.#canvasHeight, this.#clipBox[3]); + return this; + } + getSimpleIndex(dependencyName) { + return this.#simple[dependencyName]; + } + recordDependencies(idx, dependencyNames) { + const pendingDependencies = this.#pendingDependencies; + const simple = this.#simple; + const incremental = this.#incremental; + for (const name of dependencyNames) { + if (name in this.#simple) { + pendingDependencies.add(simple[name]); + } else if (name in incremental) { + incremental[name].forEach(pendingDependencies.add, pendingDependencies); + } + } + return this; + } + recordNamedDependency(idx, name) { + if (this.#namedDependencies.has(name)) { + this.#pendingDependencies.add(this.#namedDependencies.get(name)); + } + return this; + } + recordOperation(idx, preserve = false) { + this.recordDependencies(idx, [FORCED_DEPENDENCY_LABEL]); + if (this.#debugMetadata) { + const metadata = ensureDebugMetadata(this.#debugMetadata, idx); + const { + dependencies + } = metadata; + this.#pendingDependencies.forEach(dependencies.add, dependencies); + this.#savesStack.forEach(dependencies.add, dependencies); + this.#markedContentStack.forEach(dependencies.add, dependencies); + dependencies.delete(idx); + metadata.isRenderingOperation = true; + } + if (this.#pendingBBoxIdx === idx) { + const minX = floor(this.#pendingBBox[0] * 256 / this.#canvasWidth); + const minY = floor(this.#pendingBBox[1] * 256 / this.#canvasHeight); + const maxX = ceil(this.#pendingBBox[2] * 256 / this.#canvasWidth); + const maxY = ceil(this.#pendingBBox[3] * 256 / this.#canvasHeight); + expandBBox(this.#bboxesCoords, idx, minX, minY, maxX, maxY); + for (const depIdx of this.#pendingDependencies) { + if (depIdx !== idx) { + expandBBox(this.#bboxesCoords, depIdx, minX, minY, maxX, maxY); + } + } + for (const saveIdx of this.#savesStack) { + if (saveIdx !== idx) { + expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY); + } + } + for (const saveIdx of this.#markedContentStack) { + if (saveIdx !== idx) { + expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY); + } + } + if (!preserve) { + this.#pendingDependencies.clear(); + this.#pendingBBoxIdx = -1; + } + } + return this; + } + recordShowTextOperation(idx, preserve = false) { + const deps = Array.from(this.#pendingDependencies); + this.recordOperation(idx, preserve); + this.recordIncrementalData("sameLineText", idx); + for (const dep of deps) { + this.recordIncrementalData("sameLineText", dep); + } + return this; + } + bboxToClipBoxDropOperation(idx, preserve = false) { + if (this.#pendingBBoxIdx === idx) { + this.#pendingBBoxIdx = -1; + this.#clipBox[0] = Math.max(this.#clipBox[0], this.#pendingBBox[0]); + this.#clipBox[1] = Math.max(this.#clipBox[1], this.#pendingBBox[1]); + this.#clipBox[2] = Math.min(this.#clipBox[2], this.#pendingBBox[2]); + this.#clipBox[3] = Math.min(this.#clipBox[3], this.#pendingBBox[3]); + if (!preserve) { + this.#pendingDependencies.clear(); + } + } + return this; + } + _takePendingDependencies() { + const pendingDependencies = this.#pendingDependencies; + this.#pendingDependencies = new Set(); + return pendingDependencies; + } + _extractOperation(idx) { + const operation = this.#operations.get(idx); + this.#operations.delete(idx); + return operation; + } + _pushPendingDependencies(dependencies) { + for (const dep of dependencies) { + this.#pendingDependencies.add(dep); + } + } + take() { + this.#fontBBoxTrustworthy.clear(); + return new BBoxReader(this.#bboxes, this.#bboxesCoords); + } + takeDebugMetadata() { + return this.#debugMetadata; + } +} +class CanvasNestedDependencyTracker { + #dependencyTracker; + #opIdx; + #ignoreBBoxes; + #nestingLevel = 0; + #savesLevel = 0; + constructor(dependencyTracker, opIdx, ignoreBBoxes) { + if (dependencyTracker instanceof CanvasNestedDependencyTracker && dependencyTracker.#ignoreBBoxes === !!ignoreBBoxes) { + return dependencyTracker; + } + this.#dependencyTracker = dependencyTracker; + this.#opIdx = opIdx; + this.#ignoreBBoxes = !!ignoreBBoxes; + } + growOperationsCount() { + throw new Error("Unreachable"); + } + save(opIdx) { + this.#savesLevel++; + this.#dependencyTracker.save(this.#opIdx); + return this; + } + restore(opIdx) { + if (this.#savesLevel > 0) { + this.#dependencyTracker.restore(this.#opIdx); + this.#savesLevel--; + } + return this; + } + recordOpenMarker(idx) { + this.#nestingLevel++; + return this; + } + getOpenMarker() { + return this.#nestingLevel > 0 ? this.#opIdx : this.#dependencyTracker.getOpenMarker(); + } + recordCloseMarker(idx) { + this.#nestingLevel--; + return this; + } + beginMarkedContent(opIdx) { + return this; + } + endMarkedContent(opIdx) { + return this; + } + pushBaseTransform(ctx) { + this.#dependencyTracker.pushBaseTransform(ctx); + return this; + } + popBaseTransform() { + this.#dependencyTracker.popBaseTransform(); + return this; + } + recordSimpleData(name, idx) { + this.#dependencyTracker.recordSimpleData(name, this.#opIdx); + return this; + } + recordIncrementalData(name, idx) { + this.#dependencyTracker.recordIncrementalData(name, this.#opIdx); + return this; + } + resetIncrementalData(name, idx) { + this.#dependencyTracker.resetIncrementalData(name, this.#opIdx); + return this; + } + recordNamedData(name, idx) { + return this; + } + recordSimpleDataFromNamed(name, depName, fallbackIdx) { + this.#dependencyTracker.recordSimpleDataFromNamed(name, depName, this.#opIdx); + return this; + } + recordFutureForcedDependency(name, idx) { + this.#dependencyTracker.recordFutureForcedDependency(name, this.#opIdx); + return this; + } + inheritSimpleDataAsFutureForcedDependencies(names) { + this.#dependencyTracker.inheritSimpleDataAsFutureForcedDependencies(names); + return this; + } + inheritPendingDependenciesAsFutureForcedDependencies() { + this.#dependencyTracker.inheritPendingDependenciesAsFutureForcedDependencies(); + return this; + } + resetBBox(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.resetBBox(this.#opIdx); + } + return this; + } + recordClipBox(idx, ctx, minX, maxX, minY, maxY) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordClipBox(this.#opIdx, ctx, minX, maxX, minY, maxY); + } + return this; + } + recordBBox(idx, ctx, minX, maxX, minY, maxY) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordBBox(this.#opIdx, ctx, minX, maxX, minY, maxY); + } + return this; + } + recordCharacterBBox(idx, ctx, font, scale, x, y, getMeasure) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordCharacterBBox(this.#opIdx, ctx, font, scale, x, y, getMeasure); + } + return this; + } + recordFullPageBBox(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordFullPageBBox(this.#opIdx); + } + return this; + } + getSimpleIndex(dependencyName) { + return this.#dependencyTracker.getSimpleIndex(dependencyName); + } + recordDependencies(idx, dependencyNames) { + this.#dependencyTracker.recordDependencies(this.#opIdx, dependencyNames); + return this; + } + recordNamedDependency(idx, name) { + this.#dependencyTracker.recordNamedDependency(this.#opIdx, name); + return this; + } + recordOperation(idx) { + this.#dependencyTracker.recordOperation(this.#opIdx, true); + return this; + } + recordShowTextOperation(idx) { + this.#dependencyTracker.recordShowTextOperation(this.#opIdx, true); + return this; + } + bboxToClipBoxDropOperation(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.bboxToClipBoxDropOperation(this.#opIdx, true); + } + return this; + } + take() { + throw new Error("Unreachable"); + } + takeDebugMetadata() { + throw new Error("Unreachable"); + } +} +const Dependencies = { + stroke: ["path", "transform", "filter", "strokeColor", "strokeAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "dash"], + fill: ["path", "transform", "filter", "fillColor", "fillAlpha", "globalCompositeOperation", "SMask"], + imageXObject: ["transform", "SMask", "filter", "fillAlpha", "strokeAlpha", "globalCompositeOperation"], + rawFillPath: ["filter", "fillColor", "fillAlpha"], + showText: ["transform", "leading", "charSpacing", "wordSpacing", "hScale", "textRise", "moveText", "textMatrix", "font", "fontObj", "filter", "fillColor", "textRenderingMode", "SMask", "fillAlpha", "strokeAlpha", "globalCompositeOperation", "sameLineText"], + transform: ["transform"], + transformAndFill: ["transform", "fillColor"] +}; + +;// ./src/display/pattern_helper.js + + +const PathType = { + FILL: "Fill", + STROKE: "Stroke", + SHADING: "Shading" +}; +function applyBoundingBox(ctx, bbox) { + if (!bbox) { + return; + } + const width = bbox[2] - bbox[0]; + const height = bbox[3] - bbox[1]; + const region = new Path2D(); + region.rect(bbox[0], bbox[1], width, height); + ctx.clip(region); +} +class BaseShadingPattern { + isModifyingCurrentTransform() { + return false; + } + getPattern() { + unreachable("Abstract method `getPattern` called."); + } +} +class RadialAxialShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._type = IR[1]; + this._bbox = IR[2]; + this._colorStops = IR[3]; + this._p0 = IR[4]; + this._p1 = IR[5]; + this._r0 = IR[6]; + this._r1 = IR[7]; + this.matrix = null; + } + _createGradient(ctx) { + let grad; + if (this._type === "axial") { + grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]); + } else if (this._type === "radial") { + grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1); + } + for (const colorStop of this._colorStops) { + grad.addColorStop(colorStop[0], colorStop[1]); + } + return grad; + } + getPattern(ctx, owner, inverse, pathType) { + let pattern; + if (pathType === PathType.STROKE || pathType === PathType.FILL) { + const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx)) || [0, 0, 0, 0]; + const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1; + const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1; + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height); + const tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.beginPath(); + tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]); + inverse = Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]); + tmpCtx.transform(...owner.baseTransform); + if (this.matrix) { + tmpCtx.transform(...this.matrix); + } + applyBoundingBox(tmpCtx, this._bbox); + tmpCtx.fillStyle = this._createGradient(tmpCtx); + tmpCtx.fill(); + pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat"); + const domMatrix = new DOMMatrix(inverse); + pattern.setTransform(domMatrix); + } else { + applyBoundingBox(ctx, this._bbox); + pattern = this._createGradient(ctx); + } + return pattern; + } +} +function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { + const coords = context.coords, + colors = context.colors; + const bytes = data.data, + rowSize = data.width * 4; + let tmp; + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + if (coords[p2 + 1] > coords[p3 + 1]) { + tmp = p2; + p2 = p3; + p3 = tmp; + tmp = c2; + c2 = c3; + c3 = tmp; + } + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + const x1 = (coords[p1] + context.offsetX) * context.scaleX; + const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; + const x2 = (coords[p2] + context.offsetX) * context.scaleX; + const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; + const x3 = (coords[p3] + context.offsetX) * context.scaleX; + const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; + if (y1 >= y3) { + return; + } + const c1r = colors[c1], + c1g = colors[c1 + 1], + c1b = colors[c1 + 2]; + const c2r = colors[c2], + c2g = colors[c2 + 1], + c2b = colors[c2 + 2]; + const c3r = colors[c3], + c3g = colors[c3 + 1], + c3b = colors[c3 + 2]; + const minY = Math.round(y1), + maxY = Math.round(y3); + let xa, car, cag, cab; + let xb, cbr, cbg, cbb; + for (let y = minY; y <= maxY; y++) { + if (y < y2) { + const k = y < y1 ? 0 : (y1 - y) / (y1 - y2); + xa = x1 - (x1 - x2) * k; + car = c1r - (c1r - c2r) * k; + cag = c1g - (c1g - c2g) * k; + cab = c1b - (c1b - c2b) * k; + } else { + let k; + if (y > y3) { + k = 1; + } else if (y2 === y3) { + k = 0; + } else { + k = (y2 - y) / (y2 - y3); + } + xa = x2 - (x2 - x3) * k; + car = c2r - (c2r - c3r) * k; + cag = c2g - (c2g - c3g) * k; + cab = c2b - (c2b - c3b) * k; + } + let k; + if (y < y1) { + k = 0; + } else if (y > y3) { + k = 1; + } else { + k = (y1 - y) / (y1 - y3); + } + xb = x1 - (x1 - x3) * k; + cbr = c1r - (c1r - c3r) * k; + cbg = c1g - (c1g - c3g) * k; + cbb = c1b - (c1b - c3b) * k; + const x1_ = Math.round(Math.min(xa, xb)); + const x2_ = Math.round(Math.max(xa, xb)); + let j = rowSize * y + x1_ * 4; + for (let x = x1_; x <= x2_; x++) { + k = (xa - x) / (xa - xb); + if (k < 0) { + k = 0; + } else if (k > 1) { + k = 1; + } + bytes[j++] = car - (car - cbr) * k | 0; + bytes[j++] = cag - (cag - cbg) * k | 0; + bytes[j++] = cab - (cab - cbb) * k | 0; + bytes[j++] = 255; + } + } +} +function drawFigure(data, figure, context) { + const ps = figure.coords; + const cs = figure.colors; + let i, ii; + switch (figure.type) { + case MeshFigureType.LATTICE: + const verticesPerRow = figure.verticesPerRow; + const rows = Math.floor(ps.length / verticesPerRow) - 1; + const cols = verticesPerRow - 1; + for (i = 0; i < rows; i++) { + let q = i * verticesPerRow; + for (let j = 0; j < cols; j++, q++) { + drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]); + drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); + } + } + break; + case MeshFigureType.TRIANGLES: + for (i = 0, ii = ps.length; i < ii; i += 3) { + drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]); + } + break; + default: + throw new Error("illegal figure"); + } +} +class MeshShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._coords = IR[2]; + this._colors = IR[3]; + this._figures = IR[4]; + this._bounds = IR[5]; + this._bbox = IR[6]; + this._background = IR[7]; + this.matrix = null; + } + _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) { + const EXPECTED_SCALE = 1.1; + const MAX_PATTERN_SIZE = 3000; + const BORDER_SIZE = 2; + const offsetX = Math.floor(this._bounds[0]); + const offsetY = Math.floor(this._bounds[1]); + const boundsWidth = Math.ceil(this._bounds[2]) - offsetX; + const boundsHeight = Math.ceil(this._bounds[3]) - offsetY; + const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const scaleX = boundsWidth / width; + const scaleY = boundsHeight / height; + const context = { + coords: this._coords, + colors: this._colors, + offsetX: -offsetX, + offsetY: -offsetY, + scaleX: 1 / scaleX, + scaleY: 1 / scaleY + }; + const paddedWidth = width + BORDER_SIZE * 2; + const paddedHeight = height + BORDER_SIZE * 2; + const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight); + const tmpCtx = tmpCanvas.context; + const data = tmpCtx.createImageData(width, height); + if (backgroundColor) { + const bytes = data.data; + for (let i = 0, ii = bytes.length; i < ii; i += 4) { + bytes[i] = backgroundColor[0]; + bytes[i + 1] = backgroundColor[1]; + bytes[i + 2] = backgroundColor[2]; + bytes[i + 3] = 255; + } + } + for (const figure of this._figures) { + drawFigure(data, figure, context); + } + tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE); + const canvas = tmpCanvas.canvas; + return { + canvas, + offsetX: offsetX - BORDER_SIZE * scaleX, + offsetY: offsetY - BORDER_SIZE * scaleY, + scaleX, + scaleY + }; + } + isModifyingCurrentTransform() { + return true; + } + getPattern(ctx, owner, inverse, pathType) { + applyBoundingBox(ctx, this._bbox); + const scale = new Float32Array(2); + if (pathType === PathType.SHADING) { + Util.singularValueDecompose2dScale(getCurrentTransform(ctx), scale); + } else if (this.matrix) { + Util.singularValueDecompose2dScale(this.matrix, scale); + const [matrixScaleX, matrixScaleY] = scale; + Util.singularValueDecompose2dScale(owner.baseTransform, scale); + scale[0] *= matrixScaleX; + scale[1] *= matrixScaleY; + } else { + Util.singularValueDecompose2dScale(owner.baseTransform, scale); + } + const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases); + if (pathType !== PathType.SHADING) { + ctx.setTransform(...owner.baseTransform); + if (this.matrix) { + ctx.transform(...this.matrix); + } + } + ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY); + return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat"); + } +} +class DummyShadingPattern extends BaseShadingPattern { + getPattern() { + return "hotpink"; + } +} +function getShadingPattern(IR) { + switch (IR[0]) { + case "RadialAxial": + return new RadialAxialShadingPattern(IR); + case "Mesh": + return new MeshShadingPattern(IR); + case "Dummy": + return new DummyShadingPattern(); + } + throw new Error(`Unknown IR type: ${IR[0]}`); +} +const PaintType = { + COLORED: 1, + UNCOLORED: 2 +}; +class TilingPattern { + static MAX_PATTERN_SIZE = 3000; + constructor(IR, ctx, canvasGraphicsFactory, baseTransform) { + this.color = IR[1]; + this.operatorList = IR[2]; + this.matrix = IR[3]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.ctx = ctx; + this.canvasGraphicsFactory = canvasGraphicsFactory; + this.baseTransform = baseTransform; + } + createPatternCanvas(owner, opIdx) { + const { + bbox, + operatorList, + paintType, + tilingType, + color, + canvasGraphicsFactory + } = this; + let { + xstep, + ystep + } = this; + xstep = Math.abs(xstep); + ystep = Math.abs(ystep); + info("TilingType: " + tilingType); + const x0 = bbox[0], + y0 = bbox[1], + x1 = bbox[2], + y1 = bbox[3]; + const width = x1 - x0; + const height = y1 - y0; + const scale = new Float32Array(2); + Util.singularValueDecompose2dScale(this.matrix, scale); + const [matrixScaleX, matrixScaleY] = scale; + Util.singularValueDecompose2dScale(this.baseTransform, scale); + const combinedScaleX = matrixScaleX * scale[0]; + const combinedScaleY = matrixScaleY * scale[1]; + let canvasWidth = width, + canvasHeight = height, + redrawHorizontally = false, + redrawVertically = false; + const xScaledStep = Math.ceil(xstep * combinedScaleX); + const yScaledStep = Math.ceil(ystep * combinedScaleY); + const xScaledWidth = Math.ceil(width * combinedScaleX); + const yScaledHeight = Math.ceil(height * combinedScaleY); + if (xScaledStep >= xScaledWidth) { + canvasWidth = xstep; + } else { + redrawHorizontally = true; + } + if (yScaledStep >= yScaledHeight) { + canvasHeight = ystep; + } else { + redrawVertically = true; + } + const dimx = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX); + const dimy = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY); + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size); + const tmpCtx = tmpCanvas.context; + const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx, opIdx); + graphics.groupLevel = owner.groupLevel; + this.setFillAndStrokeStyleToContext(graphics, paintType, color); + tmpCtx.translate(-dimx.scale * x0, -dimy.scale * y0); + graphics.transform(0, dimx.scale, 0, 0, dimy.scale, 0, 0); + tmpCtx.save(); + graphics.dependencyTracker?.save(); + this.clipBbox(graphics, x0, y0, x1, y1); + graphics.baseTransform = getCurrentTransform(graphics.ctx); + graphics.executeOperatorList(operatorList); + graphics.endDrawing(); + graphics.dependencyTracker?.restore(); + tmpCtx.restore(); + if (redrawHorizontally || redrawVertically) { + const image = tmpCanvas.canvas; + if (redrawHorizontally) { + canvasWidth = xstep; + } + if (redrawVertically) { + canvasHeight = ystep; + } + const dimx2 = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX); + const dimy2 = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY); + const xSize = dimx2.size; + const ySize = dimy2.size; + const tmpCanvas2 = owner.cachedCanvases.getCanvas("pattern-workaround", xSize, ySize); + const tmpCtx2 = tmpCanvas2.context; + const ii = redrawHorizontally ? Math.floor(width / xstep) : 0; + const jj = redrawVertically ? Math.floor(height / ystep) : 0; + for (let i = 0; i <= ii; i++) { + for (let j = 0; j <= jj; j++) { + tmpCtx2.drawImage(image, xSize * i, ySize * j, xSize, ySize, 0, 0, xSize, ySize); + } + } + return { + canvas: tmpCanvas2.canvas, + scaleX: dimx2.scale, + scaleY: dimy2.scale, + offsetX: x0, + offsetY: y0 + }; + } + return { + canvas: tmpCanvas.canvas, + scaleX: dimx.scale, + scaleY: dimy.scale, + offsetX: x0, + offsetY: y0 + }; + } + getSizeAndScale(step, realOutputSize, scale) { + const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize); + let size = Math.ceil(step * scale); + if (size >= maxSize) { + size = maxSize; + } else { + scale = size / step; + } + return { + scale, + size + }; + } + clipBbox(graphics, x0, y0, x1, y1) { + const bboxWidth = x1 - x0; + const bboxHeight = y1 - y0; + graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); + Util.axialAlignedBoundingBox([x0, y0, x1, y1], getCurrentTransform(graphics.ctx), graphics.current.minMax); + graphics.clip(); + graphics.endPath(); + } + setFillAndStrokeStyleToContext(graphics, paintType, color) { + const context = graphics.ctx, + current = graphics.current; + switch (paintType) { + case PaintType.COLORED: + const { + fillStyle, + strokeStyle + } = this.ctx; + context.fillStyle = current.fillColor = fillStyle; + context.strokeStyle = current.strokeColor = strokeStyle; + break; + case PaintType.UNCOLORED: + context.fillStyle = context.strokeStyle = color; + current.fillColor = current.strokeColor = color; + break; + default: + throw new FormatError(`Unsupported paint type: ${paintType}`); + } + } + isModifyingCurrentTransform() { + return false; + } + getPattern(ctx, owner, inverse, pathType, opIdx) { + let matrix = inverse; + if (pathType !== PathType.SHADING) { + matrix = Util.transform(matrix, owner.baseTransform); + if (this.matrix) { + matrix = Util.transform(matrix, this.matrix); + } + } + const temporaryPatternCanvas = this.createPatternCanvas(owner, opIdx); + let domMatrix = new DOMMatrix(matrix); + domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY); + const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); + pattern.setTransform(domMatrix); + return pattern; + } +} + +;// ./src/shared/image_utils.js + +function convertToRGBA(params) { + switch (params.kind) { + case ImageKind.GRAYSCALE_1BPP: + return convertBlackAndWhiteToRGBA(params); + case ImageKind.RGB_24BPP: + return convertRGBToRGBA(params); + } + return null; +} +function convertBlackAndWhiteToRGBA({ + src, + srcPos = 0, + dest, + width, + height, + nonBlackColor = 0xffffffff, + inverseDecode = false +}) { + const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; + const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor]; + const widthInSource = width >> 3; + const widthRemainder = width & 7; + const srcLength = src.length; + dest = new Uint32Array(dest.buffer); + let destPos = 0; + for (let i = 0; i < height; i++) { + for (const max = srcPos + widthInSource; srcPos < max; srcPos++) { + const elem = srcPos < srcLength ? src[srcPos] : 255; + dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping; + } + if (widthRemainder === 0) { + continue; + } + const elem = srcPos < srcLength ? src[srcPos++] : 255; + for (let j = 0; j < widthRemainder; j++) { + dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; + } + } + return { + srcPos, + destPos + }; +} +function convertRGBToRGBA({ + src, + srcPos = 0, + dest, + destPos = 0, + width, + height +}) { + let i = 0; + const len = width * height * 3; + const len32 = len >> 2; + const src32 = new Uint32Array(src.buffer, srcPos, len32); + if (FeatureTest.isLittleEndian) { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 0xff000000; + dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000; + dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000; + dest[destPos + 3] = s3 >>> 8 | 0xff000000; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000; + } + } else { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 0xff; + dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff; + dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff; + dest[destPos + 3] = s3 << 8 | 0xff; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff; + } + } + return { + srcPos: srcPos + len, + destPos + }; +} +function grayToRGBA(src, dest) { + if (FeatureTest.isLittleEndian) { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 0x10101 | 0xff000000; + } + } else { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 0x1010100 | 0x000000ff; + } + } +} + +;// ./src/display/canvas.js + + + + + +const MIN_FONT_SIZE = 16; +const MAX_FONT_SIZE = 100; +const EXECUTION_TIME = 15; +const EXECUTION_STEPS = 10; +const FULL_CHUNK_HEIGHT = 16; +const SCALE_MATRIX = new DOMMatrix(); +const XY = new Float32Array(2); +const MIN_MAX_INIT = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); +function mirrorContextOperations(ctx, destCtx) { + if (ctx._removeMirroring) { + throw new Error("Context is already forwarding operations."); + } + ctx.__originalSave = ctx.save; + ctx.__originalRestore = ctx.restore; + ctx.__originalRotate = ctx.rotate; + ctx.__originalScale = ctx.scale; + ctx.__originalTranslate = ctx.translate; + ctx.__originalTransform = ctx.transform; + ctx.__originalSetTransform = ctx.setTransform; + ctx.__originalResetTransform = ctx.resetTransform; + ctx.__originalClip = ctx.clip; + ctx.__originalMoveTo = ctx.moveTo; + ctx.__originalLineTo = ctx.lineTo; + ctx.__originalBezierCurveTo = ctx.bezierCurveTo; + ctx.__originalRect = ctx.rect; + ctx.__originalClosePath = ctx.closePath; + ctx.__originalBeginPath = ctx.beginPath; + ctx._removeMirroring = () => { + ctx.save = ctx.__originalSave; + ctx.restore = ctx.__originalRestore; + ctx.rotate = ctx.__originalRotate; + ctx.scale = ctx.__originalScale; + ctx.translate = ctx.__originalTranslate; + ctx.transform = ctx.__originalTransform; + ctx.setTransform = ctx.__originalSetTransform; + ctx.resetTransform = ctx.__originalResetTransform; + ctx.clip = ctx.__originalClip; + ctx.moveTo = ctx.__originalMoveTo; + ctx.lineTo = ctx.__originalLineTo; + ctx.bezierCurveTo = ctx.__originalBezierCurveTo; + ctx.rect = ctx.__originalRect; + ctx.closePath = ctx.__originalClosePath; + ctx.beginPath = ctx.__originalBeginPath; + delete ctx._removeMirroring; + }; + ctx.save = function () { + destCtx.save(); + this.__originalSave(); + }; + ctx.restore = function () { + destCtx.restore(); + this.__originalRestore(); + }; + ctx.translate = function (x, y) { + destCtx.translate(x, y); + this.__originalTranslate(x, y); + }; + ctx.scale = function (x, y) { + destCtx.scale(x, y); + this.__originalScale(x, y); + }; + ctx.transform = function (a, b, c, d, e, f) { + destCtx.transform(a, b, c, d, e, f); + this.__originalTransform(a, b, c, d, e, f); + }; + ctx.setTransform = function (a, b, c, d, e, f) { + destCtx.setTransform(a, b, c, d, e, f); + this.__originalSetTransform(a, b, c, d, e, f); + }; + ctx.resetTransform = function () { + destCtx.resetTransform(); + this.__originalResetTransform(); + }; + ctx.rotate = function (angle) { + destCtx.rotate(angle); + this.__originalRotate(angle); + }; + ctx.clip = function (rule) { + destCtx.clip(rule); + this.__originalClip(rule); + }; + ctx.moveTo = function (x, y) { + destCtx.moveTo(x, y); + this.__originalMoveTo(x, y); + }; + ctx.lineTo = function (x, y) { + destCtx.lineTo(x, y); + this.__originalLineTo(x, y); + }; + ctx.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { + destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + }; + ctx.rect = function (x, y, width, height) { + destCtx.rect(x, y, width, height); + this.__originalRect(x, y, width, height); + }; + ctx.closePath = function () { + destCtx.closePath(); + this.__originalClosePath(); + }; + ctx.beginPath = function () { + destCtx.beginPath(); + this.__originalBeginPath(); + }; +} +class CachedCanvases { + constructor(canvasFactory) { + this.canvasFactory = canvasFactory; + this.cache = Object.create(null); + } + getCanvas(id, width, height) { + let canvasEntry; + if (this.cache[id] !== undefined) { + canvasEntry = this.cache[id]; + this.canvasFactory.reset(canvasEntry, width, height); + } else { + canvasEntry = this.canvasFactory.create(width, height); + this.cache[id] = canvasEntry; + } + return canvasEntry; + } + delete(id) { + delete this.cache[id]; + } + clear() { + for (const id in this.cache) { + const canvasEntry = this.cache[id]; + this.canvasFactory.destroy(canvasEntry); + delete this.cache[id]; + } + } +} +function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) { + const [a, b, c, d, tx, ty] = getCurrentTransform(ctx); + if (b === 0 && c === 0) { + const tlX = destX * a + tx; + const rTlX = Math.round(tlX); + const tlY = destY * d + ty; + const rTlY = Math.round(tlY); + const brX = (destX + destW) * a + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destY + destH) * d + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight); + ctx.setTransform(a, b, c, d, tx, ty); + return [rWidth, rHeight]; + } + if (a === 0 && d === 0) { + const tlX = destY * c + tx; + const rTlX = Math.round(tlX); + const tlY = destX * b + ty; + const rTlY = Math.round(tlY); + const brX = (destY + destH) * c + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destX + destW) * b + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth); + ctx.setTransform(a, b, c, d, tx, ty); + return [rHeight, rWidth]; + } + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + const scaleX = Math.hypot(a, b); + const scaleY = Math.hypot(c, d); + return [scaleX * destW, scaleY * destH]; +} +class CanvasExtraState { + alphaIsShape = false; + fontSize = 0; + fontSizeScale = 1; + textMatrix = null; + textMatrixScale = 1; + fontMatrix = FONT_IDENTITY_MATRIX; + leading = 0; + x = 0; + y = 0; + lineX = 0; + lineY = 0; + charSpacing = 0; + wordSpacing = 0; + textHScale = 1; + textRenderingMode = TextRenderingMode.FILL; + textRise = 0; + fillColor = "#000000"; + strokeColor = "#000000"; + patternFill = false; + patternStroke = false; + fillAlpha = 1; + strokeAlpha = 1; + lineWidth = 1; + activeSMask = null; + transferMaps = "none"; + constructor(width, height, preInit) { + preInit?.(this); + this.clipBox = new Float32Array([0, 0, width, height]); + this.minMax = MIN_MAX_INIT.slice(); + } + clone() { + const clone = Object.create(this); + clone.clipBox = this.clipBox.slice(); + clone.minMax = this.minMax.slice(); + return clone; + } + getPathBoundingBox(pathType = PathType.FILL, transform = null) { + const box = this.minMax.slice(); + if (pathType === PathType.STROKE) { + if (!transform) { + unreachable("Stroke bounding box must include transform."); + } + Util.singularValueDecompose2dScale(transform, XY); + const xStrokePad = XY[0] * this.lineWidth / 2; + const yStrokePad = XY[1] * this.lineWidth / 2; + box[0] -= xStrokePad; + box[1] -= yStrokePad; + box[2] += xStrokePad; + box[3] += yStrokePad; + } + return box; + } + updateClipFromPath() { + const intersect = Util.intersect(this.clipBox, this.getPathBoundingBox()); + this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]); + } + isEmptyClip() { + return this.minMax[0] === Infinity; + } + startNewPathAndClipBox(box) { + this.clipBox.set(box, 0); + this.minMax.set(MIN_MAX_INIT, 0); + } + getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) { + return Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform)); + } +} +function putBinaryImageData(ctx, imgData) { + if (imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + const height = imgData.height, + width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0, + destPos; + const src = imgData.data; + const dest = chunkImgData.data; + let i, j, thisChunkHeight, elemsInThisChunk; + if (imgData.kind === util_ImageKind.GRAYSCALE_1BPP) { + const srcLength = src.byteLength; + const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2); + const dest32DataLength = dest32.length; + const fullSrcDiff = width + 7 >> 3; + const white = 0xffffffff; + const black = util_FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; + for (i = 0; i < totalChunks; i++) { + thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + destPos = 0; + for (j = 0; j < thisChunkHeight; j++) { + const srcDiff = srcLength - srcPos; + let k = 0; + const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7; + const kEndUnrolled = kEnd & ~7; + let mask = 0; + let srcByte = 0; + for (; k < kEndUnrolled; k += 8) { + srcByte = src[srcPos++]; + dest32[destPos++] = srcByte & 128 ? white : black; + dest32[destPos++] = srcByte & 64 ? white : black; + dest32[destPos++] = srcByte & 32 ? white : black; + dest32[destPos++] = srcByte & 16 ? white : black; + dest32[destPos++] = srcByte & 8 ? white : black; + dest32[destPos++] = srcByte & 4 ? white : black; + dest32[destPos++] = srcByte & 2 ? white : black; + dest32[destPos++] = srcByte & 1 ? white : black; + } + for (; k < kEnd; k++) { + if (mask === 0) { + srcByte = src[srcPos++]; + mask = 128; + } + dest32[destPos++] = srcByte & mask ? white : black; + mask >>= 1; + } + } + while (destPos < dest32DataLength) { + dest32[destPos++] = 0; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else if (imgData.kind === util_ImageKind.RGBA_32BPP) { + j = 0; + elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; + for (i = 0; i < fullChunks; i++) { + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + srcPos += elemsInThisChunk; + ctx.putImageData(chunkImgData, 0, j); + j += FULL_CHUNK_HEIGHT; + } + if (i < totalChunks) { + elemsInThisChunk = width * partialChunkHeight * 4; + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + ctx.putImageData(chunkImgData, 0, j); + } + } else if (imgData.kind === util_ImageKind.RGB_24BPP) { + thisChunkHeight = FULL_CHUNK_HEIGHT; + elemsInThisChunk = width * thisChunkHeight; + for (i = 0; i < totalChunks; i++) { + if (i >= fullChunks) { + thisChunkHeight = partialChunkHeight; + elemsInThisChunk = width * thisChunkHeight; + } + destPos = 0; + for (j = elemsInThisChunk; j--;) { + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = 255; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else { + throw new Error(`bad image kind: ${imgData.kind}`); + } +} +function putBinaryImageMask(ctx, imgData) { + if (imgData.bitmap) { + ctx.drawImage(imgData.bitmap, 0, 0); + return; + } + const height = imgData.height, + width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0; + const src = imgData.data; + const dest = chunkImgData.data; + for (let i = 0; i < totalChunks; i++) { + const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + ({ + srcPos + } = convertBlackAndWhiteToRGBA({ + src, + srcPos, + dest, + width, + height: thisChunkHeight, + nonBlackColor: 0 + })); + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } +} +function copyCtxState(sourceCtx, destCtx) { + const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font", "filter"]; + for (const property of properties) { + if (sourceCtx[property] !== undefined) { + destCtx[property] = sourceCtx[property]; + } + } + if (sourceCtx.setLineDash !== undefined) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } +} +function resetCtxToDefault(ctx) { + ctx.strokeStyle = ctx.fillStyle = "#000000"; + ctx.fillRule = "nonzero"; + ctx.globalAlpha = 1; + ctx.lineWidth = 1; + ctx.lineCap = "butt"; + ctx.lineJoin = "miter"; + ctx.miterLimit = 10; + ctx.globalCompositeOperation = "source-over"; + ctx.font = "10px sans-serif"; + if (ctx.setLineDash !== undefined) { + ctx.setLineDash([]); + ctx.lineDashOffset = 0; + } + const { + filter + } = ctx; + if (filter !== "none" && filter !== "") { + ctx.filter = "none"; + } +} +function getImageSmoothingEnabled(transform, interpolate) { + if (interpolate) { + return true; + } + Util.singularValueDecompose2dScale(transform, XY); + const actualScale = Math.fround(OutputScale.pixelRatio * PixelsPerInch.PDF_TO_CSS_UNITS); + return XY[0] <= actualScale && XY[1] <= actualScale; +} +const LINE_CAP_STYLES = ["butt", "round", "square"]; +const LINE_JOIN_STYLES = ["miter", "round", "bevel"]; +const NORMAL_CLIP = {}; +const EO_CLIP = {}; +class CanvasGraphics { + constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, { + optionalContentConfig, + markedContentStack = null + }, annotationCanvasMap, pageColors, dependencyTracker) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.canvasFactory = canvasFactory; + this.filterFactory = filterFactory; + this.groupStack = []; + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + this.suspendedCtx = null; + this.contentVisible = true; + this.markedContentStack = markedContentStack || []; + this.optionalContentConfig = optionalContentConfig; + this.cachedCanvases = new CachedCanvases(this.canvasFactory); + this.cachedPatterns = new Map(); + this.annotationCanvasMap = annotationCanvasMap; + this.viewportScale = 1; + this.outputScaleX = 1; + this.outputScaleY = 1; + this.pageColors = pageColors; + this._cachedScaleForStroking = [-1, 0]; + this._cachedGetSinglePixelWidth = null; + this._cachedBitmapsMap = new Map(); + this.dependencyTracker = dependencyTracker ?? null; + } + getObject(opIdx, data, fallback = null) { + if (typeof data === "string") { + this.dependencyTracker?.recordNamedDependency(opIdx, data); + return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data); + } + return fallback; + } + beginDrawing({ + transform, + viewport, + transparency = false, + background = null + }) { + const width = this.ctx.canvas.width; + const height = this.ctx.canvas.height; + const savedFillStyle = this.ctx.fillStyle; + this.ctx.fillStyle = background || "#ffffff"; + this.ctx.fillRect(0, 0, width, height); + this.ctx.fillStyle = savedFillStyle; + if (transparency) { + const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height); + this.compositeCtx = this.ctx; + this.transparentCanvas = transparentCanvas.canvas; + this.ctx = transparentCanvas.context; + this.ctx.save(); + this.ctx.transform(...getCurrentTransform(this.compositeCtx)); + } + this.ctx.save(); + resetCtxToDefault(this.ctx); + if (transform) { + this.ctx.transform(...transform); + this.outputScaleX = transform[0]; + this.outputScaleY = transform[0]; + } + this.ctx.transform(...viewport.transform); + this.viewportScale = viewport.scale; + this.baseTransform = getCurrentTransform(this.ctx); + } + executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper, operationsFilter) { + const argsArray = operatorList.argsArray; + const fnArray = operatorList.fnArray; + let i = executionStartIdx || 0; + const argsArrayLen = argsArray.length; + if (argsArrayLen === i) { + return i; + } + const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function"; + const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; + let steps = 0; + const commonObjs = this.commonObjs; + const objs = this.objs; + let fnId, fnArgs; + while (true) { + if (stepper !== undefined && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + if (!operationsFilter || operationsFilter(i)) { + fnId = fnArray[i]; + fnArgs = argsArray[i] ?? null; + if (fnId !== OPS.dependency) { + if (fnArgs === null) { + this[fnId](i); + } else { + this[fnId](i, ...fnArgs); + } + } else { + for (const depObjId of fnArgs) { + this.dependencyTracker?.recordNamedData(depObjId, i); + const objsPool = depObjId.startsWith("g_") ? commonObjs : objs; + if (!objsPool.has(depObjId)) { + objsPool.get(depObjId, continueCallback); + return i; + } + } + } + } + i++; + if (i === argsArrayLen) { + return i; + } + if (chunkOperations && ++steps > EXECUTION_STEPS) { + if (Date.now() > endTime) { + continueCallback(); + return i; + } + steps = 0; + } + } + } + #restoreInitialState() { + while (this.stateStack.length || this.inSMaskMode) { + this.restore(); + } + this.current.activeSMask = null; + this.ctx.restore(); + if (this.transparentCanvas) { + this.ctx = this.compositeCtx; + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.drawImage(this.transparentCanvas, 0, 0); + this.ctx.restore(); + this.transparentCanvas = null; + } + } + endDrawing() { + this.#restoreInitialState(); + this.cachedCanvases.clear(); + this.cachedPatterns.clear(); + for (const cache of this._cachedBitmapsMap.values()) { + for (const canvas of cache.values()) { + if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { + canvas.width = canvas.height = 0; + } + } + cache.clear(); + } + this._cachedBitmapsMap.clear(); + this.#drawFilter(); + } + #drawFilter() { + if (this.pageColors) { + const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background); + if (hcmFilterId !== "none") { + const savedFilter = this.ctx.filter; + this.ctx.filter = hcmFilterId; + this.ctx.drawImage(this.ctx.canvas, 0, 0); + this.ctx.filter = savedFilter; + } + } + } + _scaleImage(img, inverseTransform) { + const width = img.width ?? img.displayWidth; + const height = img.height ?? img.displayHeight; + let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1); + let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1); + let paintWidth = width, + paintHeight = height; + let tmpCanvasId = "prescale1"; + let tmpCanvas, tmpCtx; + while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) { + let newWidth = paintWidth, + newHeight = paintHeight; + if (widthScale > 2 && paintWidth > 1) { + newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + if (heightScale > 2 && paintHeight > 1) { + newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2; + heightScale /= paintHeight / newHeight; + } + tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight); + img = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1"; + } + return { + img, + paintWidth, + paintHeight + }; + } + _createMaskCanvas(opIdx, img) { + const ctx = this.ctx; + const { + width, + height + } = img; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + const currentTransform = getCurrentTransform(ctx); + let cache, cacheKey, scaled, maskCanvas; + if ((img.bitmap || img.data) && img.count > 1) { + const mainKey = img.bitmap || img.data.buffer; + cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]); + cache = this._cachedBitmapsMap.get(mainKey); + if (!cache) { + cache = new Map(); + this._cachedBitmapsMap.set(mainKey, cache); + } + const cachedImage = cache.get(cacheKey); + if (cachedImage && !isPatternFill) { + const offsetX = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]); + const offsetY = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]); + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill); + return { + canvas: cachedImage, + offsetX, + offsetY + }; + } + scaled = cachedImage; + } + if (!scaled) { + maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + putBinaryImageMask(maskCanvas.context, img); + } + let maskToCanvas = Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]); + maskToCanvas = Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]); + const minMax = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, width, height], maskToCanvas, minMax); + const [minX, minY, maxX, maxY] = minMax; + const drawnWidth = Math.round(maxX - minX) || 1; + const drawnHeight = Math.round(maxY - minY) || 1; + const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight); + const fillCtx = fillCanvas.context; + const offsetX = minX; + const offsetY = minY; + fillCtx.translate(-offsetX, -offsetY); + fillCtx.transform(...maskToCanvas); + if (!scaled) { + scaled = this._scaleImage(maskCanvas.canvas, getCurrentTransformInverse(fillCtx)); + scaled = scaled.img; + if (cache && isPatternFill) { + cache.set(cacheKey, scaled); + } + } + fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(fillCtx), img.interpolate); + drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height); + fillCtx.globalCompositeOperation = "source-in"; + const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]); + fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL, opIdx) : fillColor; + fillCtx.fillRect(0, 0, width, height); + if (cache && !isPatternFill) { + this.cachedCanvases.delete("fillCanvas"); + cache.set(cacheKey, fillCanvas.canvas); + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill); + return { + canvas: fillCanvas.canvas, + offsetX: Math.round(offsetX), + offsetY: Math.round(offsetY) + }; + } + setLineWidth(opIdx, width) { + this.dependencyTracker?.recordSimpleData("lineWidth", opIdx); + if (width !== this.current.lineWidth) { + this._cachedScaleForStroking[0] = -1; + } + this.current.lineWidth = width; + this.ctx.lineWidth = width; + } + setLineCap(opIdx, style) { + this.dependencyTracker?.recordSimpleData("lineCap", opIdx); + this.ctx.lineCap = LINE_CAP_STYLES[style]; + } + setLineJoin(opIdx, style) { + this.dependencyTracker?.recordSimpleData("lineJoin", opIdx); + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + } + setMiterLimit(opIdx, limit) { + this.dependencyTracker?.recordSimpleData("miterLimit", opIdx); + this.ctx.miterLimit = limit; + } + setDash(opIdx, dashArray, dashPhase) { + this.dependencyTracker?.recordSimpleData("dash", opIdx); + const ctx = this.ctx; + if (ctx.setLineDash !== undefined) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } + } + setRenderingIntent(opIdx, intent) {} + setFlatness(opIdx, flatness) {} + setGState(opIdx, states) { + for (const [key, value] of states) { + switch (key) { + case "LW": + this.setLineWidth(opIdx, value); + break; + case "LC": + this.setLineCap(opIdx, value); + break; + case "LJ": + this.setLineJoin(opIdx, value); + break; + case "ML": + this.setMiterLimit(opIdx, value); + break; + case "D": + this.setDash(opIdx, value[0], value[1]); + break; + case "RI": + this.setRenderingIntent(opIdx, value); + break; + case "FL": + this.setFlatness(opIdx, value); + break; + case "Font": + this.setFont(opIdx, value[0], value[1]); + break; + case "CA": + this.dependencyTracker?.recordSimpleData("strokeAlpha", opIdx); + this.current.strokeAlpha = value; + break; + case "ca": + this.dependencyTracker?.recordSimpleData("fillAlpha", opIdx); + this.ctx.globalAlpha = this.current.fillAlpha = value; + break; + case "BM": + this.dependencyTracker?.recordSimpleData("globalCompositeOperation", opIdx); + this.ctx.globalCompositeOperation = value; + break; + case "SMask": + this.dependencyTracker?.recordSimpleData("SMask", opIdx); + this.current.activeSMask = value ? this.tempSMask : null; + this.tempSMask = null; + this.checkSMaskState(); + break; + case "TR": + this.dependencyTracker?.recordSimpleData("filter", opIdx); + this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value); + break; + } + } + } + get inSMaskMode() { + return !!this.suspendedCtx; + } + checkSMaskState() { + const inSMaskMode = this.inSMaskMode; + if (this.current.activeSMask && !inSMaskMode) { + this.beginSMaskMode(); + } else if (!this.current.activeSMask && inSMaskMode) { + this.endSMaskMode(); + } + } + beginSMaskMode(opIdx) { + if (this.inSMaskMode) { + throw new Error("beginSMaskMode called while already in smask mode"); + } + const drawnWidth = this.ctx.canvas.width; + const drawnHeight = this.ctx.canvas.height; + const cacheId = "smaskGroupAt" + this.groupLevel; + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + this.suspendedCtx = this.ctx; + const ctx = this.ctx = scratchCanvas.context; + ctx.setTransform(this.suspendedCtx.getTransform()); + copyCtxState(this.suspendedCtx, ctx); + mirrorContextOperations(ctx, this.suspendedCtx); + this.setGState(opIdx, [["BM", "source-over"]]); + } + endSMaskMode() { + if (!this.inSMaskMode) { + throw new Error("endSMaskMode called while not in smask mode"); + } + this.ctx._removeMirroring(); + copyCtxState(this.ctx, this.suspendedCtx); + this.ctx = this.suspendedCtx; + this.suspendedCtx = null; + } + compose(dirtyBox) { + if (!this.current.activeSMask) { + return; + } + if (!dirtyBox) { + dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height]; + } else { + dirtyBox[0] = Math.floor(dirtyBox[0]); + dirtyBox[1] = Math.floor(dirtyBox[1]); + dirtyBox[2] = Math.ceil(dirtyBox[2]); + dirtyBox[3] = Math.ceil(dirtyBox[3]); + } + const smask = this.current.activeSMask; + const suspendedCtx = this.suspendedCtx; + this.composeSMask(suspendedCtx, smask, this.ctx, dirtyBox); + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); + this.ctx.restore(); + } + composeSMask(ctx, smask, layerCtx, layerBox) { + const layerOffsetX = layerBox[0]; + const layerOffsetY = layerBox[1]; + const layerWidth = layerBox[2] - layerOffsetX; + const layerHeight = layerBox[3] - layerOffsetY; + if (layerWidth === 0 || layerHeight === 0) { + return; + } + this.genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY); + ctx.save(); + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = "source-over"; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(layerCtx.canvas, 0, 0); + ctx.restore(); + } + genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) { + let maskCanvas = maskCtx.canvas; + let maskX = layerOffsetX - maskOffsetX; + let maskY = layerOffsetY - maskOffsetY; + if (backdrop) { + if (maskX < 0 || maskY < 0 || maskX + width > maskCanvas.width || maskY + height > maskCanvas.height) { + const canvas = this.cachedCanvases.getCanvas("maskExtension", width, height); + const ctx = canvas.context; + ctx.drawImage(maskCanvas, -maskX, -maskY); + ctx.globalCompositeOperation = "destination-atop"; + ctx.fillStyle = backdrop; + ctx.fillRect(0, 0, width, height); + ctx.globalCompositeOperation = "source-over"; + maskCanvas = canvas.canvas; + maskX = maskY = 0; + } else { + maskCtx.save(); + maskCtx.globalAlpha = 1; + maskCtx.setTransform(1, 0, 0, 1, 0, 0); + const clip = new Path2D(); + clip.rect(maskX, maskY, width, height); + maskCtx.clip(clip); + maskCtx.globalCompositeOperation = "destination-atop"; + maskCtx.fillStyle = backdrop; + maskCtx.fillRect(maskX, maskY, width, height); + maskCtx.restore(); + } + } + layerCtx.save(); + layerCtx.globalAlpha = 1; + layerCtx.setTransform(1, 0, 0, 1, 0, 0); + if (subtype === "Alpha" && transferMap) { + layerCtx.filter = this.filterFactory.addAlphaFilter(transferMap); + } else if (subtype === "Luminosity") { + layerCtx.filter = this.filterFactory.addLuminosityFilter(transferMap); + } + const clip = new Path2D(); + clip.rect(layerOffsetX, layerOffsetY, width, height); + layerCtx.clip(clip); + layerCtx.globalCompositeOperation = "destination-in"; + layerCtx.drawImage(maskCanvas, maskX, maskY, width, height, layerOffsetX, layerOffsetY, width, height); + layerCtx.restore(); + } + save(opIdx) { + if (this.inSMaskMode) { + copyCtxState(this.ctx, this.suspendedCtx); + } + this.ctx.save(); + const old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + this.dependencyTracker?.save(opIdx); + } + restore(opIdx) { + this.dependencyTracker?.restore(opIdx); + if (this.stateStack.length === 0) { + if (this.inSMaskMode) { + this.endSMaskMode(); + } + return; + } + this.current = this.stateStack.pop(); + this.ctx.restore(); + if (this.inSMaskMode) { + copyCtxState(this.suspendedCtx, this.ctx); + } + this.checkSMaskState(); + this.pendingClip = null; + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + } + transform(opIdx, a, b, c, d, e, f) { + this.dependencyTracker?.recordIncrementalData("transform", opIdx); + this.ctx.transform(a, b, c, d, e, f); + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + } + constructPath(opIdx, op, data, minMax) { + let [path] = data; + if (!minMax) { + path ||= data[0] = new Path2D(); + this[op](opIdx, path); + return; + } + if (this.dependencyTracker !== null) { + const outerExtraSize = op === OPS.stroke ? this.current.lineWidth / 2 : 0; + this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, this.ctx, minMax[0] - outerExtraSize, minMax[2] + outerExtraSize, minMax[1] - outerExtraSize, minMax[3] + outerExtraSize).recordDependencies(opIdx, ["transform"]); + } + if (!(path instanceof Path2D)) { + path = data[0] = makePathFromDrawOPS(path); + } + Util.axialAlignedBoundingBox(minMax, getCurrentTransform(this.ctx), this.current.minMax); + this[op](opIdx, path); + this._pathStartIdx = opIdx; + } + closePath(opIdx) { + this.ctx.closePath(); + } + stroke(opIdx, path, consumePath = true) { + const ctx = this.ctx; + const strokeColor = this.current.strokeColor; + ctx.globalAlpha = this.current.strokeAlpha; + if (this.contentVisible) { + if (typeof strokeColor === "object" && strokeColor?.getPattern) { + const baseTransform = strokeColor.isModifyingCurrentTransform() ? ctx.getTransform() : null; + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx); + if (baseTransform) { + const newPath = new Path2D(); + newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path = newPath; + } + this.rescaleAndStroke(path, false); + ctx.restore(); + } else { + this.rescaleAndStroke(path, true); + } + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.stroke); + if (consumePath) { + this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx))); + } + ctx.globalAlpha = this.current.fillAlpha; + } + closeStroke(opIdx, path) { + this.stroke(opIdx, path); + } + fill(opIdx, path, consumePath = true) { + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + let needRestore = false; + if (isPatternFill) { + const baseTransform = fillColor.isModifyingCurrentTransform() ? ctx.getTransform() : null; + this.dependencyTracker?.save(opIdx); + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx); + if (baseTransform) { + const newPath = new Path2D(); + newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path = newPath; + } + needRestore = true; + } + const intersect = this.current.getClippedPathBoundingBox(); + if (this.contentVisible && intersect !== null) { + if (this.pendingEOFill) { + ctx.fill(path, "evenodd"); + this.pendingEOFill = false; + } else { + ctx.fill(path); + } + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.fill); + if (needRestore) { + ctx.restore(); + this.dependencyTracker?.restore(opIdx); + } + if (consumePath) { + this.consumePath(opIdx, path, intersect); + } + } + eoFill(opIdx, path) { + this.pendingEOFill = true; + this.fill(opIdx, path); + } + fillStroke(opIdx, path) { + this.fill(opIdx, path, false); + this.stroke(opIdx, path, false); + this.consumePath(opIdx, path); + } + eoFillStroke(opIdx, path) { + this.pendingEOFill = true; + this.fillStroke(opIdx, path); + } + closeFillStroke(opIdx, path) { + this.fillStroke(opIdx, path); + } + closeEOFillStroke(opIdx, path) { + this.pendingEOFill = true; + this.fillStroke(opIdx, path); + } + endPath(opIdx, path) { + this.consumePath(opIdx, path); + } + rawFillPath(opIdx, path) { + this.ctx.fill(path); + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.rawFillPath).recordOperation(opIdx); + } + clip(opIdx) { + this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx); + this.pendingClip = NORMAL_CLIP; + } + eoClip(opIdx) { + this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx); + this.pendingClip = EO_CLIP; + } + beginText(opIdx) { + this.current.textMatrix = null; + this.current.textMatrixScale = 1; + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + this.dependencyTracker?.recordOpenMarker(opIdx).resetIncrementalData("sameLineText").resetIncrementalData("moveText", opIdx); + } + endText(opIdx) { + const paths = this.pendingTextPaths; + const ctx = this.ctx; + if (this.dependencyTracker) { + const { + dependencyTracker + } = this; + if (paths !== undefined) { + dependencyTracker.recordFutureForcedDependency("textClip", dependencyTracker.getOpenMarker()).recordFutureForcedDependency("textClip", opIdx); + } + dependencyTracker.recordCloseMarker(opIdx); + } + if (paths !== undefined) { + const newPath = new Path2D(); + const invTransf = ctx.getTransform().invertSelf(); + for (const { + transform, + x, + y, + fontSize, + path + } of paths) { + if (!path) { + continue; + } + newPath.addPath(path, new DOMMatrix(transform).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize)); + } + ctx.clip(newPath); + } + delete this.pendingTextPaths; + } + setCharSpacing(opIdx, spacing) { + this.dependencyTracker?.recordSimpleData("charSpacing", opIdx); + this.current.charSpacing = spacing; + } + setWordSpacing(opIdx, spacing) { + this.dependencyTracker?.recordSimpleData("wordSpacing", opIdx); + this.current.wordSpacing = spacing; + } + setHScale(opIdx, scale) { + this.dependencyTracker?.recordSimpleData("hScale", opIdx); + this.current.textHScale = scale / 100; + } + setLeading(opIdx, leading) { + this.dependencyTracker?.recordSimpleData("leading", opIdx); + this.current.leading = -leading; + } + setFont(opIdx, fontRefName, size) { + this.dependencyTracker?.recordSimpleData("font", opIdx).recordSimpleDataFromNamed("fontObj", fontRefName, opIdx); + const fontObj = this.commonObjs.get(fontRefName); + const current = this.current; + if (!fontObj) { + throw new Error(`Can't find font for ${fontRefName}`); + } + current.fontMatrix = fontObj.fontMatrix || FONT_IDENTITY_MATRIX; + if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) { + warn("Invalid font matrix for font " + fontRefName); + } + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + this.current.font = fontObj; + this.current.fontSize = size; + if (fontObj.isType3Font) { + return; + } + const name = fontObj.loadedName || "sans-serif"; + const typeface = fontObj.systemFontInfo?.css || `"${name}", ${fontObj.fallbackName}`; + let bold = "normal"; + if (fontObj.black) { + bold = "900"; + } else if (fontObj.bold) { + bold = "bold"; + } + const italic = fontObj.italic ? "italic" : "normal"; + let browserFontSize = size; + if (size < MIN_FONT_SIZE) { + browserFontSize = MIN_FONT_SIZE; + } else if (size > MAX_FONT_SIZE) { + browserFontSize = MAX_FONT_SIZE; + } + this.current.fontSizeScale = size / browserFontSize; + this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`; + } + setTextRenderingMode(opIdx, mode) { + this.dependencyTracker?.recordSimpleData("textRenderingMode", opIdx); + this.current.textRenderingMode = mode; + } + setTextRise(opIdx, rise) { + this.dependencyTracker?.recordSimpleData("textRise", opIdx); + this.current.textRise = rise; + } + moveText(opIdx, x, y) { + this.dependencyTracker?.resetIncrementalData("sameLineText").recordIncrementalData("moveText", opIdx); + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + } + setLeadingMoveText(opIdx, x, y) { + this.setLeading(opIdx, -y); + this.moveText(opIdx, x, y); + } + setTextMatrix(opIdx, matrix) { + this.dependencyTracker?.resetIncrementalData("sameLineText").recordSimpleData("textMatrix", opIdx); + const { + current + } = this; + current.textMatrix = matrix; + current.textMatrixScale = Math.hypot(matrix[0], matrix[1]); + current.x = current.lineX = 0; + current.y = current.lineY = 0; + } + nextLine(opIdx) { + this.moveText(opIdx, 0, this.current.leading); + this.dependencyTracker?.recordIncrementalData("moveText", this.dependencyTracker.getSimpleIndex("leading") ?? opIdx); + } + #getScaledPath(path, currentTransform, transform) { + const newPath = new Path2D(); + newPath.addPath(path, new DOMMatrix(transform).invertSelf().multiplySelf(currentTransform)); + return newPath; + } + paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const textRenderingMode = current.textRenderingMode; + const fontSize = current.fontSize / current.fontSizeScale; + const fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK; + const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG); + const patternFill = current.patternFill && !font.missingFile; + const patternStroke = current.patternStroke && !font.missingFile; + let path; + if ((font.disableFontFace || isAddToPathSet || patternFill || patternStroke) && !font.missingFile) { + path = font.getPathGenerator(this.commonObjs, character); + } + if (path && (font.disableFontFace || patternFill || patternStroke)) { + ctx.save(); + ctx.translate(x, y); + ctx.scale(fontSize, -fontSize); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font); + let currentTransform; + if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (patternFillTransform) { + currentTransform = ctx.getTransform(); + ctx.setTransform(...patternFillTransform); + const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform); + ctx.fill(scaledPath); + } else { + ctx.fill(path); + } + } + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (patternStrokeTransform) { + currentTransform ||= ctx.getTransform(); + ctx.setTransform(...patternStrokeTransform); + const { + a, + b, + c, + d + } = currentTransform; + const invPatternTransform = Util.inverseTransform(patternStrokeTransform); + const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform); + Util.singularValueDecompose2dScale(transf, XY); + ctx.lineWidth *= Math.max(XY[0], XY[1]) / fontSize; + ctx.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform)); + } else { + ctx.lineWidth /= fontSize; + ctx.stroke(path); + } + } + ctx.restore(); + } else { + if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character)); + } + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (this.dependencyTracker) { + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character)).recordDependencies(opIdx, Dependencies.stroke); + } + ctx.strokeText(character, x, y); + } + } + if (isAddToPathSet) { + const paths = this.pendingTextPaths ||= []; + paths.push({ + transform: getCurrentTransform(ctx), + x, + y, + fontSize, + path + }); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y); + } + } + get isFontSubpixelAAEnabled() { + const { + context: ctx + } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10); + ctx.scale(1.5, 1); + ctx.fillText("I", 0, 10); + const data = ctx.getImageData(0, 0, 10, 10).data; + let enabled = false; + for (let i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + return shadow(this, "isFontSubpixelAAEnabled", enabled); + } + showText(opIdx, glyphs) { + if (this.dependencyTracker) { + this.dependencyTracker.recordDependencies(opIdx, Dependencies.showText).resetBBox(opIdx); + if (this.current.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG) { + this.dependencyTracker.recordFutureForcedDependency("textClip", opIdx).inheritPendingDependenciesAsFutureForcedDependencies(); + } + } + const current = this.current; + const font = current.font; + if (font.isType3Font) { + this.showType3Text(opIdx, glyphs); + this.dependencyTracker?.recordShowTextOperation(opIdx); + return undefined; + } + const fontSize = current.fontSize; + if (fontSize === 0) { + this.dependencyTracker?.recordOperation(opIdx); + return undefined; + } + const ctx = this.ctx; + const fontSizeScale = current.fontSizeScale; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const fontDirection = current.fontDirection; + const textHScale = current.textHScale * fontDirection; + const glyphsLength = glyphs.length; + const vertical = font.vertical; + const spacingDir = vertical ? 1 : -1; + const defaultVMetrics = font.defaultVMetrics; + const widthAdvanceScale = fontSize * current.fontMatrix[0]; + const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill; + ctx.save(); + if (current.textMatrix) { + ctx.transform(...current.textMatrix); + } + ctx.translate(current.x, current.y + current.textRise); + if (fontDirection > 0) { + ctx.scale(textHScale, -1); + } else { + ctx.scale(textHScale, 1); + } + let patternFillTransform, patternStrokeTransform; + if (current.patternFill) { + ctx.save(); + const pattern = current.fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx); + patternFillTransform = getCurrentTransform(ctx); + ctx.restore(); + ctx.fillStyle = pattern; + } + if (current.patternStroke) { + ctx.save(); + const pattern = current.strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx); + patternStrokeTransform = getCurrentTransform(ctx); + ctx.restore(); + ctx.strokeStyle = pattern; + } + let lineWidth = current.lineWidth; + const scale = current.textMatrixScale; + if (scale === 0 || lineWidth === 0) { + const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK; + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + lineWidth = this.getSinglePixelWidth(); + } + } else { + lineWidth /= scale; + } + if (fontSizeScale !== 1.0) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + ctx.lineWidth = lineWidth; + if (font.isInvalidPDFjsFont) { + const chars = []; + let width = 0; + for (const glyph of glyphs) { + chars.push(glyph.unicode); + width += glyph.width; + } + const joinedChars = chars.join(""); + ctx.fillText(joinedChars, 0, 0); + if (this.dependencyTracker !== null) { + const measure = ctx.measureText(joinedChars); + this.dependencyTracker.recordBBox(opIdx, this.ctx, -measure.actualBoundingBoxLeft, measure.actualBoundingBoxRight, -measure.actualBoundingBoxAscent, measure.actualBoundingBoxDescent).recordShowTextOperation(opIdx); + } + current.x += width * widthAdvanceScale * textHScale; + ctx.restore(); + this.compose(); + return undefined; + } + let x = 0, + i; + for (i = 0; i < glyphsLength; ++i) { + const glyph = glyphs[i]; + if (typeof glyph === "number") { + x += spacingDir * glyph * fontSize / 1000; + continue; + } + let restoreNeeded = false; + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const character = glyph.fontChar; + const accent = glyph.accent; + let scaledX, scaledY; + let width = glyph.width; + if (vertical) { + const vmetric = glyph.vmetric || defaultVMetrics; + const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale; + const vy = vmetric[2] * widthAdvanceScale; + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + let measure; + if (font.remeasure && width > 0) { + measure = ctx.measureText(character); + const measuredWidth = measure.width * 1000 / fontSize * fontSizeScale; + if (width < measuredWidth && this.isFontSubpixelAAEnabled) { + const characterScaleX = width / measuredWidth; + restoreNeeded = true; + ctx.save(); + ctx.scale(characterScaleX, 1); + scaledX /= characterScaleX; + } else if (width !== measuredWidth) { + scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale; + } + } + if (this.contentVisible && (glyph.isInFont || font.missingFile)) { + if (simpleFillText && !accent) { + ctx.fillText(character, scaledX, scaledY); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, measure ? { + bbox: null + } : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ?? ctx.measureText(character)); + } else { + this.paintChar(opIdx, character, scaledX, scaledY, patternFillTransform, patternStrokeTransform); + if (accent) { + const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale; + const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale; + this.paintChar(opIdx, accent.fontChar, scaledAccentX, scaledAccentY, patternFillTransform, patternStrokeTransform); + } + } + } + const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection; + x += charWidth; + if (restoreNeeded) { + ctx.restore(); + } + } + if (vertical) { + current.y -= x; + } else { + current.x += x * textHScale; + } + ctx.restore(); + this.compose(); + this.dependencyTracker?.recordShowTextOperation(opIdx); + return undefined; + } + showType3Text(opIdx, glyphs) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const fontSize = current.fontSize; + const fontDirection = current.fontDirection; + const spacingDir = font.vertical ? 1 : -1; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const textHScale = current.textHScale * fontDirection; + const fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX; + const glyphsLength = glyphs.length; + const isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE; + let i, glyph, width, spacingLength; + if (isTextInvisible || fontSize === 0) { + return; + } + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + ctx.save(); + if (current.textMatrix) { + ctx.transform(...current.textMatrix); + } + ctx.translate(current.x, current.y + current.textRise); + ctx.scale(textHScale, fontDirection); + const dependencyTracker = this.dependencyTracker; + this.dependencyTracker = dependencyTracker ? new CanvasNestedDependencyTracker(dependencyTracker, opIdx) : null; + for (i = 0; i < glyphsLength; ++i) { + glyph = glyphs[i]; + if (typeof glyph === "number") { + spacingLength = spacingDir * glyph * fontSize / 1000; + this.ctx.translate(spacingLength, 0); + current.x += spacingLength * textHScale; + continue; + } + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const operatorList = font.charProcOperatorList[glyph.operatorListId]; + if (!operatorList) { + warn(`Type3 character "${glyph.operatorListId}" is not available.`); + } else if (this.contentVisible) { + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform(...fontMatrix); + this.executeOperatorList(operatorList); + this.restore(); + } + const p = [glyph.width, 0]; + Util.applyTransform(p, fontMatrix); + width = p[0] * fontSize + spacing; + ctx.translate(width, 0); + current.x += width * textHScale; + } + ctx.restore(); + if (dependencyTracker) { + this.dependencyTracker = dependencyTracker; + } + } + setCharWidth(opIdx, xWidth, yWidth) {} + setCharWidthAndBounds(opIdx, xWidth, yWidth, llx, lly, urx, ury) { + const clip = new Path2D(); + clip.rect(llx, lly, urx - llx, ury - lly); + this.ctx.clip(clip); + this.dependencyTracker?.recordBBox(opIdx, this.ctx, llx, urx, lly, ury).recordClipBox(opIdx, this.ctx, llx, urx, lly, ury); + this.endPath(opIdx); + } + getColorN_Pattern(opIdx, IR) { + let pattern; + if (IR[0] === "TilingPattern") { + const baseTransform = this.baseTransform || getCurrentTransform(this.ctx); + const canvasGraphicsFactory = { + createCanvasGraphics: (ctx, renderingOpIdx) => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { + optionalContentConfig: this.optionalContentConfig, + markedContentStack: this.markedContentStack + }, undefined, undefined, this.dependencyTracker ? new CanvasNestedDependencyTracker(this.dependencyTracker, renderingOpIdx, true) : null) + }; + pattern = new TilingPattern(IR, this.ctx, canvasGraphicsFactory, baseTransform); + } else { + pattern = this._getPattern(opIdx, IR[1], IR[2]); + } + return pattern; + } + setStrokeColorN(opIdx, ...args) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.current.strokeColor = this.getColorN_Pattern(opIdx, args); + this.current.patternStroke = true; + } + setFillColorN(opIdx, ...args) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.current.fillColor = this.getColorN_Pattern(opIdx, args); + this.current.patternFill = true; + } + setStrokeRGBColor(opIdx, color) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.ctx.strokeStyle = this.current.strokeColor = color; + this.current.patternStroke = false; + } + setStrokeTransparent(opIdx) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.ctx.strokeStyle = this.current.strokeColor = "transparent"; + this.current.patternStroke = false; + } + setFillRGBColor(opIdx, color) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.ctx.fillStyle = this.current.fillColor = color; + this.current.patternFill = false; + } + setFillTransparent(opIdx) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.ctx.fillStyle = this.current.fillColor = "transparent"; + this.current.patternFill = false; + } + _getPattern(opIdx, objId, matrix = null) { + let pattern; + if (this.cachedPatterns.has(objId)) { + pattern = this.cachedPatterns.get(objId); + } else { + pattern = getShadingPattern(this.getObject(opIdx, objId)); + this.cachedPatterns.set(objId, pattern); + } + if (matrix) { + pattern.matrix = matrix; + } + return pattern; + } + shadingFill(opIdx, objId) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + this.save(opIdx); + const pattern = this._getPattern(opIdx, objId); + ctx.fillStyle = pattern.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.SHADING, opIdx); + const inv = getCurrentTransformInverse(ctx); + if (inv) { + const { + width, + height + } = ctx.canvas; + const minMax = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, width, height], inv, minMax); + const [x0, y0, x1, y1] = minMax; + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + this.dependencyTracker?.resetBBox(opIdx).recordFullPageBBox(opIdx).recordDependencies(opIdx, Dependencies.transform).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx); + this.compose(this.current.getClippedPathBoundingBox()); + this.restore(opIdx); + } + beginInlineImage() { + unreachable("Should not call beginInlineImage"); + } + beginImageData() { + unreachable("Should not call beginImageData"); + } + paintFormXObjectBegin(opIdx, matrix, bbox) { + if (!this.contentVisible) { + return; + } + this.save(opIdx); + this.baseTransformStack.push(this.baseTransform); + if (matrix) { + this.transform(opIdx, ...matrix); + } + this.baseTransform = getCurrentTransform(this.ctx); + if (bbox) { + Util.axialAlignedBoundingBox(bbox, this.baseTransform, this.current.minMax); + const [x0, y0, x1, y1] = bbox; + const clip = new Path2D(); + clip.rect(x0, y0, x1 - x0, y1 - y0); + this.ctx.clip(clip); + this.dependencyTracker?.recordClipBox(opIdx, this.ctx, x0, x1, y0, y1); + this.endPath(opIdx); + } + } + paintFormXObjectEnd(opIdx) { + if (!this.contentVisible) { + return; + } + this.restore(opIdx); + this.baseTransform = this.baseTransformStack.pop(); + } + beginGroup(opIdx, group) { + if (!this.contentVisible) { + return; + } + this.save(opIdx); + if (this.inSMaskMode) { + this.endSMaskMode(); + this.current.activeSMask = null; + } + const currentCtx = this.ctx; + if (!group.isolated) { + info("TODO: Support non-isolated groups."); + } + if (group.knockout) { + warn("Knockout groups not supported."); + } + const currentTransform = getCurrentTransform(currentCtx); + if (group.matrix) { + currentCtx.transform(...group.matrix); + } + if (!group.bbox) { + throw new Error("Bounding box is required."); + } + let bounds = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox(group.bbox, getCurrentTransform(currentCtx), bounds); + const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height]; + bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + const offsetX = Math.floor(bounds[0]); + const offsetY = Math.floor(bounds[1]); + const drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); + const drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); + this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]); + let cacheId = "groupAt" + this.groupLevel; + if (group.smask) { + cacheId += "_smask_" + this.smaskCounter++ % 2; + } + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + const groupCtx = scratchCanvas.context; + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform(...currentTransform); + let clip = new Path2D(); + const [x0, y0, x1, y1] = group.bbox; + clip.rect(x0, y0, x1 - x0, y1 - y0); + if (group.matrix) { + const path = new Path2D(); + path.addPath(clip, new DOMMatrix(group.matrix)); + clip = path; + } + groupCtx.clip(clip); + if (group.smask) { + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX, + offsetY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop, + transferMap: group.smask.transferMap || null, + startTransformInverse: null + }); + } + if (!group.smask || this.dependencyTracker) { + currentCtx.setTransform(1, 0, 0, 1, 0, 0); + currentCtx.translate(offsetX, offsetY); + currentCtx.save(); + } + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.dependencyTracker?.inheritSimpleDataAsFutureForcedDependencies(["fillAlpha", "strokeAlpha", "globalCompositeOperation"]).pushBaseTransform(currentCtx); + this.setGState(opIdx, [["BM", "source-over"], ["ca", 1], ["CA", 1]]); + this.groupStack.push(currentCtx); + this.groupLevel++; + } + endGroup(opIdx, group) { + if (!this.contentVisible) { + return; + } + this.groupLevel--; + const groupCtx = this.ctx; + const ctx = this.groupStack.pop(); + this.ctx = ctx; + this.ctx.imageSmoothingEnabled = false; + this.dependencyTracker?.popBaseTransform(); + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + this.restore(opIdx); + if (this.dependencyTracker) { + this.ctx.restore(); + } + } else { + this.ctx.restore(); + const currentMtx = getCurrentTransform(this.ctx); + this.restore(opIdx); + this.ctx.save(); + this.ctx.setTransform(...currentMtx); + const dirtyBox = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx, dirtyBox); + this.ctx.drawImage(groupCtx.canvas, 0, 0); + this.ctx.restore(); + this.compose(dirtyBox); + } + } + beginAnnotation(opIdx, id, rect, transform, matrix, hasOwnCanvas) { + this.#restoreInitialState(); + resetCtxToDefault(this.ctx); + this.ctx.save(); + this.save(opIdx); + if (this.baseTransform) { + this.ctx.setTransform(...this.baseTransform); + } + if (rect) { + const width = rect[2] - rect[0]; + const height = rect[3] - rect[1]; + if (hasOwnCanvas && this.annotationCanvasMap) { + transform = transform.slice(); + transform[4] -= rect[0]; + transform[5] -= rect[1]; + rect = rect.slice(); + rect[0] = rect[1] = 0; + rect[2] = width; + rect[3] = height; + Util.singularValueDecompose2dScale(getCurrentTransform(this.ctx), XY); + const { + viewportScale + } = this; + const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale); + const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale); + this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight); + const { + canvas, + context + } = this.annotationCanvas; + this.annotationCanvasMap.set(id, canvas); + this.annotationCanvas.savedCtx = this.ctx; + this.ctx = context; + this.ctx.save(); + this.ctx.setTransform(XY[0], 0, 0, -XY[1], 0, height * XY[1]); + resetCtxToDefault(this.ctx); + } else { + resetCtxToDefault(this.ctx); + this.endPath(opIdx); + const clip = new Path2D(); + clip.rect(rect[0], rect[1], width, height); + this.ctx.clip(clip); + } + } + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.transform(opIdx, ...transform); + this.transform(opIdx, ...matrix); + } + endAnnotation(opIdx) { + if (this.annotationCanvas) { + this.ctx.restore(); + this.#drawFilter(); + this.ctx = this.annotationCanvas.savedCtx; + delete this.annotationCanvas.savedCtx; + delete this.annotationCanvas; + } + } + paintImageMaskXObject(opIdx, img) { + if (!this.contentVisible) { + return; + } + const count = img.count; + img = this.getObject(opIdx, img.data, img); + img.count = count; + const ctx = this.ctx; + const mask = this._createMaskCanvas(opIdx, img); + const maskCanvas = mask.canvas; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY); + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, mask.offsetX, mask.offsetX + maskCanvas.width, mask.offsetY, mask.offsetY + maskCanvas.height).recordOperation(opIdx); + ctx.restore(); + this.compose(); + } + paintImageMaskXObjectRepeat(opIdx, img, scaleX, skewX = 0, skewY = 0, scaleY, positions) { + if (!this.contentVisible) { + return; + } + img = this.getObject(opIdx, img.data, img); + const ctx = this.ctx; + ctx.save(); + const currentTransform = getCurrentTransform(ctx); + ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0); + const mask = this._createMaskCanvas(opIdx, img); + ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]); + this.dependencyTracker?.resetBBox(opIdx); + for (let i = 0, ii = positions.length; i < ii; i += 2) { + const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]); + ctx.drawImage(mask.canvas, trans[4], trans[5]); + this.dependencyTracker?.recordBBox(opIdx, this.ctx, trans[4], trans[4] + mask.canvas.width, trans[5], trans[5] + mask.canvas.height); + } + ctx.restore(); + this.compose(); + this.dependencyTracker?.recordOperation(opIdx); + } + paintImageMaskXObjectGroup(opIdx, images) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + this.dependencyTracker?.resetBBox(opIdx).recordDependencies(opIdx, Dependencies.transformAndFill); + for (const image of images) { + const { + data, + width, + height, + transform + } = image; + const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + const maskCtx = maskCanvas.context; + maskCtx.save(); + const img = this.getObject(opIdx, data, image); + putBinaryImageMask(maskCtx, img); + maskCtx.globalCompositeOperation = "source-in"; + maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx) : fillColor; + maskCtx.fillRect(0, 0, width, height); + maskCtx.restore(); + ctx.save(); + ctx.transform(...transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1); + this.dependencyTracker?.recordBBox(opIdx, ctx, 0, width, 0, height); + ctx.restore(); + } + this.compose(); + this.dependencyTracker?.recordOperation(opIdx); + } + paintImageXObject(opIdx, objId) { + if (!this.contentVisible) { + return; + } + const imgData = this.getObject(opIdx, objId); + if (!imgData) { + warn("Dependent image isn't ready yet"); + return; + } + this.paintInlineImageXObject(opIdx, imgData); + } + paintImageXObjectRepeat(opIdx, objId, scaleX, scaleY, positions) { + if (!this.contentVisible) { + return; + } + const imgData = this.getObject(opIdx, objId); + if (!imgData) { + warn("Dependent image isn't ready yet"); + return; + } + const width = imgData.width; + const height = imgData.height; + const map = []; + for (let i = 0, ii = positions.length; i < ii; i += 2) { + map.push({ + transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]], + x: 0, + y: 0, + w: width, + h: height + }); + } + this.paintInlineImageXObjectGroup(opIdx, imgData, map); + } + applyTransferMapsToCanvas(ctx) { + if (this.current.transferMaps !== "none") { + ctx.filter = this.current.transferMaps; + ctx.drawImage(ctx.canvas, 0, 0); + ctx.filter = "none"; + } + return ctx.canvas; + } + applyTransferMapsToBitmap(imgData) { + if (this.current.transferMaps === "none") { + return imgData.bitmap; + } + const { + bitmap, + width, + height + } = imgData; + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); + const tmpCtx = tmpCanvas.context; + tmpCtx.filter = this.current.transferMaps; + tmpCtx.drawImage(bitmap, 0, 0); + tmpCtx.filter = "none"; + return tmpCanvas.canvas; + } + paintInlineImageXObject(opIdx, imgData) { + if (!this.contentVisible) { + return; + } + const width = imgData.width; + const height = imgData.height; + const ctx = this.ctx; + this.save(opIdx); + const { + filter + } = ctx; + if (filter !== "none" && filter !== "") { + ctx.filter = "none"; + } + ctx.scale(1 / width, -1 / height); + let imgToPaint; + if (imgData.bitmap) { + imgToPaint = this.applyTransferMapsToBitmap(imgData); + } else if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) { + imgToPaint = imgData; + } else { + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); + } + const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx)); + ctx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx), imgData.interpolate); + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, ctx, 0, width, -height, 0).recordDependencies(opIdx, Dependencies.imageXObject).recordOperation(opIdx); + drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height); + this.compose(); + this.restore(opIdx); + } + paintInlineImageXObjectGroup(opIdx, imgData, map) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + let imgToPaint; + if (imgData.bitmap) { + imgToPaint = imgData.bitmap; + } else { + const w = imgData.width; + const h = imgData.height; + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); + } + this.dependencyTracker?.resetBBox(opIdx); + for (const entry of map) { + ctx.save(); + ctx.transform(...entry.transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1); + this.dependencyTracker?.recordBBox(opIdx, ctx, 0, 1, -1, 0); + ctx.restore(); + } + this.dependencyTracker?.recordOperation(opIdx); + this.compose(); + } + paintSolidColorImageMask(opIdx) { + if (!this.contentVisible) { + return; + } + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, 0, 1, 0, 1).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx); + this.ctx.fillRect(0, 0, 1, 1); + this.compose(); + } + markPoint(opIdx, tag) {} + markPointProps(opIdx, tag, properties) {} + beginMarkedContent(opIdx, tag) { + this.dependencyTracker?.beginMarkedContent(opIdx); + this.markedContentStack.push({ + visible: true + }); + } + beginMarkedContentProps(opIdx, tag, properties) { + this.dependencyTracker?.beginMarkedContent(opIdx); + if (tag === "OC") { + this.markedContentStack.push({ + visible: this.optionalContentConfig.isVisible(properties) + }); + } else { + this.markedContentStack.push({ + visible: true + }); + } + this.contentVisible = this.isContentVisible(); + } + endMarkedContent(opIdx) { + this.dependencyTracker?.endMarkedContent(opIdx); + this.markedContentStack.pop(); + this.contentVisible = this.isContentVisible(); + } + beginCompat(opIdx) {} + endCompat(opIdx) {} + consumePath(opIdx, path, clipBox) { + const isEmpty = this.current.isEmptyClip(); + if (this.pendingClip) { + this.current.updateClipFromPath(); + } + if (!this.pendingClip) { + this.compose(clipBox); + } + const ctx = this.ctx; + if (this.pendingClip) { + if (!isEmpty) { + if (this.pendingClip === EO_CLIP) { + ctx.clip(path, "evenodd"); + } else { + ctx.clip(path); + } + } + this.pendingClip = null; + this.dependencyTracker?.bboxToClipBoxDropOperation(opIdx).recordFutureForcedDependency("clipPath", opIdx); + } else { + this.dependencyTracker?.recordOperation(opIdx); + } + this.current.startNewPathAndClipBox(this.current.clipBox); + } + getSinglePixelWidth() { + if (!this._cachedGetSinglePixelWidth) { + const m = getCurrentTransform(this.ctx); + if (m[1] === 0 && m[2] === 0) { + this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3])); + } else { + const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]); + const normX = Math.hypot(m[0], m[2]); + const normY = Math.hypot(m[1], m[3]); + this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet; + } + } + return this._cachedGetSinglePixelWidth; + } + getScaleForStroking() { + if (this._cachedScaleForStroking[0] === -1) { + const { + lineWidth + } = this.current; + const { + a, + b, + c, + d + } = this.ctx.getTransform(); + let scaleX, scaleY; + if (b === 0 && c === 0) { + const normX = Math.abs(a); + const normY = Math.abs(d); + if (normX === normY) { + if (lineWidth === 0) { + scaleX = scaleY = 1 / normX; + } else { + const scaledLineWidth = normX * lineWidth; + scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1; + } + } else if (lineWidth === 0) { + scaleX = 1 / normX; + scaleY = 1 / normY; + } else { + const scaledXLineWidth = normX * lineWidth; + const scaledYLineWidth = normY * lineWidth; + scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1; + scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1; + } + } else { + const absDet = Math.abs(a * d - b * c); + const normX = Math.hypot(a, b); + const normY = Math.hypot(c, d); + if (lineWidth === 0) { + scaleX = normY / absDet; + scaleY = normX / absDet; + } else { + const baseArea = lineWidth * absDet; + scaleX = normY > baseArea ? normY / baseArea : 1; + scaleY = normX > baseArea ? normX / baseArea : 1; + } + } + this._cachedScaleForStroking[0] = scaleX; + this._cachedScaleForStroking[1] = scaleY; + } + return this._cachedScaleForStroking; + } + rescaleAndStroke(path, saveRestore) { + const { + ctx, + current: { + lineWidth + } + } = this; + const [scaleX, scaleY] = this.getScaleForStroking(); + if (scaleX === scaleY) { + ctx.lineWidth = (lineWidth || 1) * scaleX; + ctx.stroke(path); + return; + } + const dashes = ctx.getLineDash(); + if (saveRestore) { + ctx.save(); + } + ctx.scale(scaleX, scaleY); + SCALE_MATRIX.a = 1 / scaleX; + SCALE_MATRIX.d = 1 / scaleY; + const newPath = new Path2D(); + newPath.addPath(path, SCALE_MATRIX); + if (dashes.length > 0) { + const scale = Math.max(scaleX, scaleY); + ctx.setLineDash(dashes.map(x => x / scale)); + ctx.lineDashOffset /= scale; + } + ctx.lineWidth = lineWidth || 1; + ctx.stroke(newPath); + if (saveRestore) { + ctx.restore(); + } + } + isContentVisible() { + for (let i = this.markedContentStack.length - 1; i >= 0; i--) { + if (!this.markedContentStack[i].visible) { + return false; + } + } + return true; + } +} +for (const op in OPS) { + if (CanvasGraphics.prototype[op] !== undefined) { + CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op]; + } +} + +;// ./src/display/canvas_factory.js + +class BaseCanvasFactory { + #enableHWA = false; + constructor({ + enableHWA = false + }) { + this.#enableHWA = enableHWA; + } + create(width, height) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + const canvas = this._createCanvas(width, height); + return { + canvas, + context: canvas.getContext("2d", { + willReadFrequently: !this.#enableHWA + }) + }; + } + reset(canvasAndContext, width, height) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + canvasAndContext.canvas.width = width; + canvasAndContext.canvas.height = height; + } + destroy(canvasAndContext) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + canvasAndContext.canvas.width = 0; + canvasAndContext.canvas.height = 0; + canvasAndContext.canvas = null; + canvasAndContext.context = null; + } + _createCanvas(width, height) { + unreachable("Abstract method `_createCanvas` called."); + } +} +class DOMCanvasFactory extends BaseCanvasFactory { + constructor({ + ownerDocument = globalThis.document, + enableHWA = false + }) { + super({ + enableHWA + }); + this._document = ownerDocument; + } + _createCanvas(width, height) { + const canvas = this._document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + return canvas; + } +} + +;// ./src/display/stubs.js +const DOMCMapReaderFactory = null; +const DOMWasmFactory = null; +const DOMStandardFontDataFactory = null; +const NodeCanvasFactory = null; +const NodeCMapReaderFactory = null; +const NodeFilterFactory = null; +const NodeWasmFactory = null; +const NodeStandardFontDataFactory = null; +const PDFFetchStream = null; +const PDFNetworkStream = null; +const PDFNodeStream = null; + +;// ./src/display/filter_factory.js + + +class BaseFilterFactory { + addFilter(maps) { + return "none"; + } + addHCMFilter(fgColor, bgColor) { + return "none"; + } + addAlphaFilter(map) { + return "none"; + } + addLuminosityFilter(map) { + return "none"; + } + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { + return "none"; + } + destroy(keepHCM = false) {} +} +class DOMFilterFactory extends BaseFilterFactory { + #baseUrl; + #_cache; + #_defs; + #docId; + #document; + #_hcmCache; + #id = 0; + constructor({ + docId, + ownerDocument = globalThis.document + }) { + super(); + this.#docId = docId; + this.#document = ownerDocument; + } + get #cache() { + return this.#_cache ||= new Map(); + } + get #hcmCache() { + return this.#_hcmCache ||= new Map(); + } + get #defs() { + if (!this.#_defs) { + const div = this.#document.createElement("div"); + const { + style + } = div; + style.visibility = "hidden"; + style.contain = "strict"; + style.width = style.height = 0; + style.position = "absolute"; + style.top = style.left = 0; + style.zIndex = -1; + const svg = this.#document.createElementNS(SVG_NS, "svg"); + svg.setAttribute("width", 0); + svg.setAttribute("height", 0); + this.#_defs = this.#document.createElementNS(SVG_NS, "defs"); + div.append(svg); + svg.append(this.#_defs); + this.#document.body.append(div); + } + return this.#_defs; + } + #createTables(maps) { + if (maps.length === 1) { + const mapR = maps[0]; + const buffer = new Array(256); + for (let i = 0; i < 256; i++) { + buffer[i] = mapR[i] / 255; + } + const table = buffer.join(","); + return [table, table, table]; + } + const [mapR, mapG, mapB] = maps; + const bufferR = new Array(256); + const bufferG = new Array(256); + const bufferB = new Array(256); + for (let i = 0; i < 256; i++) { + bufferR[i] = mapR[i] / 255; + bufferG[i] = mapG[i] / 255; + bufferB[i] = mapB[i] / 255; + } + return [bufferR.join(","), bufferG.join(","), bufferB.join(",")]; + } + #createUrl(id) { + if (this.#baseUrl === undefined) { + this.#baseUrl = ""; + const url = this.#document.URL; + if (url !== this.#document.baseURI) { + if (isDataScheme(url)) { + warn('#createUrl: ignore "data:"-URL for performance reasons.'); + } else { + this.#baseUrl = updateUrlHash(url, ""); + } + } + } + return `url(${this.#baseUrl}#${id})`; + } + addFilter(maps) { + if (!maps) { + return "none"; + } + let value = this.#cache.get(maps); + if (value) { + return value; + } + const [tableR, tableG, tableB] = this.#createTables(maps); + const key = maps.length === 1 ? tableR : `${tableR}${tableG}${tableB}`; + value = this.#cache.get(key); + if (value) { + this.#cache.set(maps, value); + return value; + } + const id = `g_${this.#docId}_transfer_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(maps, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addTransferMapConversion(tableR, tableG, tableB, filter); + return url; + } + addHCMFilter(fgColor, bgColor) { + const key = `${fgColor}-${bgColor}`; + const filterName = "base"; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; + } + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info); + } + if (!fgColor || !bgColor) { + return info.url; + } + const fgRGB = this.#getRGB(fgColor); + fgColor = Util.makeHexColor(...fgRGB); + const bgRGB = this.#getRGB(bgColor); + bgColor = Util.makeHexColor(...bgRGB); + this.#defs.style.color = ""; + if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) { + return info.url; + } + const map = new Array(256); + for (let i = 0; i <= 255; i++) { + const x = i / 255; + map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; + } + const table = map.join(","); + const id = `g_${this.#docId}_hcm_filter`; + const filter = info.filter = this.#createFilter(id); + this.#addTransferMapConversion(table, table, table, filter); + this.#addGrayConversion(filter); + const getSteps = (c, n) => { + const start = fgRGB[c] / 255; + const end = bgRGB[c] / 255; + const arr = new Array(n + 1); + for (let i = 0; i <= n; i++) { + arr[i] = start + i / n * (end - start); + } + return arr.join(","); + }; + this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter); + info.url = this.#createUrl(id); + return info.url; + } + addAlphaFilter(map) { + let value = this.#cache.get(map); + if (value) { + return value; + } + const [tableA] = this.#createTables([map]); + const key = `alpha_${tableA}`; + value = this.#cache.get(key); + if (value) { + this.#cache.set(map, value); + return value; + } + const id = `g_${this.#docId}_alpha_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(map, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addTransferMapAlphaConversion(tableA, filter); + return url; + } + addLuminosityFilter(map) { + let value = this.#cache.get(map || "luminosity"); + if (value) { + return value; + } + let tableA, key; + if (map) { + [tableA] = this.#createTables([map]); + key = `luminosity_${tableA}`; + } else { + key = "luminosity"; + } + value = this.#cache.get(key); + if (value) { + this.#cache.set(map, value); + return value; + } + const id = `g_${this.#docId}_luminosity_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(map, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addLuminosityConversion(filter); + if (map) { + this.#addTransferMapAlphaConversion(tableA, filter); + } + return url; + } + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { + const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; + let info = this.#hcmCache.get(filterName); + if (info?.key === key) { + return info.url; + } + if (info) { + info.filter?.remove(); + info.key = key; + info.url = "none"; + info.filter = null; + } else { + info = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info); + } + if (!fgColor || !bgColor) { + return info.url; + } + const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); + let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]); + let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]); + let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this)); + if (bgGray < fgGray) { + [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB]; + } + this.#defs.style.color = ""; + const getSteps = (fg, bg, n) => { + const arr = new Array(256); + const step = (bgGray - fgGray) / n; + const newStart = fg / 255; + const newStep = (bg - fg) / (255 * n); + let prev = 0; + for (let i = 0; i <= n; i++) { + const k = Math.round(fgGray + i * step); + const value = newStart + i * newStep; + for (let j = prev; j <= k; j++) { + arr[j] = value; + } + prev = k + 1; + } + for (let i = prev; i < 256; i++) { + arr[i] = arr[prev - 1]; + } + return arr.join(","); + }; + const id = `g_${this.#docId}_hcm_${filterName}_filter`; + const filter = info.filter = this.#createFilter(id); + this.#addGrayConversion(filter); + this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter); + info.url = this.#createUrl(id); + return info.url; + } + destroy(keepHCM = false) { + if (keepHCM && this.#_hcmCache?.size) { + return; + } + this.#_defs?.parentNode.parentNode.remove(); + this.#_defs = null; + this.#_cache?.clear(); + this.#_cache = null; + this.#_hcmCache?.clear(); + this.#_hcmCache = null; + this.#id = 0; + } + #addLuminosityConversion(filter) { + const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix"); + feColorMatrix.setAttribute("type", "matrix"); + feColorMatrix.setAttribute("values", "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0.59 0.11 0 0"); + filter.append(feColorMatrix); + } + #addGrayConversion(filter) { + const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix"); + feColorMatrix.setAttribute("type", "matrix"); + feColorMatrix.setAttribute("values", "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"); + filter.append(feColorMatrix); + } + #createFilter(id) { + const filter = this.#document.createElementNS(SVG_NS, "filter"); + filter.setAttribute("color-interpolation-filters", "sRGB"); + filter.setAttribute("id", id); + this.#defs.append(filter); + return filter; + } + #appendFeFunc(feComponentTransfer, func, table) { + const feFunc = this.#document.createElementNS(SVG_NS, func); + feFunc.setAttribute("type", "discrete"); + feFunc.setAttribute("tableValues", table); + feComponentTransfer.append(feFunc); + } + #addTransferMapConversion(rTable, gTable, bTable, filter) { + const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer"); + filter.append(feComponentTransfer); + this.#appendFeFunc(feComponentTransfer, "feFuncR", rTable); + this.#appendFeFunc(feComponentTransfer, "feFuncG", gTable); + this.#appendFeFunc(feComponentTransfer, "feFuncB", bTable); + } + #addTransferMapAlphaConversion(aTable, filter) { + const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer"); + filter.append(feComponentTransfer); + this.#appendFeFunc(feComponentTransfer, "feFuncA", aTable); + } + #getRGB(color) { + this.#defs.style.color = color; + return getRGB(getComputedStyle(this.#defs).getPropertyValue("color")); + } +} + +;// ./src/display/worker_options.js +class GlobalWorkerOptions { + static #port = null; + static #src = ""; + static get workerPort() { + return this.#port; + } + static set workerPort(val) { + if (!(typeof Worker !== "undefined" && val instanceof Worker) && val !== null) { + throw new Error("Invalid `workerPort` type."); + } + this.#port = val; + } + static get workerSrc() { + return this.#src; + } + static set workerSrc(val) { + if (typeof val !== "string") { + throw new Error("Invalid `workerSrc` type."); + } + this.#src = val; + } +} + +;// ./src/display/metadata.js +class Metadata { + #map; + #data; + constructor({ + parsedData, + rawData + }) { + this.#map = parsedData; + this.#data = rawData; + } + getRaw() { + return this.#data; + } + get(name) { + return this.#map.get(name) ?? null; + } + [Symbol.iterator]() { + return this.#map.entries(); + } +} + +;// ./src/display/optional_content_config.js + + +const INTERNAL = Symbol("INTERNAL"); +class OptionalContentGroup { + #isDisplay = false; + #isPrint = false; + #userSet = false; + #visible = true; + constructor(renderingIntent, { + name, + intent, + usage, + rbGroups + }) { + this.#isDisplay = !!(renderingIntent & RenderingIntentFlag.DISPLAY); + this.#isPrint = !!(renderingIntent & RenderingIntentFlag.PRINT); + this.name = name; + this.intent = intent; + this.usage = usage; + this.rbGroups = rbGroups; + } + get visible() { + if (this.#userSet) { + return this.#visible; + } + if (!this.#visible) { + return false; + } + const { + print, + view + } = this.usage; + if (this.#isDisplay) { + return view?.viewState !== "OFF"; + } else if (this.#isPrint) { + return print?.printState !== "OFF"; + } + return true; + } + _setVisible(internal, visible, userSet = false) { + if (internal !== INTERNAL) { + unreachable("Internal method `_setVisible` called."); + } + this.#userSet = userSet; + this.#visible = visible; + } +} +class OptionalContentConfig { + #cachedGetHash = null; + #groups = new Map(); + #initialHash = null; + #order = null; + constructor(data, renderingIntent = RenderingIntentFlag.DISPLAY) { + this.renderingIntent = renderingIntent; + this.name = null; + this.creator = null; + if (data === null) { + return; + } + this.name = data.name; + this.creator = data.creator; + this.#order = data.order; + for (const group of data.groups) { + this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group)); + } + if (data.baseState === "OFF") { + for (const group of this.#groups.values()) { + group._setVisible(INTERNAL, false); + } + } + for (const on of data.on) { + this.#groups.get(on)._setVisible(INTERNAL, true); + } + for (const off of data.off) { + this.#groups.get(off)._setVisible(INTERNAL, false); + } + this.#initialHash = this.getHash(); + } + #evaluateVisibilityExpression(array) { + const length = array.length; + if (length < 2) { + return true; + } + const operator = array[0]; + for (let i = 1; i < length; i++) { + const element = array[i]; + let state; + if (Array.isArray(element)) { + state = this.#evaluateVisibilityExpression(element); + } else if (this.#groups.has(element)) { + state = this.#groups.get(element).visible; + } else { + warn(`Optional content group not found: ${element}`); + return true; + } + switch (operator) { + case "And": + if (!state) { + return false; + } + break; + case "Or": + if (state) { + return true; + } + break; + case "Not": + return !state; + default: + return true; + } + } + return operator === "And"; + } + isVisible(group) { + if (this.#groups.size === 0) { + return true; + } + if (!group) { + info("Optional content group not defined."); + return true; + } + if (group.type === "OCG") { + if (!this.#groups.has(group.id)) { + warn(`Optional content group not found: ${group.id}`); + return true; + } + return this.#groups.get(group.id).visible; + } else if (group.type === "OCMD") { + if (group.expression) { + return this.#evaluateVisibilityExpression(group.expression); + } + if (!group.policy || group.policy === "AnyOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (this.#groups.get(id).visible) { + return true; + } + } + return false; + } else if (group.policy === "AllOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (!this.#groups.get(id).visible) { + return false; + } + } + return true; + } else if (group.policy === "AnyOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (!this.#groups.get(id).visible) { + return true; + } + } + return false; + } else if (group.policy === "AllOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (this.#groups.get(id).visible) { + return false; + } + } + return true; + } + warn(`Unknown optional content policy ${group.policy}.`); + return true; + } + warn(`Unknown group type ${group.type}.`); + return true; + } + setVisibility(id, visible = true, preserveRB = true) { + const group = this.#groups.get(id); + if (!group) { + warn(`Optional content group not found: ${id}`); + return; + } + if (preserveRB && visible && group.rbGroups.length) { + for (const rbGroup of group.rbGroups) { + for (const otherId of rbGroup) { + if (otherId !== id) { + this.#groups.get(otherId)?._setVisible(INTERNAL, false, true); + } + } + } + } + group._setVisible(INTERNAL, !!visible, true); + this.#cachedGetHash = null; + } + setOCGState({ + state, + preserveRB + }) { + let operator; + for (const elem of state) { + switch (elem) { + case "ON": + case "OFF": + case "Toggle": + operator = elem; + continue; + } + const group = this.#groups.get(elem); + if (!group) { + continue; + } + switch (operator) { + case "ON": + this.setVisibility(elem, true, preserveRB); + break; + case "OFF": + this.setVisibility(elem, false, preserveRB); + break; + case "Toggle": + this.setVisibility(elem, !group.visible, preserveRB); + break; + } + } + this.#cachedGetHash = null; + } + get hasInitialVisibility() { + return this.#initialHash === null || this.getHash() === this.#initialHash; + } + getOrder() { + if (!this.#groups.size) { + return null; + } + if (this.#order) { + return this.#order.slice(); + } + return [...this.#groups.keys()]; + } + getGroup(id) { + return this.#groups.get(id) || null; + } + getHash() { + if (this.#cachedGetHash !== null) { + return this.#cachedGetHash; + } + const hash = new MurmurHash3_64(); + for (const [id, group] of this.#groups) { + hash.update(`${id}:${group.visible}`); + } + return this.#cachedGetHash = hash.hexdigest(); + } + [Symbol.iterator]() { + return this.#groups.entries(); + } +} + +;// ./src/display/transport_stream.js + + +class PDFDataTransportStream { + constructor(pdfDataRangeTransport, { + disableRange = false, + disableStream = false + }) { + assert(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.'); + const { + length, + initialData, + progressiveDone, + contentDispositionFilename + } = pdfDataRangeTransport; + this._queuedChunks = []; + this._progressiveDone = progressiveDone; + this._contentDispositionFilename = contentDispositionFilename; + if (initialData?.length > 0) { + const buffer = initialData instanceof Uint8Array && initialData.byteLength === initialData.buffer.byteLength ? initialData.buffer : new Uint8Array(initialData).buffer; + this._queuedChunks.push(buffer); + } + this._pdfDataRangeTransport = pdfDataRangeTransport; + this._isStreamingSupported = !disableStream; + this._isRangeSupported = !disableRange; + this._contentLength = length; + this._fullRequestReader = null; + this._rangeReaders = []; + pdfDataRangeTransport.addRangeListener((begin, chunk) => { + this._onReceiveData({ + begin, + chunk + }); + }); + pdfDataRangeTransport.addProgressListener((loaded, total) => { + this._onProgress({ + loaded, + total + }); + }); + pdfDataRangeTransport.addProgressiveReadListener(chunk => { + this._onReceiveData({ + chunk + }); + }); + pdfDataRangeTransport.addProgressiveDoneListener(() => { + this._onProgressiveDone(); + }); + pdfDataRangeTransport.transportReady(); + } + _onReceiveData({ + begin, + chunk + }) { + const buffer = chunk instanceof Uint8Array && chunk.byteLength === chunk.buffer.byteLength ? chunk.buffer : new Uint8Array(chunk).buffer; + if (begin === undefined) { + if (this._fullRequestReader) { + this._fullRequestReader._enqueue(buffer); + } else { + this._queuedChunks.push(buffer); + } + } else { + const found = this._rangeReaders.some(function (rangeReader) { + if (rangeReader._begin !== begin) { + return false; + } + rangeReader._enqueue(buffer); + return true; + }); + assert(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found."); + } + } + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + _onProgress(evt) { + if (evt.total === undefined) { + this._rangeReaders[0]?.onProgress?.({ + loaded: evt.loaded + }); + } else { + this._fullRequestReader?.onProgress?.({ + loaded: evt.loaded, + total: evt.total + }); + } + } + _onProgressiveDone() { + this._fullRequestReader?.progressiveDone(); + this._progressiveDone = true; + } + _removeRangeReader(reader) { + const i = this._rangeReaders.indexOf(reader); + if (i >= 0) { + this._rangeReaders.splice(i, 1); + } + } + getFullReader() { + assert(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once."); + const queuedChunks = this._queuedChunks; + this._queuedChunks = null; + return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename); + } + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + const reader = new PDFDataTransportStreamRangeReader(this, begin, end); + this._pdfDataRangeTransport.requestDataRange(begin, end); + this._rangeReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeReaders.slice(0)) { + reader.cancel(reason); + } + this._pdfDataRangeTransport.abort(); + } +} +class PDFDataTransportStreamReader { + constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) { + this._stream = stream; + this._done = progressiveDone || false; + this._filename = isPdfFile(contentDispositionFilename) ? contentDispositionFilename : null; + this._queuedChunks = queuedChunks || []; + this._loaded = 0; + for (const chunk of this._queuedChunks) { + this._loaded += chunk.byteLength; + } + this._requests = []; + this._headersReady = Promise.resolve(); + stream._fullRequestReader = this; + this.onProgress = null; + } + _enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunks.push(chunk); + } + this._loaded += chunk.byteLength; + } + get headersReady() { + return this._headersReady; + } + get filename() { + return this._filename; + } + get isRangeSupported() { + return this._stream._isRangeSupported; + } + get isStreamingSupported() { + return this._stream._isStreamingSupported; + } + get contentLength() { + return this._stream._contentLength; + } + async read() { + if (this._queuedChunks.length > 0) { + const chunk = this._queuedChunks.shift(); + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: undefined, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + this._requests.length = 0; + } + progressiveDone() { + if (this._done) { + return; + } + this._done = true; + } +} +class PDFDataTransportStreamRangeReader { + constructor(stream, begin, end) { + this._stream = stream; + this._begin = begin; + this._end = end; + this._queuedChunk = null; + this._requests = []; + this._done = false; + this.onProgress = null; + } + _enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length === 0) { + this._queuedChunk = chunk; + } else { + const requestsCapability = this._requests.shift(); + requestsCapability.resolve({ + value: chunk, + done: false + }); + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + this._requests.length = 0; + } + this._done = true; + this._stream._removeRangeReader(this); + } + get isStreamingSupported() { + return false; + } + async read() { + if (this._queuedChunk) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: undefined, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: undefined, + done: true + }); + } + this._requests.length = 0; + this._stream._removeRangeReader(this); + } +} + +;// ./src/display/pdf_objects.js +const INITIAL_DATA = Symbol("INITIAL_DATA"); +class PDFObjects { + #objs = Object.create(null); + #ensureObj(objId) { + return this.#objs[objId] ||= { + ...Promise.withResolvers(), + data: INITIAL_DATA + }; + } + get(objId, callback = null) { + if (callback) { + const obj = this.#ensureObj(objId); + obj.promise.then(() => callback(obj.data)); + return null; + } + const obj = this.#objs[objId]; + if (!obj || obj.data === INITIAL_DATA) { + throw new Error(`Requesting object that isn't resolved yet ${objId}.`); + } + return obj.data; + } + has(objId) { + const obj = this.#objs[objId]; + return !!obj && obj.data !== INITIAL_DATA; + } + delete(objId) { + const obj = this.#objs[objId]; + if (!obj || obj.data === INITIAL_DATA) { + return false; + } + delete this.#objs[objId]; + return true; + } + resolve(objId, data = null) { + const obj = this.#ensureObj(objId); + obj.data = data; + obj.resolve(); + } + clear() { + for (const objId in this.#objs) { + const { + data + } = this.#objs[objId]; + data?.bitmap?.close(); + } + this.#objs = Object.create(null); + } + *[Symbol.iterator]() { + for (const objId in this.#objs) { + const { + data + } = this.#objs[objId]; + if (data === INITIAL_DATA) { + continue; + } + yield [objId, data]; + } + } +} + +;// ./src/display/text_layer.js + + +const MAX_TEXT_DIVS_TO_RENDER = 100000; +const DEFAULT_FONT_SIZE = 30; +class TextLayer { + #capability = Promise.withResolvers(); + #container = null; + #disableProcessItems = false; + #fontInspectorEnabled = !!globalThis.FontInspector?.enabled; + #lang = null; + #layoutTextParams = null; + #pageHeight = 0; + #pageWidth = 0; + #reader = null; + #rootContainer = null; + #rotation = 0; + #scale = 0; + #styleCache = Object.create(null); + #textContentItemsStr = []; + #textContentSource = null; + #textDivs = []; + #textDivProperties = new WeakMap(); + #transform = null; + static #ascentCache = new Map(); + static #canvasContexts = new Map(); + static #canvasCtxFonts = new WeakMap(); + static #minFontSize = null; + static #pendingTextLayers = new Set(); + constructor({ + textContentSource, + container, + viewport + }) { + if (textContentSource instanceof ReadableStream) { + this.#textContentSource = textContentSource; + } else { + throw new Error('No "textContentSource" parameter specified.'); + } + this.#container = this.#rootContainer = container; + this.#scale = viewport.scale * OutputScale.pixelRatio; + this.#rotation = viewport.rotation; + this.#layoutTextParams = { + div: null, + properties: null, + ctx: null + }; + const { + pageWidth, + pageHeight, + pageX, + pageY + } = viewport.rawDims; + this.#transform = [1, 0, 0, -1, -pageX, pageY + pageHeight]; + this.#pageWidth = pageWidth; + this.#pageHeight = pageHeight; + TextLayer.#ensureMinFontSizeComputed(); + setLayerDimensions(container, viewport); + this.#capability.promise.finally(() => { + TextLayer.#pendingTextLayers.delete(this); + this.#layoutTextParams = null; + this.#styleCache = null; + }).catch(() => {}); + } + static get fontFamilyMap() { + const { + isWindows, + isFirefox + } = util_FeatureTest.platform; + return shadow(this, "fontFamilyMap", new Map([["sans-serif", `${isWindows && isFirefox ? "Calibri, " : ""}sans-serif`], ["monospace", `${isWindows && isFirefox ? "Lucida Console, " : ""}monospace`]])); + } + render() { + const pump = () => { + this.#reader.read().then(({ + value, + done + }) => { + if (done) { + this.#capability.resolve(); + return; + } + this.#lang ??= value.lang; + Object.assign(this.#styleCache, value.styles); + this.#processItems(value.items); + pump(); + }, this.#capability.reject); + }; + this.#reader = this.#textContentSource.getReader(); + TextLayer.#pendingTextLayers.add(this); + pump(); + return this.#capability.promise; + } + update({ + viewport, + onBefore = null + }) { + const scale = viewport.scale * OutputScale.pixelRatio; + const rotation = viewport.rotation; + if (rotation !== this.#rotation) { + onBefore?.(); + this.#rotation = rotation; + setLayerDimensions(this.#rootContainer, { + rotation + }); + } + if (scale !== this.#scale) { + onBefore?.(); + this.#scale = scale; + const params = { + div: null, + properties: null, + ctx: TextLayer.#getCtx(this.#lang) + }; + for (const div of this.#textDivs) { + params.properties = this.#textDivProperties.get(div); + params.div = div; + this.#layout(params); + } + } + } + cancel() { + const abortEx = new AbortException("TextLayer task cancelled."); + this.#reader?.cancel(abortEx).catch(() => {}); + this.#reader = null; + this.#capability.reject(abortEx); + } + get textDivs() { + return this.#textDivs; + } + get textContentItemsStr() { + return this.#textContentItemsStr; + } + #processItems(items) { + if (this.#disableProcessItems) { + return; + } + this.#layoutTextParams.ctx ??= TextLayer.#getCtx(this.#lang); + const textDivs = this.#textDivs, + textContentItemsStr = this.#textContentItemsStr; + for (const item of items) { + if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER) { + warn("Ignoring additional textDivs for performance reasons."); + this.#disableProcessItems = true; + return; + } + if (item.str === undefined) { + if (item.type === "beginMarkedContentProps" || item.type === "beginMarkedContent") { + const parent = this.#container; + this.#container = document.createElement("span"); + this.#container.classList.add("markedContent"); + if (item.id) { + this.#container.setAttribute("id", `${item.id}`); + } + parent.append(this.#container); + } else if (item.type === "endMarkedContent") { + this.#container = this.#container.parentNode; + } + continue; + } + textContentItemsStr.push(item.str); + this.#appendText(item); + } + } + #appendText(geom) { + const textDiv = document.createElement("span"); + const textDivProperties = { + angle: 0, + canvasWidth: 0, + hasText: geom.str !== "", + hasEOL: geom.hasEOL, + fontSize: 0 + }; + this.#textDivs.push(textDiv); + const tx = Util.transform(this.#transform, geom.transform); + let angle = Math.atan2(tx[1], tx[0]); + const style = this.#styleCache[geom.fontName]; + if (style.vertical) { + angle += Math.PI / 2; + } + let fontFamily = this.#fontInspectorEnabled && style.fontSubstitution || style.fontFamily; + fontFamily = TextLayer.fontFamilyMap.get(fontFamily) || fontFamily; + const fontHeight = Math.hypot(tx[2], tx[3]); + const fontAscent = fontHeight * TextLayer.#getAscent(fontFamily, style, this.#lang); + let left, top; + if (angle === 0) { + left = tx[4]; + top = tx[5] - fontAscent; + } else { + left = tx[4] + fontAscent * Math.sin(angle); + top = tx[5] - fontAscent * Math.cos(angle); + } + const scaleFactorStr = "calc(var(--total-scale-factor) *"; + const divStyle = textDiv.style; + if (this.#container === this.#rootContainer) { + divStyle.left = `${(100 * left / this.#pageWidth).toFixed(2)}%`; + divStyle.top = `${(100 * top / this.#pageHeight).toFixed(2)}%`; + } else { + divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`; + divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`; + } + divStyle.fontSize = `${scaleFactorStr}${(TextLayer.#minFontSize * fontHeight).toFixed(2)}px)`; + divStyle.fontFamily = fontFamily; + textDivProperties.fontSize = fontHeight; + textDiv.setAttribute("role", "presentation"); + textDiv.textContent = geom.str; + textDiv.dir = geom.dir; + if (this.#fontInspectorEnabled) { + textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName; + } + if (angle !== 0) { + textDivProperties.angle = angle * (180 / Math.PI); + } + let shouldScaleText = false; + if (geom.str.length > 1) { + shouldScaleText = true; + } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) { + const absScaleX = Math.abs(geom.transform[0]), + absScaleY = Math.abs(geom.transform[3]); + if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) { + shouldScaleText = true; + } + } + if (shouldScaleText) { + textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width; + } + this.#textDivProperties.set(textDiv, textDivProperties); + this.#layoutTextParams.div = textDiv; + this.#layoutTextParams.properties = textDivProperties; + this.#layout(this.#layoutTextParams); + if (textDivProperties.hasText) { + this.#container.append(textDiv); + } + if (textDivProperties.hasEOL) { + const br = document.createElement("br"); + br.setAttribute("role", "presentation"); + this.#container.append(br); + } + } + #layout(params) { + const { + div, + properties, + ctx + } = params; + const { + style + } = div; + let transform = ""; + if (TextLayer.#minFontSize > 1) { + transform = `scale(${1 / TextLayer.#minFontSize})`; + } + if (properties.canvasWidth !== 0 && properties.hasText) { + const { + fontFamily + } = style; + const { + canvasWidth, + fontSize + } = properties; + TextLayer.#ensureCtxFont(ctx, fontSize * this.#scale, fontFamily); + const { + width + } = ctx.measureText(div.textContent); + if (width > 0) { + transform = `scaleX(${canvasWidth * this.#scale / width}) ${transform}`; + } + } + if (properties.angle !== 0) { + transform = `rotate(${properties.angle}deg) ${transform}`; + } + if (transform.length > 0) { + style.transform = transform; + } + } + static cleanup() { + if (this.#pendingTextLayers.size > 0) { + return; + } + this.#ascentCache.clear(); + for (const { + canvas + } of this.#canvasContexts.values()) { + canvas.remove(); + } + this.#canvasContexts.clear(); + } + static #getCtx(lang = null) { + let ctx = this.#canvasContexts.get(lang ||= ""); + if (!ctx) { + const canvas = document.createElement("canvas"); + canvas.className = "hiddenCanvasElement"; + canvas.lang = lang; + document.body.append(canvas); + ctx = canvas.getContext("2d", { + alpha: false, + willReadFrequently: true + }); + this.#canvasContexts.set(lang, ctx); + this.#canvasCtxFonts.set(ctx, { + size: 0, + family: "" + }); + } + return ctx; + } + static #ensureCtxFont(ctx, size, family) { + const cached = this.#canvasCtxFonts.get(ctx); + if (size === cached.size && family === cached.family) { + return; + } + ctx.font = `${size}px ${family}`; + cached.size = size; + cached.family = family; + } + static #ensureMinFontSizeComputed() { + if (this.#minFontSize !== null) { + return; + } + const div = document.createElement("div"); + div.style.opacity = 0; + div.style.lineHeight = 1; + div.style.fontSize = "1px"; + div.style.position = "absolute"; + div.textContent = "X"; + document.body.append(div); + this.#minFontSize = div.getBoundingClientRect().height; + div.remove(); + } + static #getAscent(fontFamily, style, lang) { + const cachedAscent = this.#ascentCache.get(fontFamily); + if (cachedAscent) { + return cachedAscent; + } + const ctx = this.#getCtx(lang); + ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE; + this.#ensureCtxFont(ctx, DEFAULT_FONT_SIZE, fontFamily); + const metrics = ctx.measureText(""); + const ascent = metrics.fontBoundingBoxAscent; + const descent = Math.abs(metrics.fontBoundingBoxDescent); + ctx.canvas.width = ctx.canvas.height = 0; + let ratio = 0.8; + if (ascent) { + ratio = ascent / (ascent + descent); + } else { + warn("Enable the `dom.textMetrics.fontBoundingBox.enabled` preference " + "in `about:config` to improve TextLayer rendering."); + if (style.ascent) { + ratio = style.ascent; + } else if (style.descent) { + ratio = 1 + style.descent; + } + } + this.#ascentCache.set(fontFamily, ratio); + return ratio; + } +} + +;// ./src/display/api.js + + + + + + + + + + + + + + + + + + + + + + + + + +const RENDERING_CANCELLED_TIMEOUT = 100; +function getDocument(src = {}) { + const task = new PDFDocumentLoadingTask(); + const { + docId + } = task; + const url = src.url ? getUrlProp(src.url) : null; + const data = src.data ? getDataProp(src.data) : null; + const httpHeaders = src.httpHeaders || null; + const withCredentials = src.withCredentials === true; + const password = src.password ?? null; + const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null; + const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : 2 ** 16; + let worker = src.worker instanceof PDFWorker ? src.worker : null; + const verbosity = src.verbosity; + const docBaseUrl = typeof src.docBaseUrl === "string" && !isDataScheme(src.docBaseUrl) ? src.docBaseUrl : null; + const cMapUrl = getFactoryUrlProp(src.cMapUrl); + const cMapPacked = src.cMapPacked !== false; + const CMapReaderFactory = src.CMapReaderFactory || DOMCMapReaderFactory; + const iccUrl = getFactoryUrlProp(src.iccUrl); + const standardFontDataUrl = getFactoryUrlProp(src.standardFontDataUrl); + const StandardFontDataFactory = src.StandardFontDataFactory || DOMStandardFontDataFactory; + const wasmUrl = getFactoryUrlProp(src.wasmUrl); + const WasmFactory = src.WasmFactory || DOMWasmFactory; + const ignoreErrors = src.stopAtErrors !== true; + const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1; + const isEvalSupported = src.isEvalSupported !== false; + const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS; + const isImageDecoderSupported = typeof src.isImageDecoderSupported === "boolean" ? src.isImageDecoderSupported : true; + const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1; + const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : isNodeJS; + const fontExtraProperties = src.fontExtraProperties === true; + const enableXfa = src.enableXfa === true; + const ownerDocument = src.ownerDocument || globalThis.document; + const disableRange = src.disableRange === true; + const disableStream = src.disableStream === true; + const disableAutoFetch = src.disableAutoFetch === true; + const pdfBug = src.pdfBug === true; + const CanvasFactory = src.CanvasFactory || DOMCanvasFactory; + const FilterFactory = src.FilterFactory || DOMFilterFactory; + const enableHWA = src.enableHWA === true; + const useWasm = src.useWasm !== false; + const length = rangeTransport ? rangeTransport.length : src.length ?? NaN; + const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !isNodeJS && !disableFontFace; + const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : true; + const styleElement = null; + setVerbosityLevel(verbosity); + const transportFactory = { + canvasFactory: new CanvasFactory({ + ownerDocument, + enableHWA + }), + filterFactory: new FilterFactory({ + docId, + ownerDocument + }), + cMapReaderFactory: null, + standardFontDataFactory: null, + wasmFactory: null + }; + if (!worker) { + worker = PDFWorker.create({ + verbosity, + port: GlobalWorkerOptions.workerPort + }); + task._worker = worker; + } + const docParams = { + docId, + apiVersion: "5.4.445", + data, + password, + disableAutoFetch, + rangeChunkSize, + length, + docBaseUrl, + enableXfa, + evaluatorOptions: { + maxImageSize, + disableFontFace, + ignoreErrors, + isEvalSupported, + isOffscreenCanvasSupported, + isImageDecoderSupported, + canvasMaxAreaInBytes, + fontExtraProperties, + useSystemFonts, + useWasm, + useWorkerFetch, + cMapUrl, + iccUrl, + standardFontDataUrl, + wasmUrl + } + }; + const transportParams = { + ownerDocument, + pdfBug, + styleElement, + loadingParams: { + disableAutoFetch, + enableXfa + } + }; + worker.promise.then(function () { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + const workerIdPromise = worker.messageHandler.sendWithPromise("GetDocRequest", docParams, data ? [data.buffer] : null); + let networkStream; + if (rangeTransport) { + networkStream = new PDFDataTransportStream(rangeTransport, { + disableRange, + disableStream + }); + } else if (!data) { + throw new Error("Not implemented: NetworkStream"); + } + return workerIdPromise.then(workerId => { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + const messageHandler = new MessageHandler(docId, workerId, worker.port); + const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory, enableHWA); + task._transport = transport; + messageHandler.send("Ready", null); + }); + }).catch(task._capability.reject); + return task; +} +class PDFDocumentLoadingTask { + static #docId = 0; + _capability = Promise.withResolvers(); + _transport = null; + _worker = null; + docId = `d${PDFDocumentLoadingTask.#docId++}`; + destroyed = false; + onPassword = null; + onProgress = null; + get promise() { + return this._capability.promise; + } + async destroy() { + this.destroyed = true; + try { + if (this._worker?.port) { + this._worker._pendingDestroy = true; + } + await this._transport?.destroy(); + } catch (ex) { + if (this._worker?.port) { + delete this._worker._pendingDestroy; + } + throw ex; + } + this._transport = null; + this._worker?.destroy(); + this._worker = null; + } + async getData() { + return this._transport.getData(); + } +} +class PDFDataRangeTransport { + #capability = Promise.withResolvers(); + #progressiveDoneListeners = []; + #progressiveReadListeners = []; + #progressListeners = []; + #rangeListeners = []; + constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) { + this.length = length; + this.initialData = initialData; + this.progressiveDone = progressiveDone; + this.contentDispositionFilename = contentDispositionFilename; + } + addRangeListener(listener) { + this.#rangeListeners.push(listener); + } + addProgressListener(listener) { + this.#progressListeners.push(listener); + } + addProgressiveReadListener(listener) { + this.#progressiveReadListeners.push(listener); + } + addProgressiveDoneListener(listener) { + this.#progressiveDoneListeners.push(listener); + } + onDataRange(begin, chunk) { + for (const listener of this.#rangeListeners) { + listener(begin, chunk); + } + } + onDataProgress(loaded, total) { + this.#capability.promise.then(() => { + for (const listener of this.#progressListeners) { + listener(loaded, total); + } + }); + } + onDataProgressiveRead(chunk) { + this.#capability.promise.then(() => { + for (const listener of this.#progressiveReadListeners) { + listener(chunk); + } + }); + } + onDataProgressiveDone() { + this.#capability.promise.then(() => { + for (const listener of this.#progressiveDoneListeners) { + listener(); + } + }); + } + transportReady() { + this.#capability.resolve(); + } + requestDataRange(begin, end) { + unreachable("Abstract method PDFDataRangeTransport.requestDataRange"); + } + abort() {} +} +class PDFDocumentProxy { + constructor(pdfInfo, transport) { + this._pdfInfo = pdfInfo; + this._transport = transport; + } + get annotationStorage() { + return this._transport.annotationStorage; + } + get canvasFactory() { + return this._transport.canvasFactory; + } + get filterFactory() { + return this._transport.filterFactory; + } + get numPages() { + return this._pdfInfo.numPages; + } + get fingerprints() { + return this._pdfInfo.fingerprints; + } + get isPureXfa() { + return shadow(this, "isPureXfa", !!this._transport._htmlForXfa); + } + get allXfaHtml() { + return this._transport._htmlForXfa; + } + getPage(pageNumber) { + return this._transport.getPage(pageNumber); + } + getPageIndex(ref) { + return this._transport.getPageIndex(ref); + } + getDestinations() { + return this._transport.getDestinations(); + } + getDestination(id) { + return this._transport.getDestination(id); + } + getPageLabels() { + return this._transport.getPageLabels(); + } + getPageLayout() { + return this._transport.getPageLayout(); + } + getPageMode() { + return this._transport.getPageMode(); + } + getViewerPreferences() { + return this._transport.getViewerPreferences(); + } + getOpenAction() { + return this._transport.getOpenAction(); + } + getAttachments() { + return this._transport.getAttachments(); + } + getAnnotationsByType(types, pageIndexesToSkip) { + return this._transport.getAnnotationsByType(types, pageIndexesToSkip); + } + getJSActions() { + return this._transport.getDocJSActions(); + } + getOutline() { + return this._transport.getOutline(); + } + getOptionalContentConfig({ + intent = "display" + } = {}) { + const { + renderingIntent + } = this._transport.getRenderingIntent(intent); + return this._transport.getOptionalContentConfig(renderingIntent); + } + getPermissions() { + return this._transport.getPermissions(); + } + getMetadata() { + return this._transport.getMetadata(); + } + getMarkInfo() { + return this._transport.getMarkInfo(); + } + getData() { + return this._transport.getData(); + } + saveDocument() { + return this._transport.saveDocument(); + } + extractPages(pageInfos) { + return this._transport.extractPages(pageInfos); + } + getDownloadInfo() { + return this._transport.downloadInfoCapability.promise; + } + cleanup(keepLoadedFonts = false) { + return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa); + } + destroy() { + return this.loadingTask.destroy(); + } + cachedPageNumber(ref) { + return this._transport.cachedPageNumber(ref); + } + get loadingParams() { + return this._transport.loadingParams; + } + get loadingTask() { + return this._transport.loadingTask; + } + getFieldObjects() { + return this._transport.getFieldObjects(); + } + hasJSActions() { + return this._transport.hasJSActions(); + } + getCalculationOrderIds() { + return this._transport.getCalculationOrderIds(); + } +} +class PDFPageProxy { + #pendingCleanup = false; + constructor(pageIndex, pageInfo, transport, pdfBug = false) { + this._pageIndex = pageIndex; + this._pageInfo = pageInfo; + this._transport = transport; + this._stats = pdfBug ? new StatTimer() : null; + this._pdfBug = pdfBug; + this.commonObjs = transport.commonObjs; + this.objs = new PDFObjects(); + this._intentStates = new Map(); + this.destroyed = false; + this.recordedBBoxes = null; + } + get pageNumber() { + return this._pageIndex + 1; + } + get rotate() { + return this._pageInfo.rotate; + } + get ref() { + return this._pageInfo.ref; + } + get userUnit() { + return this._pageInfo.userUnit; + } + get view() { + return this._pageInfo.view; + } + getViewport({ + scale, + rotation = this.rotate, + offsetX = 0, + offsetY = 0, + dontFlip = false + } = {}) { + return new PageViewport({ + viewBox: this.view, + userUnit: this.userUnit, + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + getAnnotations({ + intent = "display" + } = {}) { + const { + renderingIntent + } = this._transport.getRenderingIntent(intent); + return this._transport.getAnnotations(this._pageIndex, renderingIntent); + } + getJSActions() { + return this._transport.getPageJSActions(this._pageIndex); + } + get filterFactory() { + return this._transport.filterFactory; + } + get isPureXfa() { + return shadow(this, "isPureXfa", !!this._transport._htmlForXfa); + } + async getXfa() { + return this._transport._htmlForXfa?.children[this._pageIndex] || null; + } + render({ + canvasContext, + canvas = canvasContext.canvas, + viewport, + intent = "display", + annotationMode = AnnotationMode.ENABLE, + transform = null, + background = null, + optionalContentConfigPromise = null, + annotationCanvasMap = null, + pageColors = null, + printAnnotationStorage = null, + isEditing = false, + recordOperations = false, + operationsFilter = null + }) { + this._stats?.time("Overall"); + const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing); + const { + renderingIntent, + cacheKey + } = intentArgs; + this.#pendingCleanup = false; + optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent); + let intentState = this._intentStates.get(cacheKey); + if (!intentState) { + intentState = Object.create(null); + this._intentStates.set(cacheKey, intentState); + } + if (intentState.streamReaderCancelTimeout) { + clearTimeout(intentState.streamReaderCancelTimeout); + intentState.streamReaderCancelTimeout = null; + } + const intentPrint = !!(renderingIntent & RenderingIntentFlag.PRINT); + if (!intentState.displayReadyCapability) { + intentState.displayReadyCapability = Promise.withResolvers(); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false, + separateAnnots: null + }; + this._stats?.time("Page Request"); + this._pumpOperatorList(intentArgs); + } + const recordForDebugger = Boolean(this._pdfBug && globalThis.StepperManager?.enabled); + const shouldRecordOperations = !this.recordedBBoxes && (recordOperations || recordForDebugger); + const complete = error => { + intentState.renderTasks.delete(internalRenderTask); + if (shouldRecordOperations) { + const recordedBBoxes = internalRenderTask.gfx?.dependencyTracker.take(); + if (recordedBBoxes) { + if (internalRenderTask.stepper) { + internalRenderTask.stepper.setOperatorBBoxes(recordedBBoxes, internalRenderTask.gfx.dependencyTracker.takeDebugMetadata()); + } + if (recordOperations) { + this.recordedBBoxes = recordedBBoxes; + } + } + } + if (intentPrint) { + this.#pendingCleanup = true; + } + this.#tryCleanup(); + if (error) { + internalRenderTask.capability.reject(error); + this._abortOperatorList({ + intentState, + reason: error instanceof Error ? error : new Error(error) + }); + } else { + internalRenderTask.capability.resolve(); + } + if (this._stats) { + this._stats.timeEnd("Rendering"); + this._stats.timeEnd("Overall"); + if (globalThis.Stats?.enabled) { + globalThis.Stats.add(this.pageNumber, this._stats); + } + } + }; + const internalRenderTask = new InternalRenderTask({ + callback: complete, + params: { + canvas, + canvasContext, + dependencyTracker: shouldRecordOperations ? new CanvasDependencyTracker(canvas, intentState.operatorList.length, recordForDebugger) : null, + viewport, + transform, + background + }, + objs: this.objs, + commonObjs: this.commonObjs, + annotationCanvasMap, + operatorList: intentState.operatorList, + pageIndex: this._pageIndex, + canvasFactory: this._transport.canvasFactory, + filterFactory: this._transport.filterFactory, + useRequestAnimationFrame: !intentPrint, + pdfBug: this._pdfBug, + pageColors, + enableHWA: this._transport.enableHWA, + operationsFilter + }); + (intentState.renderTasks ||= new Set()).add(internalRenderTask); + const renderTask = internalRenderTask.task; + Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => { + if (this.destroyed) { + complete(); + return; + } + this._stats?.time("Rendering"); + if (!(optionalContentConfig.renderingIntent & renderingIntent)) { + throw new Error("Must use the same `intent`-argument when calling the `PDFPageProxy.render` " + "and `PDFDocumentProxy.getOptionalContentConfig` methods."); + } + internalRenderTask.initializeGraphics({ + transparency, + optionalContentConfig + }); + internalRenderTask.operatorListChanged(); + }).catch(complete); + return renderTask; + } + getOperatorList({ + intent = "display", + annotationMode = AnnotationMode.ENABLE, + printAnnotationStorage = null, + isEditing = false + } = {}) { + throw new Error("Not implemented: getOperatorList"); + } + streamTextContent({ + includeMarkedContent = false, + disableNormalization = false + } = {}) { + const TEXT_CONTENT_CHUNK_SIZE = 100; + return this._transport.messageHandler.sendWithStream("GetTextContent", { + pageIndex: this._pageIndex, + includeMarkedContent: includeMarkedContent === true, + disableNormalization: disableNormalization === true + }, { + highWaterMark: TEXT_CONTENT_CHUNK_SIZE, + size(textContent) { + return textContent.items.length; + } + }); + } + getTextContent(params = {}) { + if (this._transport._htmlForXfa) { + return this.getXfa().then(xfa => XfaText.textContent(xfa)); + } + const readableStream = this.streamTextContent(params); + return new Promise(function (resolve, reject) { + function pump() { + reader.read().then(function ({ + value, + done + }) { + if (done) { + resolve(textContent); + return; + } + textContent.lang ??= value.lang; + Object.assign(textContent.styles, value.styles); + textContent.items.push(...value.items); + pump(); + }, reject); + } + const reader = readableStream.getReader(); + const textContent = { + items: [], + styles: Object.create(null), + lang: null + }; + pump(); + }); + } + getStructTree() { + return this._transport.getStructTree(this._pageIndex); + } + _destroy() { + this.destroyed = true; + const waitOn = []; + for (const intentState of this._intentStates.values()) { + this._abortOperatorList({ + intentState, + reason: new Error("Page was destroyed."), + force: true + }); + if (intentState.opListReadCapability) { + continue; + } + for (const internalRenderTask of intentState.renderTasks) { + waitOn.push(internalRenderTask.completed); + internalRenderTask.cancel(); + } + } + this.objs.clear(); + this.#pendingCleanup = false; + return Promise.all(waitOn); + } + cleanup(resetStats = false) { + this.#pendingCleanup = true; + const success = this.#tryCleanup(); + if (resetStats && success) { + this._stats &&= new StatTimer(); + } + return success; + } + #tryCleanup() { + if (!this.#pendingCleanup || this.destroyed) { + return false; + } + for (const { + renderTasks, + operatorList + } of this._intentStates.values()) { + if (renderTasks.size > 0 || !operatorList.lastChunk) { + return false; + } + } + this._intentStates.clear(); + this.objs.clear(); + this.#pendingCleanup = false; + return true; + } + _startRenderPage(transparency, cacheKey) { + const intentState = this._intentStates.get(cacheKey); + if (!intentState) { + return; + } + this._stats?.timeEnd("Page Request"); + intentState.displayReadyCapability?.resolve(transparency); + } + _renderPageChunk(operatorListChunk, intentState) { + for (let i = 0, ii = operatorListChunk.length; i < ii; i++) { + intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); + intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]); + } + intentState.operatorList.lastChunk = operatorListChunk.lastChunk; + intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots; + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + if (operatorListChunk.lastChunk) { + this.#tryCleanup(); + } + } + _pumpOperatorList({ + renderingIntent, + cacheKey, + annotationStorageSerializable, + modifiedIds + }) { + const { + map, + transfer + } = annotationStorageSerializable; + const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", { + pageIndex: this._pageIndex, + intent: renderingIntent, + cacheKey, + annotationStorage: map, + modifiedIds + }, transfer); + const reader = readableStream.getReader(); + const intentState = this._intentStates.get(cacheKey); + intentState.streamReader = reader; + const pump = () => { + reader.read().then(({ + value, + done + }) => { + if (done) { + intentState.streamReader = null; + return; + } + if (this._transport.destroyed) { + return; + } + this._renderPageChunk(value, intentState); + pump(); + }, reason => { + intentState.streamReader = null; + if (this._transport.destroyed) { + return; + } + if (intentState.operatorList) { + intentState.operatorList.lastChunk = true; + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + this.#tryCleanup(); + } + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.reject(reason); + } else if (intentState.opListReadCapability) { + intentState.opListReadCapability.reject(reason); + } else { + throw reason; + } + }); + }; + pump(); + } + _abortOperatorList({ + intentState, + reason, + force = false + }) { + if (!intentState.streamReader) { + return; + } + if (intentState.streamReaderCancelTimeout) { + clearTimeout(intentState.streamReaderCancelTimeout); + intentState.streamReaderCancelTimeout = null; + } + if (!force) { + if (intentState.renderTasks.size > 0) { + return; + } + if (reason instanceof RenderingCancelledException) { + let delay = RENDERING_CANCELLED_TIMEOUT; + if (reason.extraDelay > 0 && reason.extraDelay < 1000) { + delay += reason.extraDelay; + } + intentState.streamReaderCancelTimeout = setTimeout(() => { + intentState.streamReaderCancelTimeout = null; + this._abortOperatorList({ + intentState, + reason, + force: true + }); + }, delay); + return; + } + } + intentState.streamReader.cancel(new AbortException(reason.message)).catch(() => {}); + intentState.streamReader = null; + if (this._transport.destroyed) { + return; + } + for (const [curCacheKey, curIntentState] of this._intentStates) { + if (curIntentState === intentState) { + this._intentStates.delete(curCacheKey); + break; + } + } + this.cleanup(); + } + get stats() { + return this._stats; + } +} +class PDFWorker { + #capability = Promise.withResolvers(); + #messageHandler = null; + #port = null; + #webWorker = null; + static #fakeWorkerId = 0; + static #isWorkerDisabled = false; + static #workerPorts = new WeakMap(); + constructor({ + name = null, + port = null, + verbosity = getVerbosityLevel() + } = {}) { + this.name = name; + this.destroyed = false; + this.verbosity = verbosity; + if (port) { + if (PDFWorker.#workerPorts.has(port)) { + throw new Error("Cannot use more than one PDFWorker per port."); + } + PDFWorker.#workerPorts.set(port, this); + this.#initializeFromPort(port); + } else { + this.#initialize(); + } + } + get promise() { + return this.#capability.promise; + } + #resolve() { + this.#capability.resolve(); + this.#messageHandler.send("configure", { + verbosity: this.verbosity + }); + } + get port() { + return this.#port; + } + get messageHandler() { + return this.#messageHandler; + } + #initializeFromPort(port) { + this.#port = port; + this.#messageHandler = new MessageHandler("main", "worker", port); + this.#messageHandler.on("ready", () => {}); + this.#resolve(); + } + #initialize() { + if (PDFWorker.#isWorkerDisabled || PDFWorker.#mainThreadWorkerMessageHandler) { + this.#setupFakeWorker(); + return; + } + let { + workerSrc + } = PDFWorker; + try { + const worker = new Worker(workerSrc, { + type: "module" + }); + const messageHandler = new MessageHandler("main", "worker", worker); + const terminateEarly = () => { + ac.abort(); + messageHandler.destroy(); + worker.terminate(); + if (this.destroyed) { + this.#capability.reject(new Error("Worker was destroyed")); + } else { + this.#setupFakeWorker(); + } + }; + const ac = new AbortController(); + worker.addEventListener("error", () => { + if (!this.#webWorker) { + terminateEarly(); + } + }, { + signal: ac.signal + }); + messageHandler.on("test", data => { + ac.abort(); + if (this.destroyed || !data) { + terminateEarly(); + return; + } + this.#messageHandler = messageHandler; + this.#port = worker; + this.#webWorker = worker; + this.#resolve(); + }); + messageHandler.on("ready", data => { + ac.abort(); + if (this.destroyed) { + terminateEarly(); + return; + } + try { + sendTest(); + } catch { + this.#setupFakeWorker(); + } + }); + const sendTest = () => { + const testObj = new Uint8Array(); + messageHandler.send("test", testObj, [testObj.buffer]); + }; + sendTest(); + return; + } catch { + info("The worker has been disabled."); + } + this.#setupFakeWorker(); + } + #setupFakeWorker() { + if (!PDFWorker.#isWorkerDisabled) { + warn("Setting up fake worker."); + PDFWorker.#isWorkerDisabled = true; + } + PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => { + if (this.destroyed) { + this.#capability.reject(new Error("Worker was destroyed")); + return; + } + const port = new LoopbackPort(); + this.#port = port; + const id = `fake${PDFWorker.#fakeWorkerId++}`; + const workerHandler = new MessageHandler(id + "_worker", id, port); + WorkerMessageHandler.setup(workerHandler, port); + this.#messageHandler = new MessageHandler(id, id + "_worker", port); + this.#resolve(); + }).catch(reason => { + this.#capability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`)); + }); + } + destroy() { + this.destroyed = true; + this.#webWorker?.terminate(); + this.#webWorker = null; + PDFWorker.#workerPorts.delete(this.#port); + this.#port = null; + this.#messageHandler?.destroy(); + this.#messageHandler = null; + } + static create(params) { + const cachedPort = this.#workerPorts.get(params?.port); + if (cachedPort) { + if (cachedPort._pendingDestroy) { + throw new Error("PDFWorker.create - the worker is being destroyed.\n" + "Please remember to await `PDFDocumentLoadingTask.destroy()`-calls."); + } + return cachedPort; + } + return new PDFWorker(params); + } + static get workerSrc() { + if (GlobalWorkerOptions.workerSrc) { + return GlobalWorkerOptions.workerSrc; + } + throw new Error('No "GlobalWorkerOptions.workerSrc" specified.'); + } + static get #mainThreadWorkerMessageHandler() { + try { + return globalThis.pdfjsWorker?.WorkerMessageHandler || null; + } catch { + return null; + } + } + static get _setupFakeWorkerGlobal() { + const loader = async () => { + if (this.#mainThreadWorkerMessageHandler) { + return this.#mainThreadWorkerMessageHandler; + } + const worker = await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + this.workerSrc); + return worker.WorkerMessageHandler; + }; + return shadow(this, "_setupFakeWorkerGlobal", loader()); + } +} +class WorkerTransport { + #methodPromises = new Map(); + #pageCache = new Map(); + #pagePromises = new Map(); + #pageRefCache = new Map(); + #passwordCapability = null; + constructor(messageHandler, loadingTask, networkStream, params, factory, enableHWA) { + this.messageHandler = messageHandler; + this.loadingTask = loadingTask; + this.commonObjs = new PDFObjects(); + this.fontLoader = new FontLoader({ + ownerDocument: params.ownerDocument, + styleElement: params.styleElement + }); + this.loadingParams = params.loadingParams; + this._params = params; + this.canvasFactory = factory.canvasFactory; + this.filterFactory = factory.filterFactory; + this.cMapReaderFactory = factory.cMapReaderFactory; + this.standardFontDataFactory = factory.standardFontDataFactory; + this.wasmFactory = factory.wasmFactory; + this.destroyed = false; + this.destroyCapability = null; + this._networkStream = networkStream; + this._fullReader = null; + this._lastProgress = null; + this.downloadInfoCapability = Promise.withResolvers(); + this.enableHWA = enableHWA; + this.setupMessageHandler(); + } + #cacheSimpleMethod(name, data = null) { + const cachedPromise = this.#methodPromises.get(name); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise(name, data); + this.#methodPromises.set(name, promise); + return promise; + } + get annotationStorage() { + return shadow(this, "annotationStorage", new AnnotationStorage()); + } + getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isEditing = false, isOpList = false) { + let renderingIntent = RenderingIntentFlag.DISPLAY; + let annotationStorageSerializable = SerializableEmpty; + switch (intent) { + case "any": + renderingIntent = RenderingIntentFlag.ANY; + break; + case "display": + break; + case "print": + renderingIntent = RenderingIntentFlag.PRINT; + break; + default: + warn(`getRenderingIntent - invalid intent: ${intent}`); + } + const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage; + switch (annotationMode) { + case AnnotationMode.DISABLE: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE; + break; + case AnnotationMode.ENABLE: + break; + case AnnotationMode.ENABLE_FORMS: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_FORMS; + break; + case AnnotationMode.ENABLE_STORAGE: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE; + annotationStorageSerializable = annotationStorage.serializable; + break; + default: + warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`); + } + if (isEditing) { + renderingIntent += RenderingIntentFlag.IS_EDITING; + } + if (isOpList) { + renderingIntent += RenderingIntentFlag.OPLIST; + } + const { + ids: modifiedIds, + hash: modifiedIdsHash + } = annotationStorage.modifiedIds; + const cacheKeyBuf = [renderingIntent, annotationStorageSerializable.hash, modifiedIdsHash]; + return { + renderingIntent, + cacheKey: cacheKeyBuf.join("_"), + annotationStorageSerializable, + modifiedIds + }; + } + destroy() { + if (this.destroyCapability) { + return this.destroyCapability.promise; + } + this.destroyed = true; + this.destroyCapability = Promise.withResolvers(); + this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback")); + const waitOn = []; + for (const page of this.#pageCache.values()) { + waitOn.push(page._destroy()); + } + this.#pageCache.clear(); + this.#pagePromises.clear(); + this.#pageRefCache.clear(); + if (this.hasOwnProperty("annotationStorage")) { + this.annotationStorage.resetModified(); + } + const terminated = this.messageHandler.sendWithPromise("Terminate", null); + waitOn.push(terminated); + Promise.all(waitOn).then(() => { + this.commonObjs.clear(); + this.fontLoader.clear(); + this.#methodPromises.clear(); + this.filterFactory.destroy(); + TextLayer.cleanup(); + this._networkStream?.cancelAllRequests(new AbortException("Worker was terminated.")); + this.messageHandler?.destroy(); + this.messageHandler = null; + this.destroyCapability.resolve(); + }, this.destroyCapability.reject); + return this.destroyCapability.promise; + } + setupMessageHandler() { + const { + messageHandler, + loadingTask + } = this; + messageHandler.on("GetReader", (data, sink) => { + assert(this._networkStream, "GetReader - no `IPDFStream` instance available."); + this._fullReader = this._networkStream.getFullReader(); + this._fullReader.onProgress = evt => { + this._lastProgress = { + loaded: evt.loaded, + total: evt.total + }; + }; + sink.onPull = () => { + this._fullReader.read().then(function ({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + assert(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch(reason => { + sink.error(reason); + }); + }; + sink.onCancel = reason => { + this._fullReader.cancel(reason); + sink.ready.catch(readyReason => { + if (this.destroyed) { + return; + } + throw readyReason; + }); + }; + }); + messageHandler.on("ReaderHeadersReady", async data => { + await this._fullReader.headersReady; + const { + isStreamingSupported, + isRangeSupported, + contentLength + } = this._fullReader; + if (!isStreamingSupported || !isRangeSupported) { + if (this._lastProgress) { + loadingTask.onProgress?.(this._lastProgress); + } + this._fullReader.onProgress = evt => { + loadingTask.onProgress?.({ + loaded: evt.loaded, + total: evt.total + }); + }; + } + return { + isStreamingSupported, + isRangeSupported, + contentLength + }; + }); + messageHandler.on("GetRangeReader", (data, sink) => { + assert(this._networkStream, "GetRangeReader - no `IPDFStream` instance available."); + const rangeReader = this._networkStream.getRangeReader(data.begin, data.end); + if (!rangeReader) { + sink.close(); + return; + } + sink.onPull = () => { + rangeReader.read().then(function ({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + assert(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch(reason => { + sink.error(reason); + }); + }; + sink.onCancel = reason => { + rangeReader.cancel(reason); + sink.ready.catch(readyReason => { + if (this.destroyed) { + return; + } + throw readyReason; + }); + }; + }); + messageHandler.on("GetDoc", ({ + pdfInfo + }) => { + this._numPages = pdfInfo.numPages; + this._htmlForXfa = pdfInfo.htmlForXfa; + delete pdfInfo.htmlForXfa; + loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this)); + }); + messageHandler.on("DocException", ex => { + loadingTask._capability.reject(wrapReason(ex)); + }); + messageHandler.on("PasswordRequest", ex => { + this.#passwordCapability = Promise.withResolvers(); + try { + if (!loadingTask.onPassword) { + throw wrapReason(ex); + } + const updatePassword = password => { + if (password instanceof Error) { + this.#passwordCapability.reject(password); + } else { + this.#passwordCapability.resolve({ + password + }); + } + }; + loadingTask.onPassword(updatePassword, ex.code); + } catch (err) { + this.#passwordCapability.reject(err); + } + return this.#passwordCapability.promise; + }); + messageHandler.on("DataLoaded", data => { + loadingTask.onProgress?.({ + loaded: data.length, + total: data.length + }); + this.downloadInfoCapability.resolve(data); + }); + messageHandler.on("StartRenderPage", data => { + if (this.destroyed) { + return; + } + const page = this.#pageCache.get(data.pageIndex); + page._startRenderPage(data.transparency, data.cacheKey); + }); + messageHandler.on("commonobj", ([id, type, exportedData]) => { + if (this.destroyed) { + return null; + } + if (this.commonObjs.has(id)) { + return null; + } + switch (type) { + case "Font": + if ("error" in exportedData) { + const exportedError = exportedData.error; + warn(`Error during font loading: ${exportedError}`); + this.commonObjs.resolve(id, exportedError); + break; + } + const fontData = new FontInfo(exportedData); + const inspectFont = this._params.pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null; + const font = new FontFaceObject(fontData, inspectFont, exportedData.extra, exportedData.charProcOperatorList); + this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", { + id + })).finally(() => { + if (!font.fontExtraProperties && font.data) { + font.clearData(); + } + this.commonObjs.resolve(id, font); + }); + break; + case "CopyLocalImage": + const { + imageRef + } = exportedData; + assert(imageRef, "The imageRef must be defined."); + for (const pageProxy of this.#pageCache.values()) { + for (const [, data] of pageProxy.objs) { + if (data?.ref !== imageRef) { + continue; + } + if (!data.dataLen) { + return null; + } + this.commonObjs.resolve(id, structuredClone(data)); + return data.dataLen; + } + } + break; + case "FontPath": + case "Image": + this.commonObjs.resolve(id, exportedData); + break; + case "Pattern": + const pattern = new PatternInfo(exportedData); + this.commonObjs.resolve(id, pattern.getIR()); + break; + default: + throw new Error(`Got unknown common object type ${type}`); + } + return null; + }); + messageHandler.on("obj", ([id, pageIndex, type, imageData]) => { + if (this.destroyed) { + return; + } + const pageProxy = this.#pageCache.get(pageIndex); + if (pageProxy.objs.has(id)) { + return; + } + if (pageProxy._intentStates.size === 0) { + imageData?.bitmap?.close(); + return; + } + switch (type) { + case "Image": + case "Pattern": + pageProxy.objs.resolve(id, imageData); + break; + default: + throw new Error(`Got unknown object type ${type}`); + } + }); + messageHandler.on("DocProgress", data => { + if (this.destroyed) { + return; + } + loadingTask.onProgress?.({ + loaded: data.loaded, + total: data.total + }); + }); + messageHandler.on("FetchBinaryData", async data => { + throw new Error("Not implemented: FetchBinaryData"); + }); + } + getData() { + return this.messageHandler.sendWithPromise("GetData", null); + } + saveDocument() { + if (this.annotationStorage.size <= 0) { + warn("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead."); + } + const { + map, + transfer + } = this.annotationStorage.serializable; + return this.messageHandler.sendWithPromise("SaveDocument", { + isPureXfa: !!this._htmlForXfa, + numPages: this._numPages, + annotationStorage: map, + filename: this._fullReader?.filename ?? null + }, transfer).finally(() => { + this.annotationStorage.resetModified(); + }); + } + extractPages(pageInfos) { + return this.messageHandler.sendWithPromise("ExtractPages", { + pageInfos + }); + } + getPage(pageNumber) { + if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) { + return Promise.reject(new Error("Invalid page request.")); + } + const pageIndex = pageNumber - 1, + cachedPromise = this.#pagePromises.get(pageIndex); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise("GetPage", { + pageIndex + }).then(pageInfo => { + if (this.destroyed) { + throw new Error("Transport destroyed"); + } + if (pageInfo.refStr) { + this.#pageRefCache.set(pageInfo.refStr, pageNumber); + } + const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug); + this.#pageCache.set(pageIndex, page); + return page; + }); + this.#pagePromises.set(pageIndex, promise); + return promise; + } + getPageIndex(ref) { + if (!isRefProxy(ref)) { + return Promise.reject(new Error("Invalid pageIndex request.")); + } + return this.messageHandler.sendWithPromise("GetPageIndex", { + num: ref.num, + gen: ref.gen + }); + } + getAnnotations(pageIndex, intent) { + return this.messageHandler.sendWithPromise("GetAnnotations", { + pageIndex, + intent + }); + } + getFieldObjects() { + return this.#cacheSimpleMethod("GetFieldObjects"); + } + hasJSActions() { + return this.#cacheSimpleMethod("HasJSActions"); + } + getCalculationOrderIds() { + return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null); + } + getDestinations() { + return this.messageHandler.sendWithPromise("GetDestinations", null); + } + getDestination(id) { + if (typeof id !== "string") { + return Promise.reject(new Error("Invalid destination request.")); + } + return this.messageHandler.sendWithPromise("GetDestination", { + id + }); + } + getPageLabels() { + return this.messageHandler.sendWithPromise("GetPageLabels", null); + } + getPageLayout() { + return this.messageHandler.sendWithPromise("GetPageLayout", null); + } + getPageMode() { + return this.messageHandler.sendWithPromise("GetPageMode", null); + } + getViewerPreferences() { + return this.messageHandler.sendWithPromise("GetViewerPreferences", null); + } + getOpenAction() { + return this.messageHandler.sendWithPromise("GetOpenAction", null); + } + getAttachments() { + return this.messageHandler.sendWithPromise("GetAttachments", null); + } + getAnnotationsByType(types, pageIndexesToSkip) { + return this.messageHandler.sendWithPromise("GetAnnotationsByType", { + types, + pageIndexesToSkip + }); + } + getDocJSActions() { + return this.#cacheSimpleMethod("GetDocJSActions"); + } + getPageJSActions(pageIndex) { + return this.messageHandler.sendWithPromise("GetPageJSActions", { + pageIndex + }); + } + getStructTree(pageIndex) { + return this.messageHandler.sendWithPromise("GetStructTree", { + pageIndex + }); + } + getOutline() { + return this.messageHandler.sendWithPromise("GetOutline", null); + } + getOptionalContentConfig(renderingIntent) { + return this.#cacheSimpleMethod("GetOptionalContentConfig").then(data => new OptionalContentConfig(data, renderingIntent)); + } + getPermissions() { + return this.messageHandler.sendWithPromise("GetPermissions", null); + } + getMetadata() { + const name = "GetMetadata", + cachedPromise = this.#methodPromises.get(name); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise(name, null).then(results => ({ + info: results[0], + metadata: results[1] ? new Metadata(results[1]) : null, + contentDispositionFilename: this._fullReader?.filename ?? null, + contentLength: this._fullReader?.contentLength ?? null, + hasStructTree: results[2] + })); + this.#methodPromises.set(name, promise); + return promise; + } + getMarkInfo() { + return this.messageHandler.sendWithPromise("GetMarkInfo", null); + } + async startCleanup(keepLoadedFonts = false) { + if (this.destroyed) { + return; + } + await this.messageHandler.sendWithPromise("Cleanup", null); + for (const page of this.#pageCache.values()) { + const cleanupSuccessful = page.cleanup(); + if (!cleanupSuccessful) { + throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`); + } + } + this.commonObjs.clear(); + if (!keepLoadedFonts) { + this.fontLoader.clear(); + } + this.#methodPromises.clear(); + this.filterFactory.destroy(true); + TextLayer.cleanup(); + } + cachedPageNumber(ref) { + if (!isRefProxy(ref)) { + return null; + } + const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`; + return this.#pageRefCache.get(refStr) ?? null; + } +} +class RenderTask { + #internalRenderTask = null; + onContinue = null; + onError = null; + constructor(internalRenderTask) { + this.#internalRenderTask = internalRenderTask; + } + get promise() { + return this.#internalRenderTask.capability.promise; + } + cancel(extraDelay = 0) { + this.#internalRenderTask.cancel(null, extraDelay); + } + get separateAnnots() { + const { + separateAnnots + } = this.#internalRenderTask.operatorList; + if (!separateAnnots) { + return false; + } + const { + annotationCanvasMap + } = this.#internalRenderTask; + return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0; + } +} +class InternalRenderTask { + #rAF = null; + static #canvasInUse = new WeakSet(); + constructor({ + callback, + params, + objs, + commonObjs, + annotationCanvasMap, + operatorList, + pageIndex, + canvasFactory, + filterFactory, + useRequestAnimationFrame = false, + pdfBug = false, + pageColors = null, + enableHWA = false, + operationsFilter = null + }) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.annotationCanvasMap = annotationCanvasMap; + this.operatorListIdx = null; + this.operatorList = operatorList; + this._pageIndex = pageIndex; + this.canvasFactory = canvasFactory; + this.filterFactory = filterFactory; + this._pdfBug = pdfBug; + this.pageColors = pageColors; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined"; + this.cancelled = false; + this.capability = Promise.withResolvers(); + this.task = new RenderTask(this); + this._cancelBound = this.cancel.bind(this); + this._continueBound = this._continue.bind(this); + this._scheduleNextBound = this._scheduleNext.bind(this); + this._nextBound = this._next.bind(this); + this._canvas = params.canvas; + this._canvasContext = params.canvas ? null : params.canvasContext; + this._enableHWA = enableHWA; + this._dependencyTracker = params.dependencyTracker; + this._operationsFilter = operationsFilter; + } + get completed() { + return this.capability.promise.catch(function () {}); + } + initializeGraphics({ + transparency = false, + optionalContentConfig + }) { + if (this.cancelled) { + return; + } + if (this._canvas) { + if (InternalRenderTask.#canvasInUse.has(this._canvas)) { + throw new Error("Cannot use the same canvas during multiple render() operations. " + "Use different canvas or ensure previous operations were " + "cancelled or completed."); + } + InternalRenderTask.#canvasInUse.add(this._canvas); + } + if (this._pdfBug && globalThis.StepperManager?.enabled) { + this.stepper = globalThis.StepperManager.create(this._pageIndex); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + const { + viewport, + transform, + background, + dependencyTracker + } = this.params; + const canvasContext = this._canvasContext || this._canvas.getContext("2d", { + alpha: false, + willReadFrequently: !this._enableHWA + }); + this.gfx = new CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { + optionalContentConfig + }, this.annotationCanvasMap, this.pageColors, dependencyTracker); + this.gfx.beginDrawing({ + transform, + viewport, + transparency, + background + }); + this.operatorListIdx = 0; + this.graphicsReady = true; + this.graphicsReadyCallback?.(); + } + cancel(error = null, extraDelay = 0) { + this.running = false; + this.cancelled = true; + this.gfx?.endDrawing(); + if (this.#rAF) { + window.cancelAnimationFrame(this.#rAF); + this.#rAF = null; + } + InternalRenderTask.#canvasInUse.delete(this._canvas); + error ||= new RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay); + this.callback(error); + this.task.onError?.(error); + } + operatorListChanged() { + if (!this.graphicsReady) { + this.graphicsReadyCallback ||= this._continueBound; + return; + } + this.gfx.dependencyTracker?.growOperationsCount(this.operatorList.fnArray.length); + this.stepper?.updateOperatorList(this.operatorList); + if (this.running) { + return; + } + this._continue(); + } + _continue() { + this.running = true; + if (this.cancelled) { + return; + } + if (this.task.onContinue) { + this.task.onContinue(this._scheduleNextBound); + } else { + this._scheduleNext(); + } + } + _scheduleNext() { + if (this._useRequestAnimationFrame) { + this.#rAF = window.requestAnimationFrame(() => { + this.#rAF = null; + this._nextBound().catch(this._cancelBound); + }); + } else { + Promise.resolve().then(this._nextBound).catch(this._cancelBound); + } + } + async _next() { + if (this.cancelled) { + return; + } + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper, this._operationsFilter); + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + InternalRenderTask.#canvasInUse.delete(this._canvas); + this.callback(); + } + } + } +} +const version = "5.4.445"; +const build = "ec5330f78"; + +;// ./src/display/editor/color_picker.js + + + +class ColorPicker { + #button = null; + #buttonSwatch = null; + #defaultColor; + #dropdown = null; + #dropdownWasFromKeyboard = false; + #isMainColorPicker = false; + #editor = null; + #eventBus; + #openDropdownAC = null; + #uiManager = null; + static #l10nColor = null; + static get _keyboardManager() { + return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]])); + } + constructor({ + editor = null, + uiManager = null + }) { + if (editor) { + this.#isMainColorPicker = false; + this.#editor = editor; + } else { + this.#isMainColorPicker = true; + } + this.#uiManager = editor?._uiManager || uiManager; + this.#eventBus = this.#uiManager._eventBus; + this.#defaultColor = editor?.color?.toUpperCase() || this.#uiManager?.highlightColors.values().next().value || "#FFFF98"; + ColorPicker.#l10nColor ||= Object.freeze({ + blue: "pdfjs-editor-colorpicker-blue", + green: "pdfjs-editor-colorpicker-green", + pink: "pdfjs-editor-colorpicker-pink", + red: "pdfjs-editor-colorpicker-red", + yellow: "pdfjs-editor-colorpicker-yellow" + }); + } + renderButton() { + const button = this.#button = document.createElement("button"); + button.className = "colorPicker"; + button.tabIndex = "0"; + button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button"); + button.ariaHasPopup = "true"; + if (this.#editor) { + button.ariaControls = `${this.#editor.id}_colorpicker_dropdown`; + } + const signal = this.#uiManager._signal; + button.addEventListener("click", this.#openDropdown.bind(this), { + signal + }); + button.addEventListener("keydown", this.#keyDown.bind(this), { + signal + }); + const swatch = this.#buttonSwatch = document.createElement("span"); + swatch.className = "swatch"; + swatch.ariaHidden = "true"; + swatch.style.backgroundColor = this.#defaultColor; + button.append(swatch); + return button; + } + renderMainDropdown() { + const dropdown = this.#dropdown = this.#getDropdownRoot(); + dropdown.ariaOrientation = "horizontal"; + dropdown.ariaLabelledBy = "highlightColorPickerLabel"; + return dropdown; + } + #getDropdownRoot() { + const div = document.createElement("div"); + const signal = this.#uiManager._signal; + div.addEventListener("contextmenu", noContextMenu, { + signal + }); + div.className = "dropdown"; + div.role = "listbox"; + div.ariaMultiSelectable = "false"; + div.ariaOrientation = "vertical"; + div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown"); + if (this.#editor) { + div.id = `${this.#editor.id}_colorpicker_dropdown`; + } + for (const [name, color] of this.#uiManager.highlightColors) { + const button = document.createElement("button"); + button.tabIndex = "0"; + button.role = "option"; + button.setAttribute("data-color", color); + button.title = name; + button.setAttribute("data-l10n-id", ColorPicker.#l10nColor[name]); + const swatch = document.createElement("span"); + button.append(swatch); + swatch.className = "swatch"; + swatch.style.backgroundColor = color; + button.ariaSelected = color === this.#defaultColor; + button.addEventListener("click", this.#colorSelect.bind(this, color), { + signal + }); + div.append(button); + } + div.addEventListener("keydown", this.#keyDown.bind(this), { + signal + }); + return div; + } + #colorSelect(color, event) { + event.stopPropagation(); + this.#eventBus.dispatch("switchannotationeditorparams", { + source: this, + type: AnnotationEditorParamsType.HIGHLIGHT_COLOR, + value: color + }); + this.updateColor(color); + } + _colorSelectFromKeyboard(event) { + if (event.target === this.#button) { + this.#openDropdown(event); + return; + } + const color = event.target.getAttribute("data-color"); + if (!color) { + return; + } + this.#colorSelect(color, event); + } + _moveToNext(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + if (event.target === this.#button) { + this.#dropdown.firstElementChild?.focus(); + return; + } + event.target.nextSibling?.focus(); + } + _moveToPrevious(event) { + if (event.target === this.#dropdown?.firstElementChild || event.target === this.#button) { + if (this.#isDropdownVisible) { + this._hideDropdownFromKeyboard(); + } + return; + } + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + } + event.target.previousSibling?.focus(); + } + _moveToBeginning(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.firstElementChild?.focus(); + } + _moveToEnd(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.lastElementChild?.focus(); + } + #keyDown(event) { + ColorPicker._keyboardManager.exec(this, event); + } + #openDropdown(event) { + if (this.#isDropdownVisible) { + this.hideDropdown(); + return; + } + this.#dropdownWasFromKeyboard = event.detail === 0; + if (!this.#openDropdownAC) { + this.#openDropdownAC = new AbortController(); + window.addEventListener("pointerdown", this.#pointerDown.bind(this), { + signal: this.#uiManager.combinedSignal(this.#openDropdownAC) + }); + } + this.#button.ariaExpanded = "true"; + if (this.#dropdown) { + this.#dropdown.classList.remove("hidden"); + return; + } + const root = this.#dropdown = this.#getDropdownRoot(); + this.#button.append(root); + } + #pointerDown(event) { + if (this.#dropdown?.contains(event.target)) { + return; + } + this.hideDropdown(); + } + hideDropdown() { + this.#dropdown?.classList.add("hidden"); + this.#button.ariaExpanded = "false"; + this.#openDropdownAC?.abort(); + this.#openDropdownAC = null; + } + get #isDropdownVisible() { + return this.#dropdown && !this.#dropdown.classList.contains("hidden"); + } + _hideDropdownFromKeyboard() { + if (this.#isMainColorPicker) { + return; + } + if (!this.#isDropdownVisible) { + this.#editor?.unselect(); + return; + } + this.hideDropdown(); + this.#button.focus({ + preventScroll: true, + focusVisible: this.#dropdownWasFromKeyboard + }); + } + updateColor(color) { + if (this.#buttonSwatch) { + this.#buttonSwatch.style.backgroundColor = color; + } + if (!this.#dropdown) { + return; + } + const i = this.#uiManager.highlightColors.values(); + for (const child of this.#dropdown.children) { + child.ariaSelected = i.next().value === color.toUpperCase(); + } + } + destroy() { + this.#button?.remove(); + this.#button = null; + this.#buttonSwatch = null; + this.#dropdown?.remove(); + this.#dropdown = null; + } +} +class BasicColorPicker { + #input = null; + #editor = null; + #uiManager = null; + static #l10nColor = null; + constructor(editor) { + this.#editor = editor; + this.#uiManager = editor._uiManager; + BasicColorPicker.#l10nColor ||= Object.freeze({ + freetext: "pdfjs-editor-color-picker-free-text-input", + ink: "pdfjs-editor-color-picker-ink-input" + }); + } + renderButton() { + if (this.#input) { + return this.#input; + } + const { + editorType, + colorType, + color + } = this.#editor; + const input = this.#input = document.createElement("input"); + input.type = "color"; + input.value = color || "#000000"; + input.className = "basicColorPicker"; + input.tabIndex = 0; + input.setAttribute("data-l10n-id", BasicColorPicker.#l10nColor[editorType]); + input.addEventListener("input", () => { + this.#uiManager.updateParams(colorType, input.value); + }, { + signal: this.#uiManager._signal + }); + return input; + } + update(value) { + if (!this.#input) { + return; + } + this.#input.value = value; + } + destroy() { + this.#input?.remove(); + this.#input = null; + } + hideDropdown() {} +} + +;// ./src/shared/scripting_utils.js +function makeColorComp(n) { + return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0"); +} +function scaleAndClamp(x) { + return Math.max(0, Math.min(255, 255 * x)); +} +class ColorConverters { + static CMYK_G([c, y, m, k]) { + return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)]; + } + static G_CMYK([g]) { + return ["CMYK", 0, 0, 0, 1 - g]; + } + static G_RGB([g]) { + return ["RGB", g, g, g]; + } + static G_rgb([g]) { + g = scaleAndClamp(g); + return [g, g, g]; + } + static G_HTML([g]) { + const G = makeColorComp(g); + return `#${G}${G}${G}`; + } + static RGB_G([r, g, b]) { + return ["G", 0.3 * r + 0.59 * g + 0.11 * b]; + } + static RGB_rgb(color) { + return color.map(scaleAndClamp); + } + static RGB_HTML(color) { + return `#${color.map(makeColorComp).join("")}`; + } + static T_HTML() { + return "#00000000"; + } + static T_rgb() { + return [null]; + } + static CMYK_RGB([c, y, m, k]) { + return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)]; + } + static CMYK_rgb([c, y, m, k]) { + return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))]; + } + static CMYK_HTML(components) { + const rgb = this.CMYK_RGB(components).slice(1); + return this.RGB_HTML(rgb); + } + static RGB_CMYK([r, g, b]) { + const c = 1 - r; + const m = 1 - g; + const y = 1 - b; + const k = Math.min(c, m, y); + return ["CMYK", c, m, y, k]; + } +} +const DateFormats = (/* unused pure expression or super */ null && (["m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy", "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy", "m/d/yy h:MM tt", "m/d/yy HH:MM"])); +const TimeFormats = (/* unused pure expression or super */ null && (["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"])); + +;// ./src/display/svg_factory.js + + +class BaseSVGFactory { + create(width, height, skipDimensions = false) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid SVG dimensions"); + } + const svg = this._createSVG("svg:svg"); + svg.setAttribute("version", "1.1"); + if (!skipDimensions) { + svg.setAttribute("width", `${width}px`); + svg.setAttribute("height", `${height}px`); + } + svg.setAttribute("preserveAspectRatio", "none"); + svg.setAttribute("viewBox", `0 0 ${width} ${height}`); + return svg; + } + createElement(type) { + if (typeof type !== "string") { + throw new Error("Invalid SVG element type"); + } + return this._createSVG(type); + } + _createSVG(type) { + unreachable("Abstract method `_createSVG` called."); + } +} +class DOMSVGFactory extends BaseSVGFactory { + _createSVG(type) { + return document.createElementNS(SVG_NS, type); + } +} + +;// ./src/display/annotation_layer.js + + + + + +const annotation_layer_DEFAULT_FONT_SIZE = 9; +const GetElementsByNameSet = new WeakSet(); +const TIMEZONE_OFFSET = new Date().getTimezoneOffset() * 60 * 1000; +class AnnotationElementFactory { + static create(parameters) { + const subtype = parameters.data.annotationType; + switch (subtype) { + case AnnotationType.LINK: + return new LinkAnnotationElement(parameters); + case AnnotationType.TEXT: + return new TextAnnotationElement(parameters); + case AnnotationType.WIDGET: + const fieldType = parameters.data.fieldType; + switch (fieldType) { + case "Tx": + return new TextWidgetAnnotationElement(parameters); + case "Btn": + if (parameters.data.radioButton) { + return new RadioButtonWidgetAnnotationElement(parameters); + } else if (parameters.data.checkBox) { + return new CheckboxWidgetAnnotationElement(parameters); + } + return new PushButtonWidgetAnnotationElement(parameters); + case "Ch": + return new ChoiceWidgetAnnotationElement(parameters); + case "Sig": + return new SignatureWidgetAnnotationElement(parameters); + } + return new WidgetAnnotationElement(parameters); + case AnnotationType.POPUP: + return new PopupAnnotationElement(parameters); + case AnnotationType.FREETEXT: + return new FreeTextAnnotationElement(parameters); + case AnnotationType.LINE: + return new LineAnnotationElement(parameters); + case AnnotationType.SQUARE: + return new SquareAnnotationElement(parameters); + case AnnotationType.CIRCLE: + return new CircleAnnotationElement(parameters); + case AnnotationType.POLYLINE: + return new PolylineAnnotationElement(parameters); + case AnnotationType.CARET: + return new CaretAnnotationElement(parameters); + case AnnotationType.INK: + return new InkAnnotationElement(parameters); + case AnnotationType.POLYGON: + return new PolygonAnnotationElement(parameters); + case AnnotationType.HIGHLIGHT: + return new HighlightAnnotationElement(parameters); + case AnnotationType.UNDERLINE: + return new UnderlineAnnotationElement(parameters); + case AnnotationType.SQUIGGLY: + return new SquigglyAnnotationElement(parameters); + case AnnotationType.STRIKEOUT: + return new StrikeOutAnnotationElement(parameters); + case AnnotationType.STAMP: + return new StampAnnotationElement(parameters); + case AnnotationType.FILEATTACHMENT: + return new FileAttachmentAnnotationElement(parameters); + default: + return new AnnotationElement(parameters); + } + } +} +class AnnotationElement { + #updates = null; + #hasBorder = false; + #popupElement = null; + constructor(parameters, { + isRenderable = false, + ignoreBorder = false, + createQuadrilaterals = false + } = {}) { + this.isRenderable = isRenderable; + this.data = parameters.data; + this.layer = parameters.layer; + this.linkService = parameters.linkService; + this.downloadManager = parameters.downloadManager; + this.imageResourcesPath = parameters.imageResourcesPath; + this.renderForms = parameters.renderForms; + this.svgFactory = parameters.svgFactory; + this.annotationStorage = parameters.annotationStorage; + this.enableComment = parameters.enableComment; + this.enableScripting = parameters.enableScripting; + this.hasJSActions = parameters.hasJSActions; + this._fieldObjects = parameters.fieldObjects; + this.parent = parameters.parent; + this.hasOwnCommentButton = false; + if (isRenderable) { + this.contentElement = this.container = this._createContainer(ignoreBorder); + } + if (createQuadrilaterals) { + this._createQuadrilaterals(); + } + } + static _hasPopupData({ + contentsObj, + richText + }) { + return !!(contentsObj?.str || richText?.str); + } + get _isEditable() { + return this.data.isEditable; + } + get hasPopupData() { + return AnnotationElement._hasPopupData(this.data) || this.enableComment && !!this.commentText; + } + get commentData() { + const { + data + } = this; + const editor = this.annotationStorage?.getEditor(data.id); + if (editor) { + return editor.getData(); + } + return data; + } + get hasCommentButton() { + return this.enableComment && this.hasPopupElement; + } + get commentButtonPosition() { + const editor = this.annotationStorage?.getEditor(this.data.id); + if (editor) { + return editor.commentButtonPositionInPage; + } + const { + quadPoints, + inkLists, + rect + } = this.data; + let maxX = -Infinity; + let maxY = -Infinity; + if (quadPoints?.length >= 8) { + for (let i = 0; i < quadPoints.length; i += 8) { + if (quadPoints[i + 1] > maxY) { + maxY = quadPoints[i + 1]; + maxX = quadPoints[i + 2]; + } else if (quadPoints[i + 1] === maxY) { + maxX = Math.max(maxX, quadPoints[i + 2]); + } + } + return [maxX, maxY]; + } + if (inkLists?.length >= 1) { + for (const inkList of inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + if (inkList[i + 1] > maxY) { + maxY = inkList[i + 1]; + maxX = inkList[i]; + } else if (inkList[i + 1] === maxY) { + maxX = Math.max(maxX, inkList[i]); + } + } + } + if (maxX !== Infinity) { + return [maxX, maxY]; + } + } + if (rect) { + return [rect[2], rect[3]]; + } + return null; + } + _normalizePoint(point) { + const { + page: { + view + }, + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } = this.parent; + point[1] = view[3] - point[1] + view[1]; + point[0] = 100 * (point[0] - pageX) / pageWidth; + point[1] = 100 * (point[1] - pageY) / pageHeight; + return point; + } + get commentText() { + const { + data + } = this; + return this.annotationStorage.getRawValue(`${AnnotationEditorPrefix}${data.id}`)?.popup?.contents || data.contentsObj?.str || ""; + } + set commentText(text) { + const { + data + } = this; + const popup = { + deleted: !text, + contents: text || "" + }; + if (!this.annotationStorage.updateEditor(data.id, { + popup + })) { + this.annotationStorage.setValue(`${AnnotationEditorPrefix}${data.id}`, { + id: data.id, + annotationType: data.annotationType, + pageIndex: this.parent.page._pageIndex, + popup, + popupRef: data.popupRef, + modificationDate: new Date() + }); + } + if (!text) { + this.removePopup(); + } + } + removePopup() { + (this.#popupElement?.popup || this.popup)?.remove(); + this.#popupElement = this.popup = null; + } + updateEdited(params) { + if (!this.container) { + return; + } + if (params.rect) { + this.#updates ||= { + rect: this.data.rect.slice(0) + }; + } + const { + rect, + popup: newPopup + } = params; + if (rect) { + this.#setRectEdited(rect); + } + let popup = this.#popupElement?.popup || this.popup; + if (!popup && newPopup?.text) { + this._createPopup(newPopup); + popup = this.#popupElement.popup; + } + if (!popup) { + return; + } + popup.updateEdited(params); + if (newPopup?.deleted) { + popup.remove(); + this.#popupElement = null; + this.popup = null; + } + } + resetEdited() { + if (!this.#updates) { + return; + } + this.#setRectEdited(this.#updates.rect); + this.#popupElement?.popup.resetEdited(); + this.#updates = null; + } + #setRectEdited(rect) { + const { + container: { + style + }, + data: { + rect: currentRect, + rotation + }, + parent: { + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } + } = this; + currentRect?.splice(0, 4, ...rect); + style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; + style.top = `${100 * (pageHeight - rect[3] + pageY) / pageHeight}%`; + if (rotation === 0) { + style.width = `${100 * (rect[2] - rect[0]) / pageWidth}%`; + style.height = `${100 * (rect[3] - rect[1]) / pageHeight}%`; + } else { + this.setRotation(rotation); + } + } + _createContainer(ignoreBorder) { + const { + data, + parent: { + page, + viewport + } + } = this; + const container = document.createElement("section"); + container.setAttribute("data-annotation-id", data.id); + if (!(this instanceof WidgetAnnotationElement) && !(this instanceof LinkAnnotationElement)) { + container.tabIndex = 0; + } + const { + style + } = container; + style.zIndex = this.parent.zIndex; + this.parent.zIndex += 2; + if (data.alternativeText) { + container.title = data.alternativeText; + } + if (data.noRotate) { + container.classList.add("norotate"); + } + if (!data.rect || this instanceof PopupAnnotationElement) { + const { + rotation + } = data; + if (!data.hasOwnCanvas && rotation !== 0) { + this.setRotation(rotation, container); + } + return container; + } + const { + width, + height + } = this; + if (!ignoreBorder && data.borderStyle.width > 0) { + style.borderWidth = `${data.borderStyle.width}px`; + const horizontalRadius = data.borderStyle.horizontalCornerRadius; + const verticalRadius = data.borderStyle.verticalCornerRadius; + if (horizontalRadius > 0 || verticalRadius > 0) { + const radius = `calc(${horizontalRadius}px * var(--total-scale-factor)) / calc(${verticalRadius}px * var(--total-scale-factor))`; + style.borderRadius = radius; + } else if (this instanceof RadioButtonWidgetAnnotationElement) { + const radius = `calc(${width}px * var(--total-scale-factor)) / calc(${height}px * var(--total-scale-factor))`; + style.borderRadius = radius; + } + switch (data.borderStyle.style) { + case AnnotationBorderStyleType.SOLID: + style.borderStyle = "solid"; + break; + case AnnotationBorderStyleType.DASHED: + style.borderStyle = "dashed"; + break; + case AnnotationBorderStyleType.BEVELED: + warn("Unimplemented border style: beveled"); + break; + case AnnotationBorderStyleType.INSET: + warn("Unimplemented border style: inset"); + break; + case AnnotationBorderStyleType.UNDERLINE: + style.borderBottomStyle = "solid"; + break; + default: + break; + } + const borderColor = data.borderColor || null; + if (borderColor) { + this.#hasBorder = true; + style.borderColor = Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0); + } else { + style.borderWidth = 0; + } + } + const rect = Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]); + const { + pageWidth, + pageHeight, + pageX, + pageY + } = viewport.rawDims; + style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; + style.top = `${100 * (rect[1] - pageY) / pageHeight}%`; + const { + rotation + } = data; + if (data.hasOwnCanvas || rotation === 0) { + style.width = `${100 * width / pageWidth}%`; + style.height = `${100 * height / pageHeight}%`; + } else { + this.setRotation(rotation, container); + } + return container; + } + setRotation(angle, container = this.container) { + if (!this.data.rect) { + return; + } + const { + pageWidth, + pageHeight + } = this.parent.viewport.rawDims; + let { + width, + height + } = this; + if (angle % 180 !== 0) { + [width, height] = [height, width]; + } + container.style.width = `${100 * width / pageWidth}%`; + container.style.height = `${100 * height / pageHeight}%`; + container.setAttribute("data-main-rotation", (360 - angle) % 360); + } + get _commonActions() { + const setColor = (jsName, styleName, event) => { + const color = event.detail[jsName]; + const colorType = color[0]; + const colorArray = color.slice(1); + event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray); + this.annotationStorage.setValue(this.data.id, { + [styleName]: ColorConverters[`${colorType}_rgb`](colorArray) + }); + }; + return shadow(this, "_commonActions", { + display: event => { + const { + display + } = event.detail; + const hidden = display % 2 === 1; + this.container.style.visibility = hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + noView: hidden, + noPrint: display === 1 || display === 2 + }); + }, + print: event => { + this.annotationStorage.setValue(this.data.id, { + noPrint: !event.detail.print + }); + }, + hidden: event => { + const { + hidden + } = event.detail; + this.container.style.visibility = hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + noPrint: hidden, + noView: hidden + }); + }, + focus: event => { + setTimeout(() => event.target.focus({ + preventScroll: false + }), 0); + }, + userName: event => { + event.target.title = event.detail.userName; + }, + readonly: event => { + event.target.disabled = event.detail.readonly; + }, + required: event => { + this._setRequired(event.target, event.detail.required); + }, + bgColor: event => { + setColor("bgColor", "backgroundColor", event); + }, + fillColor: event => { + setColor("fillColor", "backgroundColor", event); + }, + fgColor: event => { + setColor("fgColor", "color", event); + }, + textColor: event => { + setColor("textColor", "color", event); + }, + borderColor: event => { + setColor("borderColor", "borderColor", event); + }, + strokeColor: event => { + setColor("strokeColor", "borderColor", event); + }, + rotation: event => { + const angle = event.detail.rotation; + this.setRotation(angle); + this.annotationStorage.setValue(this.data.id, { + rotation: angle + }); + } + }); + } + _dispatchEventFromSandbox(actions, jsEvent) { + const commonActions = this._commonActions; + for (const name of Object.keys(jsEvent.detail)) { + const action = actions[name] || commonActions[name]; + action?.(jsEvent); + } + } + _setDefaultPropertiesFromJS(element) { + if (!this.enableScripting) { + return; + } + const storedData = this.annotationStorage.getRawValue(this.data.id); + if (!storedData) { + return; + } + const commonActions = this._commonActions; + for (const [actionName, detail] of Object.entries(storedData)) { + const action = commonActions[actionName]; + if (action) { + const eventProxy = { + detail: { + [actionName]: detail + }, + target: element + }; + action(eventProxy); + delete storedData[actionName]; + } + } + } + _createQuadrilaterals() { + if (!this.container) { + return; + } + const { + quadPoints + } = this.data; + if (!quadPoints) { + return; + } + const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map(x => Math.fround(x)); + if (quadPoints.length === 8) { + const [trX, trY, blX, blY] = quadPoints.subarray(2, 6); + if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) { + return; + } + } + const { + style + } = this.container; + let svgBuffer; + if (this.#hasBorder) { + const { + borderColor, + borderWidth + } = style; + style.borderWidth = 0; + svgBuffer = ["url('data:image/svg+xml;utf8,", ``, ``]; + this.container.classList.add("hasBorder"); + } + const width = rectTrX - rectBlX; + const height = rectTrY - rectBlY; + const { + svgFactory + } = this; + const svg = svgFactory.createElement("svg"); + svg.classList.add("quadrilateralsContainer"); + svg.setAttribute("width", 0); + svg.setAttribute("height", 0); + svg.role = "none"; + const defs = svgFactory.createElement("defs"); + svg.append(defs); + const clipPath = svgFactory.createElement("clipPath"); + const id = `clippath_${this.data.id}`; + clipPath.setAttribute("id", id); + clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); + defs.append(clipPath); + for (let i = 2, ii = quadPoints.length; i < ii; i += 8) { + const trX = quadPoints[i]; + const trY = quadPoints[i + 1]; + const blX = quadPoints[i + 2]; + const blY = quadPoints[i + 3]; + const rect = svgFactory.createElement("rect"); + const x = (blX - rectBlX) / width; + const y = (rectTrY - trY) / height; + const rectWidth = (trX - blX) / width; + const rectHeight = (trY - blY) / height; + rect.setAttribute("x", x); + rect.setAttribute("y", y); + rect.setAttribute("width", rectWidth); + rect.setAttribute("height", rectHeight); + clipPath.append(rect); + svgBuffer?.push(``); + } + if (this.#hasBorder) { + svgBuffer.push(`')`); + style.backgroundImage = svgBuffer.join(""); + } + this.container.append(svg); + this.container.style.clipPath = `url(#${id})`; + } + _createPopup(popupData = null) { + const { + data + } = this; + let contentsObj, modificationDate; + if (popupData) { + contentsObj = { + str: popupData.text + }; + modificationDate = popupData.date; + } else { + contentsObj = data.contentsObj; + modificationDate = data.modificationDate; + } + this.#popupElement = new PopupAnnotationElement({ + data: { + color: data.color, + titleObj: data.titleObj, + modificationDate, + contentsObj, + richText: data.richText, + parentRect: data.rect, + borderStyle: 0, + id: `popup_${data.id}`, + rotation: data.rotation, + noRotate: true + }, + linkService: this.linkService, + parent: this.parent, + elements: [this] + }); + } + get hasPopupElement() { + return !!(this.#popupElement || this.popup || this.data.popupRef); + } + get extraPopupElement() { + return this.#popupElement; + } + render() { + unreachable("Abstract method `AnnotationElement.render` called"); + } + _getElementsByName(name, skipId = null) { + const fields = []; + if (this._fieldObjects) { + const fieldObj = this._fieldObjects[name]; + if (fieldObj) { + for (const { + page, + id, + exportValues + } of fieldObj) { + if (page === -1) { + continue; + } + if (id === skipId) { + continue; + } + const exportValue = typeof exportValues === "string" ? exportValues : null; + const domElement = document.querySelector(`[data-element-id="${id}"]`); + if (domElement && !GetElementsByNameSet.has(domElement)) { + warn(`_getElementsByName - element not allowed: ${id}`); + continue; + } + fields.push({ + id, + exportValue, + domElement + }); + } + } + return fields; + } + for (const domElement of document.getElementsByName(name)) { + const { + exportValue + } = domElement; + const id = domElement.getAttribute("data-element-id"); + if (id === skipId) { + continue; + } + if (!GetElementsByNameSet.has(domElement)) { + continue; + } + fields.push({ + id, + exportValue, + domElement + }); + } + return fields; + } + show() { + if (this.container) { + this.container.hidden = false; + } + this.popup?.maybeShow(); + } + hide() { + if (this.container) { + this.container.hidden = true; + } + this.popup?.forceHide(); + } + getElementsToTriggerPopup() { + return this.container; + } + addHighlightArea() { + const triggers = this.getElementsToTriggerPopup(); + if (Array.isArray(triggers)) { + for (const element of triggers) { + element.classList.add("highlightArea"); + } + } else { + triggers.classList.add("highlightArea"); + } + } + _editOnDoubleClick() { + if (!this._isEditable) { + return; + } + const { + annotationEditorType: mode, + data: { + id: editId + } + } = this; + this.container.addEventListener("dblclick", () => { + this.linkService.eventBus?.dispatch("switchannotationeditormode", { + source: this, + mode, + editId, + mustEnterInEditMode: true + }); + }); + } + get width() { + return this.data.rect[2] - this.data.rect[0]; + } + get height() { + return this.data.rect[3] - this.data.rect[1]; + } +} +class EditorAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.editor = parameters.editor; + } + render() { + this.container.className = "editorAnnotation"; + return this.container; + } + createOrUpdatePopup() { + const { + editor + } = this; + if (!editor.hasComment) { + return; + } + this._createPopup(editor.comment); + } + get hasCommentButton() { + return this.enableComment && this.editor.hasComment; + } + get commentButtonPosition() { + return this.editor.commentButtonPositionInPage; + } + get commentText() { + return this.editor.comment.text; + } + set commentText(text) { + this.editor.comment = text; + if (!text) { + this.removePopup(); + } + } + get commentData() { + return this.editor.getData(); + } + remove() { + this.parent.removeAnnotation(this.data.id); + this.container.remove(); + this.container = null; + this.removePopup(); + } +} +class LinkAnnotationElement extends AnnotationElement { + constructor(parameters, options = null) { + super(parameters, { + isRenderable: true, + ignoreBorder: !!options?.ignoreBorder, + createQuadrilaterals: true + }); + this.isTooltipOnly = parameters.data.isTooltipOnly; + } + render() { + const { + data, + linkService + } = this; + const link = document.createElement("a"); + link.setAttribute("data-element-id", data.id); + let isBound = false; + if (data.url) { + linkService.addLinkAttributes(link, data.url, data.newWindow); + isBound = true; + } else if (data.action) { + this._bindNamedAction(link, data.action, data.overlaidText); + isBound = true; + } else if (data.attachment) { + this.#bindAttachment(link, data.attachment, data.overlaidText, data.attachmentDest); + isBound = true; + } else if (data.setOCGState) { + this.#bindSetOCGState(link, data.setOCGState, data.overlaidText); + isBound = true; + } else if (data.dest) { + this._bindLink(link, data.dest, data.overlaidText); + isBound = true; + } else { + if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) { + this._bindJSAction(link, data); + isBound = true; + } + if (data.resetForm) { + this._bindResetFormAction(link, data.resetForm); + isBound = true; + } else if (this.isTooltipOnly && !isBound) { + this._bindLink(link, ""); + isBound = true; + } + } + this.container.classList.add("linkAnnotation"); + if (isBound) { + this.contentElement = link; + this.container.append(link); + } + return this.container; + } + #setInternalLink() { + this.container.setAttribute("data-internal-link", ""); + } + _bindLink(link, destination, overlaidText = "") { + link.href = this.linkService.getDestinationHash(destination); + link.onclick = () => { + if (destination) { + this.linkService.goToDestination(destination); + } + return false; + }; + if (destination || destination === "") { + this.#setInternalLink(); + } + if (overlaidText) { + link.title = overlaidText; + } + } + _bindNamedAction(link, action, overlaidText = "") { + link.href = this.linkService.getAnchorUrl(""); + link.onclick = () => { + this.linkService.executeNamedAction(action); + return false; + }; + if (overlaidText) { + link.title = overlaidText; + } + this.#setInternalLink(); + } + #bindAttachment(link, attachment, overlaidText = "", dest = null) { + link.href = this.linkService.getAnchorUrl(""); + if (attachment.description) { + link.title = attachment.description; + } else if (overlaidText) { + link.title = overlaidText; + } + link.onclick = () => { + this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest); + return false; + }; + this.#setInternalLink(); + } + #bindSetOCGState(link, action, overlaidText = "") { + link.href = this.linkService.getAnchorUrl(""); + link.onclick = () => { + this.linkService.executeSetOCGState(action); + return false; + }; + if (overlaidText) { + link.title = overlaidText; + } + this.#setInternalLink(); + } + _bindJSAction(link, data) { + link.href = this.linkService.getAnchorUrl(""); + const map = new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]); + for (const name of Object.keys(data.actions)) { + const jsName = map.get(name); + if (!jsName) { + continue; + } + link[jsName] = () => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: data.id, + name + } + }); + return false; + }; + } + if (data.overlaidText) { + link.title = data.overlaidText; + } + if (!link.onclick) { + link.onclick = () => false; + } + this.#setInternalLink(); + } + _bindResetFormAction(link, resetForm) { + const otherClickAction = link.onclick; + if (!otherClickAction) { + link.href = this.linkService.getAnchorUrl(""); + } + this.#setInternalLink(); + if (!this._fieldObjects) { + warn(`_bindResetFormAction - "resetForm" action not supported, ` + "ensure that the `fieldObjects` parameter is provided."); + if (!otherClickAction) { + link.onclick = () => false; + } + return; + } + link.onclick = () => { + otherClickAction?.(); + const { + fields: resetFormFields, + refs: resetFormRefs, + include + } = resetForm; + const allFields = []; + if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) { + const fieldIds = new Set(resetFormRefs); + for (const fieldName of resetFormFields) { + const fields = this._fieldObjects[fieldName] || []; + for (const { + id + } of fields) { + fieldIds.add(id); + } + } + for (const fields of Object.values(this._fieldObjects)) { + for (const field of fields) { + if (fieldIds.has(field.id) === include) { + allFields.push(field); + } + } + } + } else { + for (const fields of Object.values(this._fieldObjects)) { + allFields.push(...fields); + } + } + const storage = this.annotationStorage; + const allIds = []; + for (const field of allFields) { + const { + id + } = field; + allIds.push(id); + switch (field.type) { + case "text": + { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + case "checkbox": + case "radiobutton": + { + const value = field.defaultValue === field.exportValues; + storage.setValue(id, { + value + }); + break; + } + case "combobox": + case "listbox": + { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + default: + continue; + } + const domElement = document.querySelector(`[data-element-id="${id}"]`); + if (!domElement) { + continue; + } else if (!GetElementsByNameSet.has(domElement)) { + warn(`_bindResetFormAction - element not allowed: ${id}`); + continue; + } + domElement.dispatchEvent(new Event("resetform")); + } + if (this.enableScripting) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: "app", + ids: allIds, + name: "ResetForm" + } + }); + } + return false; + }; + } +} +class TextAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true + }); + } + render() { + this.container.classList.add("textAnnotation"); + const image = document.createElement("img"); + image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg"; + image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type"); + image.setAttribute("data-l10n-args", JSON.stringify({ + type: this.data.name + })); + if (!this.data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.append(image); + return this.container; + } +} +class WidgetAnnotationElement extends AnnotationElement { + render() { + return this.container; + } + showElementAndHideCanvas(element) { + if (this.data.hasOwnCanvas) { + if (element.previousSibling?.nodeName === "CANVAS") { + element.previousSibling.hidden = true; + } + element.hidden = false; + } + } + _getKeyModifier(event) { + return util_FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey; + } + _setEventListener(element, elementData, baseName, eventName, valueGetter) { + if (baseName.includes("mouse")) { + element.addEventListener(baseName, event => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event), + shift: event.shiftKey, + modifier: this._getKeyModifier(event) + } + }); + }); + } else { + element.addEventListener(baseName, event => { + if (baseName === "blur") { + if (!elementData.focused || !event.relatedTarget) { + return; + } + elementData.focused = false; + } else if (baseName === "focus") { + if (elementData.focused) { + return; + } + elementData.focused = true; + } + if (!valueGetter) { + return; + } + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event) + } + }); + }); + } + } + _setEventListeners(element, elementData, names, getter) { + for (const [baseName, eventName] of names) { + if (eventName === "Action" || this.data.actions?.[eventName]) { + if (eventName === "Focus" || eventName === "Blur") { + elementData ||= { + focused: false + }; + } + this._setEventListener(element, elementData, baseName, eventName, getter); + if (eventName === "Focus" && !this.data.actions?.Blur) { + this._setEventListener(element, elementData, "blur", "Blur", null); + } else if (eventName === "Blur" && !this.data.actions?.Focus) { + this._setEventListener(element, elementData, "focus", "Focus", null); + } + } + } + } + _setBackgroundColor(element) { + const color = this.data.backgroundColor || null; + element.style.backgroundColor = color === null ? "transparent" : Util.makeHexColor(color[0], color[1], color[2]); + } + _setTextStyle(element) { + const TEXT_ALIGNMENT = ["left", "center", "right"]; + const { + fontColor + } = this.data.defaultAppearanceData; + const fontSize = this.data.defaultAppearanceData.fontSize || annotation_layer_DEFAULT_FONT_SIZE; + const style = element.style; + let computedFontSize; + const BORDER_SIZE = 2; + const roundToOneDecimal = x => Math.round(10 * x) / 10; + if (this.data.multiLine) { + const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); + const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1; + const lineHeight = height / numberOfLines; + computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / LINE_FACTOR)); + } else { + const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); + computedFontSize = Math.min(fontSize, roundToOneDecimal(height / LINE_FACTOR)); + } + style.fontSize = `calc(${computedFontSize}px * var(--total-scale-factor))`; + style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]); + if (this.data.textAlignment !== null) { + style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment]; + } + } + _setRequired(element, isRequired) { + if (isRequired) { + element.setAttribute("required", true); + } else { + element.removeAttribute("required"); + } + element.setAttribute("aria-required", isRequired); + } +} +class TextWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue; + super(parameters, { + isRenderable + }); + } + setPropertyOnSiblings(base, key, value, keyInStorage) { + const storage = this.annotationStorage; + for (const element of this._getElementsByName(base.name, base.id)) { + if (element.domElement) { + element.domElement[key] = value; + } + storage.setValue(element.id, { + [keyInStorage]: value + }); + } + } + render() { + const storage = this.annotationStorage; + const id = this.data.id; + this.container.classList.add("textWidgetAnnotation"); + let element = null; + if (this.renderForms) { + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + let textContent = storedData.value || ""; + const maxLen = storage.getValue(id, { + charLimit: this.data.maxLen + }).charLimit; + if (maxLen && textContent.length > maxLen) { + textContent = textContent.slice(0, maxLen); + } + let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join("\n") || null; + if (fieldFormattedValues && this.data.comb) { + fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, ""); + } + const elementData = { + userValue: textContent, + formattedValue: fieldFormattedValues, + lastCommittedValue: null, + commitKey: 1, + focused: false + }; + if (this.data.multiLine) { + element = document.createElement("textarea"); + element.textContent = fieldFormattedValues ?? textContent; + if (this.data.doNotScroll) { + element.style.overflowY = "hidden"; + } + } else { + element = document.createElement("input"); + element.type = this.data.password ? "password" : "text"; + element.setAttribute("value", fieldFormattedValues ?? textContent); + if (this.data.doNotScroll) { + element.style.overflowX = "hidden"; + } + } + if (this.data.hasOwnCanvas) { + element.hidden = true; + } + GetElementsByNameSet.add(element); + this.contentElement = element; + element.setAttribute("data-element-id", id); + element.disabled = this.data.readOnly; + element.name = this.data.fieldName; + element.tabIndex = 0; + const { + datetimeFormat, + datetimeType, + timeStep + } = this.data; + const hasDateOrTime = !!datetimeType && this.enableScripting; + if (datetimeFormat) { + element.title = datetimeFormat; + } + this._setRequired(element, this.data.required); + if (maxLen) { + element.maxLength = maxLen; + } + element.addEventListener("input", event => { + storage.setValue(id, { + value: event.target.value + }); + this.setPropertyOnSiblings(element, "value", event.target.value, "value"); + elementData.formattedValue = null; + }); + element.addEventListener("resetform", event => { + const defaultValue = this.data.defaultFieldValue ?? ""; + element.value = elementData.userValue = defaultValue; + elementData.formattedValue = null; + }); + let blurListener = event => { + const { + formattedValue + } = elementData; + if (formattedValue !== null && formattedValue !== undefined) { + event.target.value = formattedValue; + } + event.target.scrollLeft = 0; + }; + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("focus", event => { + if (elementData.focused) { + return; + } + const { + target + } = event; + if (hasDateOrTime) { + target.type = datetimeType; + if (timeStep) { + target.step = timeStep; + } + } + if (elementData.userValue) { + const value = elementData.userValue; + if (hasDateOrTime) { + if (datetimeType === "time") { + const date = new Date(value); + const parts = [date.getHours(), date.getMinutes(), date.getSeconds()]; + target.value = parts.map(v => v.toString().padStart(2, "0")).join(":"); + } else { + target.value = new Date(value - TIMEZONE_OFFSET).toISOString().split(datetimeType === "date" ? "T" : ".", 1)[0]; + } + } else { + target.value = value; + } + } + elementData.lastCommittedValue = target.value; + elementData.commitKey = 1; + if (!this.data.actions?.Focus) { + elementData.focused = true; + } + }); + element.addEventListener("updatefromsandbox", jsEvent => { + this.showElementAndHideCanvas(jsEvent.target); + const actions = { + value(event) { + elementData.userValue = event.detail.value ?? ""; + if (!hasDateOrTime) { + storage.setValue(id, { + value: elementData.userValue.toString() + }); + } + event.target.value = elementData.userValue; + }, + formattedValue(event) { + const { + formattedValue + } = event.detail; + elementData.formattedValue = formattedValue; + if (formattedValue !== null && formattedValue !== undefined && event.target !== document.activeElement) { + event.target.value = formattedValue; + } + const data = { + formattedValue + }; + if (hasDateOrTime) { + data.value = formattedValue; + } + storage.setValue(id, data); + }, + selRange(event) { + event.target.setSelectionRange(...event.detail.selRange); + }, + charLimit: event => { + const { + charLimit + } = event.detail; + const { + target + } = event; + if (charLimit === 0) { + target.removeAttribute("maxLength"); + return; + } + target.setAttribute("maxLength", charLimit); + let value = elementData.userValue; + if (!value || value.length <= charLimit) { + return; + } + value = value.slice(0, charLimit); + target.value = elementData.userValue = value; + storage.setValue(id, { + value + }); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: 1, + selStart: target.selectionStart, + selEnd: target.selectionEnd + } + }); + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + element.addEventListener("keydown", event => { + elementData.commitKey = 1; + let commitKey = -1; + if (event.key === "Escape") { + commitKey = 0; + } else if (event.key === "Enter" && !this.data.multiLine) { + commitKey = 2; + } else if (event.key === "Tab") { + elementData.commitKey = 3; + } + if (commitKey === -1) { + return; + } + const { + value + } = event.target; + if (elementData.lastCommittedValue === value) { + return; + } + elementData.lastCommittedValue = value; + elementData.userValue = value; + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + }); + const _blurListener = blurListener; + blurListener = null; + element.addEventListener("blur", event => { + if (!elementData.focused || !event.relatedTarget) { + return; + } + if (!this.data.actions?.Blur) { + elementData.focused = false; + } + const { + target + } = event; + let { + value + } = target; + if (hasDateOrTime) { + if (value && datetimeType === "time") { + const parts = value.split(":").map(v => parseInt(v, 10)); + value = new Date(2000, 0, 1, parts[0], parts[1], parts[2] || 0).valueOf(); + target.step = ""; + } else { + if (!value.includes("T")) { + value = `${value}T00:00`; + } + value = new Date(value).valueOf(); + } + target.type = "text"; + } + elementData.userValue = value; + if (elementData.lastCommittedValue !== value) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: elementData.commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + } + _blurListener(event); + }); + if (this.data.actions?.Keystroke) { + element.addEventListener("beforeinput", event => { + elementData.lastCommittedValue = null; + const { + data, + target + } = event; + const { + value, + selectionStart, + selectionEnd + } = target; + let selStart = selectionStart, + selEnd = selectionEnd; + switch (event.inputType) { + case "deleteWordBackward": + { + const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/); + if (match) { + selStart -= match[0].length; + } + break; + } + case "deleteWordForward": + { + const match = value.substring(selectionStart).match(/^[^\w]*\w*/); + if (match) { + selEnd += match[0].length; + } + break; + } + case "deleteContentBackward": + if (selectionStart === selectionEnd) { + selStart -= 1; + } + break; + case "deleteContentForward": + if (selectionStart === selectionEnd) { + selEnd += 1; + } + break; + } + event.preventDefault(); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + change: data || "", + willCommit: false, + selStart, + selEnd + } + }); + }); + } + this._setEventListeners(element, elementData, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.value); + } + if (blurListener) { + element.addEventListener("blur", blurListener); + } + if (this.data.comb) { + const fieldWidth = this.data.rect[2] - this.data.rect[0]; + const combWidth = fieldWidth / maxLen; + element.classList.add("comb"); + element.style.letterSpacing = `calc(${combWidth}px * var(--total-scale-factor) - 1ch)`; + } + } else { + element = document.createElement("div"); + element.textContent = this.data.fieldValue; + element.style.verticalAlign = "middle"; + element.style.display = "table-cell"; + if (this.data.hasOwnCanvas) { + element.hidden = true; + } + } + this._setTextStyle(element); + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class SignatureWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: !!parameters.data.hasOwnCanvas + }); + } +} +class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.exportValue === data.fieldValue + }).value; + if (typeof value === "string") { + value = value !== "Off"; + storage.setValue(id, { + value + }); + } + this.container.classList.add("buttonWidgetAnnotation", "checkBox"); + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + this._setRequired(element, this.data.required); + element.type = "checkbox"; + element.name = data.fieldName; + if (value) { + element.setAttribute("checked", true); + } + element.setAttribute("exportValue", data.exportValue); + element.tabIndex = 0; + element.addEventListener("change", event => { + const { + name, + checked + } = event.target; + for (const checkbox of this._getElementsByName(name, id)) { + const curChecked = checked && checkbox.exportValue === data.exportValue; + if (checkbox.domElement) { + checkbox.domElement.checked = curChecked; + } + storage.setValue(checkbox.id, { + value: curChecked + }); + } + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", event => { + const defaultValue = data.defaultFieldValue || "Off"; + event.target.checked = defaultValue === data.exportValue; + }); + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value(event) { + event.target.checked = event.detail.value !== "Off"; + storage.setValue(id, { + value: event.target.checked + }); + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); + } + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + this.container.classList.add("buttonWidgetAnnotation", "radioButton"); + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.fieldValue === data.buttonValue + }).value; + if (typeof value === "string") { + value = value !== data.buttonValue; + storage.setValue(id, { + value + }); + } + if (value) { + for (const radio of this._getElementsByName(data.fieldName, id)) { + storage.setValue(radio.id, { + value: false + }); + } + } + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + this._setRequired(element, this.data.required); + element.type = "radio"; + element.name = data.fieldName; + if (value) { + element.setAttribute("checked", true); + } + element.tabIndex = 0; + element.addEventListener("change", event => { + const { + name, + checked + } = event.target; + for (const radio of this._getElementsByName(name, id)) { + storage.setValue(radio.id, { + value: false + }); + } + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", event => { + const defaultValue = data.defaultFieldValue; + event.target.checked = defaultValue !== null && defaultValue !== undefined && defaultValue === data.buttonValue; + }); + if (this.enableScripting && this.hasJSActions) { + const pdfButtonValue = data.buttonValue; + element.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value: event => { + const checked = pdfButtonValue === event.detail.value; + for (const radio of this._getElementsByName(event.target.name)) { + const curChecked = checked && radio.id === id; + if (radio.domElement) { + radio.domElement.checked = curChecked; + } + storage.setValue(radio.id, { + value: curChecked + }); + } + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], event => event.target.checked); + } + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class PushButtonWidgetAnnotationElement extends LinkAnnotationElement { + constructor(parameters) { + super(parameters, { + ignoreBorder: parameters.data.hasAppearance + }); + } + render() { + const container = super.render(); + container.classList.add("buttonWidgetAnnotation", "pushButton"); + const linkElement = container.lastChild; + if (this.enableScripting && this.hasJSActions && linkElement) { + this._setDefaultPropertiesFromJS(linkElement); + linkElement.addEventListener("updatefromsandbox", jsEvent => { + this._dispatchEventFromSandbox({}, jsEvent); + }); + } + return container; + } +} +class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + this.container.classList.add("choiceWidgetAnnotation"); + const storage = this.annotationStorage; + const id = this.data.id; + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + const selectElement = document.createElement("select"); + GetElementsByNameSet.add(selectElement); + selectElement.setAttribute("data-element-id", id); + selectElement.disabled = this.data.readOnly; + this._setRequired(selectElement, this.data.required); + selectElement.name = this.data.fieldName; + selectElement.tabIndex = 0; + let addAnEmptyEntry = this.data.combo && this.data.options.length > 0; + if (!this.data.combo) { + selectElement.size = this.data.options.length; + if (this.data.multiSelect) { + selectElement.multiple = true; + } + } + selectElement.addEventListener("resetform", event => { + const defaultValue = this.data.defaultFieldValue; + for (const option of selectElement.options) { + option.selected = option.value === defaultValue; + } + }); + for (const option of this.data.options) { + const optionElement = document.createElement("option"); + optionElement.textContent = option.displayValue; + optionElement.value = option.exportValue; + if (storedData.value.includes(option.exportValue)) { + optionElement.setAttribute("selected", true); + addAnEmptyEntry = false; + } + selectElement.append(optionElement); + } + let removeEmptyEntry = null; + if (addAnEmptyEntry) { + const noneOptionElement = document.createElement("option"); + noneOptionElement.value = " "; + noneOptionElement.setAttribute("hidden", true); + noneOptionElement.setAttribute("selected", true); + selectElement.prepend(noneOptionElement); + removeEmptyEntry = () => { + noneOptionElement.remove(); + selectElement.removeEventListener("input", removeEmptyEntry); + removeEmptyEntry = null; + }; + selectElement.addEventListener("input", removeEmptyEntry); + } + const getValue = isExport => { + const name = isExport ? "value" : "textContent"; + const { + options, + multiple + } = selectElement; + if (!multiple) { + return options.selectedIndex === -1 ? null : options[options.selectedIndex][name]; + } + return Array.prototype.filter.call(options, option => option.selected).map(option => option[name]); + }; + let selectedValues = getValue(false); + const getItems = event => { + const options = event.target.options; + return Array.prototype.map.call(options, option => ({ + displayValue: option.textContent, + exportValue: option.value + })); + }; + if (this.enableScripting && this.hasJSActions) { + selectElement.addEventListener("updatefromsandbox", jsEvent => { + const actions = { + value(event) { + removeEmptyEntry?.(); + const value = event.detail.value; + const values = new Set(Array.isArray(value) ? value : [value]); + for (const option of selectElement.options) { + option.selected = values.has(option.value); + } + storage.setValue(id, { + value: getValue(true) + }); + selectedValues = getValue(false); + }, + multipleSelection(event) { + selectElement.multiple = true; + }, + remove(event) { + const options = selectElement.options; + const index = event.detail.remove; + options[index].selected = false; + selectElement.remove(index); + if (options.length > 0) { + const i = Array.prototype.findIndex.call(options, option => option.selected); + if (i === -1) { + options[0].selected = true; + } + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + clear(event) { + while (selectElement.length !== 0) { + selectElement.remove(0); + } + storage.setValue(id, { + value: null, + items: [] + }); + selectedValues = getValue(false); + }, + insert(event) { + const { + index, + displayValue, + exportValue + } = event.detail.insert; + const selectChild = selectElement.children[index]; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + if (selectChild) { + selectChild.before(optionElement); + } else { + selectElement.append(optionElement); + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + items(event) { + const { + items + } = event.detail; + while (selectElement.length !== 0) { + selectElement.remove(0); + } + for (const item of items) { + const { + displayValue, + exportValue + } = item; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + selectElement.append(optionElement); + } + if (selectElement.options.length > 0) { + selectElement.options[0].selected = true; + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + indices(event) { + const indices = new Set(event.detail.indices); + for (const option of event.target.options) { + option.selected = indices.has(option.index); + } + storage.setValue(id, { + value: getValue(true) + }); + selectedValues = getValue(false); + }, + editable(event) { + event.target.disabled = !event.detail.editable; + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + selectElement.addEventListener("input", event => { + const exportValue = getValue(true); + const change = getValue(false); + storage.setValue(id, { + value: exportValue + }); + event.preventDefault(); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value: selectedValues, + change, + changeEx: exportValue, + willCommit: false, + commitKey: 1, + keyDown: false + } + }); + }); + this._setEventListeners(selectElement, null, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"], ["input", "Validate"]], event => event.target.value); + } else { + selectElement.addEventListener("input", function (event) { + storage.setValue(id, { + value: getValue(true) + }); + }); + } + if (this.data.combo) { + this._setTextStyle(selectElement); + } else {} + this._setBackgroundColor(selectElement); + this._setDefaultPropertiesFromJS(selectElement); + this.container.append(selectElement); + return this.container; + } +} +class PopupAnnotationElement extends AnnotationElement { + constructor(parameters) { + const { + data, + elements, + parent + } = parameters; + const hasCommentManager = !!parent._commentManager; + super(parameters, { + isRenderable: !hasCommentManager && AnnotationElement._hasPopupData(data) + }); + this.elements = elements; + if (hasCommentManager && AnnotationElement._hasPopupData(data)) { + const popup = this.popup = this.#createPopup(); + for (const element of elements) { + element.popup = popup; + } + } else { + this.popup = null; + } + } + #createPopup() { + return new PopupElement({ + container: this.container, + color: this.data.color, + titleObj: this.data.titleObj, + modificationDate: this.data.modificationDate || this.data.creationDate, + contentsObj: this.data.contentsObj, + richText: this.data.richText, + rect: this.data.rect, + parentRect: this.data.parentRect || null, + parent: this.parent, + elements: this.elements, + open: this.data.open, + commentManager: this.parent._commentManager + }); + } + render() { + const { + container + } = this; + container.classList.add("popupAnnotation"); + container.role = "comment"; + const popup = this.popup = this.#createPopup(); + const elementIds = []; + for (const element of this.elements) { + element.popup = popup; + element.container.ariaHasPopup = "dialog"; + elementIds.push(element.data.id); + element.addHighlightArea(); + } + this.container.setAttribute("aria-controls", elementIds.map(id => `${AnnotationPrefix}${id}`).join(",")); + return this.container; + } +} +class PopupElement { + #commentManager = null; + #boundKeyDown = this.#keyDown.bind(this); + #boundHide = this.#hide.bind(this); + #boundShow = this.#show.bind(this); + #boundToggle = this.#toggle.bind(this); + #color = null; + #container = null; + #contentsObj = null; + #dateObj = null; + #elements = null; + #parent = null; + #parentRect = null; + #pinned = false; + #popup = null; + #popupAbortController = null; + #position = null; + #commentButton = null; + #commentButtonPosition = null; + #popupPosition = null; + #rect = null; + #richText = null; + #titleObj = null; + #updates = null; + #wasVisible = false; + #firstElement = null; + #commentText = null; + constructor({ + container, + color, + elements, + titleObj, + modificationDate, + contentsObj, + richText, + parent, + rect, + parentRect, + open, + commentManager = null + }) { + this.#container = container; + this.#titleObj = titleObj; + this.#contentsObj = contentsObj; + this.#richText = richText; + this.#parent = parent; + this.#color = color; + this.#rect = rect; + this.#parentRect = parentRect; + this.#elements = elements; + this.#commentManager = commentManager; + this.#firstElement = elements[0]; + this.#dateObj = PDFDateString.toDateObject(modificationDate); + this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup()); + if (!commentManager) { + this.#addEventListeners(); + this.#container.hidden = true; + if (open) { + this.#toggle(); + } + } + } + #addEventListeners() { + if (this.#popupAbortController) { + return; + } + this.#popupAbortController = new AbortController(); + const { + signal + } = this.#popupAbortController; + for (const element of this.trigger) { + element.addEventListener("click", this.#boundToggle, { + signal + }); + element.addEventListener("pointerenter", this.#boundShow, { + signal + }); + element.addEventListener("pointerleave", this.#boundHide, { + signal + }); + element.classList.add("popupTriggerArea"); + } + for (const element of this.#elements) { + element.container?.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + } + } + #setCommentButtonPosition() { + const element = this.#elements.find(e => e.hasCommentButton); + if (!element) { + return; + } + this.#commentButtonPosition = element._normalizePoint(element.commentButtonPosition); + } + renderCommentButton() { + if (this.#commentButton) { + if (!this.#commentButton.parentNode) { + this.#firstElement.container.after(this.#commentButton); + } + return; + } + if (!this.#commentButtonPosition) { + this.#setCommentButtonPosition(); + } + if (!this.#commentButtonPosition) { + return; + } + const { + signal + } = this.#popupAbortController = new AbortController(); + const hasOwnButton = this.#firstElement.hasOwnCommentButton; + const togglePopup = () => { + this.#commentManager.toggleCommentPopup(this, true, undefined, !hasOwnButton); + }; + const showPopup = () => { + this.#commentManager.toggleCommentPopup(this, false, true, !hasOwnButton); + }; + const hidePopup = () => { + this.#commentManager.toggleCommentPopup(this, false, false); + }; + if (!hasOwnButton) { + const button = this.#commentButton = document.createElement("button"); + button.className = "annotationCommentButton"; + const parentContainer = this.#firstElement.container; + button.style.zIndex = parentContainer.style.zIndex + 1; + button.tabIndex = 0; + button.ariaHasPopup = "dialog"; + button.ariaControls = "commentPopup"; + button.setAttribute("data-l10n-id", "pdfjs-show-comment-button"); + this.#updateColor(); + this.#updateCommentButtonPosition(); + button.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + button.addEventListener("click", togglePopup, { + signal + }); + button.addEventListener("pointerenter", showPopup, { + signal + }); + button.addEventListener("pointerleave", hidePopup, { + signal + }); + parentContainer.after(button); + } else { + this.#commentButton = this.#firstElement.container; + for (const element of this.trigger) { + element.ariaHasPopup = "dialog"; + element.ariaControls = "commentPopup"; + element.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + element.addEventListener("click", togglePopup, { + signal + }); + element.addEventListener("pointerenter", showPopup, { + signal + }); + element.addEventListener("pointerleave", hidePopup, { + signal + }); + element.classList.add("popupTriggerArea"); + } + } + } + #updateCommentButtonPosition() { + if (this.#firstElement.extraPopupElement && !this.#firstElement.editor) { + return; + } + if (!this.#commentButton) { + this.renderCommentButton(); + } + const [x, y] = this.#commentButtonPosition; + const { + style + } = this.#commentButton; + style.left = `calc(${x}%)`; + style.top = `calc(${y}% - var(--comment-button-dim))`; + } + #updateColor() { + if (this.#firstElement.extraPopupElement) { + return; + } + if (!this.#commentButton) { + this.renderCommentButton(); + } + this.#commentButton.style.backgroundColor = this.commentButtonColor || ""; + } + get commentButtonColor() { + const { + color, + opacity + } = this.#firstElement.commentData; + if (!color) { + return null; + } + return this.#parent._commentManager.makeCommentColor(color, opacity); + } + focusCommentButton() { + setTimeout(() => { + this.#commentButton?.focus(); + }, 0); + } + getData() { + const { + richText, + color, + opacity, + creationDate, + modificationDate + } = this.#firstElement.commentData; + return { + contentsObj: { + str: this.comment + }, + richText, + color, + opacity, + creationDate, + modificationDate + }; + } + get elementBeforePopup() { + return this.#commentButton; + } + get comment() { + this.#commentText ||= this.#firstElement.commentText; + return this.#commentText; + } + set comment(text) { + if (text === this.comment) { + return; + } + this.#firstElement.commentText = this.#commentText = text; + } + focus() { + this.#firstElement.container?.focus(); + } + get parentBoundingClientRect() { + return this.#firstElement.layer.getBoundingClientRect(); + } + setCommentButtonStates({ + selected, + hasPopup + }) { + if (!this.#commentButton) { + return; + } + this.#commentButton.classList.toggle("selected", selected); + this.#commentButton.ariaExpanded = hasPopup; + } + setSelectedCommentButton(selected) { + this.#commentButton.classList.toggle("selected", selected); + } + get commentPopupPosition() { + if (this.#popupPosition) { + return this.#popupPosition; + } + const { + x, + y, + height + } = this.#commentButton.getBoundingClientRect(); + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = this.#firstElement.layer.getBoundingClientRect(); + return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight]; + } + set commentPopupPosition(pos) { + this.#popupPosition = pos; + } + hasDefaultPopupPosition() { + return this.#popupPosition === null; + } + get commentButtonPosition() { + return this.#commentButtonPosition; + } + get commentButtonWidth() { + return this.#commentButton.getBoundingClientRect().width / this.parentBoundingClientRect.width; + } + editComment(options) { + const [posX, posY] = this.#popupPosition || this.commentButtonPosition.map(x => x / 100); + const parentDimensions = this.parentBoundingClientRect; + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = parentDimensions; + this.#commentManager.showDialog(null, this, parentX + posX * parentWidth, parentY + posY * parentHeight, { + ...options, + parentDimensions + }); + } + render() { + if (this.#popup) { + return; + } + const popup = this.#popup = document.createElement("div"); + popup.className = "popup"; + if (this.#color) { + const baseColor = popup.style.outlineColor = Util.makeHexColor(...this.#color); + popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`; + } + const header = document.createElement("span"); + header.className = "header"; + if (this.#titleObj?.str) { + const title = document.createElement("span"); + title.className = "title"; + header.append(title); + ({ + dir: title.dir, + str: title.textContent + } = this.#titleObj); + } + popup.append(header); + if (this.#dateObj) { + const modificationDate = document.createElement("time"); + modificationDate.className = "popupDate"; + modificationDate.setAttribute("data-l10n-id", "pdfjs-annotation-date-time-string"); + modificationDate.setAttribute("data-l10n-args", JSON.stringify({ + dateObj: this.#dateObj.valueOf() + })); + modificationDate.dateTime = this.#dateObj.toISOString(); + header.append(modificationDate); + } + renderRichText({ + html: this.#html || this.#contentsObj.str, + dir: this.#contentsObj?.dir, + className: "popupContent" + }, popup); + this.#container.append(popup); + } + get #html() { + const richText = this.#richText; + const contentsObj = this.#contentsObj; + if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) { + return this.#richText.html || null; + } + return null; + } + get #fontSize() { + return this.#html?.attributes?.style?.fontSize || 0; + } + get #fontColor() { + return this.#html?.attributes?.style?.color || null; + } + #makePopupContent(text) { + const popupLines = []; + const popupContent = { + str: text, + html: { + name: "div", + attributes: { + dir: "auto" + }, + children: [{ + name: "p", + children: popupLines + }] + } + }; + const lineAttributes = { + style: { + color: this.#fontColor, + fontSize: this.#fontSize ? `calc(${this.#fontSize}px * var(--total-scale-factor))` : "" + } + }; + for (const line of text.split("\n")) { + popupLines.push({ + name: "span", + value: line, + attributes: lineAttributes + }); + } + return popupContent; + } + #keyDown(event) { + if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) { + return; + } + if (event.key === "Enter" || event.key === "Escape" && this.#pinned) { + this.#toggle(); + } + } + updateEdited({ + rect, + popup, + deleted + }) { + if (this.#commentManager) { + if (deleted) { + this.remove(); + this.#commentText = null; + } else if (popup) { + if (popup.deleted) { + this.remove(); + } else { + this.#updateColor(); + this.#commentText = popup.text; + } + } + if (rect) { + this.#commentButtonPosition = null; + this.#setCommentButtonPosition(); + this.#updateCommentButtonPosition(); + } + return; + } + if (deleted || popup?.deleted) { + this.remove(); + return; + } + this.#addEventListeners(); + this.#updates ||= { + contentsObj: this.#contentsObj, + richText: this.#richText + }; + if (rect) { + this.#position = null; + } + if (popup && popup.text) { + this.#richText = this.#makePopupContent(popup.text); + this.#dateObj = PDFDateString.toDateObject(popup.date); + this.#contentsObj = null; + } + this.#popup?.remove(); + this.#popup = null; + } + resetEdited() { + if (!this.#updates) { + return; + } + ({ + contentsObj: this.#contentsObj, + richText: this.#richText + } = this.#updates); + this.#updates = null; + this.#popup?.remove(); + this.#popup = null; + this.#position = null; + } + remove() { + this.#popupAbortController?.abort(); + this.#popupAbortController = null; + this.#popup?.remove(); + this.#popup = null; + this.#wasVisible = false; + this.#pinned = false; + this.#commentButton?.remove(); + this.#commentButton = null; + if (this.trigger) { + for (const element of this.trigger) { + element.classList.remove("popupTriggerArea"); + } + } + } + #setPosition() { + if (this.#position !== null) { + return; + } + const { + page: { + view + }, + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } = this.#parent; + let useParentRect = !!this.#parentRect; + let rect = useParentRect ? this.#parentRect : this.#rect; + for (const element of this.#elements) { + if (!rect || Util.intersect(element.data.rect, rect) !== null) { + rect = element.data.rect; + useParentRect = true; + break; + } + } + const normalizedRect = Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]); + const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5; + const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0; + const popupLeft = normalizedRect[0] + parentWidth; + const popupTop = normalizedRect[1]; + this.#position = [100 * (popupLeft - pageX) / pageWidth, 100 * (popupTop - pageY) / pageHeight]; + const { + style + } = this.#container; + style.left = `${this.#position[0]}%`; + style.top = `${this.#position[1]}%`; + } + #toggle() { + if (this.#commentManager) { + this.#commentManager.toggleCommentPopup(this, false); + return; + } + this.#pinned = !this.#pinned; + if (this.#pinned) { + this.#show(); + this.#container.addEventListener("click", this.#boundToggle); + this.#container.addEventListener("keydown", this.#boundKeyDown); + } else { + this.#hide(); + this.#container.removeEventListener("click", this.#boundToggle); + this.#container.removeEventListener("keydown", this.#boundKeyDown); + } + } + #show() { + if (!this.#popup) { + this.render(); + } + if (!this.isVisible) { + this.#setPosition(); + this.#container.hidden = false; + this.#container.style.zIndex = parseInt(this.#container.style.zIndex) + 1000; + } else if (this.#pinned) { + this.#container.classList.add("focused"); + } + } + #hide() { + this.#container.classList.remove("focused"); + if (this.#pinned || !this.isVisible) { + return; + } + this.#container.hidden = true; + this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1000; + } + forceHide() { + this.#wasVisible = this.isVisible; + if (!this.#wasVisible) { + return; + } + this.#container.hidden = true; + } + maybeShow() { + if (this.#commentManager) { + return; + } + this.#addEventListeners(); + if (!this.#wasVisible) { + return; + } + if (!this.#popup) { + this.#show(); + } + this.#wasVisible = false; + this.#container.hidden = false; + } + get isVisible() { + if (this.#commentManager) { + return false; + } + return this.#container.hidden === false; + } +} +class FreeTextAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.textContent = parameters.data.textContent; + this.textPosition = parameters.data.textPosition; + this.annotationEditorType = AnnotationEditorType.FREETEXT; + } + render() { + this.container.classList.add("freeTextAnnotation"); + if (this.textContent) { + const content = this.contentElement = document.createElement("div"); + content.classList.add("annotationTextContent"); + content.setAttribute("role", "comment"); + for (const line of this.textContent) { + const lineSpan = document.createElement("span"); + lineSpan.textContent = line; + content.append(lineSpan); + } + this.container.append(content); + } + if (!this.data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this._editOnDoubleClick(); + return this.container; + } +} +class LineAnnotationElement extends AnnotationElement { + #line = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("lineAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const line = this.#line = this.svgFactory.createElement("svg:line"); + line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]); + line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]); + line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]); + line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]); + line.setAttribute("stroke-width", data.borderStyle.width || 1); + line.setAttribute("stroke", "transparent"); + line.setAttribute("fill", "transparent"); + svg.append(line); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#line; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class SquareAnnotationElement extends AnnotationElement { + #square = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("squareAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const square = this.#square = this.svgFactory.createElement("svg:rect"); + square.setAttribute("x", borderWidth / 2); + square.setAttribute("y", borderWidth / 2); + square.setAttribute("width", width - borderWidth); + square.setAttribute("height", height - borderWidth); + square.setAttribute("stroke-width", borderWidth || 1); + square.setAttribute("stroke", "transparent"); + square.setAttribute("fill", "transparent"); + svg.append(square); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#square; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class CircleAnnotationElement extends AnnotationElement { + #circle = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("circleAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const circle = this.#circle = this.svgFactory.createElement("svg:ellipse"); + circle.setAttribute("cx", width / 2); + circle.setAttribute("cy", height / 2); + circle.setAttribute("rx", width / 2 - borderWidth / 2); + circle.setAttribute("ry", height / 2 - borderWidth / 2); + circle.setAttribute("stroke-width", borderWidth || 1); + circle.setAttribute("stroke", "transparent"); + circle.setAttribute("fill", "transparent"); + svg.append(circle); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#circle; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class PolylineAnnotationElement extends AnnotationElement { + #polyline = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.containerClassName = "polylineAnnotation"; + this.svgElementName = "svg:polyline"; + } + render() { + this.container.classList.add(this.containerClassName); + const { + data: { + rect, + vertices, + borderStyle, + popupRef + }, + width, + height + } = this; + if (!vertices) { + return this.container; + } + const svg = this.svgFactory.create(width, height, true); + let points = []; + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + const x = vertices[i] - rect[0]; + const y = rect[3] - vertices[i + 1]; + points.push(`${x},${y}`); + } + points = points.join(" "); + const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName); + polyline.setAttribute("points", points); + polyline.setAttribute("stroke-width", borderStyle.width || 1); + polyline.setAttribute("stroke", "transparent"); + polyline.setAttribute("fill", "transparent"); + svg.append(polyline); + this.container.append(svg); + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#polyline; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class PolygonAnnotationElement extends PolylineAnnotationElement { + constructor(parameters) { + super(parameters); + this.containerClassName = "polygonAnnotation"; + this.svgElementName = "svg:polygon"; + } +} +class CaretAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("caretAnnotation"); + if (!this.data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + return this.container; + } +} +class InkAnnotationElement extends AnnotationElement { + #polylinesGroupElement = null; + #polylines = []; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.containerClassName = "inkAnnotation"; + this.svgElementName = "svg:polyline"; + this.annotationEditorType = this.data.it === "InkHighlight" ? AnnotationEditorType.HIGHLIGHT : AnnotationEditorType.INK; + } + #getTransform(rotation, rect) { + switch (rotation) { + case 90: + return { + transform: `rotate(90) translate(${-rect[0]},${rect[1]}) scale(1,-1)`, + width: rect[3] - rect[1], + height: rect[2] - rect[0] + }; + case 180: + return { + transform: `rotate(180) translate(${-rect[2]},${rect[1]}) scale(1,-1)`, + width: rect[2] - rect[0], + height: rect[3] - rect[1] + }; + case 270: + return { + transform: `rotate(270) translate(${-rect[2]},${rect[3]}) scale(1,-1)`, + width: rect[3] - rect[1], + height: rect[2] - rect[0] + }; + default: + return { + transform: `translate(${-rect[0]},${rect[3]}) scale(1,-1)`, + width: rect[2] - rect[0], + height: rect[3] - rect[1] + }; + } + } + render() { + this.container.classList.add(this.containerClassName); + const { + data: { + rect, + rotation, + inkLists, + borderStyle, + popupRef + } + } = this; + const { + transform, + width, + height + } = this.#getTransform(rotation, rect); + const svg = this.svgFactory.create(width, height, true); + const g = this.#polylinesGroupElement = this.svgFactory.createElement("svg:g"); + svg.append(g); + g.setAttribute("stroke-width", borderStyle.width || 1); + g.setAttribute("stroke-linecap", "round"); + g.setAttribute("stroke-linejoin", "round"); + g.setAttribute("stroke-miterlimit", 10); + g.setAttribute("stroke", "transparent"); + g.setAttribute("fill", "transparent"); + g.setAttribute("transform", transform); + for (let i = 0, ii = inkLists.length; i < ii; i++) { + const polyline = this.svgFactory.createElement(this.svgElementName); + this.#polylines.push(polyline); + polyline.setAttribute("points", inkLists[i].join(",")); + g.append(polyline); + } + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.append(svg); + this._editOnDoubleClick(); + return this.container; + } + updateEdited(params) { + super.updateEdited(params); + const { + thickness, + points, + rect + } = params; + const g = this.#polylinesGroupElement; + if (thickness >= 0) { + g.setAttribute("stroke-width", thickness || 1); + } + if (points) { + for (let i = 0, ii = this.#polylines.length; i < ii; i++) { + this.#polylines[i].setAttribute("points", points[i].join(",")); + } + } + if (rect) { + const { + transform, + width, + height + } = this.#getTransform(this.data.rotation, rect); + const root = g.parentElement; + root.setAttribute("viewBox", `0 0 ${width} ${height}`); + g.setAttribute("transform", transform); + } + } + getElementsToTriggerPopup() { + return this.#polylines; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class HighlightAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + this.annotationEditorType = AnnotationEditorType.HIGHLIGHT; + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.classList.add("highlightAnnotation"); + this._editOnDoubleClick(); + if (overlaidText) { + const mark = document.createElement("mark"); + mark.classList.add("overlaidText"); + mark.textContent = overlaidText; + this.container.append(mark); + } + return this.container; + } +} +class UnderlineAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.classList.add("underlineAnnotation"); + if (overlaidText) { + const underline = document.createElement("u"); + underline.classList.add("overlaidText"); + underline.textContent = overlaidText; + this.container.append(underline); + } + return this.container; + } +} +class SquigglyAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.classList.add("squigglyAnnotation"); + if (overlaidText) { + const underline = document.createElement("u"); + underline.classList.add("overlaidText"); + underline.textContent = overlaidText; + this.container.append(underline); + } + return this.container; + } +} +class StrikeOutAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this.container.classList.add("strikeoutAnnotation"); + if (overlaidText) { + const strikeout = document.createElement("s"); + strikeout.classList.add("overlaidText"); + strikeout.textContent = overlaidText; + this.container.append(strikeout); + } + return this.container; + } +} +class StampAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.annotationEditorType = AnnotationEditorType.STAMP; + } + render() { + this.container.classList.add("stampAnnotation"); + this.container.setAttribute("role", "img"); + if (!this.data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } + this._editOnDoubleClick(); + return this.container; + } +} +class FileAttachmentAnnotationElement extends AnnotationElement { + #trigger = null; + constructor(parameters) { + super(parameters, { + isRenderable: true + }); + const { + file + } = this.data; + this.filename = file.filename; + this.content = file.content; + this.linkService.eventBus?.dispatch("fileattachmentannotation", { + source: this, + ...file + }); + } + render() { + this.container.classList.add("fileAttachmentAnnotation"); + const { + container, + data + } = this; + let trigger; + if (data.hasAppearance || data.fillAlpha === 0) { + trigger = document.createElement("div"); + } else { + trigger = document.createElement("img"); + trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? "paperclip" : "pushpin"}.svg`; + if (data.fillAlpha && data.fillAlpha < 1) { + trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`; + } + } + trigger.addEventListener("dblclick", this.#download.bind(this)); + this.#trigger = trigger; + const { + isMac + } = util_FeatureTest.platform; + container.addEventListener("keydown", evt => { + if (evt.key === "Enter" && (isMac ? evt.metaKey : evt.ctrlKey)) { + this.#download(); + } + }); + if (!data.popupRef && this.hasPopupData) { + this.hasOwnCommentButton = true; + this._createPopup(); + } else { + trigger.classList.add("popupTriggerArea"); + } + container.append(trigger); + return container; + } + getElementsToTriggerPopup() { + return this.#trigger; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } + #download() { + this.downloadManager?.openOrDownloadData(this.content, this.filename); + } +} +class AnnotationLayer { + #accessibilityManager = null; + #annotationCanvasMap = null; + #annotationStorage = null; + #editableAnnotations = new Map(); + #structTreeLayer = null; + #linkService = null; + #elements = []; + #hasAriaAttributesFromStructTree = false; + constructor({ + div, + accessibilityManager, + annotationCanvasMap, + annotationEditorUIManager, + page, + viewport, + structTreeLayer, + commentManager, + linkService, + annotationStorage + }) { + this.div = div; + this.#accessibilityManager = accessibilityManager; + this.#annotationCanvasMap = annotationCanvasMap; + this.#structTreeLayer = structTreeLayer || null; + this.#linkService = linkService || null; + this.#annotationStorage = annotationStorage || new AnnotationStorage(); + this.page = page; + this.viewport = viewport; + this.zIndex = 0; + this._annotationEditorUIManager = annotationEditorUIManager; + this._commentManager = commentManager || null; + } + hasEditableAnnotations() { + return this.#editableAnnotations.size > 0; + } + async render(params) { + const { + annotations + } = params; + const layer = this.div; + setLayerDimensions(layer, this.viewport); + const popupToElements = new Map(); + const popupAnnotations = []; + const elementParams = { + data: null, + layer, + linkService: this.#linkService, + downloadManager: params.downloadManager, + imageResourcesPath: params.imageResourcesPath || "", + renderForms: params.renderForms !== false, + svgFactory: new DOMSVGFactory(), + annotationStorage: this.#annotationStorage, + enableComment: params.enableComment === true, + enableScripting: params.enableScripting === true, + hasJSActions: params.hasJSActions, + fieldObjects: params.fieldObjects, + parent: this, + elements: null + }; + for (const data of annotations) { + if (data.noHTML) { + continue; + } + const isPopupAnnotation = data.annotationType === AnnotationType.POPUP; + if (!isPopupAnnotation) { + if (data.rect[2] === data.rect[0] || data.rect[3] === data.rect[1]) { + continue; + } + } else { + const elements = popupToElements.get(data.id); + if (!elements) { + continue; + } + if (!this._commentManager) { + popupAnnotations.push(data); + continue; + } + elementParams.elements = elements; + } + elementParams.data = data; + const element = AnnotationElementFactory.create(elementParams); + if (!element.isRenderable) { + continue; + } + if (!isPopupAnnotation) { + this.#elements.push(element); + if (data.popupRef) { + const elements = popupToElements.get(data.popupRef); + if (!elements) { + popupToElements.set(data.popupRef, [element]); + } else { + elements.push(element); + } + } + } + const rendered = element.render(); + if (data.hidden) { + rendered.style.visibility = "hidden"; + } + if (element._isEditable) { + this.#editableAnnotations.set(element.data.id, element); + this._annotationEditorUIManager?.renderAnnotationElement(element); + } + } + await this.#addElementsToDOM(); + for (const data of popupAnnotations) { + const elements = elementParams.elements = popupToElements.get(data.id); + elementParams.data = data; + const element = AnnotationElementFactory.create(elementParams); + if (!element.isRenderable) { + continue; + } + const rendered = element.render(); + element.contentElement.id = `${AnnotationPrefix}${data.id}`; + if (data.hidden) { + rendered.style.visibility = "hidden"; + } + elements.at(-1).container.after(rendered); + } + this.#setAnnotationCanvasMap(); + } + async #addElementsToDOM() { + if (this.#elements.length === 0) { + return; + } + this.div.replaceChildren(); + const promises = []; + if (!this.#hasAriaAttributesFromStructTree) { + this.#hasAriaAttributesFromStructTree = true; + for (const { + contentElement, + data: { + id + } + } of this.#elements) { + const annotationId = contentElement.id = `${AnnotationPrefix}${id}`; + promises.push(this.#structTreeLayer?.getAriaAttributes(annotationId).then(ariaAttributes => { + if (ariaAttributes) { + for (const [key, value] of ariaAttributes) { + contentElement.setAttribute(key, value); + } + } + })); + } + } + this.#elements.sort(({ + data: { + rect: [a0, a1, a2, a3] + } + }, { + data: { + rect: [b0, b1, b2, b3] + } + }) => { + if (a0 === a2 && a1 === a3) { + return +1; + } + if (b0 === b2 && b1 === b3) { + return -1; + } + const top1 = a3; + const bot1 = a1; + const mid1 = (a1 + a3) / 2; + const top2 = b3; + const bot2 = b1; + const mid2 = (b1 + b3) / 2; + if (mid1 >= top2 && mid2 <= bot1) { + return -1; + } + if (mid2 >= top1 && mid1 <= bot2) { + return +1; + } + const centerX1 = (a0 + a2) / 2; + const centerX2 = (b0 + b2) / 2; + return centerX1 - centerX2; + }); + const fragment = document.createDocumentFragment(); + for (const element of this.#elements) { + fragment.append(element.container); + if (this._commentManager) { + (element.extraPopupElement?.popup || element.popup)?.renderCommentButton(); + } else if (element.extraPopupElement) { + fragment.append(element.extraPopupElement.render()); + } + } + this.div.append(fragment); + await Promise.all(promises); + if (this.#accessibilityManager) { + for (const element of this.#elements) { + this.#accessibilityManager.addPointerInTextLayer(element.contentElement, false); + } + } + } + async addLinkAnnotations(annotations) { + const elementParams = { + data: null, + layer: this.div, + linkService: this.#linkService, + svgFactory: new DOMSVGFactory(), + parent: this + }; + for (const data of annotations) { + data.borderStyle ||= AnnotationLayer._defaultBorderStyle; + elementParams.data = data; + const element = AnnotationElementFactory.create(elementParams); + if (!element.isRenderable) { + continue; + } + element.render(); + element.contentElement.id = `${AnnotationPrefix}${data.id}`; + this.#elements.push(element); + } + await this.#addElementsToDOM(); + } + update({ + viewport + }) { + const layer = this.div; + this.viewport = viewport; + setLayerDimensions(layer, { + rotation: viewport.rotation + }); + this.#setAnnotationCanvasMap(); + layer.hidden = false; + } + #setAnnotationCanvasMap() { + if (!this.#annotationCanvasMap) { + return; + } + const layer = this.div; + for (const [id, canvas] of this.#annotationCanvasMap) { + const element = layer.querySelector(`[data-annotation-id="${id}"]`); + if (!element) { + continue; + } + canvas.className = "annotationContent"; + const { + firstChild + } = element; + if (!firstChild) { + element.append(canvas); + } else if (firstChild.nodeName === "CANVAS") { + firstChild.replaceWith(canvas); + } else if (!firstChild.classList.contains("annotationContent")) { + firstChild.before(canvas); + } else { + firstChild.after(canvas); + } + const editableAnnotation = this.#editableAnnotations.get(id); + if (!editableAnnotation) { + continue; + } + if (editableAnnotation._hasNoCanvas) { + this._annotationEditorUIManager?.setMissingCanvas(id, element.id, canvas); + editableAnnotation._hasNoCanvas = false; + } else { + editableAnnotation.canvas = canvas; + } + } + this.#annotationCanvasMap.clear(); + } + getEditableAnnotations() { + return Array.from(this.#editableAnnotations.values()); + } + getEditableAnnotation(id) { + return this.#editableAnnotations.get(id); + } + addFakeAnnotation(editor) { + const { + div + } = this; + const { + id, + rotation + } = editor; + const element = new EditorAnnotationElement({ + data: { + id, + rect: editor.getPDFRect(), + rotation + }, + editor, + layer: div, + parent: this, + enableComment: !!this._commentManager, + linkService: this.#linkService, + annotationStorage: this.#annotationStorage + }); + element.render(); + element.contentElement.id = `${AnnotationPrefix}${id}`; + element.createOrUpdatePopup(); + this.#elements.push(element); + return element; + } + removeAnnotation(id) { + const index = this.#elements.findIndex(el => el.data.id === id); + if (index < 0) { + return; + } + const [element] = this.#elements.splice(index, 1); + this.#accessibilityManager?.removePointerInTextLayer(element.contentElement); + } + updateFakeAnnotations(editors) { + if (editors.length === 0) { + return; + } + for (const editor of editors) { + editor.updateFakeAnnotationElement(this); + } + this.#addElementsToDOM(); + } + togglePointerEvents(enabled = false) { + this.div.classList.toggle("disabled", !enabled); + } + static get _defaultBorderStyle() { + return shadow(this, "_defaultBorderStyle", Object.freeze({ + width: 1, + rawWidth: 1, + style: AnnotationBorderStyleType.SOLID, + dashArray: [3], + horizontalCornerRadius: 0, + verticalCornerRadius: 0 + })); + } +} + +;// ./src/display/editor/freetext.js + + + + + +const EOL_PATTERN = /\r\n?|\n/g; +class FreeTextEditor extends AnnotationEditor { + #content = ""; + #editorDivId = `${this.id}-editor`; + #editModeAC = null; + #fontSize; + _colorPicker = null; + static _freeTextDefaultContent = ""; + static _internalPadding = 0; + static _defaultColor = null; + static _defaultFontSize = 10; + static get _keyboardManager() { + const proto = FreeTextEditor.prototype; + const arrowChecker = self => self.isEmpty(); + const small = AnnotationEditorUIManager.TRANSLATE_SMALL; + const big = AnnotationEditorUIManager.TRANSLATE_BIG; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+s", "mac+meta+s", "ctrl+p", "mac+meta+p"], proto.commitOrRemove, { + bubbles: true + }], [["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], proto.commitOrRemove], [["ArrowLeft", "mac+ArrowLeft"], proto._translateEmpty, { + args: [-small, 0], + checker: arrowChecker + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto._translateEmpty, { + args: [-big, 0], + checker: arrowChecker + }], [["ArrowRight", "mac+ArrowRight"], proto._translateEmpty, { + args: [small, 0], + checker: arrowChecker + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto._translateEmpty, { + args: [big, 0], + checker: arrowChecker + }], [["ArrowUp", "mac+ArrowUp"], proto._translateEmpty, { + args: [0, -small], + checker: arrowChecker + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto._translateEmpty, { + args: [0, -big], + checker: arrowChecker + }], [["ArrowDown", "mac+ArrowDown"], proto._translateEmpty, { + args: [0, small], + checker: arrowChecker + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto._translateEmpty, { + args: [0, big], + checker: arrowChecker + }]])); + } + static _type = "freetext"; + static _editorType = AnnotationEditorType.FREETEXT; + constructor(params) { + super({ + ...params, + name: "freeTextEditor" + }); + this.color = params.color || FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor; + this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize; + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-freetext-added-alert"); + } + this.canAddComment = false; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + const style = getComputedStyle(document.documentElement); + this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding")); + } + static updateDefaultParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.FREETEXT_SIZE: + FreeTextEditor._defaultFontSize = value; + break; + case AnnotationEditorParamsType.FREETEXT_COLOR: + FreeTextEditor._defaultColor = value; + break; + } + } + updateParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.FREETEXT_SIZE: + this.#updateFontSize(value); + break; + case AnnotationEditorParamsType.FREETEXT_COLOR: + this.#updateColor(value); + break; + } + } + static get defaultPropertiesToUpdate() { + return [[AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor]]; + } + get propertiesToUpdate() { + return [[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, this.color]]; + } + get toolbarButtons() { + this._colorPicker ||= new BasicColorPicker(this); + return [["colorPicker", this._colorPicker]]; + } + get colorType() { + return AnnotationEditorParamsType.FREETEXT_COLOR; + } + #updateFontSize(fontSize) { + const setFontsize = size => { + this.editorDiv.style.fontSize = `calc(${size}px * var(--total-scale-factor))`; + this.translate(0, -(size - this.#fontSize) * this.parentScale); + this.#fontSize = size; + this.#setEditorDimensions(); + }; + const savedFontsize = this.#fontSize; + this.addCommands({ + cmd: setFontsize.bind(this, fontSize), + undo: setFontsize.bind(this, savedFontsize), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.FREETEXT_SIZE, + overwriteIfSameType: true, + keepUndo: true + }); + } + onUpdatedColor() { + this.editorDiv.style.color = this.color; + this._colorPicker?.update(this.color); + super.onUpdatedColor(); + } + #updateColor(color) { + const setColor = col => { + this.color = col; + this.onUpdatedColor(); + }; + const savedColor = this.color; + this.addCommands({ + cmd: setColor.bind(this, color), + undo: setColor.bind(this, savedColor), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.FREETEXT_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + } + _translateEmpty(x, y) { + this._uiManager.translateSelectedEditors(x, y, true); + } + getInitialTranslation() { + const scale = this.parentScale; + return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale]; + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + enableEditMode() { + if (!super.enableEditMode()) { + return false; + } + this.overlayDiv.classList.remove("enabled"); + this.editorDiv.contentEditable = true; + this._isDraggable = false; + this.div.removeAttribute("aria-activedescendant"); + this.#editModeAC = new AbortController(); + const signal = this._uiManager.combinedSignal(this.#editModeAC); + this.editorDiv.addEventListener("keydown", this.editorDivKeydown.bind(this), { + signal + }); + this.editorDiv.addEventListener("focus", this.editorDivFocus.bind(this), { + signal + }); + this.editorDiv.addEventListener("blur", this.editorDivBlur.bind(this), { + signal + }); + this.editorDiv.addEventListener("input", this.editorDivInput.bind(this), { + signal + }); + this.editorDiv.addEventListener("paste", this.editorDivPaste.bind(this), { + signal + }); + return true; + } + disableEditMode() { + if (!super.disableEditMode()) { + return false; + } + this.overlayDiv.classList.add("enabled"); + this.editorDiv.contentEditable = false; + this.div.setAttribute("aria-activedescendant", this.#editorDivId); + this._isDraggable = true; + this.#editModeAC?.abort(); + this.#editModeAC = null; + this.div.focus({ + preventScroll: true + }); + this.isEditing = false; + this.parent.div.classList.add("freetextEditing"); + return true; + } + focusin(event) { + if (!this._focusEventsAllowed) { + return; + } + super.focusin(event); + if (event.target !== this.editorDiv) { + this.editorDiv.focus(); + } + } + onceAdded(focus) { + if (this.width) { + return; + } + this.enableEditMode(); + if (focus) { + this.editorDiv.focus(); + } + if (this._initialOptions?.isCentered) { + this.center(); + } + this._initialOptions = null; + } + isEmpty() { + return !this.editorDiv || this.editorDiv.innerText.trim() === ""; + } + remove() { + this.isEditing = false; + if (this.parent) { + this.parent.setEditingState(true); + this.parent.div.classList.add("freetextEditing"); + } + super.remove(); + } + #extractText() { + const buffer = []; + this.editorDiv.normalize(); + let prevChild = null; + for (const child of this.editorDiv.childNodes) { + if (prevChild?.nodeType === Node.TEXT_NODE && child.nodeName === "BR") { + continue; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + prevChild = child; + } + return buffer.join("\n"); + } + #setEditorDimensions() { + const [parentWidth, parentHeight] = this.parentDimensions; + let rect; + if (this.isAttachedToDOM) { + rect = this.div.getBoundingClientRect(); + } else { + const { + currentLayer, + div + } = this; + const savedDisplay = div.style.display; + const savedVisibility = div.classList.contains("hidden"); + div.classList.remove("hidden"); + div.style.display = "hidden"; + currentLayer.div.append(this.div); + rect = div.getBoundingClientRect(); + div.remove(); + div.style.display = savedDisplay; + div.classList.toggle("hidden", savedVisibility); + } + if (this.rotation % 180 === this.parentRotation % 180) { + this.width = rect.width / parentWidth; + this.height = rect.height / parentHeight; + } else { + this.width = rect.height / parentWidth; + this.height = rect.width / parentHeight; + } + this.fixAndSetPosition(); + } + commit() { + if (!this.isInEditMode()) { + return; + } + super.commit(); + this.disableEditMode(); + const savedText = this.#content; + const newText = this.#content = this.#extractText().trimEnd(); + if (savedText === newText) { + return; + } + const setText = text => { + this.#content = text; + if (!text) { + this.remove(); + return; + } + this.#setContent(); + this._uiManager.rebuild(this); + this.#setEditorDimensions(); + }; + this.addCommands({ + cmd: () => { + setText(newText); + }, + undo: () => { + setText(savedText); + }, + mustExec: false + }); + this.#setEditorDimensions(); + } + shouldGetKeyboardEvents() { + return this.isInEditMode(); + } + enterInEditMode() { + this.enableEditMode(); + this.editorDiv.focus(); + } + keydown(event) { + if (event.target === this.div && event.key === "Enter") { + this.enterInEditMode(); + event.preventDefault(); + } + } + editorDivKeydown(event) { + FreeTextEditor._keyboardManager.exec(this, event); + } + editorDivFocus(event) { + this.isEditing = true; + } + editorDivBlur(event) { + this.isEditing = false; + } + editorDivInput(event) { + this.parent.div.classList.toggle("freetextEditing", this.isEmpty()); + } + disableEditing() { + this.editorDiv.setAttribute("role", "comment"); + this.editorDiv.removeAttribute("aria-multiline"); + } + enableEditing() { + this.editorDiv.setAttribute("role", "textbox"); + this.editorDiv.setAttribute("aria-multiline", true); + } + get canChangeContent() { + return true; + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy || this.annotationElementId) { + baseX = this.x; + baseY = this.y; + } + super.render(); + this.editorDiv = document.createElement("div"); + this.editorDiv.className = "internal"; + this.editorDiv.setAttribute("id", this.#editorDivId); + this.editorDiv.setAttribute("data-l10n-id", "pdfjs-free-text2"); + this.editorDiv.setAttribute("data-l10n-attrs", "default-content"); + this.enableEditing(); + this.editorDiv.contentEditable = true; + const { + style + } = this.editorDiv; + style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`; + style.color = this.color; + this.div.append(this.editorDiv); + this.overlayDiv = document.createElement("div"); + this.overlayDiv.classList.add("overlay", "enabled"); + this.div.append(this.overlayDiv); + if (this._isCopy || this.annotationElementId) { + const [parentWidth, parentHeight] = this.parentDimensions; + if (this.annotationElementId) { + const { + position + } = this._initialData; + let [tx, ty] = this.getInitialTranslation(); + [tx, ty] = this.pageTranslationToScreen(tx, ty); + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + let posX, posY; + switch (this.rotation) { + case 0: + posX = baseX + (position[0] - pageX) / pageWidth; + posY = baseY + this.height - (position[1] - pageY) / pageHeight; + break; + case 90: + posX = baseX + (position[0] - pageX) / pageWidth; + posY = baseY - (position[1] - pageY) / pageHeight; + [tx, ty] = [ty, -tx]; + break; + case 180: + posX = baseX - this.width + (position[0] - pageX) / pageWidth; + posY = baseY - (position[1] - pageY) / pageHeight; + [tx, ty] = [-tx, -ty]; + break; + case 270: + posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth; + posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight; + [tx, ty] = [-ty, tx]; + break; + } + this.setAt(posX * parentWidth, posY * parentHeight, tx, ty); + } else { + this._moveAfterPaste(baseX, baseY); + } + this.#setContent(); + this._isDraggable = true; + this.editorDiv.contentEditable = false; + } else { + this._isDraggable = false; + this.editorDiv.contentEditable = true; + } + return this.div; + } + static #getNodeContent(node) { + return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, ""); + } + editorDivPaste(event) { + const clipboardData = event.clipboardData || window.clipboardData; + const { + types + } = clipboardData; + if (types.length === 1 && types[0] === "text/plain") { + return; + } + event.preventDefault(); + const paste = FreeTextEditor.#deserializeContent(clipboardData.getData("text") || "").replaceAll(EOL_PATTERN, "\n"); + if (!paste) { + return; + } + const selection = window.getSelection(); + if (!selection.rangeCount) { + return; + } + this.editorDiv.normalize(); + selection.deleteFromDocument(); + const range = selection.getRangeAt(0); + if (!paste.includes("\n")) { + range.insertNode(document.createTextNode(paste)); + this.editorDiv.normalize(); + selection.collapseToStart(); + return; + } + const { + startContainer, + startOffset + } = range; + const bufferBefore = []; + const bufferAfter = []; + if (startContainer.nodeType === Node.TEXT_NODE) { + const parent = startContainer.parentElement; + bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, "")); + if (parent !== this.editorDiv) { + let buffer = bufferBefore; + for (const child of this.editorDiv.childNodes) { + if (child === parent) { + buffer = bufferAfter; + continue; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + } + } + bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, "")); + } else if (startContainer === this.editorDiv) { + let buffer = bufferBefore; + let i = 0; + for (const child of this.editorDiv.childNodes) { + if (i++ === startOffset) { + buffer = bufferAfter; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + } + } + this.#content = `${bufferBefore.join("\n")}${paste}${bufferAfter.join("\n")}`; + this.#setContent(); + const newRange = new Range(); + let beforeLength = Math.sumPrecise(bufferBefore.map(line => line.length)); + for (const { + firstChild + } of this.editorDiv.childNodes) { + if (firstChild.nodeType === Node.TEXT_NODE) { + const length = firstChild.nodeValue.length; + if (beforeLength <= length) { + newRange.setStart(firstChild, beforeLength); + newRange.setEnd(firstChild, beforeLength); + break; + } + beforeLength -= length; + } + } + selection.removeAllRanges(); + selection.addRange(newRange); + } + #setContent() { + this.editorDiv.replaceChildren(); + if (!this.#content) { + return; + } + for (const line of this.#content.split("\n")) { + const div = document.createElement("div"); + div.append(line ? document.createTextNode(line) : document.createElement("br")); + this.editorDiv.append(div); + } + } + #serializeContent() { + return this.#content.replaceAll("\xa0", " "); + } + static #deserializeContent(content) { + return content.replaceAll(" ", "\xa0"); + } + get contentDiv() { + return this.editorDiv; + } + getPDFRect() { + const padding = FreeTextEditor._internalPadding * this.parentScale; + return this.getRect(padding, padding); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof FreeTextAnnotationElement) { + const { + data: { + defaultAppearanceData: { + fontSize, + fontColor + }, + rect, + rotation, + id, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + textContent, + textPosition, + parent: { + page: { + pageNumber + } + } + } = data; + if (!textContent || textContent.length === 0) { + return null; + } + initialData = data = { + annotationType: AnnotationEditorType.FREETEXT, + color: Array.from(fontColor), + fontSize, + value: textContent.join("\n"), + position: textPosition, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + comment: contentsObj?.str || null, + richText, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + editor.#fontSize = data.fontSize; + editor.color = Util.makeHexColor(...data.color); + editor.#content = FreeTextEditor.#deserializeContent(data.value); + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + return editor; + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const color = AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.color); + const serialized = Object.assign(super.serialize(isForCopying), { + color, + fontSize: this.#fontSize, + value: this.#serializeContent() + }); + this.addComment(serialized); + if (isForCopying) { + serialized.isCopy = true; + return serialized; + } + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + value, + fontSize, + color, + pageIndex + } = this._initialData; + return this.hasEditedComment || this._hasBeenMoved || serialized.value !== value || serialized.fontSize !== fontSize || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex; + } + renderAnnotationElement(annotation) { + const content = super.renderAnnotationElement(annotation); + if (!content) { + return null; + } + const { + style + } = content; + style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`; + style.color = this.color; + content.replaceChildren(); + for (const line of this.#content.split("\n")) { + const div = document.createElement("div"); + div.append(line ? document.createTextNode(line) : document.createElement("br")); + content.append(div); + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this._uiManager.hasCommentManager() || this.hasEditedComment ? this.comment : { + text: this.#content + } + }); + return content; + } + resetAnnotationElement(annotation) { + super.resetAnnotationElement(annotation); + annotation.resetEdited(); + } +} + +;// ./src/display/editor/drawers/outline.js + +class Outline { + static PRECISION = 1e-4; + toSVGPath() { + unreachable("Abstract method `toSVGPath` must be implemented."); + } + get box() { + unreachable("Abstract getter `box` must be implemented."); + } + serialize(_bbox, _rotation) { + unreachable("Abstract method `serialize` must be implemented."); + } + static _rescale(src, tx, ty, sx, sy, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i] * sx; + dest[i + 1] = ty + src[i + 1] * sy; + } + return dest; + } + static _rescaleAndSwap(src, tx, ty, sx, sy, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i + 1] * sx; + dest[i + 1] = ty + src[i] * sy; + } + return dest; + } + static _translate(src, tx, ty, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i]; + dest[i + 1] = ty + src[i + 1]; + } + return dest; + } + static svgRound(x) { + return Math.round(x * 10000); + } + static _normalizePoint(x, y, parentWidth, parentHeight, rotation) { + switch (rotation) { + case 90: + return [1 - y / parentWidth, x / parentHeight]; + case 180: + return [1 - x / parentWidth, 1 - y / parentHeight]; + case 270: + return [y / parentWidth, 1 - x / parentHeight]; + default: + return [x / parentWidth, y / parentHeight]; + } + } + static _normalizePagePoint(x, y, rotation) { + switch (rotation) { + case 90: + return [1 - y, x]; + case 180: + return [1 - x, 1 - y]; + case 270: + return [y, 1 - x]; + default: + return [x, y]; + } + } + static createBezierPoints(x1, y1, x2, y2, x3, y3) { + return [(x1 + 5 * x2) / 6, (y1 + 5 * y2) / 6, (5 * x2 + x3) / 6, (5 * y2 + y3) / 6, (x2 + x3) / 2, (y2 + y3) / 2]; + } +} + +;// ./src/display/editor/drawers/freedraw.js + + +class FreeDrawOutliner { + #box; + #bottom = []; + #innerMargin; + #isLTR; + #top = []; + #last = new Float32Array(18); + #lastX; + #lastY; + #min; + #min_dist; + #scaleFactor; + #thickness; + #points = []; + static #MIN_DIST = 8; + static #MIN_DIFF = 2; + static #MIN = FreeDrawOutliner.#MIN_DIST + FreeDrawOutliner.#MIN_DIFF; + constructor({ + x, + y + }, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + this.#box = box; + this.#thickness = thickness * scaleFactor; + this.#isLTR = isLTR; + this.#last.set([NaN, NaN, NaN, NaN, x, y], 6); + this.#innerMargin = innerMargin; + this.#min_dist = FreeDrawOutliner.#MIN_DIST * scaleFactor; + this.#min = FreeDrawOutliner.#MIN * scaleFactor; + this.#scaleFactor = scaleFactor; + this.#points.push(x, y); + } + isEmpty() { + return isNaN(this.#last[8]); + } + #getLastCoords() { + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [x, y, width, height] = this.#box; + return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height]; + } + add({ + x, + y + }) { + this.#lastX = x; + this.#lastY = y; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + let [x1, y1, x2, y2] = this.#last.subarray(8, 12); + const diffX = x - x2; + const diffY = y - y2; + const d = Math.hypot(diffX, diffY); + if (d < this.#min) { + return false; + } + const diffD = d - this.#min_dist; + const K = diffD / d; + const shiftX = K * diffX; + const shiftY = K * diffY; + let x0 = x1; + let y0 = y1; + x1 = x2; + y1 = y2; + x2 += shiftX; + y2 += shiftY; + this.#points?.push(x, y); + const nX = -shiftY / diffD; + const nY = shiftX / diffD; + const thX = nX * this.#thickness; + const thY = nY * this.#thickness; + this.#last.set(this.#last.subarray(2, 8), 0); + this.#last.set([x2 + thX, y2 + thY], 4); + this.#last.set(this.#last.subarray(14, 18), 12); + this.#last.set([x2 - thX, y2 - thY], 16); + if (isNaN(this.#last[6])) { + if (this.#top.length === 0) { + this.#last.set([x1 + thX, y1 + thY], 2); + this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight); + this.#last.set([x1 - thX, y1 - thY], 14); + this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + return !this.isEmpty(); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX)); + if (angle < Math.PI / 2) { + [x1, y1, x2, y2] = this.#last.subarray(2, 6); + this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x1, y1, x0, y0] = this.#last.subarray(14, 18); + this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight); + return true; + } + [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6); + this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18); + this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + return true; + } + toSVGPath() { + if (this.isEmpty()) { + return ""; + } + const top = this.#top; + const bottom = this.#bottom; + if (isNaN(this.#last[6]) && !this.isEmpty()) { + return this.#toSVGPathTwoPoints(); + } + const buffer = []; + buffer.push(`M${top[4]} ${top[5]}`); + for (let i = 6; i < top.length; i += 6) { + if (isNaN(top[i])) { + buffer.push(`L${top[i + 4]} ${top[i + 5]}`); + } else { + buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`); + } + } + this.#toSVGPathEnd(buffer); + for (let i = bottom.length - 6; i >= 6; i -= 6) { + if (isNaN(bottom[i])) { + buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`); + } else { + buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`); + } + } + this.#toSVGPathStart(buffer); + return buffer.join(" "); + } + #toSVGPathTwoPoints() { + const [x, y, width, height] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`; + } + #toSVGPathStart(buffer) { + const bottom = this.#bottom; + buffer.push(`L${bottom[4]} ${bottom[5]} Z`); + } + #toSVGPathEnd(buffer) { + const [x, y, width, height] = this.#box; + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`); + } + newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) { + return new FreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR); + } + getOutlines() { + const top = this.#top; + const bottom = this.#bottom; + const last = this.#last; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const points = new Float32Array((this.#points?.length ?? 0) + 2); + for (let i = 0, ii = points.length - 2; i < ii; i += 2) { + points[i] = (this.#points[i] - layerX) / layerWidth; + points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight; + } + points[points.length - 2] = (this.#lastX - layerX) / layerWidth; + points[points.length - 1] = (this.#lastY - layerY) / layerHeight; + if (isNaN(last[6]) && !this.isEmpty()) { + return this.#getOutlineTwoPoints(points); + } + const outline = new Float32Array(this.#top.length + 24 + this.#bottom.length); + let N = top.length; + for (let i = 0; i < N; i += 2) { + if (isNaN(top[i])) { + outline[i] = outline[i + 1] = NaN; + continue; + } + outline[i] = top[i]; + outline[i + 1] = top[i + 1]; + } + N = this.#getOutlineEnd(outline, N); + for (let i = bottom.length - 6; i >= 6; i -= 6) { + for (let j = 0; j < 6; j += 2) { + if (isNaN(bottom[i + j])) { + outline[N] = outline[N + 1] = NaN; + N += 2; + continue; + } + outline[N] = bottom[i + j]; + outline[N + 1] = bottom[i + j + 1]; + N += 2; + } + } + this.#getOutlineStart(outline, N); + return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } + #getOutlineTwoPoints(points) { + const last = this.#last; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + const outline = new Float32Array(36); + outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0); + return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } + #getOutlineStart(outline, pos) { + const bottom = this.#bottom; + outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], pos); + return pos += 6; + } + #getOutlineEnd(outline, pos) { + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], pos); + return pos += 24; + } +} +class FreeDrawOutline extends Outline { + #box; + #bbox = new Float32Array(4); + #innerMargin; + #isLTR; + #points; + #scaleFactor; + #outline; + constructor(outline, points, box, scaleFactor, innerMargin, isLTR) { + super(); + this.#outline = outline; + this.#points = points; + this.#box = box; + this.#scaleFactor = scaleFactor; + this.#innerMargin = innerMargin; + this.#isLTR = isLTR; + this.firstPoint = [NaN, NaN]; + this.lastPoint = [NaN, NaN]; + this.#computeMinMax(isLTR); + const [x, y, width, height] = this.#bbox; + for (let i = 0, ii = outline.length; i < ii; i += 2) { + outline[i] = (outline[i] - x) / width; + outline[i + 1] = (outline[i + 1] - y) / height; + } + for (let i = 0, ii = points.length; i < ii; i += 2) { + points[i] = (points[i] - x) / width; + points[i + 1] = (points[i + 1] - y) / height; + } + } + toSVGPath() { + const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`]; + for (let i = 6, ii = this.#outline.length; i < ii; i += 6) { + if (isNaN(this.#outline[i])) { + buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + continue; + } + buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + } + buffer.push("Z"); + return buffer.join(" "); + } + serialize([blX, blY, trX, trY], rotation) { + const width = trX - blX; + const height = trY - blY; + let outline; + let points; + switch (rotation) { + case 0: + outline = Outline._rescale(this.#outline, blX, trY, width, -height); + points = Outline._rescale(this.#points, blX, trY, width, -height); + break; + case 90: + outline = Outline._rescaleAndSwap(this.#outline, blX, blY, width, height); + points = Outline._rescaleAndSwap(this.#points, blX, blY, width, height); + break; + case 180: + outline = Outline._rescale(this.#outline, trX, blY, -width, height); + points = Outline._rescale(this.#points, trX, blY, -width, height); + break; + case 270: + outline = Outline._rescaleAndSwap(this.#outline, trX, trY, -width, -height); + points = Outline._rescaleAndSwap(this.#points, trX, trY, -width, -height); + break; + } + return { + outline: Array.from(outline), + points: [Array.from(points)] + }; + } + #computeMinMax(isLTR) { + const outline = this.#outline; + let lastX = outline[4]; + let lastY = outline[5]; + const minMax = [lastX, lastY, lastX, lastY]; + let firstPointX = lastX; + let firstPointY = lastY; + let lastPointX = lastX; + let lastPointY = lastY; + const ltrCallback = isLTR ? Math.max : Math.min; + const bezierBbox = new Float32Array(4); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + const x = outline[i + 4], + y = outline[i + 5]; + if (isNaN(outline[i])) { + Util.pointBoundingBox(x, y, minMax); + if (firstPointY > y) { + firstPointX = x; + firstPointY = y; + } else if (firstPointY === y) { + firstPointX = ltrCallback(firstPointX, x); + } + if (lastPointY < y) { + lastPointX = x; + lastPointY = y; + } else if (lastPointY === y) { + lastPointX = ltrCallback(lastPointX, x); + } + } else { + bezierBbox[0] = bezierBbox[1] = Infinity; + bezierBbox[2] = bezierBbox[3] = -Infinity; + Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6), bezierBbox); + Util.rectBoundingBox(bezierBbox[0], bezierBbox[1], bezierBbox[2], bezierBbox[3], minMax); + if (firstPointY > bezierBbox[1]) { + firstPointX = bezierBbox[0]; + firstPointY = bezierBbox[1]; + } else if (firstPointY === bezierBbox[1]) { + firstPointX = ltrCallback(firstPointX, bezierBbox[0]); + } + if (lastPointY < bezierBbox[3]) { + lastPointX = bezierBbox[2]; + lastPointY = bezierBbox[3]; + } else if (lastPointY === bezierBbox[3]) { + lastPointX = ltrCallback(lastPointX, bezierBbox[2]); + } + } + lastX = x; + lastY = y; + } + const bbox = this.#bbox; + bbox[0] = minMax[0] - this.#innerMargin; + bbox[1] = minMax[1] - this.#innerMargin; + bbox[2] = minMax[2] - minMax[0] + 2 * this.#innerMargin; + bbox[3] = minMax[3] - minMax[1] + 2 * this.#innerMargin; + this.firstPoint = [firstPointX, firstPointY]; + this.lastPoint = [lastPointX, lastPointY]; + } + get box() { + return this.#bbox; + } + newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + return new FreeDrawOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin); + } + getNewOutline(thickness, innerMargin) { + const [x, y, width, height] = this.#bbox; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const sx = width * layerWidth; + const sy = height * layerHeight; + const tx = x * layerWidth + layerX; + const ty = y * layerHeight + layerY; + const outliner = this.newOutliner({ + x: this.#points[0] * sx + tx, + y: this.#points[1] * sy + ty + }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin); + for (let i = 2; i < this.#points.length; i += 2) { + outliner.add({ + x: this.#points[i] * sx + tx, + y: this.#points[i + 1] * sy + ty + }); + } + return outliner.getOutlines(); + } +} + +;// ./src/display/editor/drawers/highlight.js + + + +class HighlightOutliner { + #box; + #firstPoint; + #lastPoint; + #verticalEdges = []; + #intervals = []; + constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) { + const minMax = [Infinity, Infinity, -Infinity, -Infinity]; + const NUMBER_OF_DIGITS = 4; + const EPSILON = 10 ** -NUMBER_OF_DIGITS; + for (const { + x, + y, + width, + height + } of boxes) { + const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON; + const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON; + const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON; + const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON; + const left = [x1, y1, y2, true]; + const right = [x2, y1, y2, false]; + this.#verticalEdges.push(left, right); + Util.rectBoundingBox(x1, y1, x2, y2, minMax); + } + const bboxWidth = minMax[2] - minMax[0] + 2 * innerMargin; + const bboxHeight = minMax[3] - minMax[1] + 2 * innerMargin; + const shiftedMinX = minMax[0] - innerMargin; + const shiftedMinY = minMax[1] - innerMargin; + let firstPointX = isLTR ? -Infinity : Infinity; + let firstPointY = Infinity; + const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2); + const lastPoint = [lastEdge[0], lastEdge[2]]; + for (const edge of this.#verticalEdges) { + const [x, y1, y2, left] = edge; + if (!left && isLTR) { + if (y1 < firstPointY) { + firstPointY = y1; + firstPointX = x; + } else if (y1 === firstPointY) { + firstPointX = Math.max(firstPointX, x); + } + } else if (left && !isLTR) { + if (y1 < firstPointY) { + firstPointY = y1; + firstPointX = x; + } else if (y1 === firstPointY) { + firstPointX = Math.min(firstPointX, x); + } + } + edge[0] = (x - shiftedMinX) / bboxWidth; + edge[1] = (y1 - shiftedMinY) / bboxHeight; + edge[2] = (y2 - shiftedMinY) / bboxHeight; + } + this.#box = new Float32Array([shiftedMinX, shiftedMinY, bboxWidth, bboxHeight]); + this.#firstPoint = [firstPointX, firstPointY]; + this.#lastPoint = lastPoint; + } + getOutlines() { + this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const outlineVerticalEdges = []; + for (const edge of this.#verticalEdges) { + if (edge[3]) { + outlineVerticalEdges.push(...this.#breakEdge(edge)); + this.#insert(edge); + } else { + this.#remove(edge); + outlineVerticalEdges.push(...this.#breakEdge(edge)); + } + } + return this.#getOutlines(outlineVerticalEdges); + } + #getOutlines(outlineVerticalEdges) { + const edges = []; + const allEdges = new Set(); + for (const edge of outlineVerticalEdges) { + const [x, y1, y2] = edge; + edges.push([x, y1, edge], [x, y2, edge]); + } + edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]); + for (let i = 0, ii = edges.length; i < ii; i += 2) { + const edge1 = edges[i][2]; + const edge2 = edges[i + 1][2]; + edge1.push(edge2); + edge2.push(edge1); + allEdges.add(edge1); + allEdges.add(edge2); + } + const outlines = []; + let outline; + while (allEdges.size > 0) { + const edge = allEdges.values().next().value; + let [x, y1, y2, edge1, edge2] = edge; + allEdges.delete(edge); + let lastPointX = x; + let lastPointY = y1; + outline = [x, y2]; + outlines.push(outline); + while (true) { + let e; + if (allEdges.has(edge1)) { + e = edge1; + } else if (allEdges.has(edge2)) { + e = edge2; + } else { + break; + } + allEdges.delete(e); + [x, y1, y2, edge1, edge2] = e; + if (lastPointX !== x) { + outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2); + lastPointX = x; + } + lastPointY = lastPointY === y1 ? y2 : y1; + } + outline.push(lastPointX, lastPointY); + } + return new HighlightOutline(outlines, this.#box, this.#firstPoint, this.#lastPoint); + } + #binarySearch(y) { + const array = this.#intervals; + let start = 0; + let end = array.length - 1; + while (start <= end) { + const middle = start + end >> 1; + const y1 = array[middle][0]; + if (y1 === y) { + return middle; + } + if (y1 < y) { + start = middle + 1; + } else { + end = middle - 1; + } + } + return end + 1; + } + #insert([, y1, y2]) { + const index = this.#binarySearch(y1); + this.#intervals.splice(index, 0, [y1, y2]); + } + #remove([, y1, y2]) { + const index = this.#binarySearch(y1); + for (let i = index; i < this.#intervals.length; i++) { + const [start, end] = this.#intervals[i]; + if (start !== y1) { + break; + } + if (start === y1 && end === y2) { + this.#intervals.splice(i, 1); + return; + } + } + for (let i = index - 1; i >= 0; i--) { + const [start, end] = this.#intervals[i]; + if (start !== y1) { + break; + } + if (start === y1 && end === y2) { + this.#intervals.splice(i, 1); + return; + } + } + } + #breakEdge(edge) { + const [x, y1, y2] = edge; + const results = [[x, y1, y2]]; + const index = this.#binarySearch(y2); + for (let i = 0; i < index; i++) { + const [start, end] = this.#intervals[i]; + for (let j = 0, jj = results.length; j < jj; j++) { + const [, y3, y4] = results[j]; + if (end <= y3 || y4 <= start) { + continue; + } + if (y3 >= start) { + if (y4 > end) { + results[j][1] = end; + } else { + if (jj === 1) { + return []; + } + results.splice(j, 1); + j--; + jj--; + } + continue; + } + results[j][2] = start; + if (y4 > end) { + results.push([x, end, y4]); + } + } + } + return results; + } +} +class HighlightOutline extends Outline { + #box; + #outlines; + constructor(outlines, box, firstPoint, lastPoint) { + super(); + this.#outlines = outlines; + this.#box = box; + this.firstPoint = firstPoint; + this.lastPoint = lastPoint; + } + toSVGPath() { + const buffer = []; + for (const polygon of this.#outlines) { + let [prevX, prevY] = polygon; + buffer.push(`M${prevX} ${prevY}`); + for (let i = 2; i < polygon.length; i += 2) { + const x = polygon[i]; + const y = polygon[i + 1]; + if (x === prevX) { + buffer.push(`V${y}`); + prevY = y; + } else if (y === prevY) { + buffer.push(`H${x}`); + prevX = x; + } + } + buffer.push("Z"); + } + return buffer.join(" "); + } + serialize([blX, blY, trX, trY], _rotation) { + const outlines = []; + const width = trX - blX; + const height = trY - blY; + for (const outline of this.#outlines) { + const points = new Array(outline.length); + for (let i = 0; i < outline.length; i += 2) { + points[i] = blX + outline[i] * width; + points[i + 1] = trY - outline[i + 1] * height; + } + outlines.push(points); + } + return outlines; + } + get box() { + return this.#box; + } + get classNamesForOutlining() { + return ["highlightOutline"]; + } +} +class FreeHighlightOutliner extends FreeDrawOutliner { + newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) { + return new FreeHighlightOutline(outline, points, box, scaleFactor, innerMargin, isLTR); + } +} +class FreeHighlightOutline extends FreeDrawOutline { + newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + return new FreeHighlightOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin); + } +} + +;// ./src/display/editor/highlight.js + + + + + + + +class HighlightEditor extends AnnotationEditor { + #anchorNode = null; + #anchorOffset = 0; + #boxes; + #clipPathId = null; + #colorPicker = null; + #focusOutlines = null; + #focusNode = null; + #focusOffset = 0; + #highlightDiv = null; + #highlightOutlines = null; + #id = null; + #isFreeHighlight = false; + #firstPoint = null; + #lastPoint = null; + #outlineId = null; + #text = ""; + #thickness; + #methodOfCreation = ""; + static _defaultColor = null; + static _defaultOpacity = 1; + static _defaultThickness = 12; + static _type = "highlight"; + static _editorType = AnnotationEditorType.HIGHLIGHT; + static _freeHighlightId = -1; + static _freeHighlight = null; + static _freeHighlightClipId = ""; + static get _keyboardManager() { + const proto = HighlightEditor.prototype; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], proto._moveCaret, { + args: [0] + }], [["ArrowRight", "mac+ArrowRight"], proto._moveCaret, { + args: [1] + }], [["ArrowUp", "mac+ArrowUp"], proto._moveCaret, { + args: [2] + }], [["ArrowDown", "mac+ArrowDown"], proto._moveCaret, { + args: [3] + }]])); + } + constructor(params) { + super({ + ...params, + name: "highlightEditor" + }); + this.color = params.color || HighlightEditor._defaultColor; + this.#thickness = params.thickness || HighlightEditor._defaultThickness; + this.opacity = params.opacity || HighlightEditor._defaultOpacity; + this.#boxes = params.boxes || null; + this.#methodOfCreation = params.methodOfCreation || ""; + this.#text = params.text || ""; + this._isDraggable = false; + this.defaultL10nId = "pdfjs-editor-highlight-editor"; + if (params.highlightId > -1) { + this.#isFreeHighlight = true; + this.#createFreeOutlines(params); + this.#addToDrawLayer(); + } else if (this.#boxes) { + this.#anchorNode = params.anchorNode; + this.#anchorOffset = params.anchorOffset; + this.#focusNode = params.focusNode; + this.#focusOffset = params.focusOffset; + this.#createOutlines(); + this.#addToDrawLayer(); + this.rotate(this.rotation); + } + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-highlight-added-alert"); + } + } + get telemetryInitialData() { + return { + action: "added", + type: this.#isFreeHighlight ? "free_highlight" : "highlight", + color: this._uiManager.getNonHCMColorName(this.color), + thickness: this.#thickness, + methodOfCreation: this.#methodOfCreation + }; + } + get telemetryFinalData() { + return { + type: "highlight", + color: this._uiManager.getNonHCMColorName(this.color) + }; + } + static computeTelemetryFinalData(data) { + return { + numberOfColors: data.get("color").size + }; + } + #createOutlines() { + const outliner = new HighlightOutliner(this.#boxes, 0.001); + this.#highlightOutlines = outliner.getOutlines(); + [this.x, this.y, this.width, this.height] = this.#highlightOutlines.box; + const outlinerForOutline = new HighlightOutliner(this.#boxes, 0.0025, 0.001, this._uiManager.direction === "ltr"); + this.#focusOutlines = outlinerForOutline.getOutlines(); + const { + firstPoint + } = this.#highlightOutlines; + this.#firstPoint = [(firstPoint[0] - this.x) / this.width, (firstPoint[1] - this.y) / this.height]; + const { + lastPoint + } = this.#focusOutlines; + this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height]; + } + #createFreeOutlines({ + highlightOutlines, + highlightId, + clipPathId + }) { + this.#highlightOutlines = highlightOutlines; + const extraThickness = 1.5; + this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 0.0025); + if (highlightId >= 0) { + this.#id = highlightId; + this.#clipPathId = clipPathId; + this.parent.drawLayer.finalizeDraw(highlightId, { + bbox: highlightOutlines.box, + path: { + d: highlightOutlines.toSVGPath() + } + }); + this.#outlineId = this.parent.drawLayer.drawOutline({ + rootClass: { + highlightOutline: true, + free: true + }, + bbox: this.#focusOutlines.box, + path: { + d: this.#focusOutlines.toSVGPath() + } + }, true); + } else if (this.parent) { + const angle = this.parent.viewport.rotation; + this.parent.drawLayer.updateProperties(this.#id, { + bbox: HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360), + path: { + d: highlightOutlines.toSVGPath() + } + }); + this.parent.drawLayer.updateProperties(this.#outlineId, { + bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle), + path: { + d: this.#focusOutlines.toSVGPath() + } + }); + } + const [x, y, width, height] = highlightOutlines.box; + switch (this.rotation) { + case 0: + this.x = x; + this.y = y; + this.width = width; + this.height = height; + break; + case 90: + { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = y; + this.y = 1 - x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + case 180: + this.x = 1 - x; + this.y = 1 - y; + this.width = width; + this.height = height; + break; + case 270: + { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = 1 - y; + this.y = x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + } + const { + firstPoint + } = highlightOutlines; + this.#firstPoint = [(firstPoint[0] - x) / width, (firstPoint[1] - y) / height]; + const { + lastPoint + } = this.#focusOutlines; + this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height]; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066"; + } + static updateDefaultParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.HIGHLIGHT_COLOR: + HighlightEditor._defaultColor = value; + break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + HighlightEditor._defaultThickness = value; + break; + } + } + translateInPage(x, y) {} + get toolbarPosition() { + return this.#lastPoint; + } + get commentButtonPosition() { + return this.#firstPoint; + } + updateParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.HIGHLIGHT_COLOR: + this.#updateColor(value); + break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + this.#updateThickness(value); + break; + } + } + static get defaultPropertiesToUpdate() { + return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]]; + } + get propertiesToUpdate() { + return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]]; + } + onUpdatedColor() { + this.parent?.drawLayer.updateProperties(this.#id, { + root: { + fill: this.color, + "fill-opacity": this.opacity + } + }); + this.#colorPicker?.updateColor(this.color); + super.onUpdatedColor(); + } + #updateColor(color) { + const setColorAndOpacity = (col, opa) => { + this.color = col; + this.opacity = opa; + this.onUpdatedColor(); + }; + const savedColor = this.color; + const savedOpacity = this.opacity; + this.addCommands({ + cmd: setColorAndOpacity.bind(this, color, HighlightEditor._defaultOpacity), + undo: setColorAndOpacity.bind(this, savedColor, savedOpacity), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.HIGHLIGHT_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + this._reportTelemetry({ + action: "color_changed", + color: this._uiManager.getNonHCMColorName(color) + }, true); + } + #updateThickness(thickness) { + const savedThickness = this.#thickness; + const setThickness = th => { + this.#thickness = th; + this.#changeThickness(th); + }; + this.addCommands({ + cmd: setThickness.bind(this, thickness), + undo: setThickness.bind(this, savedThickness), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.INK_THICKNESS, + overwriteIfSameType: true, + keepUndo: true + }); + this._reportTelemetry({ + action: "thickness_changed", + thickness + }, true); + } + get toolbarButtons() { + if (this._uiManager.highlightColors) { + const colorPicker = this.#colorPicker = new ColorPicker({ + editor: this + }); + return [["colorPicker", colorPicker]]; + } + return super.toolbarButtons; + } + disableEditing() { + super.disableEditing(); + this.div.classList.toggle("disabled", true); + } + enableEditing() { + super.enableEditing(); + this.div.classList.toggle("disabled", false); + } + fixAndSetPosition() { + return super.fixAndSetPosition(this.#getRotation()); + } + getBaseTranslation() { + return [0, 0]; + } + getRect(tx, ty) { + return super.getRect(tx, ty, this.#getRotation()); + } + onceAdded(focus) { + if (!this.annotationElementId) { + this.parent.addUndoableEditor(this); + } + if (focus) { + this.div.focus(); + } + } + remove() { + this.#cleanDrawLayer(); + this._reportTelemetry({ + action: "deleted" + }); + super.remove(); + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + this.#addToDrawLayer(); + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + setParent(parent) { + let mustBeSelected = false; + if (this.parent && !parent) { + this.#cleanDrawLayer(); + } else if (parent) { + this.#addToDrawLayer(parent); + mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor"); + } + super.setParent(parent); + this.show(this._isVisible); + if (mustBeSelected) { + this.select(); + } + } + #changeThickness(thickness) { + if (!this.#isFreeHighlight) { + return; + } + this.#createFreeOutlines({ + highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2) + }); + this.fixAndSetPosition(); + this.setDims(); + } + #cleanDrawLayer() { + if (this.#id === null || !this.parent) { + return; + } + this.parent.drawLayer.remove(this.#id); + this.#id = null; + this.parent.drawLayer.remove(this.#outlineId); + this.#outlineId = null; + } + #addToDrawLayer(parent = this.parent) { + if (this.#id !== null) { + return; + } + ({ + id: this.#id, + clipPathId: this.#clipPathId + } = parent.drawLayer.draw({ + bbox: this.#highlightOutlines.box, + root: { + viewBox: "0 0 1 1", + fill: this.color, + "fill-opacity": this.opacity + }, + rootClass: { + highlight: true, + free: this.#isFreeHighlight + }, + path: { + d: this.#highlightOutlines.toSVGPath() + } + }, false, true)); + this.#outlineId = parent.drawLayer.drawOutline({ + rootClass: { + highlightOutline: true, + free: this.#isFreeHighlight + }, + bbox: this.#focusOutlines.box, + path: { + d: this.#focusOutlines.toSVGPath() + } + }, this.#isFreeHighlight); + if (this.#highlightDiv) { + this.#highlightDiv.style.clipPath = this.#clipPathId; + } + } + static #rotateBbox([x, y, width, height], angle) { + switch (angle) { + case 90: + return [1 - y - height, x, height, width]; + case 180: + return [1 - x - width, 1 - y - height, width, height]; + case 270: + return [y, 1 - x - width, height, width]; + } + return [x, y, width, height]; + } + rotate(angle) { + const { + drawLayer + } = this.parent; + let box; + if (this.#isFreeHighlight) { + angle = (angle - this.rotation + 360) % 360; + box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle); + } else { + box = HighlightEditor.#rotateBbox([this.x, this.y, this.width, this.height], angle); + } + drawLayer.updateProperties(this.#id, { + bbox: box, + root: { + "data-main-rotation": angle + } + }); + drawLayer.updateProperties(this.#outlineId, { + bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle), + root: { + "data-main-rotation": angle + } + }); + } + render() { + if (this.div) { + return this.div; + } + const div = super.render(); + if (this.#text) { + div.setAttribute("aria-label", this.#text); + div.setAttribute("role", "mark"); + } + if (this.#isFreeHighlight) { + div.classList.add("free"); + } else { + this.div.addEventListener("keydown", this.#keydown.bind(this), { + signal: this._uiManager._signal + }); + } + const highlightDiv = this.#highlightDiv = document.createElement("div"); + div.append(highlightDiv); + highlightDiv.setAttribute("aria-hidden", "true"); + highlightDiv.className = "internal"; + highlightDiv.style.clipPath = this.#clipPathId; + this.setDims(); + bindEvents(this, this.#highlightDiv, ["pointerover", "pointerleave"]); + this.enableEditing(); + return div; + } + pointerover() { + if (!this.isSelected) { + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: true + } + }); + } + } + pointerleave() { + if (!this.isSelected) { + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: false + } + }); + } + } + #keydown(event) { + HighlightEditor._keyboardManager.exec(this, event); + } + _moveCaret(direction) { + this.parent.unselect(this); + switch (direction) { + case 0: + case 2: + this.#setCaret(true); + break; + case 1: + case 3: + this.#setCaret(false); + break; + } + } + #setCaret(start) { + if (!this.#anchorNode) { + return; + } + const selection = window.getSelection(); + if (start) { + selection.setPosition(this.#anchorNode, this.#anchorOffset); + } else { + selection.setPosition(this.#focusNode, this.#focusOffset); + } + } + select() { + super.select(); + if (!this.#outlineId) { + return; + } + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: false, + selected: true + } + }); + } + unselect() { + super.unselect(); + if (!this.#outlineId) { + return; + } + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + selected: false + } + }); + if (!this.#isFreeHighlight) { + this.#setCaret(false); + } + } + get _mustFixPosition() { + return !this.#isFreeHighlight; + } + show(visible = this._isVisible) { + super.show(visible); + if (this.parent) { + this.parent.drawLayer.updateProperties(this.#id, { + rootClass: { + hidden: !visible + } + }); + this.parent.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hidden: !visible + } + }); + } + } + #getRotation() { + return this.#isFreeHighlight ? this.rotation : 0; + } + #serializeBoxes() { + if (this.#isFreeHighlight) { + return null; + } + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + const boxes = this.#boxes; + const quadPoints = new Float32Array(boxes.length * 8); + let i = 0; + for (const { + x, + y, + width, + height + } of boxes) { + const sx = x * pageWidth + pageX; + const sy = (1 - y) * pageHeight + pageY; + quadPoints[i] = quadPoints[i + 4] = sx; + quadPoints[i + 1] = quadPoints[i + 3] = sy; + quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth; + quadPoints[i + 5] = quadPoints[i + 7] = sy - height * pageHeight; + i += 8; + } + return quadPoints; + } + #serializeOutlines(rect) { + return this.#highlightOutlines.serialize(rect, this.#getRotation()); + } + static startHighlighting(parent, isLTR, { + target: textLayer, + x, + y + }) { + const { + x: layerX, + y: layerY, + width: parentWidth, + height: parentHeight + } = textLayer.getBoundingClientRect(); + const ac = new AbortController(); + const signal = parent.combinedSignal(ac); + const pointerUpCallback = e => { + ac.abort(); + this.#endHighlight(parent, e); + }; + window.addEventListener("blur", pointerUpCallback, { + signal + }); + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("pointerdown", stopEvent, { + capture: true, + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + textLayer.addEventListener("pointermove", this.#highlightMove.bind(this, parent), { + signal + }); + this._freeHighlight = new FreeHighlightOutliner({ + x, + y + }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 0.001); + ({ + id: this._freeHighlightId, + clipPathId: this._freeHighlightClipId + } = parent.drawLayer.draw({ + bbox: [0, 0, 1, 1], + root: { + viewBox: "0 0 1 1", + fill: this._defaultColor, + "fill-opacity": this._defaultOpacity + }, + rootClass: { + highlight: true, + free: true + }, + path: { + d: this._freeHighlight.toSVGPath() + } + }, true, true)); + } + static #highlightMove(parent, event) { + if (this._freeHighlight.add(event)) { + parent.drawLayer.updateProperties(this._freeHighlightId, { + path: { + d: this._freeHighlight.toSVGPath() + } + }); + } + } + static #endHighlight(parent, event) { + if (!this._freeHighlight.isEmpty()) { + parent.createAndAddNewEditor(event, false, { + highlightId: this._freeHighlightId, + highlightOutlines: this._freeHighlight.getOutlines(), + clipPathId: this._freeHighlightClipId, + methodOfCreation: "main_toolbar" + }); + } else { + parent.drawLayer.remove(this._freeHighlightId); + } + this._freeHighlightId = -1; + this._freeHighlight = null; + this._freeHighlightClipId = ""; + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof HighlightAnnotationElement) { + const { + data: { + quadPoints, + rect, + rotation, + id, + color, + opacity, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.HIGHLIGHT, + color: Array.from(color), + opacity, + quadPoints, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } else if (data instanceof InkAnnotationElement) { + const { + data: { + inkLists, + rect, + rotation, + id, + color, + borderStyle: { + rawWidth: thickness + }, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.HIGHLIGHT, + color: Array.from(color), + thickness, + inkLists, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const { + color, + quadPoints, + inkLists, + opacity + } = data; + const editor = await super.deserialize(data, parent, uiManager); + editor.color = Util.makeHexColor(...color); + editor.opacity = opacity || 1; + if (inkLists) { + editor.#thickness = data.thickness; + } + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + const [pageWidth, pageHeight] = editor.pageDimensions; + const [pageX, pageY] = editor.pageTranslation; + if (quadPoints) { + const boxes = editor.#boxes = []; + for (let i = 0; i < quadPoints.length; i += 8) { + boxes.push({ + x: (quadPoints[i] - pageX) / pageWidth, + y: 1 - (quadPoints[i + 1] - pageY) / pageHeight, + width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth, + height: (quadPoints[i + 1] - quadPoints[i + 5]) / pageHeight + }); + } + editor.#createOutlines(); + editor.#addToDrawLayer(); + editor.rotate(editor.rotation); + } else if (inkLists) { + editor.#isFreeHighlight = true; + const points = inkLists[0]; + const point = { + x: points[0] - pageX, + y: pageHeight - (points[1] - pageY) + }; + const outliner = new FreeHighlightOutliner(point, [0, 0, pageWidth, pageHeight], 1, editor.#thickness / 2, true, 0.001); + for (let i = 0, ii = points.length; i < ii; i += 2) { + point.x = points[i] - pageX; + point.y = pageHeight - (points[i + 1] - pageY); + outliner.add(point); + } + const { + id, + clipPathId + } = parent.drawLayer.draw({ + bbox: [0, 0, 1, 1], + root: { + viewBox: "0 0 1 1", + fill: editor.color, + "fill-opacity": editor._defaultOpacity + }, + rootClass: { + highlight: true, + free: true + }, + path: { + d: outliner.toSVGPath() + } + }, true, true); + editor.#createFreeOutlines({ + highlightOutlines: outliner.getOutlines(), + highlightId: id, + clipPathId + }); + editor.#addToDrawLayer(); + editor.rotate(editor.parentRotation); + } + return editor; + } + serialize(isForCopying = false) { + if (this.isEmpty() || isForCopying) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const color = AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color)); + const serialized = super.serialize(isForCopying); + Object.assign(serialized, { + color, + opacity: this.opacity, + thickness: this.#thickness, + quadPoints: this.#serializeBoxes(), + outlines: this.#serializeOutlines(serialized.rect) + }); + this.addComment(serialized); + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + color + } = this._initialData; + return this.hasEditedComment || serialized.color.some((c, i) => c !== color[i]); + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + return null; + } + static canCreateNewEmptyEditor() { + return false; + } +} + +;// ./src/display/editor/draw.js + + + + +class DrawingOptions { + #svgProperties = Object.create(null); + updateProperty(name, value) { + this[name] = value; + this.updateSVGProperty(name, value); + } + updateProperties(properties) { + if (!properties) { + return; + } + for (const [name, value] of Object.entries(properties)) { + if (!name.startsWith("_")) { + this.updateProperty(name, value); + } + } + } + updateSVGProperty(name, value) { + this.#svgProperties[name] = value; + } + toSVGProperties() { + const root = this.#svgProperties; + this.#svgProperties = Object.create(null); + return { + root + }; + } + reset() { + this.#svgProperties = Object.create(null); + } + updateAll(options = this) { + this.updateProperties(options); + } + clone() { + unreachable("Not implemented"); + } +} +class DrawingEditor extends AnnotationEditor { + #drawOutlines = null; + #mustBeCommitted; + _colorPicker = null; + _drawId = null; + static _currentDrawId = -1; + static _currentParent = null; + static #currentDraw = null; + static #currentDrawingAC = null; + static #currentDrawingOptions = null; + static _INNER_MARGIN = 3; + constructor(params) { + super(params); + this.#mustBeCommitted = params.mustBeCommitted || false; + this._addOutlines(params); + } + onUpdatedColor() { + this._colorPicker?.update(this.color); + super.onUpdatedColor(); + } + _addOutlines(params) { + if (params.drawOutlines) { + this.#createDrawOutlines(params); + this.#addToDrawLayer(); + } + } + #createDrawOutlines({ + drawOutlines, + drawId, + drawingOptions + }) { + this.#drawOutlines = drawOutlines; + this._drawingOptions ||= drawingOptions; + if (!this.annotationElementId) { + this._uiManager.a11yAlert(`pdfjs-editor-${this.editorType}-added-alert`); + } + if (drawId >= 0) { + this._drawId = drawId; + this.parent.drawLayer.finalizeDraw(drawId, drawOutlines.defaultProperties); + } else { + this._drawId = this.#createDrawing(drawOutlines, this.parent); + } + this.#updateBbox(drawOutlines.box); + } + #createDrawing(drawOutlines, parent) { + const { + id + } = parent.drawLayer.draw(DrawingEditor._mergeSVGProperties(this._drawingOptions.toSVGProperties(), drawOutlines.defaultSVGProperties), false, false); + return id; + } + static _mergeSVGProperties(p1, p2) { + const p1Keys = new Set(Object.keys(p1)); + for (const [key, value] of Object.entries(p2)) { + if (p1Keys.has(key)) { + Object.assign(p1[key], value); + } else { + p1[key] = value; + } + } + return p1; + } + static getDefaultDrawingOptions(_options) { + unreachable("Not implemented"); + } + static get typesMap() { + unreachable("Not implemented"); + } + static get isDrawer() { + return true; + } + static get supportMultipleDrawings() { + return false; + } + static updateDefaultParams(type, value) { + const propertyName = this.typesMap.get(type); + if (propertyName) { + this._defaultDrawingOptions.updateProperty(propertyName, value); + } + if (this._currentParent) { + DrawingEditor.#currentDraw.updateProperty(propertyName, value); + this._currentParent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties()); + } + } + updateParams(type, value) { + const propertyName = this.constructor.typesMap.get(type); + if (propertyName) { + this._updateProperty(type, propertyName, value); + } + } + static get defaultPropertiesToUpdate() { + const properties = []; + const options = this._defaultDrawingOptions; + for (const [type, name] of this.typesMap) { + properties.push([type, options[name]]); + } + return properties; + } + get propertiesToUpdate() { + const properties = []; + const { + _drawingOptions + } = this; + for (const [type, name] of this.constructor.typesMap) { + properties.push([type, _drawingOptions[name]]); + } + return properties; + } + _updateProperty(type, name, value) { + const options = this._drawingOptions; + const savedValue = options[name]; + const setter = val => { + options.updateProperty(name, val); + const bbox = this.#drawOutlines.updateProperty(name, val); + if (bbox) { + this.#updateBbox(bbox); + } + this.parent?.drawLayer.updateProperties(this._drawId, options.toSVGProperties()); + if (type === this.colorType) { + this.onUpdatedColor(); + } + }; + this.addCommands({ + cmd: setter.bind(this, value), + undo: setter.bind(this, savedValue), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type, + overwriteIfSameType: true, + keepUndo: true + }); + } + _onResizing() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizingSVGProperties(this.#convertToDrawSpace()), { + bbox: this.#rotateBox() + })); + } + _onResized() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizedSVGProperties(this.#convertToDrawSpace()), { + bbox: this.#rotateBox() + })); + } + _onTranslating(_x, _y) { + this.parent?.drawLayer.updateProperties(this._drawId, { + bbox: this.#rotateBox() + }); + } + _onTranslated() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathTranslatedSVGProperties(this.#convertToDrawSpace(), this.parentDimensions), { + bbox: this.#rotateBox() + })); + } + _onStartDragging() { + this.parent?.drawLayer.updateProperties(this._drawId, { + rootClass: { + moving: true + } + }); + } + _onStopDragging() { + this.parent?.drawLayer.updateProperties(this._drawId, { + rootClass: { + moving: false + } + }); + } + commit() { + super.commit(); + this.disableEditMode(); + this.disableEditing(); + } + disableEditing() { + super.disableEditing(); + this.div.classList.toggle("disabled", true); + } + enableEditing() { + super.enableEditing(); + this.div.classList.toggle("disabled", false); + } + getBaseTranslation() { + return [0, 0]; + } + get isResizable() { + return true; + } + onceAdded(focus) { + if (!this.annotationElementId) { + this.parent.addUndoableEditor(this); + } + this._isDraggable = true; + if (this.#mustBeCommitted) { + this.#mustBeCommitted = false; + this.commit(); + this.parent.setSelected(this); + if (focus && this.isOnScreen) { + this.div.focus(); + } + } + } + remove() { + this.#cleanDrawLayer(); + super.remove(); + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + this.#addToDrawLayer(); + this.#updateBbox(this.#drawOutlines.box); + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + setParent(parent) { + let mustBeSelected = false; + if (this.parent && !parent) { + this._uiManager.removeShouldRescale(this); + this.#cleanDrawLayer(); + } else if (parent) { + this._uiManager.addShouldRescale(this); + this.#addToDrawLayer(parent); + mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor"); + } + super.setParent(parent); + if (mustBeSelected) { + this.select(); + } + } + #cleanDrawLayer() { + if (this._drawId === null || !this.parent) { + return; + } + this.parent.drawLayer.remove(this._drawId); + this._drawId = null; + this._drawingOptions.reset(); + } + #addToDrawLayer(parent = this.parent) { + if (this._drawId !== null && this.parent === parent) { + return; + } + if (this._drawId !== null) { + this.parent.drawLayer.updateParent(this._drawId, parent.drawLayer); + return; + } + this._drawingOptions.updateAll(); + this._drawId = this.#createDrawing(this.#drawOutlines, parent); + } + #convertToParentSpace([x, y, width, height]) { + const { + parentDimensions: [pW, pH], + rotation + } = this; + switch (rotation) { + case 90: + return [y, 1 - x, width * (pH / pW), height * (pW / pH)]; + case 180: + return [1 - x, 1 - y, width, height]; + case 270: + return [1 - y, x, width * (pH / pW), height * (pW / pH)]; + default: + return [x, y, width, height]; + } + } + #convertToDrawSpace() { + const { + x, + y, + width, + height, + parentDimensions: [pW, pH], + rotation + } = this; + switch (rotation) { + case 90: + return [1 - y, x, width * (pW / pH), height * (pH / pW)]; + case 180: + return [1 - x, 1 - y, width, height]; + case 270: + return [y, 1 - x, width * (pW / pH), height * (pH / pW)]; + default: + return [x, y, width, height]; + } + } + #updateBbox(bbox) { + [this.x, this.y, this.width, this.height] = this.#convertToParentSpace(bbox); + if (this.div) { + this.fixAndSetPosition(); + this.setDims(); + } + this._onResized(); + } + #rotateBox() { + const { + x, + y, + width, + height, + rotation, + parentRotation, + parentDimensions: [pW, pH] + } = this; + switch ((rotation * 4 + parentRotation) / 90) { + case 1: + return [1 - y - height, x, height, width]; + case 2: + return [1 - x - width, 1 - y - height, width, height]; + case 3: + return [y, 1 - x - width, height, width]; + case 4: + return [x, y - width * (pW / pH), height * (pH / pW), width * (pW / pH)]; + case 5: + return [1 - y, x, width * (pW / pH), height * (pH / pW)]; + case 6: + return [1 - x - height * (pH / pW), 1 - y, height * (pH / pW), width * (pW / pH)]; + case 7: + return [y - width * (pW / pH), 1 - x - height * (pH / pW), width * (pW / pH), height * (pH / pW)]; + case 8: + return [x - width, y - height, width, height]; + case 9: + return [1 - y, x - width, height, width]; + case 10: + return [1 - x, 1 - y, width, height]; + case 11: + return [y - height, 1 - x, height, width]; + case 12: + return [x - height * (pH / pW), y, height * (pH / pW), width * (pW / pH)]; + case 13: + return [1 - y - width * (pW / pH), x - height * (pH / pW), width * (pW / pH), height * (pH / pW)]; + case 14: + return [1 - x, 1 - y - width * (pW / pH), height * (pH / pW), width * (pW / pH)]; + case 15: + return [y, 1 - x, width * (pW / pH), height * (pH / pW)]; + default: + return [x, y, width, height]; + } + } + rotate() { + if (!this.parent) { + return; + } + this.parent.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties({ + bbox: this.#rotateBox() + }, this.#drawOutlines.updateRotation((this.parentRotation - this.rotation + 360) % 360))); + } + onScaleChanging() { + if (!this.parent) { + return; + } + this.#updateBbox(this.#drawOutlines.updateParentDimensions(this.parentDimensions, this.parent.scale)); + } + static onScaleChangingWhenDrawing() {} + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy) { + baseX = this.x; + baseY = this.y; + } + const div = super.render(); + div.classList.add("draw"); + const drawDiv = document.createElement("div"); + div.append(drawDiv); + drawDiv.setAttribute("aria-hidden", "true"); + drawDiv.className = "internal"; + this.setDims(); + this._uiManager.addShouldRescale(this); + this.disableEditing(); + if (this._isCopy) { + this._moveAfterPaste(baseX, baseY); + } + return div; + } + static createDrawerInstance(_x, _y, _parentWidth, _parentHeight, _rotation) { + unreachable("Not implemented"); + } + static startDrawing(parent, uiManager, _isLTR, event) { + const { + target, + offsetX: x, + offsetY: y, + pointerId, + pointerType + } = event; + if (CurrentPointers.isInitializedAndDifferentPointerType(pointerType)) { + return; + } + const { + viewport: { + rotation + } + } = parent; + const { + width: parentWidth, + height: parentHeight + } = target.getBoundingClientRect(); + const ac = DrawingEditor.#currentDrawingAC = new AbortController(); + const signal = parent.combinedSignal(ac); + CurrentPointers.setPointer(pointerType, pointerId); + window.addEventListener("pointerup", e => { + if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) { + this._endDraw(e); + } + }, { + signal + }); + window.addEventListener("pointercancel", e => { + if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) { + this._currentParent.endDrawingSession(); + } + }, { + signal + }); + window.addEventListener("pointerdown", e => { + if (!CurrentPointers.isSamePointerType(e.pointerType)) { + return; + } + CurrentPointers.initializeAndAddPointerId(e.pointerId); + if (DrawingEditor.#currentDraw.isCancellable()) { + DrawingEditor.#currentDraw.removeLastElement(); + if (DrawingEditor.#currentDraw.isEmpty()) { + this._currentParent.endDrawingSession(true); + } else { + this._endDraw(null); + } + } + }, { + capture: true, + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + target.addEventListener("pointermove", this._drawMove.bind(this), { + signal + }); + target.addEventListener("touchmove", e => { + if (CurrentPointers.isSameTimeStamp(e.timeStamp)) { + stopEvent(e); + } + }, { + signal + }); + parent.toggleDrawing(); + uiManager._editorUndoBar?.hide(); + if (DrawingEditor.#currentDraw) { + parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.startNew(x, y, parentWidth, parentHeight, rotation)); + return; + } + uiManager.updateUIForDefaultProperties(this); + DrawingEditor.#currentDraw = this.createDrawerInstance(x, y, parentWidth, parentHeight, rotation); + DrawingEditor.#currentDrawingOptions = this.getDefaultDrawingOptions(); + this._currentParent = parent; + ({ + id: this._currentDrawId + } = parent.drawLayer.draw(this._mergeSVGProperties(DrawingEditor.#currentDrawingOptions.toSVGProperties(), DrawingEditor.#currentDraw.defaultSVGProperties), true, false)); + } + static _drawMove(event) { + CurrentPointers.isSameTimeStamp(event.timeStamp); + if (!DrawingEditor.#currentDraw) { + return; + } + const { + offsetX, + offsetY, + pointerId + } = event; + if (!CurrentPointers.isSamePointerId(pointerId)) { + return; + } + if (CurrentPointers.isUsingMultiplePointers()) { + this._endDraw(event); + return; + } + this._currentParent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.add(offsetX, offsetY)); + CurrentPointers.setTimeStamp(event.timeStamp); + stopEvent(event); + } + static _cleanup(all) { + if (all) { + this._currentDrawId = -1; + this._currentParent = null; + DrawingEditor.#currentDraw = null; + DrawingEditor.#currentDrawingOptions = null; + CurrentPointers.clearPointerType(); + CurrentPointers.clearTimeStamp(); + } + if (DrawingEditor.#currentDrawingAC) { + DrawingEditor.#currentDrawingAC.abort(); + DrawingEditor.#currentDrawingAC = null; + CurrentPointers.clearPointerIds(); + } + } + static _endDraw(event) { + const parent = this._currentParent; + if (!parent) { + return; + } + parent.toggleDrawing(true); + this._cleanup(false); + if (event?.target === parent.div) { + parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.end(event.offsetX, event.offsetY)); + } + if (this.supportMultipleDrawings) { + const draw = DrawingEditor.#currentDraw; + const drawId = this._currentDrawId; + const lastElement = draw.getLastElement(); + parent.addCommands({ + cmd: () => { + parent.drawLayer.updateProperties(drawId, draw.setLastElement(lastElement)); + }, + undo: () => { + parent.drawLayer.updateProperties(drawId, draw.removeLastElement()); + }, + mustExec: false, + type: AnnotationEditorParamsType.DRAW_STEP + }); + return; + } + this.endDrawing(false); + } + static endDrawing(isAborted) { + const parent = this._currentParent; + if (!parent) { + return null; + } + parent.toggleDrawing(true); + parent.cleanUndoStack(AnnotationEditorParamsType.DRAW_STEP); + if (!DrawingEditor.#currentDraw.isEmpty()) { + const { + pageDimensions: [pageWidth, pageHeight], + scale + } = parent; + const editor = parent.createAndAddNewEditor({ + offsetX: 0, + offsetY: 0 + }, false, { + drawId: this._currentDrawId, + drawOutlines: DrawingEditor.#currentDraw.getOutlines(pageWidth * scale, pageHeight * scale, scale, this._INNER_MARGIN), + drawingOptions: DrawingEditor.#currentDrawingOptions, + mustBeCommitted: !isAborted + }); + this._cleanup(true); + return editor; + } + parent.drawLayer.remove(this._currentDrawId); + this._cleanup(true); + return null; + } + createDrawingOptions(_data) {} + static deserializeDraw(_pageX, _pageY, _pageWidth, _pageHeight, _innerWidth, _data) { + unreachable("Not implemented"); + } + static async deserialize(data, parent, uiManager) { + const { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } = parent.viewport; + const drawOutlines = this.deserializeDraw(pageX, pageY, pageWidth, pageHeight, this._INNER_MARGIN, data); + const editor = await super.deserialize(data, parent, uiManager); + editor.createDrawingOptions(data); + editor.#createDrawOutlines({ + drawOutlines + }); + editor.#addToDrawLayer(); + editor.onScaleChanging(); + editor.rotate(); + return editor; + } + serializeDraw(isForCopying) { + const [pageX, pageY] = this.pageTranslation; + const [pageWidth, pageHeight] = this.pageDimensions; + return this.#drawOutlines.serialize([pageX, pageY, pageWidth, pageHeight], isForCopying); + } + renderAnnotationElement(annotation) { + annotation.updateEdited({ + rect: this.getPDFRect() + }); + return null; + } + static canCreateNewEmptyEditor() { + return false; + } +} + +;// ./src/display/editor/drawers/inkdraw.js + + +class InkDrawOutliner { + #last = new Float64Array(6); + #line; + #lines; + #rotation; + #thickness; + #points; + #lastSVGPath = ""; + #lastIndex = 0; + #outlines = new InkDrawOutline(); + #parentWidth; + #parentHeight; + constructor(x, y, parentWidth, parentHeight, rotation, thickness) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#rotation = rotation; + this.#thickness = thickness; + [x, y] = this.#normalizePoint(x, y); + const line = this.#line = [NaN, NaN, NaN, NaN, x, y]; + this.#points = [x, y]; + this.#lines = [{ + line, + points: this.#points + }]; + this.#last.set(line, 0); + } + updateProperty(name, value) { + if (name === "stroke-width") { + this.#thickness = value; + } + } + #normalizePoint(x, y) { + return Outline._normalizePoint(x, y, this.#parentWidth, this.#parentHeight, this.#rotation); + } + isEmpty() { + return !this.#lines || this.#lines.length === 0; + } + isCancellable() { + return this.#points.length <= 10; + } + add(x, y) { + [x, y] = this.#normalizePoint(x, y); + const [x1, y1, x2, y2] = this.#last.subarray(2, 6); + const diffX = x - x2; + const diffY = y - y2; + const d = Math.hypot(this.#parentWidth * diffX, this.#parentHeight * diffY); + if (d <= 2) { + return null; + } + this.#points.push(x, y); + if (isNaN(x1)) { + this.#last.set([x2, y2, x, y], 2); + this.#line.push(NaN, NaN, NaN, NaN, x, y); + return { + path: { + d: this.toSVGPath() + } + }; + } + if (isNaN(this.#last[0])) { + this.#line.splice(6, 6); + } + this.#last.set([x1, y1, x2, y2, x, y], 0); + this.#line.push(...Outline.createBezierPoints(x1, y1, x2, y2, x, y)); + return { + path: { + d: this.toSVGPath() + } + }; + } + end(x, y) { + const change = this.add(x, y); + if (change) { + return change; + } + if (this.#points.length === 2) { + return { + path: { + d: this.toSVGPath() + } + }; + } + return null; + } + startNew(x, y, parentWidth, parentHeight, rotation) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#rotation = rotation; + [x, y] = this.#normalizePoint(x, y); + const line = this.#line = [NaN, NaN, NaN, NaN, x, y]; + this.#points = [x, y]; + const last = this.#lines.at(-1); + if (last) { + last.line = new Float32Array(last.line); + last.points = new Float32Array(last.points); + } + this.#lines.push({ + line, + points: this.#points + }); + this.#last.set(line, 0); + this.#lastIndex = 0; + this.toSVGPath(); + return null; + } + getLastElement() { + return this.#lines.at(-1); + } + setLastElement(element) { + if (!this.#lines) { + return this.#outlines.setLastElement(element); + } + this.#lines.push(element); + this.#line = element.line; + this.#points = element.points; + this.#lastIndex = 0; + return { + path: { + d: this.toSVGPath() + } + }; + } + removeLastElement() { + if (!this.#lines) { + return this.#outlines.removeLastElement(); + } + this.#lines.pop(); + this.#lastSVGPath = ""; + for (let i = 0, ii = this.#lines.length; i < ii; i++) { + const { + line, + points + } = this.#lines[i]; + this.#line = line; + this.#points = points; + this.#lastIndex = 0; + this.toSVGPath(); + } + return { + path: { + d: this.#lastSVGPath + } + }; + } + toSVGPath() { + const firstX = Outline.svgRound(this.#line[4]); + const firstY = Outline.svgRound(this.#line[5]); + if (this.#points.length === 2) { + this.#lastSVGPath = `${this.#lastSVGPath} M ${firstX} ${firstY} Z`; + return this.#lastSVGPath; + } + if (this.#points.length <= 6) { + const i = this.#lastSVGPath.lastIndexOf("M"); + this.#lastSVGPath = `${this.#lastSVGPath.slice(0, i)} M ${firstX} ${firstY}`; + this.#lastIndex = 6; + } + if (this.#points.length === 4) { + const secondX = Outline.svgRound(this.#line[10]); + const secondY = Outline.svgRound(this.#line[11]); + this.#lastSVGPath = `${this.#lastSVGPath} L ${secondX} ${secondY}`; + this.#lastIndex = 12; + return this.#lastSVGPath; + } + const buffer = []; + if (this.#lastIndex === 0) { + buffer.push(`M ${firstX} ${firstY}`); + this.#lastIndex = 6; + } + for (let i = this.#lastIndex, ii = this.#line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = this.#line.slice(i, i + 6).map(Outline.svgRound); + buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`); + } + this.#lastSVGPath += buffer.join(" "); + this.#lastIndex = this.#line.length; + return this.#lastSVGPath; + } + getOutlines(parentWidth, parentHeight, scale, innerMargin) { + const last = this.#lines.at(-1); + last.line = new Float32Array(last.line); + last.points = new Float32Array(last.points); + this.#outlines.build(this.#lines, parentWidth, parentHeight, scale, this.#rotation, this.#thickness, innerMargin); + this.#last = null; + this.#line = null; + this.#lines = null; + this.#lastSVGPath = null; + return this.#outlines; + } + get defaultSVGProperties() { + return { + root: { + viewBox: "0 0 10000 10000" + }, + rootClass: { + draw: true + }, + bbox: [0, 0, 1, 1] + }; + } +} +class InkDrawOutline extends Outline { + #bbox; + #currentRotation = 0; + #innerMargin; + #lines; + #parentWidth; + #parentHeight; + #parentScale; + #rotation; + #thickness; + build(lines, parentWidth, parentHeight, parentScale, rotation, thickness, innerMargin) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#parentScale = parentScale; + this.#rotation = rotation; + this.#thickness = thickness; + this.#innerMargin = innerMargin ?? 0; + this.#lines = lines; + this.#computeBbox(); + } + get thickness() { + return this.#thickness; + } + setLastElement(element) { + this.#lines.push(element); + return { + path: { + d: this.toSVGPath() + } + }; + } + removeLastElement() { + this.#lines.pop(); + return { + path: { + d: this.toSVGPath() + } + }; + } + toSVGPath() { + const buffer = []; + for (const { + line + } of this.#lines) { + buffer.push(`M${Outline.svgRound(line[4])} ${Outline.svgRound(line[5])}`); + if (line.length === 6) { + buffer.push("Z"); + continue; + } + if (line.length === 12 && isNaN(line[6])) { + buffer.push(`L${Outline.svgRound(line[10])} ${Outline.svgRound(line[11])}`); + continue; + } + for (let i = 6, ii = line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6).map(Outline.svgRound); + buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`); + } + } + return buffer.join(""); + } + serialize([pageX, pageY, pageWidth, pageHeight], isForCopying) { + const serializedLines = []; + const serializedPoints = []; + const [x, y, width, height] = this.#getBBoxWithNoMargin(); + let tx, ty, sx, sy, x1, y1, x2, y2, rescaleFn; + switch (this.#rotation) { + case 0: + rescaleFn = Outline._rescale; + tx = pageX; + ty = pageY + pageHeight; + sx = pageWidth; + sy = -pageHeight; + x1 = pageX + x * pageWidth; + y1 = pageY + (1 - y - height) * pageHeight; + x2 = pageX + (x + width) * pageWidth; + y2 = pageY + (1 - y) * pageHeight; + break; + case 90: + rescaleFn = Outline._rescaleAndSwap; + tx = pageX; + ty = pageY; + sx = pageWidth; + sy = pageHeight; + x1 = pageX + y * pageWidth; + y1 = pageY + x * pageHeight; + x2 = pageX + (y + height) * pageWidth; + y2 = pageY + (x + width) * pageHeight; + break; + case 180: + rescaleFn = Outline._rescale; + tx = pageX + pageWidth; + ty = pageY; + sx = -pageWidth; + sy = pageHeight; + x1 = pageX + (1 - x - width) * pageWidth; + y1 = pageY + y * pageHeight; + x2 = pageX + (1 - x) * pageWidth; + y2 = pageY + (y + height) * pageHeight; + break; + case 270: + rescaleFn = Outline._rescaleAndSwap; + tx = pageX + pageWidth; + ty = pageY + pageHeight; + sx = -pageWidth; + sy = -pageHeight; + x1 = pageX + (1 - y - height) * pageWidth; + y1 = pageY + (1 - x - width) * pageHeight; + x2 = pageX + (1 - y) * pageWidth; + y2 = pageY + (1 - x) * pageHeight; + break; + } + for (const { + line, + points + } of this.#lines) { + serializedLines.push(rescaleFn(line, tx, ty, sx, sy, isForCopying ? new Array(line.length) : null)); + serializedPoints.push(rescaleFn(points, tx, ty, sx, sy, isForCopying ? new Array(points.length) : null)); + } + return { + lines: serializedLines, + points: serializedPoints, + rect: [x1, y1, x2, y2] + }; + } + static deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, { + paths: { + lines, + points + }, + rotation, + thickness + }) { + const newLines = []; + let tx, ty, sx, sy, rescaleFn; + switch (rotation) { + case 0: + rescaleFn = Outline._rescale; + tx = -pageX / pageWidth; + ty = pageY / pageHeight + 1; + sx = 1 / pageWidth; + sy = -1 / pageHeight; + break; + case 90: + rescaleFn = Outline._rescaleAndSwap; + tx = -pageY / pageHeight; + ty = -pageX / pageWidth; + sx = 1 / pageHeight; + sy = 1 / pageWidth; + break; + case 180: + rescaleFn = Outline._rescale; + tx = pageX / pageWidth + 1; + ty = -pageY / pageHeight; + sx = -1 / pageWidth; + sy = 1 / pageHeight; + break; + case 270: + rescaleFn = Outline._rescaleAndSwap; + tx = pageY / pageHeight + 1; + ty = pageX / pageWidth + 1; + sx = -1 / pageHeight; + sy = -1 / pageWidth; + break; + } + if (!lines) { + lines = []; + for (const point of points) { + const len = point.length; + if (len === 2) { + lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1]])); + continue; + } + if (len === 4) { + lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1], NaN, NaN, NaN, NaN, point[2], point[3]])); + continue; + } + const line = new Float32Array(3 * (len - 2)); + lines.push(line); + let [x1, y1, x2, y2] = point.subarray(0, 4); + line.set([NaN, NaN, NaN, NaN, x1, y1], 0); + for (let i = 4; i < len; i += 2) { + const x = point[i]; + const y = point[i + 1]; + line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3); + [x1, y1, x2, y2] = [x2, y2, x, y]; + } + } + } + for (let i = 0, ii = lines.length; i < ii; i++) { + newLines.push({ + line: rescaleFn(lines[i].map(x => x ?? NaN), tx, ty, sx, sy), + points: rescaleFn(points[i].map(x => x ?? NaN), tx, ty, sx, sy) + }); + } + const outlines = new this.prototype.constructor(); + outlines.build(newLines, pageWidth, pageHeight, 1, rotation, thickness, innerMargin); + return outlines; + } + #getMarginComponents(thickness = this.#thickness) { + const margin = this.#innerMargin + thickness / 2 * this.#parentScale; + return this.#rotation % 180 === 0 ? [margin / this.#parentWidth, margin / this.#parentHeight] : [margin / this.#parentHeight, margin / this.#parentWidth]; + } + #getBBoxWithNoMargin() { + const [x, y, width, height] = this.#bbox; + const [marginX, marginY] = this.#getMarginComponents(0); + return [x + marginX, y + marginY, width - 2 * marginX, height - 2 * marginY]; + } + #computeBbox() { + const bbox = this.#bbox = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + for (const { + line + } of this.#lines) { + if (line.length <= 12) { + for (let i = 4, ii = line.length; i < ii; i += 6) { + Util.pointBoundingBox(line[i], line[i + 1], bbox); + } + continue; + } + let lastX = line[4], + lastY = line[5]; + for (let i = 6, ii = line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6); + Util.bezierBoundingBox(lastX, lastY, c1x, c1y, c2x, c2y, x, y, bbox); + lastX = x; + lastY = y; + } + } + const [marginX, marginY] = this.#getMarginComponents(); + bbox[0] = MathClamp(bbox[0] - marginX, 0, 1); + bbox[1] = MathClamp(bbox[1] - marginY, 0, 1); + bbox[2] = MathClamp(bbox[2] + marginX, 0, 1); + bbox[3] = MathClamp(bbox[3] + marginY, 0, 1); + bbox[2] -= bbox[0]; + bbox[3] -= bbox[1]; + } + get box() { + return this.#bbox; + } + updateProperty(name, value) { + if (name === "stroke-width") { + return this.#updateThickness(value); + } + return null; + } + #updateThickness(thickness) { + const [oldMarginX, oldMarginY] = this.#getMarginComponents(); + this.#thickness = thickness; + const [newMarginX, newMarginY] = this.#getMarginComponents(); + const [diffMarginX, diffMarginY] = [newMarginX - oldMarginX, newMarginY - oldMarginY]; + const bbox = this.#bbox; + bbox[0] -= diffMarginX; + bbox[1] -= diffMarginY; + bbox[2] += 2 * diffMarginX; + bbox[3] += 2 * diffMarginY; + return bbox; + } + updateParentDimensions([width, height], scale) { + const [oldMarginX, oldMarginY] = this.#getMarginComponents(); + this.#parentWidth = width; + this.#parentHeight = height; + this.#parentScale = scale; + const [newMarginX, newMarginY] = this.#getMarginComponents(); + const diffMarginX = newMarginX - oldMarginX; + const diffMarginY = newMarginY - oldMarginY; + const bbox = this.#bbox; + bbox[0] -= diffMarginX; + bbox[1] -= diffMarginY; + bbox[2] += 2 * diffMarginX; + bbox[3] += 2 * diffMarginY; + return bbox; + } + updateRotation(rotation) { + this.#currentRotation = rotation; + return { + path: { + transform: this.rotationTransform + } + }; + } + get viewBox() { + return this.#bbox.map(Outline.svgRound).join(" "); + } + get defaultProperties() { + const [x, y] = this.#bbox; + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}` + } + }; + } + get rotationTransform() { + const [,, width, height] = this.#bbox; + let a = 0, + b = 0, + c = 0, + d = 0, + e = 0, + f = 0; + switch (this.#currentRotation) { + case 90: + b = height / width; + c = -width / height; + e = width; + break; + case 180: + a = -1; + d = -1; + e = width; + f = height; + break; + case 270: + b = -height / width; + c = width / height; + f = height; + break; + default: + return ""; + } + return `matrix(${a} ${b} ${c} ${d} ${Outline.svgRound(e)} ${Outline.svgRound(f)})`; + } + getPathResizingSVGProperties([newX, newY, newWidth, newHeight]) { + const [marginX, marginY] = this.#getMarginComponents(); + const [x, y, width, height] = this.#bbox; + if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) { + const tx = newX + newWidth / 2 - (x + width / 2); + const ty = newY + newHeight / 2 - (y + height / 2); + return { + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: `${this.rotationTransform} translate(${tx} ${ty})` + } + }; + } + const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX); + const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY); + const s2x = width / newWidth; + const s2y = height / newHeight; + return { + path: { + "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}`, + transform: `${this.rotationTransform} scale(${s2x} ${s2y}) ` + `translate(${Outline.svgRound(marginX)} ${Outline.svgRound(marginY)}) scale(${s1x} ${s1y}) ` + `translate(${Outline.svgRound(-marginX)} ${Outline.svgRound(-marginY)})` + } + }; + } + getPathResizedSVGProperties([newX, newY, newWidth, newHeight]) { + const [marginX, marginY] = this.#getMarginComponents(); + const bbox = this.#bbox; + const [x, y, width, height] = bbox; + bbox[0] = newX; + bbox[1] = newY; + bbox[2] = newWidth; + bbox[3] = newHeight; + if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) { + const tx = newX + newWidth / 2 - (x + width / 2); + const ty = newY + newHeight / 2 - (y + height / 2); + for (const { + line, + points + } of this.#lines) { + Outline._translate(line, tx, ty, line); + Outline._translate(points, tx, ty, points); + } + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: this.rotationTransform || null, + d: this.toSVGPath() + } + }; + } + const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX); + const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY); + const tx = -s1x * (x + marginX) + newX + marginX; + const ty = -s1y * (y + marginY) + newY + marginY; + if (s1x !== 1 || s1y !== 1 || tx !== 0 || ty !== 0) { + for (const { + line, + points + } of this.#lines) { + Outline._rescale(line, tx, ty, s1x, s1y, line); + Outline._rescale(points, tx, ty, s1x, s1y, points); + } + } + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: this.rotationTransform || null, + d: this.toSVGPath() + } + }; + } + getPathTranslatedSVGProperties([newX, newY], parentDimensions) { + const [newParentWidth, newParentHeight] = parentDimensions; + const bbox = this.#bbox; + const tx = newX - bbox[0]; + const ty = newY - bbox[1]; + if (this.#parentWidth === newParentWidth && this.#parentHeight === newParentHeight) { + for (const { + line, + points + } of this.#lines) { + Outline._translate(line, tx, ty, line); + Outline._translate(points, tx, ty, points); + } + } else { + const sx = this.#parentWidth / newParentWidth; + const sy = this.#parentHeight / newParentHeight; + this.#parentWidth = newParentWidth; + this.#parentHeight = newParentHeight; + for (const { + line, + points + } of this.#lines) { + Outline._rescale(line, tx, ty, sx, sy, line); + Outline._rescale(points, tx, ty, sx, sy, points); + } + bbox[2] *= sx; + bbox[3] *= sy; + } + bbox[0] = newX; + bbox[1] = newY; + return { + root: { + viewBox: this.viewBox + }, + path: { + d: this.toSVGPath(), + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}` + } + }; + } + get defaultSVGProperties() { + const bbox = this.#bbox; + return { + root: { + viewBox: this.viewBox + }, + rootClass: { + draw: true + }, + path: { + d: this.toSVGPath(), + "transform-origin": `${Outline.svgRound(bbox[0])} ${Outline.svgRound(bbox[1])}`, + transform: this.rotationTransform || null + }, + bbox + }; + } +} + +;// ./src/display/editor/ink.js + + + + + + +class InkDrawingOptions extends DrawingOptions { + constructor(viewerParameters) { + super(); + this._viewParameters = viewerParameters; + super.updateProperties({ + fill: "none", + stroke: AnnotationEditor._defaultLineColor, + "stroke-opacity": 1, + "stroke-width": 1, + "stroke-linecap": "round", + "stroke-linejoin": "round", + "stroke-miterlimit": 10 + }); + } + updateSVGProperty(name, value) { + if (name === "stroke-width") { + value ??= this["stroke-width"]; + value *= this._viewParameters.realScale; + } + super.updateSVGProperty(name, value); + } + clone() { + const clone = new InkDrawingOptions(this._viewParameters); + clone.updateAll(this); + return clone; + } +} +class InkEditor extends DrawingEditor { + static _type = "ink"; + static _editorType = AnnotationEditorType.INK; + static _defaultDrawingOptions = null; + constructor(params) { + super({ + ...params, + name: "inkEditor" + }); + this._willKeepAspectRatio = true; + this.defaultL10nId = "pdfjs-editor-ink-editor"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + this._defaultDrawingOptions = new InkDrawingOptions(uiManager.viewParameters); + } + static getDefaultDrawingOptions(options) { + const clone = this._defaultDrawingOptions.clone(); + clone.updateProperties(options); + return clone; + } + static get supportMultipleDrawings() { + return true; + } + static get typesMap() { + return shadow(this, "typesMap", new Map([[AnnotationEditorParamsType.INK_THICKNESS, "stroke-width"], [AnnotationEditorParamsType.INK_COLOR, "stroke"], [AnnotationEditorParamsType.INK_OPACITY, "stroke-opacity"]])); + } + static createDrawerInstance(x, y, parentWidth, parentHeight, rotation) { + return new InkDrawOutliner(x, y, parentWidth, parentHeight, rotation, this._defaultDrawingOptions["stroke-width"]); + } + static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) { + return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof InkAnnotationElement) { + const { + data: { + inkLists, + rect, + rotation, + id, + color, + opacity, + borderStyle: { + rawWidth: thickness + }, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.INK, + color: Array.from(color), + thickness, + opacity, + paths: { + points: inkLists + }, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + return editor; + } + get toolbarButtons() { + this._colorPicker ||= new BasicColorPicker(this); + return [["colorPicker", this._colorPicker]]; + } + get colorType() { + return AnnotationEditorParamsType.INK_COLOR; + } + get color() { + return this._drawingOptions.stroke; + } + get opacity() { + return this._drawingOptions["stroke-opacity"]; + } + onScaleChanging() { + if (!this.parent) { + return; + } + super.onScaleChanging(); + const { + _drawId, + _drawingOptions, + parent + } = this; + _drawingOptions.updateSVGProperty("stroke-width"); + parent.drawLayer.updateProperties(_drawId, _drawingOptions.toSVGProperties()); + } + static onScaleChangingWhenDrawing() { + const parent = this._currentParent; + if (!parent) { + return; + } + super.onScaleChangingWhenDrawing(); + this._defaultDrawingOptions.updateSVGProperty("stroke-width"); + parent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties()); + } + createDrawingOptions({ + color, + thickness, + opacity + }) { + this._drawingOptions = InkEditor.getDefaultDrawingOptions({ + stroke: Util.makeHexColor(...color), + "stroke-width": thickness, + "stroke-opacity": opacity + }); + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const { + lines, + points + } = this.serializeDraw(isForCopying); + const { + _drawingOptions: { + stroke, + "stroke-opacity": opacity, + "stroke-width": thickness + } + } = this; + const serialized = Object.assign(super.serialize(isForCopying), { + color: AnnotationEditor._colorManager.convert(stroke), + opacity, + thickness, + paths: { + lines, + points + } + }); + this.addComment(serialized); + if (isForCopying) { + serialized.isCopy = true; + return serialized; + } + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + color, + thickness, + opacity, + pageIndex + } = this._initialData; + return this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized || serialized.color.some((c, i) => c !== color[i]) || serialized.thickness !== thickness || serialized.opacity !== opacity || serialized.pageIndex !== pageIndex; + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + const { + points, + rect + } = this.serializeDraw(false); + annotation.updateEdited({ + rect, + thickness: this._drawingOptions["stroke-width"], + points, + popup: this.comment + }); + return null; + } +} + +;// ./src/display/editor/drawers/contour.js + +class ContourDrawOutline extends InkDrawOutline { + toSVGPath() { + let path = super.toSVGPath(); + if (!path.endsWith("Z")) { + path += "Z"; + } + return path; + } +} + +;// ./src/display/editor/drawers/signaturedraw.js + + + + +const BASE_HEADER_LENGTH = 8; +const POINTS_PROPERTIES_NUMBER = 3; +class SignatureExtractor { + static #PARAMETERS = { + maxDim: 512, + sigmaSFactor: 0.02, + sigmaR: 25, + kernelSize: 16 + }; + static #neighborIndexToId(i0, j0, i, j) { + i -= i0; + j -= j0; + if (i === 0) { + return j > 0 ? 0 : 4; + } + if (i === 1) { + return j + 6; + } + return 2 - j; + } + static #neighborIdToIndex = new Int32Array([0, 1, -1, 1, -1, 0, -1, -1, 0, -1, 1, -1, 1, 0, 1, 1]); + static #clockwiseNonZero(buf, width, i0, j0, i, j, offset) { + const id = this.#neighborIndexToId(i0, j0, i, j); + for (let k = 0; k < 8; k++) { + const kk = (-k + id - offset + 16) % 8; + const shiftI = this.#neighborIdToIndex[2 * kk]; + const shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) { + return kk; + } + } + return -1; + } + static #counterClockwiseNonZero(buf, width, i0, j0, i, j, offset) { + const id = this.#neighborIndexToId(i0, j0, i, j); + for (let k = 0; k < 8; k++) { + const kk = (k + id + offset + 16) % 8; + const shiftI = this.#neighborIdToIndex[2 * kk]; + const shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) { + return kk; + } + } + return -1; + } + static #findContours(buf, width, height, threshold) { + const N = buf.length; + const types = new Int32Array(N); + for (let i = 0; i < N; i++) { + types[i] = buf[i] <= threshold ? 1 : 0; + } + for (let i = 1; i < height - 1; i++) { + types[i * width] = types[i * width + width - 1] = 0; + } + for (let i = 0; i < width; i++) { + types[i] = types[width * height - 1 - i] = 0; + } + let nbd = 1; + let lnbd; + const contours = []; + for (let i = 1; i < height - 1; i++) { + lnbd = 1; + for (let j = 1; j < width - 1; j++) { + const ij = i * width + j; + const pix = types[ij]; + if (pix === 0) { + continue; + } + let i2 = i; + let j2 = j; + if (pix === 1 && types[ij - 1] === 0) { + nbd += 1; + j2 -= 1; + } else if (pix >= 1 && types[ij + 1] === 0) { + nbd += 1; + j2 += 1; + if (pix > 1) { + lnbd = pix; + } + } else { + if (pix !== 1) { + lnbd = Math.abs(pix); + } + continue; + } + const points = [j, i]; + const isHole = j2 === j + 1; + const contour = { + isHole, + points, + id: nbd, + parent: 0 + }; + contours.push(contour); + let contour0; + for (const c of contours) { + if (c.id === lnbd) { + contour0 = c; + break; + } + } + if (!contour0) { + contour.parent = isHole ? lnbd : 0; + } else if (contour0.isHole) { + contour.parent = isHole ? contour0.parent : lnbd; + } else { + contour.parent = isHole ? lnbd : contour0.parent; + } + const k = this.#clockwiseNonZero(types, width, i, j, i2, j2, 0); + if (k === -1) { + types[ij] = -nbd; + if (types[ij] !== 1) { + lnbd = Math.abs(types[ij]); + } + continue; + } + let shiftI = this.#neighborIdToIndex[2 * k]; + let shiftJ = this.#neighborIdToIndex[2 * k + 1]; + const i1 = i + shiftI; + const j1 = j + shiftJ; + i2 = i1; + j2 = j1; + let i3 = i; + let j3 = j; + while (true) { + const kk = this.#counterClockwiseNonZero(types, width, i3, j3, i2, j2, 1); + shiftI = this.#neighborIdToIndex[2 * kk]; + shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + const i4 = i3 + shiftI; + const j4 = j3 + shiftJ; + points.push(j4, i4); + const ij3 = i3 * width + j3; + if (types[ij3 + 1] === 0) { + types[ij3] = -nbd; + } else if (types[ij3] === 1) { + types[ij3] = nbd; + } + if (i4 === i && j4 === j && i3 === i1 && j3 === j1) { + if (types[ij] !== 1) { + lnbd = Math.abs(types[ij]); + } + break; + } else { + i2 = i3; + j2 = j3; + i3 = i4; + j3 = j4; + } + } + } + } + return contours; + } + static #douglasPeuckerHelper(points, start, end, output) { + if (end - start <= 4) { + for (let i = start; i < end - 2; i += 2) { + output.push(points[i], points[i + 1]); + } + return; + } + const ax = points[start]; + const ay = points[start + 1]; + const abx = points[end - 4] - ax; + const aby = points[end - 3] - ay; + const dist = Math.hypot(abx, aby); + const nabx = abx / dist; + const naby = aby / dist; + const aa = nabx * ay - naby * ax; + const m = aby / abx; + const invS = 1 / dist; + const phi = Math.atan(m); + const cosPhi = Math.cos(phi); + const sinPhi = Math.sin(phi); + const tmax = invS * (Math.abs(cosPhi) + Math.abs(sinPhi)); + const poly = invS * (1 - tmax + tmax ** 2); + const partialPhi = Math.max(Math.atan(Math.abs(sinPhi + cosPhi) * poly), Math.atan(Math.abs(sinPhi - cosPhi) * poly)); + let dmax = 0; + let index = start; + for (let i = start + 2; i < end - 2; i += 2) { + const d = Math.abs(aa - nabx * points[i + 1] + naby * points[i]); + if (d > dmax) { + index = i; + dmax = d; + } + } + if (dmax > (dist * partialPhi) ** 2) { + this.#douglasPeuckerHelper(points, start, index + 2, output); + this.#douglasPeuckerHelper(points, index, end, output); + } else { + output.push(ax, ay); + } + } + static #douglasPeucker(points) { + const output = []; + const len = points.length; + this.#douglasPeuckerHelper(points, 0, len, output); + output.push(points[len - 2], points[len - 1]); + return output.length <= 4 ? null : output; + } + static #bilateralFilter(buf, width, height, sigmaS, sigmaR, kernelSize) { + const kernel = new Float32Array(kernelSize ** 2); + const sigmaS2 = -2 * sigmaS ** 2; + const halfSize = kernelSize >> 1; + for (let i = 0; i < kernelSize; i++) { + const x = (i - halfSize) ** 2; + for (let j = 0; j < kernelSize; j++) { + kernel[i * kernelSize + j] = Math.exp((x + (j - halfSize) ** 2) / sigmaS2); + } + } + const rangeValues = new Float32Array(256); + const sigmaR2 = -2 * sigmaR ** 2; + for (let i = 0; i < 256; i++) { + rangeValues[i] = Math.exp(i ** 2 / sigmaR2); + } + const N = buf.length; + const out = new Uint8Array(N); + const histogram = new Uint32Array(256); + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const ij = i * width + j; + const center = buf[ij]; + let sum = 0; + let norm = 0; + for (let k = 0; k < kernelSize; k++) { + const y = i + k - halfSize; + if (y < 0 || y >= height) { + continue; + } + for (let l = 0; l < kernelSize; l++) { + const x = j + l - halfSize; + if (x < 0 || x >= width) { + continue; + } + const neighbour = buf[y * width + x]; + const w = kernel[k * kernelSize + l] * rangeValues[Math.abs(neighbour - center)]; + sum += neighbour * w; + norm += w; + } + } + const pix = out[ij] = Math.round(sum / norm); + histogram[pix]++; + } + } + return [out, histogram]; + } + static #getHistogram(buf) { + const histogram = new Uint32Array(256); + for (const g of buf) { + histogram[g]++; + } + return histogram; + } + static #toUint8(buf) { + const N = buf.length; + const out = new Uint8ClampedArray(N >> 2); + let max = -Infinity; + let min = Infinity; + for (let i = 0, ii = out.length; i < ii; i++) { + const pix = out[i] = buf[i << 2]; + max = Math.max(max, pix); + min = Math.min(min, pix); + } + const ratio = 255 / (max - min); + for (let i = 0, ii = out.length; i < ii; i++) { + out[i] = (out[i] - min) * ratio; + } + return out; + } + static #guessThreshold(histogram) { + let i; + let M = -Infinity; + let L = -Infinity; + const min = histogram.findIndex(v => v !== 0); + let pos = min; + let spos = min; + for (i = min; i < 256; i++) { + const v = histogram[i]; + if (v > M) { + if (i - pos > L) { + L = i - pos; + spos = i - 1; + } + M = v; + pos = i; + } + } + for (i = spos - 1; i >= 0; i--) { + if (histogram[i] > histogram[i + 1]) { + break; + } + } + return i; + } + static #getGrayPixels(bitmap) { + const originalBitmap = bitmap; + const { + width, + height + } = bitmap; + const { + maxDim + } = this.#PARAMETERS; + let newWidth = width; + let newHeight = height; + if (width > maxDim || height > maxDim) { + let prevWidth = width; + let prevHeight = height; + let steps = Math.log2(Math.max(width, height) / maxDim); + const isteps = Math.floor(steps); + steps = steps === isteps ? isteps - 1 : isteps; + for (let i = 0; i < steps; i++) { + newWidth = Math.ceil(prevWidth / 2); + newHeight = Math.ceil(prevHeight / 2); + const offscreen = new OffscreenCanvas(newWidth, newHeight); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + prevWidth = newWidth; + prevHeight = newHeight; + if (bitmap !== originalBitmap) { + bitmap.close(); + } + bitmap = offscreen.transferToImageBitmap(); + } + const ratio = Math.min(maxDim / newWidth, maxDim / newHeight); + newWidth = Math.round(newWidth * ratio); + newHeight = Math.round(newHeight * ratio); + } + const offscreen = new OffscreenCanvas(newWidth, newHeight); + const ctx = offscreen.getContext("2d", { + willReadFrequently: true + }); + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, newWidth, newHeight); + ctx.filter = "grayscale(1)"; + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, newWidth, newHeight); + const grayImage = ctx.getImageData(0, 0, newWidth, newHeight).data; + const uint8Buf = this.#toUint8(grayImage); + return [uint8Buf, newWidth, newHeight]; + } + static extractContoursFromText(text, { + fontFamily, + fontStyle, + fontWeight + }, pageWidth, pageHeight, rotation, innerMargin) { + let canvas = new OffscreenCanvas(1, 1); + let ctx = canvas.getContext("2d", { + alpha: false + }); + const fontSize = 200; + const font = ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`; + const { + actualBoundingBoxLeft, + actualBoundingBoxRight, + actualBoundingBoxAscent, + actualBoundingBoxDescent, + fontBoundingBoxAscent, + fontBoundingBoxDescent, + width + } = ctx.measureText(text); + const SCALE = 1.5; + const canvasWidth = Math.ceil(Math.max(Math.abs(actualBoundingBoxLeft) + Math.abs(actualBoundingBoxRight) || 0, width) * SCALE); + const canvasHeight = Math.ceil(Math.max(Math.abs(actualBoundingBoxAscent) + Math.abs(actualBoundingBoxDescent) || fontSize, Math.abs(fontBoundingBoxAscent) + Math.abs(fontBoundingBoxDescent) || fontSize) * SCALE); + canvas = new OffscreenCanvas(canvasWidth, canvasHeight); + ctx = canvas.getContext("2d", { + alpha: true, + willReadFrequently: true + }); + ctx.font = font; + ctx.filter = "grayscale(1)"; + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + ctx.fillStyle = "black"; + ctx.fillText(text, canvasWidth * (SCALE - 1) / 2, canvasHeight * (3 - SCALE) / 2); + const uint8Buf = this.#toUint8(ctx.getImageData(0, 0, canvasWidth, canvasHeight).data); + const histogram = this.#getHistogram(uint8Buf); + const threshold = this.#guessThreshold(histogram); + const contourList = this.#findContours(uint8Buf, canvasWidth, canvasHeight, threshold); + return this.processDrawnLines({ + lines: { + curves: contourList, + width: canvasWidth, + height: canvasHeight + }, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth: true, + areContours: true + }); + } + static process(bitmap, pageWidth, pageHeight, rotation, innerMargin) { + const [uint8Buf, width, height] = this.#getGrayPixels(bitmap); + const [buffer, histogram] = this.#bilateralFilter(uint8Buf, width, height, Math.hypot(width, height) * this.#PARAMETERS.sigmaSFactor, this.#PARAMETERS.sigmaR, this.#PARAMETERS.kernelSize); + const threshold = this.#guessThreshold(histogram); + const contourList = this.#findContours(buffer, width, height, threshold); + return this.processDrawnLines({ + lines: { + curves: contourList, + width, + height + }, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth: true, + areContours: true + }); + } + static processDrawnLines({ + lines, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth, + areContours + }) { + if (rotation % 180 !== 0) { + [pageWidth, pageHeight] = [pageHeight, pageWidth]; + } + const { + curves, + width, + height + } = lines; + const thickness = lines.thickness ?? 0; + const linesAndPoints = []; + const ratio = Math.min(pageWidth / width, pageHeight / height); + const xScale = ratio / pageWidth; + const yScale = ratio / pageHeight; + const newCurves = []; + for (const { + points + } of curves) { + const reducedPoints = mustSmooth ? this.#douglasPeucker(points) : points; + if (!reducedPoints) { + continue; + } + newCurves.push(reducedPoints); + const len = reducedPoints.length; + const newPoints = new Float32Array(len); + const line = new Float32Array(3 * (len === 2 ? 2 : len - 2)); + linesAndPoints.push({ + line, + points: newPoints + }); + if (len === 2) { + newPoints[0] = reducedPoints[0] * xScale; + newPoints[1] = reducedPoints[1] * yScale; + line.set([NaN, NaN, NaN, NaN, newPoints[0], newPoints[1]], 0); + continue; + } + let [x1, y1, x2, y2] = reducedPoints; + x1 *= xScale; + y1 *= yScale; + x2 *= xScale; + y2 *= yScale; + newPoints.set([x1, y1, x2, y2], 0); + line.set([NaN, NaN, NaN, NaN, x1, y1], 0); + for (let i = 4; i < len; i += 2) { + const x = newPoints[i] = reducedPoints[i] * xScale; + const y = newPoints[i + 1] = reducedPoints[i + 1] * yScale; + line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3); + [x1, y1, x2, y2] = [x2, y2, x, y]; + } + } + if (linesAndPoints.length === 0) { + return null; + } + const outline = areContours ? new ContourDrawOutline() : new InkDrawOutline(); + outline.build(linesAndPoints, pageWidth, pageHeight, 1, rotation, areContours ? 0 : thickness, innerMargin); + return { + outline, + newCurves, + areContours, + thickness, + width, + height + }; + } + static async compressSignature({ + outlines, + areContours, + thickness, + width, + height + }) { + let minDiff = Infinity; + let maxDiff = -Infinity; + let outlinesLength = 0; + for (const points of outlines) { + outlinesLength += points.length; + for (let i = 2, ii = points.length; i < ii; i++) { + const dx = points[i] - points[i - 2]; + minDiff = Math.min(minDiff, dx); + maxDiff = Math.max(maxDiff, dx); + } + } + let bufferType; + if (minDiff >= -128 && maxDiff <= 127) { + bufferType = Int8Array; + } else if (minDiff >= -32768 && maxDiff <= 32767) { + bufferType = Int16Array; + } else { + bufferType = Int32Array; + } + const len = outlines.length; + const headerLength = BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * len; + const header = new Uint32Array(headerLength); + let offset = 0; + header[offset++] = headerLength * Uint32Array.BYTES_PER_ELEMENT + (outlinesLength - 2 * len) * bufferType.BYTES_PER_ELEMENT; + header[offset++] = 0; + header[offset++] = width; + header[offset++] = height; + header[offset++] = areContours ? 0 : 1; + header[offset++] = Math.max(0, Math.floor(thickness ?? 0)); + header[offset++] = len; + header[offset++] = bufferType.BYTES_PER_ELEMENT; + for (const points of outlines) { + header[offset++] = points.length - 2; + header[offset++] = points[0]; + header[offset++] = points[1]; + } + const cs = new CompressionStream("deflate-raw"); + const writer = cs.writable.getWriter(); + await writer.ready; + writer.write(header); + const BufferCtor = bufferType.prototype.constructor; + for (const points of outlines) { + const diffs = new BufferCtor(points.length - 2); + for (let i = 2, ii = points.length; i < ii; i++) { + diffs[i - 2] = points[i] - points[i - 2]; + } + writer.write(diffs); + } + writer.close(); + const buf = await new Response(cs.readable).arrayBuffer(); + const bytes = new Uint8Array(buf); + return toBase64Util(bytes); + } + static async decompressSignature(signatureData) { + try { + const bytes = fromBase64Util(signatureData); + const { + readable, + writable + } = new DecompressionStream("deflate-raw"); + const writer = writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => {}); + let data = null; + let offset = 0; + for await (const chunk of readable) { + data ||= new Uint8Array(new Uint32Array(chunk.buffer, 0, 4)[0]); + data.set(chunk, offset); + offset += chunk.length; + } + const header = new Uint32Array(data.buffer, 0, data.length >> 2); + const version = header[1]; + if (version !== 0) { + throw new Error(`Invalid version: ${version}`); + } + const width = header[2]; + const height = header[3]; + const areContours = header[4] === 0; + const thickness = header[5]; + const numberOfDrawings = header[6]; + const bufferType = header[7]; + const outlines = []; + const diffsOffset = (BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * numberOfDrawings) * Uint32Array.BYTES_PER_ELEMENT; + let diffs; + switch (bufferType) { + case Int8Array.BYTES_PER_ELEMENT: + diffs = new Int8Array(data.buffer, diffsOffset); + break; + case Int16Array.BYTES_PER_ELEMENT: + diffs = new Int16Array(data.buffer, diffsOffset); + break; + case Int32Array.BYTES_PER_ELEMENT: + diffs = new Int32Array(data.buffer, diffsOffset); + break; + } + offset = 0; + for (let i = 0; i < numberOfDrawings; i++) { + const len = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH]; + const points = new Float32Array(len + 2); + outlines.push(points); + for (let j = 0; j < POINTS_PROPERTIES_NUMBER - 1; j++) { + points[j] = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH + j + 1]; + } + for (let j = 0; j < len; j++) { + points[j + 2] = points[j] + diffs[offset++]; + } + } + return { + areContours, + thickness, + outlines, + width, + height + }; + } catch (e) { + warn(`decompressSignature: ${e}`); + return null; + } + } +} + +;// ./src/display/editor/signature.js + + + + + + + +class SignatureOptions extends DrawingOptions { + constructor() { + super(); + super.updateProperties({ + fill: AnnotationEditor._defaultLineColor, + "stroke-width": 0 + }); + } + clone() { + const clone = new SignatureOptions(); + clone.updateAll(this); + return clone; + } +} +class DrawnSignatureOptions extends InkDrawingOptions { + constructor(viewerParameters) { + super(viewerParameters); + super.updateProperties({ + stroke: AnnotationEditor._defaultLineColor, + "stroke-width": 1 + }); + } + clone() { + const clone = new DrawnSignatureOptions(this._viewParameters); + clone.updateAll(this); + return clone; + } +} +class SignatureEditor extends DrawingEditor { + #isExtracted = false; + #description = null; + #signatureData = null; + #signatureUUID = null; + static _type = "signature"; + static _editorType = AnnotationEditorType.SIGNATURE; + static _defaultDrawingOptions = null; + constructor(params) { + super({ + ...params, + mustBeCommitted: true, + name: "signatureEditor" + }); + this._willKeepAspectRatio = true; + this.#signatureData = params.signatureData || null; + this.#description = null; + this.defaultL10nId = "pdfjs-editor-signature-editor1"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + this._defaultDrawingOptions = new SignatureOptions(); + this._defaultDrawnSignatureOptions = new DrawnSignatureOptions(uiManager.viewParameters); + } + static getDefaultDrawingOptions(options) { + const clone = this._defaultDrawingOptions.clone(); + clone.updateProperties(options); + return clone; + } + static get supportMultipleDrawings() { + return false; + } + static get typesMap() { + return shadow(this, "typesMap", new Map()); + } + static get isDrawer() { + return false; + } + get telemetryFinalData() { + return { + type: "signature", + hasDescription: !!this.#description + }; + } + static computeTelemetryFinalData(data) { + const hasDescriptionStats = data.get("hasDescription"); + return { + hasAltText: hasDescriptionStats.get(true) ?? 0, + hasNoAltText: hasDescriptionStats.get(false) ?? 0 + }; + } + get isResizable() { + return true; + } + onScaleChanging() { + if (this._drawId === null) { + return; + } + super.onScaleChanging(); + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + const { + _isCopy + } = this; + if (_isCopy) { + this._isCopy = false; + baseX = this.x; + baseY = this.y; + } + super.render(); + if (this._drawId === null) { + if (this.#signatureData) { + const { + lines, + mustSmooth, + areContours, + description, + uuid, + heightInPage + } = this.#signatureData; + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + const outline = SignatureExtractor.processDrawnLines({ + lines, + pageWidth, + pageHeight, + rotation, + innerMargin: SignatureEditor._INNER_MARGIN, + mustSmooth, + areContours + }); + this.addSignature(outline, heightInPage, description, uuid); + } else { + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description: "" + })); + this.div.hidden = true; + this._uiManager.getSignature(this); + } + } else { + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description: this.#description || "" + })); + } + if (_isCopy) { + this._isCopy = true; + this._moveAfterPaste(baseX, baseY); + } + return this.div; + } + setUuid(uuid) { + this.#signatureUUID = uuid; + this.addEditToolbar(); + } + getUuid() { + return this.#signatureUUID; + } + get description() { + return this.#description; + } + set description(description) { + this.#description = description; + if (!this.div) { + return; + } + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description + })); + super.addEditToolbar().then(toolbar => { + toolbar?.updateEditSignatureButton(description); + }); + } + getSignaturePreview() { + const { + newCurves, + areContours, + thickness, + width, + height + } = this.#signatureData; + const maxDim = Math.max(width, height); + const outlineData = SignatureExtractor.processDrawnLines({ + lines: { + curves: newCurves.map(points => ({ + points + })), + thickness, + width, + height + }, + pageWidth: maxDim, + pageHeight: maxDim, + rotation: 0, + innerMargin: 0, + mustSmooth: false, + areContours + }); + return { + areContours, + outline: outlineData.outline + }; + } + get toolbarButtons() { + if (this._uiManager.signatureManager) { + return [["editSignature", this._uiManager.signatureManager]]; + } + return super.toolbarButtons; + } + addSignature(data, heightInPage, description, uuid) { + const { + x: savedX, + y: savedY + } = this; + const { + outline + } = this.#signatureData = data; + this.#isExtracted = outline instanceof ContourDrawOutline; + this.description = description; + let drawingOptions; + if (this.#isExtracted) { + drawingOptions = SignatureEditor.getDefaultDrawingOptions(); + } else { + drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone(); + drawingOptions.updateProperties({ + "stroke-width": outline.thickness + }); + } + this._addOutlines({ + drawOutlines: outline, + drawingOptions + }); + const [, pageHeight] = this.pageDimensions; + let newHeight = heightInPage / pageHeight; + newHeight = newHeight >= 1 ? 0.5 : newHeight; + this.width *= newHeight / this.height; + if (this.width >= 1) { + newHeight *= 0.9 / this.width; + this.width = 0.9; + } + this.height = newHeight; + this.setDims(); + this.x = savedX; + this.y = savedY; + this.center(); + this._onResized(); + this.onScaleChanging(); + this.rotate(); + this._uiManager.addToAnnotationStorage(this); + this.setUuid(uuid); + this._reportTelemetry({ + action: "pdfjs.signature.inserted", + data: { + hasBeenSaved: !!uuid, + hasDescription: !!description + } + }); + this.div.hidden = false; + } + getFromImage(bitmap) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.process(bitmap, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN); + } + getFromText(text, fontInfo) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.extractContoursFromText(text, fontInfo, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN); + } + getDrawnSignature(curves) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.processDrawnLines({ + lines: curves, + pageWidth, + pageHeight, + rotation, + innerMargin: SignatureEditor._INNER_MARGIN, + mustSmooth: false, + areContours: false + }); + } + createDrawingOptions({ + areContours, + thickness + }) { + if (areContours) { + this._drawingOptions = SignatureEditor.getDefaultDrawingOptions(); + } else { + this._drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone(); + this._drawingOptions.updateProperties({ + "stroke-width": thickness + }); + } + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + const { + lines, + points + } = this.serializeDraw(isForCopying); + const { + _drawingOptions: { + "stroke-width": thickness + } + } = this; + const serialized = Object.assign(super.serialize(isForCopying), { + isSignature: true, + areContours: this.#isExtracted, + color: [0, 0, 0], + thickness: this.#isExtracted ? 0 : thickness + }); + this.addComment(serialized); + if (isForCopying) { + serialized.paths = { + lines, + points + }; + serialized.uuid = this.#signatureUUID; + serialized.isCopy = true; + } else { + serialized.lines = lines; + } + if (this.#description) { + serialized.accessibilityData = { + type: "Figure", + alt: this.#description + }; + } + return serialized; + } + static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) { + if (data.areContours) { + return ContourDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + static async deserialize(data, parent, uiManager) { + const editor = await super.deserialize(data, parent, uiManager); + editor.#isExtracted = data.areContours; + editor.description = data.accessibilityData?.alt || ""; + editor.#signatureUUID = data.uuid; + return editor; + } +} + +;// ./src/display/editor/stamp.js + + + + +class StampEditor extends AnnotationEditor { + #bitmap = null; + #bitmapId = null; + #bitmapPromise = null; + #bitmapUrl = null; + #bitmapFile = null; + #bitmapFileName = ""; + #canvas = null; + #missingCanvas = false; + #resizeTimeoutId = null; + #isSvg = false; + #hasBeenAddedInUndoStack = false; + static _type = "stamp"; + static _editorType = AnnotationEditorType.STAMP; + constructor(params) { + super({ + ...params, + name: "stampEditor" + }); + this.#bitmapUrl = params.bitmapUrl; + this.#bitmapFile = params.bitmapFile; + this.defaultL10nId = "pdfjs-editor-stamp-editor"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + } + static isHandlingMimeForPasting(mime) { + return SupportedImageMimeTypes.includes(mime); + } + static paste(item, parent) { + parent.pasteEditor({ + mode: AnnotationEditorType.STAMP + }, { + bitmapFile: item.getAsFile() + }); + } + altTextFinish() { + if (this._uiManager.useNewAltTextFlow) { + this.div.hidden = false; + } + super.altTextFinish(); + } + get telemetryFinalData() { + return { + type: "stamp", + hasAltText: !!this.altTextData?.altText + }; + } + static computeTelemetryFinalData(data) { + const hasAltTextStats = data.get("hasAltText"); + return { + hasAltText: hasAltTextStats.get(true) ?? 0, + hasNoAltText: hasAltTextStats.get(false) ?? 0 + }; + } + #getBitmapFetched(data, fromId = false) { + if (!data) { + this.remove(); + return; + } + this.#bitmap = data.bitmap; + if (!fromId) { + this.#bitmapId = data.id; + this.#isSvg = data.isSvg; + } + if (data.file) { + this.#bitmapFileName = data.file.name; + } + this.#createCanvas(); + } + #getBitmapDone() { + this.#bitmapPromise = null; + this._uiManager.enableWaiting(false); + if (!this.#canvas) { + return; + } + if (this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) { + this.addEditToolbar().then(() => { + this._editToolbar.hide(); + this._uiManager.editAltText(this, true); + }); + return; + } + if (!this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) { + this._reportTelemetry({ + action: "pdfjs.image.image_added", + data: { + alt_text_modal: false, + alt_text_type: "empty" + } + }); + try { + this.mlGuessAltText(); + } catch {} + } + this.div.focus(); + } + async mlGuessAltText(imageData = null, updateAltTextData = true) { + if (this.hasAltTextData()) { + return null; + } + const { + mlManager + } = this._uiManager; + if (!mlManager) { + throw new Error("No ML."); + } + if (!(await mlManager.isEnabledFor("altText"))) { + throw new Error("ML isn't enabled for alt text."); + } + const { + data, + width, + height + } = imageData || this.copyCanvas(null, null, true).imageData; + const response = await mlManager.guess({ + name: "altText", + request: { + data, + width, + height, + channels: data.length / (width * height) + } + }); + if (!response) { + throw new Error("No response from the AI service."); + } + if (response.error) { + throw new Error("Error from the AI service."); + } + if (response.cancel) { + return null; + } + if (!response.output) { + throw new Error("No valid response from the AI service."); + } + const altText = response.output; + await this.setGuessedAltText(altText); + if (updateAltTextData && !this.hasAltTextData()) { + this.altTextData = { + alt: altText, + decorative: false + }; + } + return altText; + } + #getBitmap() { + if (this.#bitmapId) { + this._uiManager.enableWaiting(true); + this._uiManager.imageManager.getFromId(this.#bitmapId).then(data => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone()); + return; + } + if (this.#bitmapUrl) { + const url = this.#bitmapUrl; + this.#bitmapUrl = null; + this._uiManager.enableWaiting(true); + this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); + return; + } + if (this.#bitmapFile) { + const file = this.#bitmapFile; + this.#bitmapFile = null; + this._uiManager.enableWaiting(true); + this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then(data => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); + return; + } + const input = document.createElement("input"); + input.type = "file"; + input.accept = SupportedImageMimeTypes.join(","); + const signal = this._uiManager._signal; + this.#bitmapPromise = new Promise(resolve => { + input.addEventListener("change", async () => { + if (!input.files || input.files.length === 0) { + this.remove(); + } else { + this._uiManager.enableWaiting(true); + const data = await this._uiManager.imageManager.getFromFile(input.files[0]); + this._reportTelemetry({ + action: "pdfjs.image.image_selected", + data: { + alt_text_modal: this._uiManager.useNewAltTextFlow + } + }); + this.#getBitmapFetched(data); + } + resolve(); + }, { + signal + }); + input.addEventListener("cancel", () => { + this.remove(); + resolve(); + }, { + signal + }); + }).finally(() => this.#getBitmapDone()); + input.click(); + } + remove() { + if (this.#bitmapId) { + this.#bitmap = null; + this._uiManager.imageManager.deleteId(this.#bitmapId); + this.#canvas?.remove(); + this.#canvas = null; + if (this.#resizeTimeoutId) { + clearTimeout(this.#resizeTimeoutId); + this.#resizeTimeoutId = null; + } + } + super.remove(); + } + rebuild() { + if (!this.parent) { + if (this.#bitmapId) { + this.#getBitmap(); + } + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + if (this.#bitmapId && this.#canvas === null) { + this.#getBitmap(); + } + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + onceAdded(focus) { + this._isDraggable = true; + if (focus) { + this.div.focus(); + } + } + isEmpty() { + return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId || this.#missingCanvas); + } + get toolbarButtons() { + return [["altText", this.createAltText()]]; + } + get isResizable() { + return true; + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy) { + baseX = this.x; + baseY = this.y; + } + super.render(); + this.div.hidden = true; + this.createAltText(); + if (!this.#missingCanvas) { + if (this.#bitmap) { + this.#createCanvas(); + } else { + this.#getBitmap(); + } + } + if (this._isCopy) { + this._moveAfterPaste(baseX, baseY); + } + this._uiManager.addShouldRescale(this); + return this.div; + } + setCanvas(annotationElementId, canvas) { + const { + id: bitmapId, + bitmap + } = this._uiManager.imageManager.getFromCanvas(annotationElementId, canvas); + canvas.remove(); + if (bitmapId && this._uiManager.imageManager.isValidId(bitmapId)) { + this.#bitmapId = bitmapId; + if (bitmap) { + this.#bitmap = bitmap; + } + this.#missingCanvas = false; + this.#createCanvas(); + } + } + _onResized() { + this.onScaleChanging(); + } + onScaleChanging() { + if (!this.parent) { + return; + } + if (this.#resizeTimeoutId !== null) { + clearTimeout(this.#resizeTimeoutId); + } + const TIME_TO_WAIT = 200; + this.#resizeTimeoutId = setTimeout(() => { + this.#resizeTimeoutId = null; + this.#drawBitmap(); + }, TIME_TO_WAIT); + } + #createCanvas() { + const { + div + } = this; + let { + width, + height + } = this.#bitmap; + const [pageWidth, pageHeight] = this.pageDimensions; + const MAX_RATIO = 0.75; + if (this.width) { + width = this.width * pageWidth; + height = this.height * pageHeight; + } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) { + const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height); + width *= factor; + height *= factor; + } + this._uiManager.enableWaiting(false); + const canvas = this.#canvas = document.createElement("canvas"); + canvas.setAttribute("role", "img"); + this.addContainer(canvas); + this.width = width / pageWidth; + this.height = height / pageHeight; + this.setDims(); + if (this._initialOptions?.isCentered) { + this.center(); + } else { + this.fixAndSetPosition(); + } + this._initialOptions = null; + if (!this._uiManager.useNewAltTextWhenAddingImage || !this._uiManager.useNewAltTextFlow || this.annotationElementId) { + div.hidden = false; + } + this.#drawBitmap(); + if (!this.#hasBeenAddedInUndoStack) { + this.parent.addUndoableEditor(this); + this.#hasBeenAddedInUndoStack = true; + } + this._reportTelemetry({ + action: "inserted_image" + }); + if (this.#bitmapFileName) { + this.div.setAttribute("aria-description", this.#bitmapFileName); + } + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-stamp-added-alert"); + } + } + copyCanvas(maxDataDimension, maxPreviewDimension, createImageData = false) { + if (!maxDataDimension) { + maxDataDimension = 224; + } + const { + width: bitmapWidth, + height: bitmapHeight + } = this.#bitmap; + const outputScale = new OutputScale(); + let bitmap = this.#bitmap; + let width = bitmapWidth, + height = bitmapHeight; + let canvas = null; + if (maxPreviewDimension) { + if (bitmapWidth > maxPreviewDimension || bitmapHeight > maxPreviewDimension) { + const ratio = Math.min(maxPreviewDimension / bitmapWidth, maxPreviewDimension / bitmapHeight); + width = Math.floor(bitmapWidth * ratio); + height = Math.floor(bitmapHeight * ratio); + } + canvas = document.createElement("canvas"); + const scaledWidth = canvas.width = Math.ceil(width * outputScale.sx); + const scaledHeight = canvas.height = Math.ceil(height * outputScale.sy); + if (!this.#isSvg) { + bitmap = this.#scaleBitmap(scaledWidth, scaledHeight); + } + const ctx = canvas.getContext("2d"); + ctx.filter = this._uiManager.hcmFilter; + let white = "white", + black = "#cfcfd8"; + if (this._uiManager.hcmFilter !== "none") { + black = "black"; + } else if (ColorScheme.isDarkMode) { + white = "#8f8f9d"; + black = "#42414d"; + } + const boxDim = 15; + const boxDimWidth = boxDim * outputScale.sx; + const boxDimHeight = boxDim * outputScale.sy; + const pattern = new OffscreenCanvas(boxDimWidth * 2, boxDimHeight * 2); + const patternCtx = pattern.getContext("2d"); + patternCtx.fillStyle = white; + patternCtx.fillRect(0, 0, boxDimWidth * 2, boxDimHeight * 2); + patternCtx.fillStyle = black; + patternCtx.fillRect(0, 0, boxDimWidth, boxDimHeight); + patternCtx.fillRect(boxDimWidth, boxDimHeight, boxDimWidth, boxDimHeight); + ctx.fillStyle = ctx.createPattern(pattern, "repeat"); + ctx.fillRect(0, 0, scaledWidth, scaledHeight); + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight); + } + let imageData = null; + if (createImageData) { + let dataWidth, dataHeight; + if (outputScale.symmetric && bitmap.width < maxDataDimension && bitmap.height < maxDataDimension) { + dataWidth = bitmap.width; + dataHeight = bitmap.height; + } else { + bitmap = this.#bitmap; + if (bitmapWidth > maxDataDimension || bitmapHeight > maxDataDimension) { + const ratio = Math.min(maxDataDimension / bitmapWidth, maxDataDimension / bitmapHeight); + dataWidth = Math.floor(bitmapWidth * ratio); + dataHeight = Math.floor(bitmapHeight * ratio); + if (!this.#isSvg) { + bitmap = this.#scaleBitmap(dataWidth, dataHeight); + } + } + } + const offscreen = new OffscreenCanvas(dataWidth, dataHeight); + const offscreenCtx = offscreen.getContext("2d", { + willReadFrequently: true + }); + offscreenCtx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, dataWidth, dataHeight); + imageData = { + width: dataWidth, + height: dataHeight, + data: offscreenCtx.getImageData(0, 0, dataWidth, dataHeight).data + }; + } + return { + canvas, + width, + height, + imageData + }; + } + #scaleBitmap(width, height) { + const { + width: bitmapWidth, + height: bitmapHeight + } = this.#bitmap; + let newWidth = bitmapWidth; + let newHeight = bitmapHeight; + let bitmap = this.#bitmap; + while (newWidth > 2 * width || newHeight > 2 * height) { + const prevWidth = newWidth; + const prevHeight = newHeight; + if (newWidth > 2 * width) { + newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2); + } + if (newHeight > 2 * height) { + newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2); + } + const offscreen = new OffscreenCanvas(newWidth, newHeight); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + bitmap = offscreen.transferToImageBitmap(); + } + return bitmap; + } + #drawBitmap() { + const [parentWidth, parentHeight] = this.parentDimensions; + const { + width, + height + } = this; + const outputScale = new OutputScale(); + const scaledWidth = Math.ceil(width * parentWidth * outputScale.sx); + const scaledHeight = Math.ceil(height * parentHeight * outputScale.sy); + const canvas = this.#canvas; + if (!canvas || canvas.width === scaledWidth && canvas.height === scaledHeight) { + return; + } + canvas.width = scaledWidth; + canvas.height = scaledHeight; + const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(scaledWidth, scaledHeight); + const ctx = canvas.getContext("2d"); + ctx.filter = this._uiManager.hcmFilter; + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight); + } + #serializeBitmap(toUrl) { + if (toUrl) { + if (this.#isSvg) { + const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId); + if (url) { + return url; + } + } + const canvas = document.createElement("canvas"); + ({ + width: canvas.width, + height: canvas.height + } = this.#bitmap); + const ctx = canvas.getContext("2d"); + ctx.drawImage(this.#bitmap, 0, 0); + return canvas.toDataURL(); + } + if (this.#isSvg) { + const [pageWidth, pageHeight] = this.pageDimensions; + const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS); + const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS); + const offscreen = new OffscreenCanvas(width, height); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height); + return offscreen.transferToImageBitmap(); + } + return structuredClone(this.#bitmap); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + let missingCanvas = false; + if (data instanceof StampAnnotationElement) { + const { + data: { + rect, + rotation, + id, + structParent, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + container, + parent: { + page: { + pageNumber + } + }, + canvas + } = data; + let bitmapId, bitmap; + if (canvas) { + delete data.canvas; + ({ + id: bitmapId, + bitmap + } = uiManager.imageManager.getFromCanvas(container.id, canvas)); + canvas.remove(); + } else { + missingCanvas = true; + data._hasNoCanvas = true; + } + const altText = (await parent._structTree.getAriaAttributes(`${AnnotationPrefix}${id}`))?.get("aria-label") || ""; + initialData = data = { + annotationType: AnnotationEditorType.STAMP, + bitmapId, + bitmap, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + accessibilityData: { + decorative: false, + altText + }, + isSvg: false, + structParent, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + const { + rect, + bitmap, + bitmapUrl, + bitmapId, + isSvg, + accessibilityData + } = data; + if (missingCanvas) { + uiManager.addMissingCanvas(data.id, editor); + editor.#missingCanvas = true; + } else if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) { + editor.#bitmapId = bitmapId; + if (bitmap) { + editor.#bitmap = bitmap; + } + } else { + editor.#bitmapUrl = bitmapUrl; + } + editor.#isSvg = isSvg; + const [parentWidth, parentHeight] = editor.pageDimensions; + editor.width = (rect[2] - rect[0]) / parentWidth; + editor.height = (rect[3] - rect[1]) / parentHeight; + if (accessibilityData) { + editor.altTextData = accessibilityData; + } + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + editor.#hasBeenAddedInUndoStack = !!initialData; + return editor; + } + serialize(isForCopying = false, context = null) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const serialized = Object.assign(super.serialize(isForCopying), { + bitmapId: this.#bitmapId, + isSvg: this.#isSvg + }); + this.addComment(serialized); + if (isForCopying) { + serialized.bitmapUrl = this.#serializeBitmap(true); + serialized.accessibilityData = this.serializeAltText(true); + serialized.isCopy = true; + return serialized; + } + const { + decorative, + altText + } = this.serializeAltText(false); + if (!decorative && altText) { + serialized.accessibilityData = { + type: "Figure", + alt: altText + }; + } + if (this.annotationElementId) { + const changes = this.#hasElementChanged(serialized); + if (changes.isSame) { + return null; + } + if (changes.isSameAltText) { + delete serialized.accessibilityData; + } else { + serialized.accessibilityData.structParent = this._initialData.structParent ?? -1; + } + serialized.id = this.annotationElementId; + delete serialized.bitmapId; + return serialized; + } + if (context === null) { + return serialized; + } + context.stamps ||= new Map(); + const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null; + if (!context.stamps.has(this.#bitmapId)) { + context.stamps.set(this.#bitmapId, { + area, + serialized + }); + serialized.bitmap = this.#serializeBitmap(false); + } else if (this.#isSvg) { + const prevData = context.stamps.get(this.#bitmapId); + if (area > prevData.area) { + prevData.area = area; + prevData.serialized.bitmap.close(); + prevData.serialized.bitmap = this.#serializeBitmap(false); + } + } + return serialized; + } + #hasElementChanged(serialized) { + const { + pageIndex, + accessibilityData: { + altText + } + } = this._initialData; + const isSamePageIndex = serialized.pageIndex === pageIndex; + const isSameAltText = (serialized.accessibilityData?.alt || "") === altText; + return { + isSame: !this.hasEditedComment && !this._hasBeenMoved && !this._hasBeenResized && isSamePageIndex && isSameAltText, + isSameAltText + }; + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + return null; + } +} + +;// ./src/display/editor/annotation_editor_layer.js + + + + + + + + +class AnnotationEditorLayer { + #accessibilityManager; + #allowClick = false; + #annotationLayer = null; + #clickAC = null; + #editorFocusTimeoutId = null; + #editors = new Map(); + #hadPointerDown = false; + #isDisabling = false; + #isEnabling = false; + #drawingAC = null; + #focusedElement = null; + #textLayer = null; + #textSelectionAC = null; + #textLayerDblClickAC = null; + #lastPointerDownTimestamp = -1; + #uiManager; + static _initialized = false; + static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor, SignatureEditor].map(type => [type._editorType, type])); + constructor({ + uiManager, + pageIndex, + div, + structTreeLayer, + accessibilityManager, + annotationLayer, + drawLayer, + textLayer, + viewport, + l10n + }) { + const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()]; + if (!AnnotationEditorLayer._initialized) { + AnnotationEditorLayer._initialized = true; + for (const editorType of editorTypes) { + editorType.initialize(l10n, uiManager); + } + } + uiManager.registerEditorTypes(editorTypes); + this.#uiManager = uiManager; + this.pageIndex = pageIndex; + this.div = div; + this.#accessibilityManager = accessibilityManager; + this.#annotationLayer = annotationLayer; + this.viewport = viewport; + this.#textLayer = textLayer; + this.drawLayer = drawLayer; + this._structTree = structTreeLayer; + this.#uiManager.addLayer(this); + } + get isEmpty() { + return this.#editors.size === 0; + } + get isInvisible() { + return this.isEmpty && this.#uiManager.getMode() === AnnotationEditorType.NONE; + } + updateToolbar(options) { + this.#uiManager.updateToolbar(options); + } + updateMode(mode = this.#uiManager.getMode()) { + this.#cleanup(); + switch (mode) { + case AnnotationEditorType.NONE: + this.div.classList.toggle("nonEditing", true); + this.disableTextSelection(); + this.togglePointerEvents(false); + this.toggleAnnotationLayerPointerEvents(true); + this.disableClick(); + return; + case AnnotationEditorType.INK: + this.disableTextSelection(); + this.togglePointerEvents(true); + this.enableClick(); + break; + case AnnotationEditorType.HIGHLIGHT: + this.enableTextSelection(); + this.togglePointerEvents(false); + this.disableClick(); + break; + default: + this.disableTextSelection(); + this.togglePointerEvents(true); + this.enableClick(); + } + this.toggleAnnotationLayerPointerEvents(false); + const { + classList + } = this.div; + classList.toggle("nonEditing", false); + if (mode === AnnotationEditorType.POPUP) { + classList.toggle("commentEditing", true); + } else { + classList.toggle("commentEditing", false); + for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { + classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType); + } + } + this.div.hidden = false; + } + hasTextLayer(textLayer) { + return textLayer === this.#textLayer?.div; + } + setEditingState(isEditing) { + this.#uiManager.setEditingState(isEditing); + } + addCommands(params) { + this.#uiManager.addCommands(params); + } + cleanUndoStack(type) { + this.#uiManager.cleanUndoStack(type); + } + toggleDrawing(enabled = false) { + this.div.classList.toggle("drawing", !enabled); + } + togglePointerEvents(enabled = false) { + this.div.classList.toggle("disabled", !enabled); + } + toggleAnnotationLayerPointerEvents(enabled = false) { + this.#annotationLayer?.togglePointerEvents(enabled); + } + get #allEditorsIterator() { + return this.#editors.size !== 0 ? this.#editors.values() : this.#uiManager.getEditors(this.pageIndex); + } + async enable() { + this.#isEnabling = true; + this.div.tabIndex = 0; + this.togglePointerEvents(true); + this.div.classList.toggle("nonEditing", false); + this.#textLayerDblClickAC?.abort(); + this.#textLayerDblClickAC = null; + const annotationElementIds = new Set(); + for (const editor of this.#allEditorsIterator) { + editor.enableEditing(); + editor.show(true); + if (editor.annotationElementId) { + this.#uiManager.removeChangedExistingAnnotation(editor); + annotationElementIds.add(editor.annotationElementId); + } + } + const annotationLayer = this.#annotationLayer; + if (annotationLayer) { + for (const editable of annotationLayer.getEditableAnnotations()) { + editable.hide(); + if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) { + continue; + } + if (annotationElementIds.has(editable.data.id)) { + continue; + } + const editor = await this.deserialize(editable); + if (!editor) { + continue; + } + this.addOrRebuild(editor); + editor.enableEditing(); + } + } + this.#isEnabling = false; + this.#uiManager._eventBus.dispatch("editorsrendered", { + source: this, + pageNumber: this.pageIndex + 1 + }); + } + disable() { + this.#isDisabling = true; + this.div.tabIndex = -1; + this.togglePointerEvents(false); + this.div.classList.toggle("nonEditing", true); + if (this.#textLayer && !this.#textLayerDblClickAC) { + this.#textLayerDblClickAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#textLayerDblClickAC); + this.#textLayer.div.addEventListener("pointerdown", e => { + const DBL_CLICK_THRESHOLD = 500; + const { + clientX, + clientY, + timeStamp + } = e; + const lastPointerDownTimestamp = this.#lastPointerDownTimestamp; + if (timeStamp - lastPointerDownTimestamp > DBL_CLICK_THRESHOLD) { + this.#lastPointerDownTimestamp = timeStamp; + return; + } + this.#lastPointerDownTimestamp = -1; + const { + classList + } = this.div; + classList.toggle("getElements", true); + const elements = document.elementsFromPoint(clientX, clientY); + classList.toggle("getElements", false); + if (!this.div.contains(elements[0])) { + return; + } + let id; + const regex = new RegExp(`^${AnnotationEditorPrefix}[0-9]+$`); + for (const element of elements) { + if (regex.test(element.id)) { + id = element.id; + break; + } + } + if (!id) { + return; + } + const editor = this.#editors.get(id); + if (editor?.annotationElementId === null) { + e.stopPropagation(); + e.preventDefault(); + editor.dblclick(e); + } + }, { + signal, + capture: true + }); + } + const annotationLayer = this.#annotationLayer; + const needFakeAnnotation = []; + if (annotationLayer) { + const changedAnnotations = new Map(); + const resetAnnotations = new Map(); + for (const editor of this.#allEditorsIterator) { + editor.disableEditing(); + if (!editor.annotationElementId) { + needFakeAnnotation.push(editor); + continue; + } + if (editor.serialize() !== null) { + changedAnnotations.set(editor.annotationElementId, editor); + continue; + } else { + resetAnnotations.set(editor.annotationElementId, editor); + } + this.getEditableAnnotation(editor.annotationElementId)?.show(); + editor.remove(); + } + const editables = annotationLayer.getEditableAnnotations(); + for (const editable of editables) { + const { + id + } = editable.data; + if (this.#uiManager.isDeletedAnnotationElement(id)) { + editable.updateEdited({ + deleted: true + }); + continue; + } + let editor = resetAnnotations.get(id); + if (editor) { + editor.resetAnnotationElement(editable); + editor.show(false); + editable.show(); + continue; + } + editor = changedAnnotations.get(id); + if (editor) { + this.#uiManager.addChangedExistingAnnotation(editor); + if (editor.renderAnnotationElement(editable)) { + editor.show(false); + } + } + editable.show(); + } + } + this.#cleanup(); + if (this.isEmpty) { + this.div.hidden = true; + } + const { + classList + } = this.div; + for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { + classList.remove(`${editorType._type}Editing`); + } + this.disableTextSelection(); + this.toggleAnnotationLayerPointerEvents(true); + annotationLayer?.updateFakeAnnotations(needFakeAnnotation); + this.#isDisabling = false; + } + getEditableAnnotation(id) { + return this.#annotationLayer?.getEditableAnnotation(id) || null; + } + setActiveEditor(editor) { + const currentActive = this.#uiManager.getActive(); + if (currentActive === editor) { + return; + } + this.#uiManager.setActiveEditor(editor); + } + enableTextSelection() { + this.div.tabIndex = -1; + if (this.#textLayer?.div && !this.#textSelectionAC) { + this.#textSelectionAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#textSelectionAC); + this.#textLayer.div.addEventListener("pointerdown", this.#textLayerPointerDown.bind(this), { + signal + }); + this.#textLayer.div.classList.add("highlighting"); + } + } + disableTextSelection() { + this.div.tabIndex = 0; + if (this.#textLayer?.div && this.#textSelectionAC) { + this.#textSelectionAC.abort(); + this.#textSelectionAC = null; + this.#textLayer.div.classList.remove("highlighting"); + } + } + #textLayerPointerDown(event) { + this.#uiManager.unselectAll(); + const { + target + } = event; + if (target === this.#textLayer.div || (target.getAttribute("role") === "img" || target.classList.contains("endOfContent")) && this.#textLayer.div.contains(target)) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + this.#uiManager.showAllEditors("highlight", true, true); + this.#textLayer.div.classList.add("free"); + this.toggleDrawing(); + HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", { + target: this.#textLayer.div, + x: event.x, + y: event.y + }); + this.#textLayer.div.addEventListener("pointerup", () => { + this.#textLayer.div.classList.remove("free"); + this.toggleDrawing(true); + }, { + once: true, + signal: this.#uiManager._signal + }); + event.preventDefault(); + } + } + enableClick() { + if (this.#clickAC) { + return; + } + this.#clickAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#clickAC); + this.div.addEventListener("pointerdown", this.pointerdown.bind(this), { + signal + }); + const pointerup = this.pointerup.bind(this); + this.div.addEventListener("pointerup", pointerup, { + signal + }); + this.div.addEventListener("pointercancel", pointerup, { + signal + }); + } + disableClick() { + this.#clickAC?.abort(); + this.#clickAC = null; + } + attach(editor) { + this.#editors.set(editor.id, editor); + const { + annotationElementId + } = editor; + if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) { + this.#uiManager.removeDeletedAnnotationElement(editor); + } + } + detach(editor) { + this.#editors.delete(editor.id); + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + if (!this.#isDisabling && editor.annotationElementId) { + this.#uiManager.addDeletedAnnotationElement(editor); + } + } + remove(editor) { + this.detach(editor); + this.#uiManager.removeEditor(editor); + editor.div.remove(); + editor.isAttachedToDOM = false; + } + changeParent(editor) { + if (editor.parent === this) { + return; + } + if (editor.parent && editor.annotationElementId) { + this.#uiManager.addDeletedAnnotationElement(editor); + AnnotationEditor.deleteAnnotationElement(editor); + editor.annotationElementId = null; + } + this.attach(editor); + editor.parent?.detach(editor); + editor.setParent(this); + if (editor.div && editor.isAttachedToDOM) { + editor.div.remove(); + this.div.append(editor.div); + } + } + add(editor) { + if (editor.parent === this && editor.isAttachedToDOM) { + return; + } + this.changeParent(editor); + this.#uiManager.addEditor(editor); + this.attach(editor); + if (!editor.isAttachedToDOM) { + const div = editor.render(); + this.div.append(div); + editor.isAttachedToDOM = true; + } + editor.fixAndSetPosition(); + editor.onceAdded(!this.#isEnabling); + this.#uiManager.addToAnnotationStorage(editor); + editor._reportTelemetry(editor.telemetryInitialData); + } + moveEditorInDOM(editor) { + if (!editor.isAttachedToDOM) { + return; + } + const { + activeElement + } = document; + if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) { + editor._focusEventsAllowed = false; + this.#editorFocusTimeoutId = setTimeout(() => { + this.#editorFocusTimeoutId = null; + if (!editor.div.contains(document.activeElement)) { + editor.div.addEventListener("focusin", () => { + editor._focusEventsAllowed = true; + }, { + once: true, + signal: this.#uiManager._signal + }); + activeElement.focus(); + } else { + editor._focusEventsAllowed = true; + } + }, 0); + } + editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true); + } + addOrRebuild(editor) { + if (editor.needsToBeRebuilt()) { + editor.parent ||= this; + editor.rebuild(); + editor.show(); + } else { + this.add(editor); + } + } + addUndoableEditor(editor) { + const cmd = () => editor._uiManager.rebuild(editor); + const undo = () => { + editor.remove(); + }; + this.addCommands({ + cmd, + undo, + mustExec: false + }); + } + getEditorByUID(uid) { + for (const editor of this.#editors.values()) { + if (editor.uid === uid) { + return editor; + } + } + return null; + } + getNextId() { + return this.#uiManager.getId(); + } + get #currentEditorType() { + return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode()); + } + combinedSignal(ac) { + return this.#uiManager.combinedSignal(ac); + } + #createNewEditor(params) { + const editorType = this.#currentEditorType; + return editorType ? new editorType.prototype.constructor(params) : null; + } + canCreateNewEmptyEditor() { + return this.#currentEditorType?.canCreateNewEmptyEditor(); + } + async pasteEditor(options, params) { + this.updateToolbar(options); + await this.#uiManager.updateMode(options.mode); + const { + offsetX, + offsetY + } = this.#getCenterPoint(); + const id = this.getNextId(); + const editor = this.#createNewEditor({ + parent: this, + id, + x: offsetX, + y: offsetY, + uiManager: this.#uiManager, + isCentered: true, + ...params + }); + if (editor) { + this.add(editor); + } + } + async deserialize(data) { + return (await AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager)) || null; + } + createAndAddNewEditor(event, isCentered, data = {}) { + const id = this.getNextId(); + const editor = this.#createNewEditor({ + parent: this, + id, + x: event.offsetX, + y: event.offsetY, + uiManager: this.#uiManager, + isCentered, + ...data + }); + if (editor) { + this.add(editor); + } + return editor; + } + get boundingClientRect() { + return this.div.getBoundingClientRect(); + } + #getCenterPoint() { + const { + x, + y, + width, + height + } = this.boundingClientRect; + const tlX = Math.max(0, x); + const tlY = Math.max(0, y); + const brX = Math.min(window.innerWidth, x + width); + const brY = Math.min(window.innerHeight, y + height); + const centerX = (tlX + brX) / 2 - x; + const centerY = (tlY + brY) / 2 - y; + const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX]; + return { + offsetX, + offsetY + }; + } + addNewEditor(data = {}) { + this.createAndAddNewEditor(this.#getCenterPoint(), true, data); + } + setSelected(editor) { + this.#uiManager.setSelected(editor); + } + toggleSelected(editor) { + this.#uiManager.toggleSelected(editor); + } + unselect(editor) { + this.#uiManager.unselect(editor); + } + pointerup(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + if (event.target !== this.div) { + return; + } + if (!this.#hadPointerDown) { + return; + } + this.#hadPointerDown = false; + if (this.#currentEditorType?.isDrawer && this.#currentEditorType.supportMultipleDrawings) { + return; + } + if (!this.#allowClick) { + this.#allowClick = true; + return; + } + const currentMode = this.#uiManager.getMode(); + if (currentMode === AnnotationEditorType.STAMP || currentMode === AnnotationEditorType.SIGNATURE) { + this.#uiManager.unselectAll(); + return; + } + this.createAndAddNewEditor(event, false); + } + pointerdown(event) { + if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) { + this.enableTextSelection(); + } + if (this.#hadPointerDown) { + this.#hadPointerDown = false; + return; + } + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + if (event.target !== this.div) { + return; + } + this.#hadPointerDown = true; + if (this.#currentEditorType?.isDrawer) { + this.startDrawingSession(event); + return; + } + const editor = this.#uiManager.getActive(); + this.#allowClick = !editor || editor.isEmpty(); + } + startDrawingSession(event) { + this.div.focus({ + preventScroll: true + }); + if (this.#drawingAC) { + this.#currentEditorType.startDrawing(this, this.#uiManager, false, event); + return; + } + this.#uiManager.setCurrentDrawingSession(this); + this.#drawingAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#drawingAC); + this.div.addEventListener("blur", ({ + relatedTarget + }) => { + if (relatedTarget && !this.div.contains(relatedTarget)) { + this.#focusedElement = null; + this.commitOrRemove(); + } + }, { + signal + }); + this.#currentEditorType.startDrawing(this, this.#uiManager, false, event); + } + pause(on) { + if (on) { + const { + activeElement + } = document; + if (this.div.contains(activeElement)) { + this.#focusedElement = activeElement; + } + return; + } + if (this.#focusedElement) { + setTimeout(() => { + this.#focusedElement?.focus(); + this.#focusedElement = null; + }, 0); + } + } + endDrawingSession(isAborted = false) { + if (!this.#drawingAC) { + return null; + } + this.#uiManager.setCurrentDrawingSession(null); + this.#drawingAC.abort(); + this.#drawingAC = null; + this.#focusedElement = null; + return this.#currentEditorType.endDrawing(isAborted); + } + findNewParent(editor, x, y) { + const layer = this.#uiManager.findParent(x, y); + if (layer === null || layer === this) { + return false; + } + layer.changeParent(editor); + return true; + } + commitOrRemove() { + if (this.#drawingAC) { + this.endDrawingSession(); + return true; + } + return false; + } + onScaleChanging() { + if (!this.#drawingAC) { + return; + } + this.#currentEditorType.onScaleChangingWhenDrawing(this); + } + destroy() { + this.commitOrRemove(); + if (this.#uiManager.getActive()?.parent === this) { + this.#uiManager.commitOrRemove(); + this.#uiManager.setActiveEditor(null); + } + if (this.#editorFocusTimeoutId) { + clearTimeout(this.#editorFocusTimeoutId); + this.#editorFocusTimeoutId = null; + } + for (const editor of this.#editors.values()) { + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + editor.setParent(null); + editor.isAttachedToDOM = false; + editor.div.remove(); + } + this.div = null; + this.#editors.clear(); + this.#uiManager.removeLayer(this); + } + #cleanup() { + for (const editor of this.#editors.values()) { + if (editor.isEmpty()) { + editor.remove(); + } + } + } + render({ + viewport + }) { + this.viewport = viewport; + setLayerDimensions(this.div, viewport); + for (const editor of this.#uiManager.getEditors(this.pageIndex)) { + this.add(editor); + editor.rebuild(); + } + this.updateMode(); + } + update({ + viewport + }) { + this.#uiManager.commitOrRemove(); + this.#cleanup(); + const oldRotation = this.viewport.rotation; + const rotation = viewport.rotation; + this.viewport = viewport; + setLayerDimensions(this.div, { + rotation + }); + if (oldRotation !== rotation) { + for (const editor of this.#editors.values()) { + editor.rotate(rotation); + } + } + } + get pageDimensions() { + const { + pageWidth, + pageHeight + } = this.viewport.rawDims; + return [pageWidth, pageHeight]; + } + get scale() { + return this.#uiManager.viewParameters.realScale; + } +} + +;// ./src/display/draw_layer.js + + +class DrawLayer { + #parent = null; + #mapping = new Map(); + #toUpdate = new Map(); + static #id = 0; + constructor({ + pageIndex + }) { + this.pageIndex = pageIndex; + } + setParent(parent) { + if (!this.#parent) { + this.#parent = parent; + return; + } + if (this.#parent !== parent) { + if (this.#mapping.size > 0) { + for (const root of this.#mapping.values()) { + root.remove(); + parent.append(root); + } + } + this.#parent = parent; + } + } + static get _svgFactory() { + return shadow(this, "_svgFactory", new DOMSVGFactory()); + } + static #setBox(element, [x, y, width, height]) { + const { + style + } = element; + style.top = `${100 * y}%`; + style.left = `${100 * x}%`; + style.width = `${100 * width}%`; + style.height = `${100 * height}%`; + } + #createSVG() { + const svg = DrawLayer._svgFactory.create(1, 1, true); + this.#parent.append(svg); + svg.setAttribute("aria-hidden", true); + return svg; + } + #createClipPath(defs, pathId) { + const clipPath = DrawLayer._svgFactory.createElement("clipPath"); + defs.append(clipPath); + const clipPathId = `clip_${pathId}`; + clipPath.setAttribute("id", clipPathId); + clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); + const clipPathUse = DrawLayer._svgFactory.createElement("use"); + clipPath.append(clipPathUse); + clipPathUse.setAttribute("href", `#${pathId}`); + clipPathUse.classList.add("clip"); + return clipPathId; + } + #updateProperties(element, properties) { + for (const [key, value] of Object.entries(properties)) { + if (value === null) { + element.removeAttribute(key); + } else { + element.setAttribute(key, value); + } + } + } + draw(properties, isPathUpdatable = false, hasClip = false) { + const id = DrawLayer.#id++; + const root = this.#createSVG(); + const defs = DrawLayer._svgFactory.createElement("defs"); + root.append(defs); + const path = DrawLayer._svgFactory.createElement("path"); + defs.append(path); + const pathId = `path_p${this.pageIndex}_${id}`; + path.setAttribute("id", pathId); + path.setAttribute("vector-effect", "non-scaling-stroke"); + if (isPathUpdatable) { + this.#toUpdate.set(id, path); + } + const clipPathId = hasClip ? this.#createClipPath(defs, pathId) : null; + const use = DrawLayer._svgFactory.createElement("use"); + root.append(use); + use.setAttribute("href", `#${pathId}`); + this.updateProperties(root, properties); + this.#mapping.set(id, root); + return { + id, + clipPathId: `url(#${clipPathId})` + }; + } + drawOutline(properties, mustRemoveSelfIntersections) { + const id = DrawLayer.#id++; + const root = this.#createSVG(); + const defs = DrawLayer._svgFactory.createElement("defs"); + root.append(defs); + const path = DrawLayer._svgFactory.createElement("path"); + defs.append(path); + const pathId = `path_p${this.pageIndex}_${id}`; + path.setAttribute("id", pathId); + path.setAttribute("vector-effect", "non-scaling-stroke"); + let maskId; + if (mustRemoveSelfIntersections) { + const mask = DrawLayer._svgFactory.createElement("mask"); + defs.append(mask); + maskId = `mask_p${this.pageIndex}_${id}`; + mask.setAttribute("id", maskId); + mask.setAttribute("maskUnits", "objectBoundingBox"); + const rect = DrawLayer._svgFactory.createElement("rect"); + mask.append(rect); + rect.setAttribute("width", "1"); + rect.setAttribute("height", "1"); + rect.setAttribute("fill", "white"); + const use = DrawLayer._svgFactory.createElement("use"); + mask.append(use); + use.setAttribute("href", `#${pathId}`); + use.setAttribute("stroke", "none"); + use.setAttribute("fill", "black"); + use.setAttribute("fill-rule", "nonzero"); + use.classList.add("mask"); + } + const use1 = DrawLayer._svgFactory.createElement("use"); + root.append(use1); + use1.setAttribute("href", `#${pathId}`); + if (maskId) { + use1.setAttribute("mask", `url(#${maskId})`); + } + const use2 = use1.cloneNode(); + root.append(use2); + use1.classList.add("mainOutline"); + use2.classList.add("secondaryOutline"); + this.updateProperties(root, properties); + this.#mapping.set(id, root); + return id; + } + finalizeDraw(id, properties) { + this.#toUpdate.delete(id); + this.updateProperties(id, properties); + } + updateProperties(elementOrId, properties) { + if (!properties) { + return; + } + const { + root, + bbox, + rootClass, + path + } = properties; + const element = typeof elementOrId === "number" ? this.#mapping.get(elementOrId) : elementOrId; + if (!element) { + return; + } + if (root) { + this.#updateProperties(element, root); + } + if (bbox) { + DrawLayer.#setBox(element, bbox); + } + if (rootClass) { + const { + classList + } = element; + for (const [className, value] of Object.entries(rootClass)) { + classList.toggle(className, value); + } + } + if (path) { + const defs = element.firstElementChild; + const pathElement = defs.firstElementChild; + this.#updateProperties(pathElement, path); + } + } + updateParent(id, layer) { + if (layer === this) { + return; + } + const root = this.#mapping.get(id); + if (!root) { + return; + } + layer.#parent.append(root); + this.#mapping.delete(id); + layer.#mapping.set(id, root); + } + remove(id) { + this.#toUpdate.delete(id); + if (this.#parent === null) { + return; + } + this.#mapping.get(id).remove(); + this.#mapping.delete(id); + } + destroy() { + this.#parent = null; + for (const root of this.#mapping.values()) { + root.remove(); + } + this.#mapping.clear(); + this.#toUpdate.clear(); + } +} + +;// ./src/pdf.js + + + + + + + + + + + + + + + + +globalThis.pdfjsLib = { + AbortException: AbortException, + AnnotationEditorLayer: AnnotationEditorLayer, + AnnotationEditorParamsType: AnnotationEditorParamsType, + AnnotationEditorType: AnnotationEditorType, + AnnotationEditorUIManager: AnnotationEditorUIManager, + AnnotationLayer: AnnotationLayer, + AnnotationMode: AnnotationMode, + AnnotationType: AnnotationType, + applyOpacity: applyOpacity, + build: build, + ColorPicker: ColorPicker, + createValidAbsoluteUrl: createValidAbsoluteUrl, + CSSConstants: CSSConstants, + DOMSVGFactory: DOMSVGFactory, + DrawLayer: DrawLayer, + FeatureTest: util_FeatureTest, + fetchData: fetchData, + findContrastColor: findContrastColor, + getDocument: getDocument, + getFilenameFromUrl: getFilenameFromUrl, + getPdfFilenameFromUrl: getPdfFilenameFromUrl, + getRGB: getRGB, + getUuid: getUuid, + getXfaPageViewport: getXfaPageViewport, + GlobalWorkerOptions: GlobalWorkerOptions, + ImageKind: util_ImageKind, + InvalidPDFException: InvalidPDFException, + isDataScheme: isDataScheme, + isPdfFile: isPdfFile, + isValidExplicitDest: isValidExplicitDest, + MathClamp: MathClamp, + noContextMenu: noContextMenu, + normalizeUnicode: normalizeUnicode, + OPS: OPS, + OutputScale: OutputScale, + PasswordResponses: PasswordResponses, + PDFDataRangeTransport: PDFDataRangeTransport, + PDFDateString: PDFDateString, + PDFWorker: PDFWorker, + PermissionFlag: PermissionFlag, + PixelsPerInch: PixelsPerInch, + RenderingCancelledException: RenderingCancelledException, + renderRichText: renderRichText, + ResponseException: ResponseException, + setLayerDimensions: setLayerDimensions, + shadow: shadow, + SignatureExtractor: SignatureExtractor, + stopEvent: stopEvent, + SupportedImageMimeTypes: SupportedImageMimeTypes, + TextLayer: TextLayer, + TouchManager: TouchManager, + updateUrlHash: updateUrlHash, + Util: Util, + VerbosityLevel: VerbosityLevel, + version: version, + XfaLayer: XfaLayer +}; + +export { AbortException, AnnotationEditorLayer, AnnotationEditorParamsType, AnnotationEditorType, AnnotationEditorUIManager, AnnotationLayer, AnnotationMode, AnnotationType, CSSConstants, ColorPicker, DOMSVGFactory, DrawLayer, util_FeatureTest as FeatureTest, GlobalWorkerOptions, util_ImageKind as ImageKind, InvalidPDFException, MathClamp, OPS, OutputScale, PDFDataRangeTransport, PDFDateString, PDFWorker, PasswordResponses, PermissionFlag, PixelsPerInch, RenderingCancelledException, ResponseException, SignatureExtractor, SupportedImageMimeTypes, TextLayer, TouchManager, Util, VerbosityLevel, XfaLayer, applyOpacity, build, createValidAbsoluteUrl, fetchData, findContrastColor, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl, getRGB, getUuid, getXfaPageViewport, isDataScheme, isPdfFile, isValidExplicitDest, noContextMenu, normalizeUnicode, renderRichText, setLayerDimensions, shadow, stopEvent, updateUrlHash, version }; diff --git a/pdf.worker.mjs b/pdf.worker.mjs new file mode 100644 index 0000000..ffb62ab --- /dev/null +++ b/pdf.worker.mjs @@ -0,0 +1,60412 @@ +/** + * @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.445 + * pdfjsBuild = ec5330f78 + */ +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; + +;// ./src/shared/util.js +const isNodeJS = false; +const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; +const LINE_FACTOR = 1.35; +const LINE_DESCENT_FACTOR = 0.35; +const BASELINE_FACTOR = LINE_DESCENT_FACTOR / LINE_FACTOR; +const RenderingIntentFlag = { + ANY: 0x01, + DISPLAY: 0x02, + PRINT: 0x04, + SAVE: 0x08, + ANNOTATIONS_FORMS: 0x10, + ANNOTATIONS_STORAGE: 0x20, + ANNOTATIONS_DISABLE: 0x40, + IS_EDITING: 0x80, + OPLIST: 0x100 +}; +const AnnotationMode = { + DISABLE: 0, + ENABLE: 1, + ENABLE_FORMS: 2, + ENABLE_STORAGE: 3 +}; +const AnnotationEditorPrefix = "pdfjs_internal_editor_"; +const AnnotationEditorType = { + DISABLE: -1, + NONE: 0, + FREETEXT: 3, + HIGHLIGHT: 9, + STAMP: 13, + INK: 15, + POPUP: 16, + SIGNATURE: 101, + COMMENT: 102 +}; +const AnnotationEditorParamsType = { + RESIZE: 1, + CREATE: 2, + FREETEXT_SIZE: 11, + FREETEXT_COLOR: 12, + FREETEXT_OPACITY: 13, + INK_COLOR: 21, + INK_THICKNESS: 22, + INK_OPACITY: 23, + HIGHLIGHT_COLOR: 31, + HIGHLIGHT_THICKNESS: 32, + HIGHLIGHT_FREE: 33, + HIGHLIGHT_SHOW_ALL: 34, + DRAW_STEP: 41 +}; +const PermissionFlag = { + PRINT: 0x04, + MODIFY_CONTENTS: 0x08, + COPY: 0x10, + MODIFY_ANNOTATIONS: 0x20, + FILL_INTERACTIVE_FORMS: 0x100, + COPY_FOR_ACCESSIBILITY: 0x200, + ASSEMBLE: 0x400, + PRINT_HIGH_QUALITY: 0x800 +}; +const MeshFigureType = { + TRIANGLES: 1, + LATTICE: 2, + PATCH: 3 +}; +const TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; +const ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; +const AnnotationType = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 +}; +const AnnotationReplyType = { + GROUP: "Group", + REPLY: "R" +}; +const AnnotationFlag = { + INVISIBLE: 0x01, + HIDDEN: 0x02, + PRINT: 0x04, + NOZOOM: 0x08, + NOROTATE: 0x10, + NOVIEW: 0x20, + READONLY: 0x40, + LOCKED: 0x80, + TOGGLENOVIEW: 0x100, + LOCKEDCONTENTS: 0x200 +}; +const AnnotationFieldFlag = { + READONLY: 0x0000001, + REQUIRED: 0x0000002, + NOEXPORT: 0x0000004, + MULTILINE: 0x0001000, + PASSWORD: 0x0002000, + NOTOGGLETOOFF: 0x0004000, + RADIO: 0x0008000, + PUSHBUTTON: 0x0010000, + COMBO: 0x0020000, + EDIT: 0x0040000, + SORT: 0x0080000, + FILESELECT: 0x0100000, + MULTISELECT: 0x0200000, + DONOTSPELLCHECK: 0x0400000, + DONOTSCROLL: 0x0800000, + COMB: 0x1000000, + RICHTEXT: 0x2000000, + RADIOSINUNISON: 0x2000000, + COMMITONSELCHANGE: 0x4000000 +}; +const AnnotationBorderStyleType = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 +}; +const AnnotationActionEventType = { + E: "Mouse Enter", + X: "Mouse Exit", + D: "Mouse Down", + U: "Mouse Up", + Fo: "Focus", + Bl: "Blur", + PO: "PageOpen", + PC: "PageClose", + PV: "PageVisible", + PI: "PageInvisible", + K: "Keystroke", + F: "Format", + V: "Validate", + C: "Calculate" +}; +const DocumentActionEventType = { + WC: "WillClose", + WS: "WillSave", + DS: "DidSave", + WP: "WillPrint", + DP: "DidPrint" +}; +const PageActionEventType = { + O: "PageOpen", + C: "PageClose" +}; +const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 +}; +const OPS = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotation: 80, + endAnnotation: 81, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91, + setStrokeTransparent: 92, + setFillTransparent: 93, + rawFillPath: 94 +}; +const DrawOPS = { + moveTo: 0, + lineTo: 1, + curveTo: 2, + quadraticCurveTo: 3, + closePath: 4 +}; +const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; +let verbosity = VerbosityLevel.WARNINGS; +function setVerbosityLevel(level) { + if (Number.isInteger(level)) { + verbosity = level; + } +} +function getVerbosityLevel() { + return verbosity; +} +function info(msg) { + if (verbosity >= VerbosityLevel.INFOS) { + console.info(`Info: ${msg}`); + } +} +function warn(msg) { + if (verbosity >= VerbosityLevel.WARNINGS) { + console.warn(`Warning: ${msg}`); + } +} +function unreachable(msg) { + throw new Error(msg); +} +function assert(cond, msg) { + if (!cond) { + unreachable(msg); + } +} +function _isValidProtocol(url) { + switch (url?.protocol) { + case "http:": + case "https:": + case "ftp:": + case "mailto:": + case "tel:": + return true; + default: + return false; + } +} +function createValidAbsoluteUrl(url, baseUrl = null, options = null) { + if (!url) { + return null; + } + if (options && typeof url === "string") { + if (options.addDefaultProtocol && url.startsWith("www.")) { + const dots = url.match(/\./g); + if (dots?.length >= 2) { + url = `http://${url}`; + } + } + if (options.tryConvertEncoding) { + try { + url = stringToUTF8String(url); + } catch {} + } + } + const absoluteUrl = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url); + return _isValidProtocol(absoluteUrl) ? absoluteUrl : null; +} +function updateUrlHash(url, hash, allowRel = false) { + const res = URL.parse(url); + if (res) { + res.hash = hash; + return res.href; + } + if (allowRel && createValidAbsoluteUrl(url, "http://example.com")) { + return url.split("#", 1)[0] + `${hash ? `#${hash}` : ""}`; + } + return ""; +} +function shadow(obj, prop, value, nonSerializable = false) { + Object.defineProperty(obj, prop, { + value, + enumerable: !nonSerializable, + configurable: true, + writable: false + }); + return value; +} +const BaseException = function BaseExceptionClosure() { + function BaseException(message, name) { + this.message = message; + this.name = name; + } + BaseException.prototype = new Error(); + BaseException.constructor = BaseException; + return BaseException; +}(); +class PasswordException extends BaseException { + constructor(msg, code) { + super(msg, "PasswordException"); + this.code = code; + } +} +class UnknownErrorException extends BaseException { + constructor(msg, details) { + super(msg, "UnknownErrorException"); + this.details = details; + } +} +class InvalidPDFException extends BaseException { + constructor(msg) { + super(msg, "InvalidPDFException"); + } +} +class ResponseException extends BaseException { + constructor(msg, status, missing) { + super(msg, "ResponseException"); + this.status = status; + this.missing = missing; + } +} +class FormatError extends BaseException { + constructor(msg) { + super(msg, "FormatError"); + } +} +class AbortException extends BaseException { + constructor(msg) { + super(msg, "AbortException"); + } +} +function bytesToString(bytes) { + if (typeof bytes !== "object" || bytes?.length === undefined) { + unreachable("Invalid argument for bytesToString"); + } + const length = bytes.length; + const MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + const strBuf = []; + for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + const chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(""); +} +function stringToBytes(str) { + if (typeof str !== "string") { + unreachable("Invalid argument for stringToBytes"); + } + const length = str.length; + const bytes = new Uint8Array(length); + for (let i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xff; + } + return bytes; +} +function string32(value) { + return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); +} +function objectSize(obj) { + return Object.keys(obj).length; +} +function isLittleEndian() { + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + return view32[0] === 1; +} +function isEvalSupported() { + try { + new Function(""); + return true; + } catch { + return false; + } +} +class FeatureTest { + static get isLittleEndian() { + return shadow(this, "isLittleEndian", isLittleEndian()); + } + static get isEvalSupported() { + return shadow(this, "isEvalSupported", isEvalSupported()); + } + static get isOffscreenCanvasSupported() { + return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); + } + static get isImageDecoderSupported() { + return shadow(this, "isImageDecoderSupported", typeof ImageDecoder !== "undefined"); + } + static get isFloat16ArraySupported() { + return shadow(this, "isFloat16ArraySupported", typeof Float16Array !== "undefined"); + } + static get isSanitizerSupported() { + return shadow(this, "isSanitizerSupported", typeof Sanitizer !== "undefined"); + } + static get platform() { + const { + platform, + userAgent + } = navigator; + return shadow(this, "platform", { + isAndroid: userAgent.includes("Android"), + isLinux: platform.includes("Linux"), + isMac: platform.includes("Mac"), + isWindows: platform.includes("Win"), + isFirefox: true + }); + } + static get isCSSRoundSupported() { + return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)")); + } +} +const hexNumbers = Array.from(Array(256).keys(), n => n.toString(16).padStart(2, "0")); +class Util { + static makeHexColor(r, g, b) { + return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; + } + static domMatrixToTransform(dm) { + return [dm.a, dm.b, dm.c, dm.d, dm.e, dm.f]; + } + static scaleMinMax(transform, minMax) { + let temp; + if (transform[0]) { + if (transform[0] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[0]; + minMax[2] *= transform[0]; + if (transform[3] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[3]; + minMax[3] *= transform[3]; + } else { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + if (transform[1] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[1]; + minMax[3] *= transform[1]; + if (transform[2] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[2]; + minMax[2] *= transform[2]; + } + minMax[0] += transform[4]; + minMax[1] += transform[5]; + minMax[2] += transform[4]; + minMax[3] += transform[5]; + } + static transform(m1, m2) { + return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; + } + static multiplyByDOMMatrix(m, md) { + return [m[0] * md.a + m[2] * md.b, m[1] * md.a + m[3] * md.b, m[0] * md.c + m[2] * md.d, m[1] * md.c + m[3] * md.d, m[0] * md.e + m[2] * md.f + m[4], m[1] * md.e + m[3] * md.f + m[5]]; + } + static applyTransform(p, m, pos = 0) { + const p0 = p[pos]; + const p1 = p[pos + 1]; + p[pos] = p0 * m[0] + p1 * m[2] + m[4]; + p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5]; + } + static applyTransformToBezier(p, transform, pos = 0) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + for (let i = 0; i < 6; i += 2) { + const pI = p[pos + i]; + const pI1 = p[pos + i + 1]; + p[pos + i] = pI * m0 + pI1 * m2 + m4; + p[pos + i + 1] = pI * m1 + pI1 * m3 + m5; + } + } + static applyInverseTransform(p, m) { + const p0 = p[0]; + const p1 = p[1]; + const d = m[0] * m[3] - m[1] * m[2]; + p[0] = (p0 * m[3] - p1 * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + p[1] = (-p0 * m[1] + p1 * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + } + static axialAlignedBoundingBox(rect, transform, output) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + const r0 = rect[0]; + const r1 = rect[1]; + const r2 = rect[2]; + const r3 = rect[3]; + let a0 = m0 * r0 + m4; + let a2 = a0; + let a1 = m0 * r2 + m4; + let a3 = a1; + let b0 = m3 * r1 + m5; + let b2 = b0; + let b1 = m3 * r3 + m5; + let b3 = b1; + if (m1 !== 0 || m2 !== 0) { + const m1r0 = m1 * r0; + const m1r2 = m1 * r2; + const m2r1 = m2 * r1; + const m2r3 = m2 * r3; + a0 += m2r1; + a3 += m2r1; + a1 += m2r3; + a2 += m2r3; + b0 += m1r0; + b3 += m1r0; + b1 += m1r2; + b2 += m1r2; + } + output[0] = Math.min(output[0], a0, a1, a2, a3); + output[1] = Math.min(output[1], b0, b1, b2, b3); + output[2] = Math.max(output[2], a0, a1, a2, a3); + output[3] = Math.max(output[3], b0, b1, b2, b3); + } + static inverseTransform(m) { + const d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + } + static singularValueDecompose2dScale(matrix, output) { + const m0 = matrix[0]; + const m1 = matrix[1]; + const m2 = matrix[2]; + const m3 = matrix[3]; + const a = m0 ** 2 + m1 ** 2; + const b = m0 * m2 + m1 * m3; + const c = m2 ** 2 + m3 ** 2; + const first = (a + c) / 2; + const second = Math.sqrt(first ** 2 - (a * c - b ** 2)); + output[0] = Math.sqrt(first + second || 1); + output[1] = Math.sqrt(first - second || 1); + } + static normalizeRect(rect) { + const r = rect.slice(0); + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + } + static intersect(rect1, rect2) { + const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); + const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); + if (xLow > xHigh) { + return null; + } + const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); + const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); + if (yLow > yHigh) { + return null; + } + return [xLow, yLow, xHigh, yHigh]; + } + static pointBoundingBox(x, y, minMax) { + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static rectBoundingBox(x0, y0, x1, y1, minMax) { + minMax[0] = Math.min(minMax[0], x0, x1); + minMax[1] = Math.min(minMax[1], y0, y1); + minMax[2] = Math.max(minMax[2], x0, x1); + minMax[3] = Math.max(minMax[3], y0, y1); + } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; + } + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); + } + return; + } + const delta = b ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + } +} +const PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2d8, 0x2c7, 0x2c6, 0x2d9, 0x2dd, 0x2db, 0x2da, 0x2dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x141, 0x152, 0x160, 0x178, 0x17d, 0x131, 0x142, 0x153, 0x161, 0x17e, 0, 0x20ac]; +function stringToPDFString(str, keepEscapeSequence = false) { + if (str[0] >= "\xEF") { + let encoding; + if (str[0] === "\xFE" && str[1] === "\xFF") { + encoding = "utf-16be"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xFF" && str[1] === "\xFE") { + encoding = "utf-16le"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") { + encoding = "utf-8"; + } + if (encoding) { + try { + const decoder = new TextDecoder(encoding, { + fatal: true + }); + const buffer = stringToBytes(str); + const decoded = decoder.decode(buffer); + if (keepEscapeSequence || !decoded.includes("\x1b")) { + return decoded; + } + return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, ""); + } catch (ex) { + warn(`stringToPDFString: "${ex}".`); + } + } + } + const strBuf = []; + for (let i = 0, ii = str.length; i < ii; i++) { + const charCode = str.charCodeAt(i); + if (!keepEscapeSequence && charCode === 0x1b) { + while (++i < ii && str.charCodeAt(i) !== 0x1b) {} + continue; + } + const code = PDFStringTranslateTable[charCode]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + return strBuf.join(""); +} +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} +function isArrayEqual(arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + for (let i = 0, ii = arr1.length; i < ii; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + return true; +} +function getModificationDate(date = new Date()) { + if (!(date instanceof Date)) { + date = new Date(date); + } + const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")]; + return buffer.join(""); +} +let NormalizeRegex = null; +let NormalizationMap = null; +function normalizeUnicode(str) { + if (!NormalizeRegex) { + NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; + NormalizationMap = new Map([["ſt", "ſt"]]); + } + return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); +} +function getUuid() { + return crypto.randomUUID(); +} +const AnnotationPrefix = "pdfjs_internal_id_"; +function _isValidExplicitDest(validRef, validName, dest) { + if (!Array.isArray(dest) || dest.length < 2) { + return false; + } + const [page, zoom, ...args] = dest; + if (!validRef(page) && !Number.isInteger(page)) { + return false; + } + if (!validName(zoom)) { + return false; + } + const argsLen = args.length; + let allowNull = true; + switch (zoom.name) { + case "XYZ": + if (argsLen < 2 || argsLen > 3) { + return false; + } + break; + case "Fit": + case "FitB": + return argsLen === 0; + case "FitH": + case "FitBH": + case "FitV": + case "FitBV": + if (argsLen > 1) { + return false; + } + break; + case "FitR": + if (argsLen !== 4) { + return false; + } + allowNull = false; + break; + default: + return false; + } + for (const arg of args) { + if (typeof arg === "number" || allowNull && arg === null) { + continue; + } + return false; + } + return true; +} +function MathClamp(v, min, max) { + return Math.min(Math.max(v, min), max); +} +function toHexUtil(arr) { + if (Uint8Array.prototype.toHex) { + return arr.toHex(); + } + return Array.from(arr, num => hexNumbers[num]).join(""); +} +function toBase64Util(arr) { + if (Uint8Array.prototype.toBase64) { + return arr.toBase64(); + } + return btoa(bytesToString(arr)); +} +function fromBase64Util(str) { + if (Uint8Array.fromBase64) { + return Uint8Array.fromBase64(str); + } + return stringToBytes(atob(str)); +} +if (typeof Promise.try !== "function") { + Promise.try = function (fn, ...args) { + return new Promise(resolve => { + resolve(fn(...args)); + }); + }; +} +if (typeof Math.sumPrecise !== "function") { + Math.sumPrecise = function (numbers) { + return numbers.reduce((a, b) => a + b, 0); + }; +} + +;// ./src/core/primitives.js + +const CIRCULAR_REF = Symbol("CIRCULAR_REF"); +const EOF = Symbol("EOF"); +let CmdCache = Object.create(null); +let NameCache = Object.create(null); +let RefCache = Object.create(null); +function clearPrimitiveCaches() { + CmdCache = Object.create(null); + NameCache = Object.create(null); + RefCache = Object.create(null); +} +class Name { + constructor(name) { + this.name = name; + } + static get(name) { + return NameCache[name] ||= new Name(name); + } +} +class Cmd { + constructor(cmd) { + this.cmd = cmd; + } + static get(cmd) { + return CmdCache[cmd] ||= new Cmd(cmd); + } +} +const nonSerializable = function nonSerializableClosure() { + return nonSerializable; +}; +class Dict { + constructor(xref = null) { + this._map = new Map(); + this.xref = xref; + this.objId = null; + this.suppressEncryption = false; + this.__nonSerializable__ = nonSerializable; + } + assignXref(newXref) { + this.xref = newXref; + } + get size() { + return this._map.size; + } + get(key1, key2, key3) { + let value = this._map.get(key1); + if (value === undefined && key2 !== undefined) { + value = this._map.get(key2); + if (value === undefined && key3 !== undefined) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + return this.xref.fetch(value, this.suppressEncryption); + } + return value; + } + async getAsync(key1, key2, key3) { + let value = this._map.get(key1); + if (value === undefined && key2 !== undefined) { + value = this._map.get(key2); + if (value === undefined && key3 !== undefined) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + return this.xref.fetchAsync(value, this.suppressEncryption); + } + return value; + } + getArray(key1, key2, key3) { + let value = this._map.get(key1); + if (value === undefined && key2 !== undefined) { + value = this._map.get(key2); + if (value === undefined && key3 !== undefined) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + value = this.xref.fetch(value, this.suppressEncryption); + } + if (Array.isArray(value)) { + value = value.slice(); + for (let i = 0, ii = value.length; i < ii; i++) { + if (value[i] instanceof Ref && this.xref) { + value[i] = this.xref.fetch(value[i], this.suppressEncryption); + } + } + } + return value; + } + getRaw(key) { + return this._map.get(key); + } + getKeys() { + return [...this._map.keys()]; + } + getRawValues() { + return [...this._map.values()]; + } + getRawEntries() { + return this._map.entries(); + } + set(key, value) { + this._map.set(key, value); + } + setIfNotExists(key, value) { + if (!this.has(key)) { + this.set(key, value); + } + } + setIfNumber(key, value) { + if (typeof value === "number") { + this.set(key, value); + } + } + setIfArray(key, value) { + if (Array.isArray(value) || ArrayBuffer.isView(value)) { + this.set(key, value); + } + } + setIfDefined(key, value) { + if (value !== undefined && value !== null) { + this.set(key, value); + } + } + setIfName(key, value) { + if (typeof value === "string") { + this.set(key, Name.get(value)); + } else if (value instanceof Name) { + this.set(key, value); + } + } + setIfDict(key, value) { + if (value instanceof Dict) { + this.set(key, value); + } + } + has(key) { + return this._map.has(key); + } + *[Symbol.iterator]() { + for (const [key, value] of this._map) { + yield [key, value instanceof Ref && this.xref ? this.xref.fetch(value, this.suppressEncryption) : value]; + } + } + static get empty() { + const emptyDict = new Dict(null); + emptyDict.set = (key, value) => { + unreachable("Should not call `set` on the empty dictionary."); + }; + return shadow(this, "empty", emptyDict); + } + static merge({ + xref, + dictArray, + mergeSubDicts = false + }) { + const mergedDict = new Dict(xref), + properties = new Map(); + for (const dict of dictArray) { + if (!(dict instanceof Dict)) { + continue; + } + for (const [key, value] of dict._map) { + let property = properties.get(key); + if (property === undefined) { + property = []; + properties.set(key, property); + } else if (!mergeSubDicts || !(value instanceof Dict)) { + continue; + } + property.push(value); + } + } + for (const [name, values] of properties) { + if (values.length === 1 || !(values[0] instanceof Dict)) { + mergedDict._map.set(name, values[0]); + continue; + } + const subDict = new Dict(xref); + for (const dict of values) { + for (const [key, value] of dict._map) { + if (!subDict._map.has(key)) { + subDict._map.set(key, value); + } + } + } + if (subDict.size > 0) { + mergedDict._map.set(name, subDict); + } + } + properties.clear(); + return mergedDict.size > 0 ? mergedDict : Dict.empty; + } + clone() { + const dict = new Dict(this.xref); + for (const key of this.getKeys()) { + dict.set(key, this.getRaw(key)); + } + return dict; + } + delete(key) { + this._map.delete(key); + } +} +class Ref { + constructor(num, gen) { + this.num = num; + this.gen = gen; + } + toString() { + if (this.gen === 0) { + return `${this.num}R`; + } + return `${this.num}R${this.gen}`; + } + static fromString(str) { + const ref = RefCache[str]; + if (ref) { + return ref; + } + const m = /^(\d+)R(\d*)$/.exec(str); + if (!m || m[1] === "0") { + return null; + } + return RefCache[str] = new Ref(parseInt(m[1]), !m[2] ? 0 : parseInt(m[2])); + } + static get(num, gen) { + const key = gen === 0 ? `${num}R` : `${num}R${gen}`; + return RefCache[key] ||= new Ref(num, gen); + } +} +class RefSet { + constructor(parent = null) { + this._set = new Set(parent?._set); + } + has(ref) { + return this._set.has(ref.toString()); + } + put(ref) { + this._set.add(ref.toString()); + } + remove(ref) { + this._set.delete(ref.toString()); + } + [Symbol.iterator]() { + return this._set.values(); + } + clear() { + this._set.clear(); + } +} +class RefSetCache { + constructor() { + this._map = new Map(); + } + get size() { + return this._map.size; + } + get(ref) { + return this._map.get(ref.toString()); + } + has(ref) { + return this._map.has(ref.toString()); + } + put(ref, obj) { + this._map.set(ref.toString(), obj); + } + putAlias(ref, aliasRef) { + this._map.set(ref.toString(), this.get(aliasRef)); + } + [Symbol.iterator]() { + return this._map.values(); + } + clear() { + this._map.clear(); + } + *values() { + yield* this._map.values(); + } + *items() { + for (const [ref, value] of this._map) { + yield [Ref.fromString(ref), value]; + } + } + *keys() { + for (const ref of this._map.keys()) { + yield Ref.fromString(ref); + } + } +} +function isName(v, name) { + return v instanceof Name && (name === undefined || v.name === name); +} +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} +function isDict(v, type) { + return v instanceof Dict && (type === undefined || isName(v.get("Type"), type)); +} +function isRefsEqual(v1, v2) { + return v1.num === v2.num && v1.gen === v2.gen; +} + +;// ./src/core/base_stream.js + +class BaseStream { + get length() { + unreachable("Abstract getter `length` accessed"); + } + get isEmpty() { + unreachable("Abstract getter `isEmpty` accessed"); + } + get isDataLoaded() { + return shadow(this, "isDataLoaded", true); + } + getByte() { + unreachable("Abstract method `getByte` called"); + } + getBytes(length) { + unreachable("Abstract method `getBytes` called"); + } + async getImageData(length, decoderOptions) { + return this.getBytes(length, decoderOptions); + } + async asyncGetBytes() { + unreachable("Abstract method `asyncGetBytes` called"); + } + get isAsync() { + return false; + } + get isAsyncDecoder() { + return false; + } + get canAsyncDecodeImageFromBuffer() { + return false; + } + async getTransferableImage() { + return null; + } + peekByte() { + const peekedByte = this.getByte(); + if (peekedByte !== -1) { + this.pos--; + } + return peekedByte; + } + peekBytes(length) { + const bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + } + getUint16() { + const b0 = this.getByte(); + const b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + } + getInt32() { + const b0 = this.getByte(); + const b1 = this.getByte(); + const b2 = this.getByte(); + const b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + getByteRange(begin, end) { + unreachable("Abstract method `getByteRange` called"); + } + getString(length) { + return bytesToString(this.getBytes(length)); + } + skip(n) { + this.pos += n || 1; + } + reset() { + unreachable("Abstract method `reset` called"); + } + moveStart() { + unreachable("Abstract method `moveStart` called"); + } + makeSubStream(start, length, dict = null) { + unreachable("Abstract method `makeSubStream` called"); + } + getBaseStreams() { + return null; + } + getOriginalStream() { + return this.stream?.getOriginalStream() || this; + } +} + +;// ./src/core/core_utils.js + + + +const PDF_VERSION_REGEXP = /^[1-9]\.\d$/; +const MAX_INT_32 = 2 ** 31 - 1; +const MIN_INT_32 = -(2 ** 31); +const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; +const RESOURCES_KEYS_OPERATOR_LIST = ["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]; +const RESOURCES_KEYS_TEXT_CONTENT = ["ExtGState", "Font", "Properties", "XObject"]; +function getLookupTableFactory(initializer) { + let lookup; + return function () { + if (initializer) { + lookup = Object.create(null); + initializer(lookup); + initializer = null; + } + return lookup; + }; +} +class MissingDataException extends BaseException { + constructor(begin, end) { + super(`Missing data [${begin}, ${end})`, "MissingDataException"); + this.begin = begin; + this.end = end; + } +} +class ParserEOFException extends BaseException { + constructor(msg) { + super(msg, "ParserEOFException"); + } +} +class XRefEntryException extends BaseException { + constructor(msg) { + super(msg, "XRefEntryException"); + } +} +class XRefParseException extends BaseException { + constructor(msg) { + super(msg, "XRefParseException"); + } +} +function arrayBuffersToBytes(arr) { + const length = arr.length; + if (length === 0) { + return new Uint8Array(0); + } + if (length === 1) { + return new Uint8Array(arr[0]); + } + let dataLength = 0; + for (let i = 0; i < length; i++) { + dataLength += arr[i].byteLength; + } + const data = new Uint8Array(dataLength); + let pos = 0; + for (let i = 0; i < length; i++) { + const item = new Uint8Array(arr[i]); + data.set(item, pos); + pos += item.byteLength; + } + return data; +} +async function fetchBinaryData(url) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch file "${url}" with "${response.statusText}".`); + } + return new Uint8Array(await response.arrayBuffer()); +} +function getInheritableProperty({ + dict, + key, + getArray = false, + stopWhenFound = true +}) { + let values; + const visited = new RefSet(); + while (dict instanceof Dict && !(dict.objId && visited.has(dict.objId))) { + if (dict.objId) { + visited.put(dict.objId); + } + const value = getArray ? dict.getArray(key) : dict.get(key); + if (value !== undefined) { + if (stopWhenFound) { + return value; + } + (values ||= []).push(value); + } + dict = dict.get("Parent"); + } + return values; +} +function getParentToUpdate(dict, ref, xref) { + const visited = new RefSet(); + const firstDict = dict; + const result = { + dict: null, + ref: null + }; + while (dict instanceof Dict && !visited.has(ref)) { + visited.put(ref); + if (dict.has("T")) { + break; + } + ref = dict.getRaw("Parent"); + if (!(ref instanceof Ref)) { + return result; + } + dict = xref.fetch(ref); + } + if (dict instanceof Dict && dict !== firstDict) { + result.dict = dict; + result.ref = ref; + } + return result; +} +const ROMAN_NUMBER_MAP = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]; +function toRomanNumerals(number, lowerCase = false) { + assert(Number.isInteger(number) && number > 0, "The number should be a positive integer."); + const roman = "M".repeat(number / 1000 | 0) + ROMAN_NUMBER_MAP[number % 1000 / 100 | 0] + ROMAN_NUMBER_MAP[10 + (number % 100 / 10 | 0)] + ROMAN_NUMBER_MAP[20 + number % 10]; + return lowerCase ? roman.toLowerCase() : roman; +} +function log2(x) { + return x > 0 ? Math.ceil(Math.log2(x)) : 0; +} +function readInt8(data, offset) { + return data[offset] << 24 >> 24; +} +function readInt16(data, offset) { + return (data[offset] << 24 | data[offset + 1] << 16) >> 16; +} +function readUint16(data, offset) { + return data[offset] << 8 | data[offset + 1]; +} +function readUint32(data, offset) { + return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0; +} +function isWhiteSpace(ch) { + return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a; +} +function isBooleanArray(arr, len) { + return Array.isArray(arr) && (len === null || arr.length === len) && arr.every(x => typeof x === "boolean"); +} +function isNumberArray(arr, len) { + if (Array.isArray(arr)) { + return (len === null || arr.length === len) && arr.every(x => typeof x === "number"); + } + return ArrayBuffer.isView(arr) && !(arr instanceof BigInt64Array || arr instanceof BigUint64Array) && (len === null || arr.length === len); +} +function lookupMatrix(arr, fallback) { + return isNumberArray(arr, 6) ? arr : fallback; +} +function lookupRect(arr, fallback) { + return isNumberArray(arr, 4) ? arr : fallback; +} +function lookupNormalRect(arr, fallback) { + return isNumberArray(arr, 4) ? Util.normalizeRect(arr) : fallback; +} +function parseXFAPath(path) { + const positionPattern = /(.+)\[(\d+)\]$/; + return path.split(".").map(component => { + const m = component.match(positionPattern); + if (m) { + return { + name: m[1], + pos: parseInt(m[2], 10) + }; + } + return { + name: component, + pos: 0 + }; + }); +} +function escapePDFName(str) { + const buffer = []; + let start = 0; + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.charCodeAt(i); + if (char < 0x21 || char > 0x7e || char === 0x23 || char === 0x28 || char === 0x29 || char === 0x3c || char === 0x3e || char === 0x5b || char === 0x5d || char === 0x7b || char === 0x7d || char === 0x2f || char === 0x25) { + if (start < i) { + buffer.push(str.substring(start, i)); + } + buffer.push(`#${char.toString(16)}`); + start = i + 1; + } + } + if (buffer.length === 0) { + return str; + } + if (start < str.length) { + buffer.push(str.substring(start, str.length)); + } + return buffer.join(""); +} +function escapeString(str) { + return str.replaceAll(/([()\\\n\r])/g, match => { + if (match === "\n") { + return "\\n"; + } else if (match === "\r") { + return "\\r"; + } + return `\\${match}`; + }); +} +function _collectJS(entry, xref, list, parents) { + if (!entry) { + return; + } + let parent = null; + if (entry instanceof Ref) { + if (parents.has(entry)) { + return; + } + parent = entry; + parents.put(parent); + entry = xref.fetch(entry); + } + if (Array.isArray(entry)) { + for (const element of entry) { + _collectJS(element, xref, list, parents); + } + } else if (entry instanceof Dict) { + if (isName(entry.get("S"), "JavaScript")) { + const js = entry.get("JS"); + let code; + if (js instanceof BaseStream) { + code = js.getString(); + } else if (typeof js === "string") { + code = js; + } + code &&= stringToPDFString(code, true).replaceAll("\x00", ""); + if (code) { + list.push(code.trim()); + } + } + _collectJS(entry.getRaw("Next"), xref, list, parents); + } + if (parent) { + parents.remove(parent); + } +} +function collectActions(xref, dict, eventType) { + const actions = Object.create(null); + const additionalActionsDicts = getInheritableProperty({ + dict, + key: "AA", + stopWhenFound: false + }); + if (additionalActionsDicts) { + for (let i = additionalActionsDicts.length - 1; i >= 0; i--) { + const additionalActions = additionalActionsDicts[i]; + if (!(additionalActions instanceof Dict)) { + continue; + } + for (const key of additionalActions.getKeys()) { + const action = eventType[key]; + if (!action) { + continue; + } + const actionDict = additionalActions.getRaw(key); + const parents = new RefSet(); + const list = []; + _collectJS(actionDict, xref, list, parents); + if (list.length > 0) { + actions[action] = list; + } + } + } + } + if (dict.has("A")) { + const actionDict = dict.get("A"); + const parents = new RefSet(); + const list = []; + _collectJS(actionDict, xref, list, parents); + if (list.length > 0) { + actions.Action = list; + } + } + return objectSize(actions) > 0 ? actions : null; +} +const XMLEntities = { + 0x3c: "<", + 0x3e: ">", + 0x26: "&", + 0x22: """, + 0x27: "'" +}; +function* codePointIter(str) { + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.codePointAt(i); + if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) { + i++; + } + yield char; + } +} +function encodeToXmlString(str) { + const buffer = []; + let start = 0; + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.codePointAt(i); + if (0x20 <= char && char <= 0x7e) { + const entity = XMLEntities[char]; + if (entity) { + if (start < i) { + buffer.push(str.substring(start, i)); + } + buffer.push(entity); + start = i + 1; + } + } else { + if (start < i) { + buffer.push(str.substring(start, i)); + } + buffer.push(`&#x${char.toString(16).toUpperCase()};`); + if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) { + i++; + } + start = i + 1; + } + } + if (buffer.length === 0) { + return str; + } + if (start < str.length) { + buffer.push(str.substring(start, str.length)); + } + return buffer.join(""); +} +function validateFontName(fontFamily, mustWarn = false) { + const m = /^("|').*("|')$/.exec(fontFamily); + if (m && m[1] === m[2]) { + const re = new RegExp(`[^\\\\]${m[1]}`); + if (re.test(fontFamily.slice(1, -1))) { + if (mustWarn) { + warn(`FontFamily contains unescaped ${m[1]}: ${fontFamily}.`); + } + return false; + } + } else { + for (const ident of fontFamily.split(/[ \t]+/)) { + if (/^(\d|(-(\d|-)))/.test(ident) || !/^[\w-\\]+$/.test(ident)) { + if (mustWarn) { + warn(`FontFamily contains invalid : ${fontFamily}.`); + } + return false; + } + } + } + return true; +} +function validateCSSFont(cssFontInfo) { + const DEFAULT_CSS_FONT_OBLIQUE = "14"; + const DEFAULT_CSS_FONT_WEIGHT = "400"; + const CSS_FONT_WEIGHT_VALUES = new Set(["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000", "normal", "bold", "bolder", "lighter"]); + const { + fontFamily, + fontWeight, + italicAngle + } = cssFontInfo; + if (!validateFontName(fontFamily, true)) { + return false; + } + const weight = fontWeight ? fontWeight.toString() : ""; + cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight) ? weight : DEFAULT_CSS_FONT_WEIGHT; + const angle = parseFloat(italicAngle); + cssFontInfo.italicAngle = isNaN(angle) || angle < -90 || angle > 90 ? DEFAULT_CSS_FONT_OBLIQUE : italicAngle.toString(); + return true; +} +function recoverJsURL(str) { + const URL_OPEN_METHODS = ["app.launchURL", "window.open", "xfa.host.gotoURL"]; + const regex = new RegExp("^\\s*(" + URL_OPEN_METHODS.join("|").replaceAll(".", "\\.") + ")\\((?:'|\")([^'\"]*)(?:'|\")(?:,\\s*(\\w+)\\)|\\))", "i"); + const jsUrl = regex.exec(str); + if (jsUrl?.[2]) { + return { + url: jsUrl[2], + newWindow: jsUrl[1] === "app.launchURL" && jsUrl[3] === "true" + }; + } + return null; +} +function numberToString(value) { + if (Number.isInteger(value)) { + return value.toString(); + } + const roundedValue = Math.round(value * 100); + if (roundedValue % 100 === 0) { + return (roundedValue / 100).toString(); + } + if (roundedValue % 10 === 0) { + return value.toFixed(1); + } + return value.toFixed(2); +} +function getNewAnnotationsMap(annotationStorage) { + if (!annotationStorage) { + return null; + } + const newAnnotationsByPage = new Map(); + for (const [key, value] of annotationStorage) { + if (!key.startsWith(AnnotationEditorPrefix)) { + continue; + } + let annotations = newAnnotationsByPage.get(value.pageIndex); + if (!annotations) { + annotations = []; + newAnnotationsByPage.set(value.pageIndex, annotations); + } + annotations.push(value); + } + return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null; +} +function stringToAsciiOrUTF16BE(str) { + if (str === null || str === undefined) { + return str; + } + return isAscii(str) ? str : stringToUTF16String(str, true); +} +function isAscii(str) { + if (typeof str !== "string") { + return false; + } + return !str || /^[\x00-\x7F]*$/.test(str); +} +function stringToUTF16HexString(str) { + const buf = []; + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.charCodeAt(i); + buf.push(hexNumbers[char >> 8 & 0xff], hexNumbers[char & 0xff]); + } + return buf.join(""); +} +function stringToUTF16String(str, bigEndian = false) { + const buf = []; + if (bigEndian) { + buf.push("\xFE\xFF"); + } + for (let i = 0, ii = str.length; i < ii; i++) { + const char = str.charCodeAt(i); + buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff)); + } + return buf.join(""); +} +function getRotationMatrix(rotation, width, height) { + switch (rotation) { + case 90: + return [0, 1, -1, 0, width, 0]; + case 180: + return [-1, 0, 0, -1, width, height]; + case 270: + return [0, -1, 1, 0, 0, height]; + default: + throw new Error("Invalid rotation"); + } +} +function getSizeInBytes(x) { + return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8); +} + +;// ./external/qcms/qcms_utils.js +class QCMS { + static #memoryArray = null; + static _memory = null; + static _mustAddAlpha = false; + static _destBuffer = null; + static _destOffset = 0; + static _destLength = 0; + static _cssColor = ""; + static _makeHexColor = null; + static get _memoryArray() { + const array = this.#memoryArray; + if (array?.byteLength) { + return array; + } + return this.#memoryArray = new Uint8Array(this._memory.buffer); + } +} +function copy_result(ptr, len) { + const { + _mustAddAlpha, + _destBuffer, + _destOffset, + _destLength, + _memoryArray + } = QCMS; + if (len === _destLength) { + _destBuffer.set(_memoryArray.subarray(ptr, ptr + len), _destOffset); + return; + } + if (_mustAddAlpha) { + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; + _destBuffer[j + 3] = 255; + } + } else { + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; + } + } +} +function copy_rgb(ptr) { + const { + _destBuffer, + _destOffset, + _memoryArray + } = QCMS; + _destBuffer[_destOffset] = _memoryArray[ptr]; + _destBuffer[_destOffset + 1] = _memoryArray[ptr + 1]; + _destBuffer[_destOffset + 2] = _memoryArray[ptr + 2]; +} +function make_cssRGB(ptr) { + const { + _memoryArray + } = QCMS; + QCMS._cssColor = QCMS._makeHexColor(_memoryArray[ptr], _memoryArray[ptr + 1], _memoryArray[ptr + 2]); +} + +;// ./external/qcms/qcms.js + +let wasm; +const cachedTextDecoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { + ignoreBOM: true, + fatal: true +}) : { + decode: () => { + throw Error('TextDecoder not available'); + } +}; +if (typeof TextDecoder !== 'undefined') { + cachedTextDecoder.decode(); +} +; +let cachedUint8ArrayMemory0 = null; +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} +let WASM_VECTOR_LEN = 0; +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} +function qcms_convert_array(transformer, src) { + const ptr0 = passArray8ToWasm0(src, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + wasm.qcms_convert_array(transformer, ptr0, len0); +} +function qcms_convert_one(transformer, src, css) { + wasm.qcms_convert_one(transformer, src, css); +} +function qcms_convert_three(transformer, src1, src2, src3, css) { + wasm.qcms_convert_three(transformer, src1, src2, src3, css); +} +function qcms_convert_four(transformer, src1, src2, src3, src4, css) { + wasm.qcms_convert_four(transformer, src1, src2, src3, src4, css); +} +function qcms_transformer_from_memory(mem, in_type, intent) { + const ptr0 = passArray8ToWasm0(mem, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.qcms_transformer_from_memory(ptr0, len0, in_type, intent); + return ret >>> 0; +} +function qcms_drop_transformer(transformer) { + wasm.qcms_drop_transformer(transformer); +} +const DataType = Object.freeze({ + RGB8: 0, + "0": "RGB8", + RGBA8: 1, + "1": "RGBA8", + BGRA8: 2, + "2": "BGRA8", + Gray8: 3, + "3": "Gray8", + GrayA8: 4, + "4": "GrayA8", + CMYK: 5, + "5": "CMYK" +}); +const Intent = Object.freeze({ + Perceptual: 0, + "0": "Perceptual", + RelativeColorimetric: 1, + "1": "RelativeColorimetric", + Saturation: 2, + "2": "Saturation", + AbsoluteColorimetric: 3, + "3": "AbsoluteColorimetric" +}); +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + } else { + throw e; + } + } + } + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + if (instance instanceof WebAssembly.Instance) { + return { + instance, + module + }; + } else { + return instance; + } + } +} +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_copyresult_b08ee7d273f295dd = function (arg0, arg1) { + copy_result(arg0 >>> 0, arg1 >>> 0); + }; + imports.wbg.__wbg_copyrgb_d60ce17bb05d9b67 = function (arg0) { + copy_rgb(arg0 >>> 0); + }; + imports.wbg.__wbg_makecssRGB_893bf0cd9fdb302d = function (arg0) { + make_cssRGB(arg0 >>> 0); + }; + imports.wbg.__wbindgen_init_externref_table = function () { + const table = wasm.__wbindgen_export_0; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }; + imports.wbg.__wbindgen_throw = function (arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + return imports; +} +function __wbg_init_memory(imports, memory) {} +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; +} +function initSync(module) { + if (wasm !== undefined) return wasm; + if (typeof module !== 'undefined') { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({ + module + } = module); + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead'); + } + } + const imports = __wbg_get_imports(); + __wbg_init_memory(imports); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); +} +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + if (typeof module_or_path !== 'undefined') { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({ + module_or_path + } = module_or_path); + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead'); + } + } + const imports = __wbg_get_imports(); + if (typeof module_or_path === 'string' || typeof Request === 'function' && module_or_path instanceof Request || typeof URL === 'function' && module_or_path instanceof URL) { + module_or_path = fetch(module_or_path); + } + __wbg_init_memory(imports); + const { + instance, + module + } = await __wbg_load(await module_or_path, imports); + return __wbg_finalize_init(instance, module); +} + +/* harmony default export */ const qcms = ((/* unused pure expression or super */ null && (__wbg_init))); +;// ./src/core/colorspace.js + + +function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) { + const COMPONENTS = 3; + alpha01 = alpha01 !== 1 ? 0 : alpha01; + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let newIndex = 0, + oldIndex; + const xScaled = new Uint16Array(w2); + const w1Scanline = w1 * COMPONENTS; + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (let i = 0; i < h2; i++) { + const py = Math.floor(i * yRatio) * w1Scanline; + for (let j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + newIndex += alpha01; + } + } +} +function resizeRgbaImage(src, dest, w1, h1, w2, h2, alpha01) { + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let newIndex = 0; + const xScaled = new Uint16Array(w2); + if (alpha01 === 1) { + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio); + } + const src32 = new Uint32Array(src.buffer); + const dest32 = new Uint32Array(dest.buffer); + const rgbMask = FeatureTest.isLittleEndian ? 0x00ffffff : 0xffffff00; + for (let i = 0; i < h2; i++) { + const buf = src32.subarray(Math.floor(i * yRatio) * w1); + for (let j = 0; j < w2; j++) { + dest32[newIndex++] |= buf[xScaled[j]] & rgbMask; + } + } + } else { + const COMPONENTS = 4; + const w1Scanline = w1 * COMPONENTS; + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (let i = 0; i < h2; i++) { + const buf = src.subarray(Math.floor(i * yRatio) * w1Scanline); + for (let j = 0; j < w2; j++) { + const oldIndex = xScaled[j]; + dest[newIndex++] = buf[oldIndex]; + dest[newIndex++] = buf[oldIndex + 1]; + dest[newIndex++] = buf[oldIndex + 2]; + } + } + } +} +function copyRgbaImage(src, dest, alpha01) { + if (alpha01 === 1) { + const src32 = new Uint32Array(src.buffer); + const dest32 = new Uint32Array(dest.buffer); + const rgbMask = FeatureTest.isLittleEndian ? 0x00ffffff : 0xffffff00; + for (let i = 0, ii = src32.length; i < ii; i++) { + dest32[i] |= src32[i] & rgbMask; + } + } else { + let j = 0; + for (let i = 0, ii = src.length; i < ii; i += 4) { + dest[j++] = src[i]; + dest[j++] = src[i + 1]; + dest[j++] = src[i + 2]; + } + } +} +class ColorSpace { + static #rgbBuf = new Uint8ClampedArray(3); + constructor(name, numComps) { + this.name = name; + this.numComps = numComps; + } + getRgb(src, srcOffset, output = new Uint8ClampedArray(3)) { + this.getRgbItem(src, srcOffset, output, 0); + return output; + } + getRgbHex(src, srcOffset) { + const buffer = this.getRgb(src, srcOffset, ColorSpace.#rgbBuf); + return Util.makeHexColor(buffer[0], buffer[1], buffer[2]); + } + getRgbItem(src, srcOffset, dest, destOffset) { + unreachable("Should not call ColorSpace.getRgbItem"); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + unreachable("Should not call ColorSpace.getRgbBuffer"); + } + getOutputLength(inputLength, alpha01) { + unreachable("Should not call ColorSpace.getOutputLength"); + } + isPassthrough(bits) { + return false; + } + isDefaultDecode(decodeMap, bpc) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + } + fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { + const count = originalWidth * originalHeight; + let rgbBuf = null; + const numComponentColors = 1 << bpc; + const needsResizing = originalHeight !== height || originalWidth !== width; + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") { + const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors); + for (let i = 0; i < numComponentColors; i++) { + allColors[i] = i; + } + const colorMap = new Uint8ClampedArray(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0); + if (!needsResizing) { + let destPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; + } + } else { + rgbBuf = new Uint8Array(count * 3); + let rgbPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; + } + } + } else if (!needsResizing) { + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01); + } else { + rgbBuf = new Uint8ClampedArray(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0); + } + if (rgbBuf) { + if (needsResizing) { + resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01); + } else { + let destPos = 0, + rgbPos = 0; + for (let i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; + } + } + } + } + get usesZeroToOneRange() { + return shadow(this, "usesZeroToOneRange", true); + } + static isDefaultDecode(decode, numComps) { + if (!Array.isArray(decode)) { + return true; + } + if (numComps * 2 !== decode.length) { + warn("The decode map is not the correct length"); + return true; + } + for (let i = 0, ii = decode.length; i < ii; i += 2) { + if (decode[i] !== 0 || decode[i + 1] !== 1) { + return false; + } + } + return true; + } +} +class AlternateCS extends ColorSpace { + constructor(numComps, base, tintFn) { + super("Alternate", numComps); + this.base = base; + this.tintFn = tintFn; + this.tmpBuf = new Float32Array(base.numComps); + } + getRgbItem(src, srcOffset, dest, destOffset) { + const tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const tintFn = this.tintFn; + const base = this.base; + const scale = 1 / ((1 << bits) - 1); + const baseNumComps = base.numComps; + const usesZeroToOneRange = base.usesZeroToOneRange; + const isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0; + let pos = isPassthrough ? destOffset : 0; + const baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count); + const numComps = this.numComps; + const scaled = new Float32Array(numComps); + const tinted = new Float32Array(baseNumComps); + let i, j; + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + if (usesZeroToOneRange) { + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } else { + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + } + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01); + } +} +class PatternCS extends ColorSpace { + constructor(baseCS) { + super("Pattern", null); + this.base = baseCS; + } + isDefaultDecode(decodeMap, bpc) { + unreachable("Should not call PatternCS.isDefaultDecode"); + } +} +class IndexedCS extends ColorSpace { + constructor(base, highVal, lookup) { + super("Indexed", 1); + this.base = base; + this.highVal = highVal; + const length = base.numComps * (highVal + 1); + this.lookup = new Uint8Array(length); + if (lookup instanceof BaseStream) { + const bytes = lookup.getBytes(length); + this.lookup.set(bytes); + } else if (typeof lookup === "string") { + for (let i = 0; i < length; ++i) { + this.lookup[i] = lookup.charCodeAt(i) & 0xff; + } + } else { + throw new FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`); + } + } + getRgbItem(src, srcOffset, dest, destOffset) { + const { + base, + highVal, + lookup + } = this; + const start = MathClamp(Math.round(src[srcOffset]), 0, highVal) * base.numComps; + base.getRgbBuffer(lookup, start, 1, dest, destOffset, 8, 0); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const { + base, + highVal, + lookup + } = this; + const { + numComps + } = base; + const outputDelta = base.getOutputLength(numComps, alpha01); + for (let i = 0; i < count; ++i) { + const lookupPos = MathClamp(Math.round(src[srcOffset++]), 0, highVal) * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + } + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, alpha01); + } + isDefaultDecode(decodeMap, bpc) { + if (!Array.isArray(decodeMap)) { + return true; + } + if (decodeMap.length !== 2) { + warn("Decode map length is not correct"); + return true; + } + if (!Number.isInteger(bpc) || bpc < 1) { + warn("Bits per component is not correct"); + return true; + } + return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1; + } +} +class DeviceGrayCS extends ColorSpace { + constructor() { + super("DeviceGray", 1); + } + getRgbItem(src, srcOffset, dest, destOffset) { + const c = src[srcOffset] * 255; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 255 / ((1 << bits) - 1); + let j = srcOffset, + q = destOffset; + for (let i = 0; i < count; ++i) { + const c = scale * src[j++]; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + } +} +class DeviceRgbCS extends ColorSpace { + constructor() { + super("DeviceRGB", 3); + } + getRgbItem(src, srcOffset, dest, destOffset) { + dest[destOffset] = src[srcOffset] * 255; + dest[destOffset + 1] = src[srcOffset + 1] * 255; + dest[destOffset + 2] = src[srcOffset + 2] * 255; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + const scale = 255 / ((1 << bits) - 1); + let j = srcOffset, + q = destOffset; + for (let i = 0; i < count; ++i) { + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + q += alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } + isPassthrough(bits) { + return bits === 8; + } +} +class DeviceRgbaCS extends ColorSpace { + constructor() { + super("DeviceRGBA", 4); + } + getOutputLength(inputLength, _alpha01) { + return inputLength * 4; + } + isPassthrough(bits) { + return bits === 8; + } + fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { + if (originalHeight !== height || originalWidth !== width) { + resizeRgbaImage(comps, dest, originalWidth, originalHeight, width, height, alpha01); + } else { + copyRgbaImage(comps, dest, alpha01); + } + } +} +class DeviceCmykCS extends ColorSpace { + constructor() { + super("DeviceCMYK", 4); + } + #toRgb(src, srcOffset, srcScale, dest, destOffset) { + const c = src[srcOffset] * srcScale; + const m = src[srcOffset + 1] * srcScale; + const y = src[srcOffset + 2] * srcScale; + const k = src[srcOffset + 3] * srcScale; + dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747); + dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578); + dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367); + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, 1, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; i++) { + this.#toRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength / 4 * (3 + alpha01) | 0; + } +} +class CalGrayCS extends ColorSpace { + constructor(whitePoint, blackPoint, gamma) { + super("CalGray", 1); + if (!whitePoint) { + throw new FormatError("WhitePoint missing - required for color space CalGray"); + } + [this.XW, this.YW, this.ZW] = whitePoint; + [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0]; + this.G = gamma || 1; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info(`Invalid BlackPoint for ${this.name}, falling back to default.`); + this.XB = this.YB = this.ZB = 0; + } + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ` + `ZB: ${this.ZB}, only default values are supported.`); + } + if (this.G < 1) { + info(`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`); + this.G = 1; + } + } + #toRgb(src, srcOffset, dest, destOffset, scale) { + const A = src[srcOffset] * scale; + const AG = A ** this.G; + const L = this.YW * AG; + const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0); + dest[destOffset] = val; + dest[destOffset + 1] = val; + dest[destOffset + 2] = val; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, dest, destOffset, 1); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; ++i) { + this.#toRgb(src, srcOffset, dest, destOffset, scale); + srcOffset += 1; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + } +} +class CalRGBCS extends ColorSpace { + static #BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]); + static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]); + static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]); + static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); + static #tempNormalizeMatrix = new Float32Array(3); + static #tempConvertMatrix1 = new Float32Array(3); + static #tempConvertMatrix2 = new Float32Array(3); + static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8.0; + constructor(whitePoint, blackPoint, gamma, matrix) { + super("CalRGB", 3); + if (!whitePoint) { + throw new FormatError("WhitePoint missing - required for color space CalRGB"); + } + const [XW, YW, ZW] = this.whitePoint = whitePoint; + const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3); + [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]); + [this.MXA, this.MYA, this.MZA, this.MXB, this.MYB, this.MZB, this.MXC, this.MYC, this.MZC] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); + if (XW < 0 || ZW < 0 || YW !== 1) { + throw new FormatError(`Invalid WhitePoint components for ${this.name}, no fallback available`); + } + if (XB < 0 || YB < 0 || ZB < 0) { + info(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], ` + "falling back to default."); + this.blackPoint = new Float32Array(3); + } + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ` + `${this.name}, falling back to default.`); + this.GR = this.GG = this.GB = 1; + } + } + #matrixProduct(a, b, result) { + result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; + result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; + } + #toFlat(sourceWhitePoint, LMS, result) { + result[0] = LMS[0] * 1 / sourceWhitePoint[0]; + result[1] = LMS[1] * 1 / sourceWhitePoint[1]; + result[2] = LMS[2] * 1 / sourceWhitePoint[2]; + } + #toD65(sourceWhitePoint, LMS, result) { + const D65X = 0.95047; + const D65Y = 1; + const D65Z = 1.08883; + result[0] = LMS[0] * D65X / sourceWhitePoint[0]; + result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; + result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; + } + #sRGBTransferFunction(color) { + if (color <= 0.0031308) { + return MathClamp(12.92 * color, 0, 1); + } + if (color >= 0.99554525) { + return 1; + } + return MathClamp((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1); + } + #decodeL(L) { + if (L < 0) { + return -this.#decodeL(-L); + } + if (L > 8.0) { + return ((L + 16) / 116) ** 3; + } + return L * CalRGBCS.#DECODE_L_CONSTANT; + } + #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { + if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) { + result[0] = XYZ_Flat[0]; + result[1] = XYZ_Flat[1]; + result[2] = XYZ_Flat[2]; + return; + } + const zeroDecodeL = this.#decodeL(0); + const X_DST = zeroDecodeL; + const X_SRC = this.#decodeL(sourceBlackPoint[0]); + const Y_DST = zeroDecodeL; + const Y_SRC = this.#decodeL(sourceBlackPoint[1]); + const Z_DST = zeroDecodeL; + const Z_SRC = this.#decodeL(sourceBlackPoint[2]); + const X_Scale = (1 - X_DST) / (1 - X_SRC); + const X_Offset = 1 - X_Scale; + const Y_Scale = (1 - Y_DST) / (1 - Y_SRC); + const Y_Offset = 1 - Y_Scale; + const Z_Scale = (1 - Z_DST) / (1 - Z_SRC); + const Z_Offset = 1 - Z_Scale; + result[0] = XYZ_Flat[0] * X_Scale + X_Offset; + result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; + result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; + } + #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { + if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { + result[0] = XYZ_In[0]; + result[1] = XYZ_In[1]; + result[2] = XYZ_In[2]; + return; + } + const LMS = result; + this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + const LMS_Flat = CalRGBCS.#tempNormalizeMatrix; + this.#toFlat(sourceWhitePoint, LMS, LMS_Flat); + this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); + } + #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { + const LMS = result; + this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + const LMS_D65 = CalRGBCS.#tempNormalizeMatrix; + this.#toD65(sourceWhitePoint, LMS, LMS_D65); + this.#matrixProduct(CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); + } + #toRgb(src, srcOffset, dest, destOffset, scale) { + const A = MathClamp(src[srcOffset] * scale, 0, 1); + const B = MathClamp(src[srcOffset + 1] * scale, 0, 1); + const C = MathClamp(src[srcOffset + 2] * scale, 0, 1); + const AGR = A === 1 ? 1 : A ** this.GR; + const BGG = B === 1 ? 1 : B ** this.GG; + const CGB = C === 1 ? 1 : C ** this.GB; + const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB; + const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB; + const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB; + const XYZ = CalRGBCS.#tempConvertMatrix1; + XYZ[0] = X; + XYZ[1] = Y; + XYZ[2] = Z; + const XYZ_Flat = CalRGBCS.#tempConvertMatrix2; + this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat); + const XYZ_Black = CalRGBCS.#tempConvertMatrix1; + this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black); + const XYZ_D65 = CalRGBCS.#tempConvertMatrix2; + this.#normalizeWhitePointToD65(CalRGBCS.#FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); + const SRGB = CalRGBCS.#tempConvertMatrix1; + this.#matrixProduct(CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); + dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255; + dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255; + dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, dest, destOffset, 1); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; ++i) { + this.#toRgb(src, srcOffset, dest, destOffset, scale); + srcOffset += 3; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } +} +class LabCS extends ColorSpace { + constructor(whitePoint, blackPoint, range) { + super("Lab", 3); + if (!whitePoint) { + throw new FormatError("WhitePoint missing - required for color space Lab"); + } + [this.XW, this.YW, this.ZW] = whitePoint; + [this.amin, this.amax, this.bmin, this.bmax] = range || [-100, 100, -100, 100]; + [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0]; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError("Invalid WhitePoint components, no fallback available"); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info("Invalid BlackPoint, falling back to default"); + this.XB = this.YB = this.ZB = 0; + } + if (this.amin > this.amax || this.bmin > this.bmax) { + info("Invalid Range, falling back to defaults"); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + #fn_g(x) { + return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29); + } + #decode(value, high1, low2, high2) { + return low2 + value * (high2 - low2) / high1; + } + #toRgb(src, srcOffset, maxVal, dest, destOffset) { + let Ls = src[srcOffset]; + let as = src[srcOffset + 1]; + let bs = src[srcOffset + 2]; + if (maxVal !== false) { + Ls = this.#decode(Ls, maxVal, 0, 100); + as = this.#decode(as, maxVal, this.amin, this.amax); + bs = this.#decode(bs, maxVal, this.bmin, this.bmax); + } + if (as > this.amax) { + as = this.amax; + } else if (as < this.amin) { + as = this.amin; + } + if (bs > this.bmax) { + bs = this.bmax; + } else if (bs < this.bmin) { + bs = this.bmin; + } + const M = (Ls + 16) / 116; + const L = M + as / 500; + const N = M - bs / 200; + const X = this.XW * this.#fn_g(L); + const Y = this.YW * this.#fn_g(M); + const Z = this.ZW * this.#fn_g(N); + let r, g, b; + if (this.ZW < 1) { + r = X * 3.1339 + Y * -1.617 + Z * -0.4906; + g = X * -0.9785 + Y * 1.916 + Z * 0.0333; + b = X * 0.072 + Y * -0.229 + Z * 1.4057; + } else { + r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; + g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; + b = X * 0.0557 + Y * -0.204 + Z * 1.057; + } + dest[destOffset] = Math.sqrt(r) * 255; + dest[destOffset + 1] = Math.sqrt(g) * 255; + dest[destOffset + 2] = Math.sqrt(b) * 255; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, false, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const maxVal = (1 << bits) - 1; + for (let i = 0; i < count; i++) { + this.#toRgb(src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } + isDefaultDecode(decodeMap, bpc) { + return true; + } + get usesZeroToOneRange() { + return shadow(this, "usesZeroToOneRange", false); + } +} + +;// ./src/core/icc_colorspace.js + + + + +function fetchSync(url) { + const xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.responseType = "arraybuffer"; + xhr.send(null); + return xhr.response; +} +class IccColorSpace extends ColorSpace { + #transformer; + #convertPixel; + static #useWasm = true; + static #wasmUrl = null; + static #finalizer = null; + constructor(iccProfile, name, numComps) { + if (!IccColorSpace.isUsable) { + throw new Error("No ICC color space support"); + } + super(name, numComps); + let inType; + switch (numComps) { + case 1: + inType = DataType.Gray8; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_one(this.#transformer, src[srcOffset] * 255, css); + break; + case 3: + inType = DataType.RGB8; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_three(this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, src[srcOffset + 2] * 255, css); + break; + case 4: + inType = DataType.CMYK; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_four(this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, src[srcOffset + 2] * 255, src[srcOffset + 3] * 255, css); + break; + default: + throw new Error(`Unsupported number of components: ${numComps}`); + } + this.#transformer = qcms_transformer_from_memory(iccProfile, inType, Intent.Perceptual); + if (!this.#transformer) { + throw new Error("Failed to create ICC color space"); + } + IccColorSpace.#finalizer ||= new FinalizationRegistry(transformer => { + qcms_drop_transformer(transformer); + }); + IccColorSpace.#finalizer.register(this, this.#transformer); + } + getRgbHex(src, srcOffset) { + this.#convertPixel(src, srcOffset, true); + return QCMS._cssColor; + } + getRgbItem(src, srcOffset, dest, destOffset) { + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = 3; + this.#convertPixel(src, srcOffset, false); + QCMS._destBuffer = null; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + src = src.subarray(srcOffset, srcOffset + count * this.numComps); + if (bits !== 8) { + const scale = 255 / ((1 << bits) - 1); + for (let i = 0, ii = src.length; i < ii; i++) { + src[i] *= scale; + } + } + QCMS._mustAddAlpha = alpha01 && dest.buffer === src.buffer; + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = count * (3 + alpha01); + qcms_convert_array(this.#transformer, src); + QCMS._mustAddAlpha = false; + QCMS._destBuffer = null; + } + getOutputLength(inputLength, alpha01) { + return inputLength / this.numComps * (3 + alpha01) | 0; + } + static setOptions({ + useWasm, + useWorkerFetch, + wasmUrl + }) { + if (!useWorkerFetch) { + this.#useWasm = false; + return; + } + this.#useWasm = useWasm; + this.#wasmUrl = wasmUrl; + } + static get isUsable() { + let isUsable = false; + if (this.#useWasm) { + if (this.#wasmUrl) { + try { + this._module = initSync({ + module: fetchSync(`${this.#wasmUrl}qcms_bg.wasm`) + }); + isUsable = !!this._module; + QCMS._memory = this._module.memory; + QCMS._makeHexColor = Util.makeHexColor; + } catch (e) { + warn(`ICCBased color space: "${e}".`); + } + } else { + warn("No ICC color space support due to missing `wasmUrl` API option"); + } + } + return shadow(this, "isUsable", isUsable); + } +} +class CmykICCBasedCS extends IccColorSpace { + static #iccUrl; + constructor() { + const iccProfile = new Uint8Array(fetchSync(`${CmykICCBasedCS.#iccUrl}CGATS001Compat-v2-micro.icc`)); + super(iccProfile, "DeviceCMYK", 4); + } + static setOptions({ + iccUrl + }) { + this.#iccUrl = iccUrl; + } + static get isUsable() { + let isUsable = false; + if (IccColorSpace.isUsable) { + if (this.#iccUrl) { + isUsable = true; + } else { + warn("No CMYK ICC profile support due to missing `iccUrl` API option"); + } + } + return shadow(this, "isUsable", isUsable); + } +} + +;// ./src/core/stream.js + + +class Stream extends BaseStream { + constructor(arrayBuffer, start, length, dict) { + super(); + this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer); + this.start = start || 0; + this.pos = this.start; + this.end = start + length || this.bytes.length; + this.dict = dict; + } + get length() { + return this.end - this.start; + } + get isEmpty() { + return this.length === 0; + } + getByte() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + } + getBytes(length) { + const bytes = this.bytes; + const pos = this.pos; + const strEnd = this.end; + if (!length) { + return bytes.subarray(pos, strEnd); + } + let end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + return bytes.subarray(pos, end); + } + getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } + return this.bytes.subarray(begin, end); + } + reset() { + this.pos = this.start; + } + moveStart() { + this.start = this.pos; + } + makeSubStream(start, length, dict = null) { + return new Stream(this.bytes.buffer, start, length, dict); + } + clone() { + return new Stream(this.bytes.buffer, this.start, this.end - this.start, this.dict.clone()); + } +} +class StringStream extends Stream { + constructor(str) { + super(stringToBytes(str)); + } +} +class NullStream extends Stream { + constructor() { + super(new Uint8Array(0)); + } +} + +;// ./src/core/chunked_stream.js + + + +class ChunkedStream extends Stream { + constructor(length, chunkSize, manager) { + super(new Uint8Array(length), 0, length, null); + this.chunkSize = chunkSize; + this._loadedChunks = new Set(); + this.numChunks = Math.ceil(length / chunkSize); + this.manager = manager; + this.progressiveDataLength = 0; + this.lastSuccessfulEnsureByteChunk = -1; + } + getMissingChunks() { + const chunks = []; + for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) { + if (!this._loadedChunks.has(chunk)) { + chunks.push(chunk); + } + } + return chunks; + } + get numChunksLoaded() { + return this._loadedChunks.size; + } + get isDataLoaded() { + return this.numChunksLoaded === this.numChunks; + } + onReceiveData(begin, chunk) { + const chunkSize = this.chunkSize; + if (begin % chunkSize !== 0) { + throw new Error(`Bad begin offset: ${begin}`); + } + const end = begin + chunk.byteLength; + if (end % chunkSize !== 0 && end !== this.bytes.length) { + throw new Error(`Bad end offset: ${end}`); + } + this.bytes.set(new Uint8Array(chunk), begin); + const beginChunk = Math.floor(begin / chunkSize); + const endChunk = Math.floor((end - 1) / chunkSize) + 1; + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + this._loadedChunks.add(curChunk); + } + } + onReceiveProgressiveData(data) { + let position = this.progressiveDataLength; + const beginChunk = Math.floor(position / this.chunkSize); + this.bytes.set(new Uint8Array(data), position); + position += data.byteLength; + this.progressiveDataLength = position; + const endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize); + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + this._loadedChunks.add(curChunk); + } + } + ensureByte(pos) { + if (pos < this.progressiveDataLength) { + return; + } + const chunk = Math.floor(pos / this.chunkSize); + if (chunk > this.numChunks) { + return; + } + if (chunk === this.lastSuccessfulEnsureByteChunk) { + return; + } + if (!this._loadedChunks.has(chunk)) { + throw new MissingDataException(pos, pos + 1); + } + this.lastSuccessfulEnsureByteChunk = chunk; + } + ensureRange(begin, end) { + if (begin >= end) { + return; + } + if (end <= this.progressiveDataLength) { + return; + } + const beginChunk = Math.floor(begin / this.chunkSize); + if (beginChunk > this.numChunks) { + return; + } + const endChunk = Math.min(Math.floor((end - 1) / this.chunkSize) + 1, this.numChunks); + for (let chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this._loadedChunks.has(chunk)) { + throw new MissingDataException(begin, end); + } + } + } + nextEmptyChunk(beginChunk) { + const numChunks = this.numChunks; + for (let i = 0; i < numChunks; ++i) { + const chunk = (beginChunk + i) % numChunks; + if (!this._loadedChunks.has(chunk)) { + return chunk; + } + } + return null; + } + hasChunk(chunk) { + return this._loadedChunks.has(chunk); + } + getByte() { + const pos = this.pos; + if (pos >= this.end) { + return -1; + } + if (pos >= this.progressiveDataLength) { + this.ensureByte(pos); + } + return this.bytes[this.pos++]; + } + getBytes(length) { + const bytes = this.bytes; + const pos = this.pos; + const strEnd = this.end; + if (!length) { + if (strEnd > this.progressiveDataLength) { + this.ensureRange(pos, strEnd); + } + return bytes.subarray(pos, strEnd); + } + let end = pos + length; + if (end > strEnd) { + end = strEnd; + } + if (end > this.progressiveDataLength) { + this.ensureRange(pos, end); + } + this.pos = end; + return bytes.subarray(pos, end); + } + getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } + if (end > this.progressiveDataLength) { + this.ensureRange(begin, end); + } + return this.bytes.subarray(begin, end); + } + makeSubStream(start, length, dict = null) { + if (length) { + if (start + length > this.progressiveDataLength) { + this.ensureRange(start, start + length); + } + } else if (start >= this.progressiveDataLength) { + this.ensureByte(start); + } + function ChunkedStreamSubstream() {} + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function () { + const chunkSize = this.chunkSize; + const beginChunk = Math.floor(this.start / chunkSize); + const endChunk = Math.floor((this.end - 1) / chunkSize) + 1; + const missingChunks = []; + for (let chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this._loadedChunks.has(chunk)) { + missingChunks.push(chunk); + } + } + return missingChunks; + }; + Object.defineProperty(ChunkedStreamSubstream.prototype, "isDataLoaded", { + get() { + if (this.numChunksLoaded === this.numChunks) { + return true; + } + return this.getMissingChunks().length === 0; + }, + configurable: true + }); + const subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + } + getBaseStreams() { + return [this]; + } +} +class ChunkedStreamManager { + constructor(pdfNetworkStream, args) { + this.length = args.length; + this.chunkSize = args.rangeChunkSize; + this.stream = new ChunkedStream(this.length, this.chunkSize, this); + this.pdfNetworkStream = pdfNetworkStream; + this.disableAutoFetch = args.disableAutoFetch; + this.msgHandler = args.msgHandler; + this.currRequestId = 0; + this._chunksNeededByRequest = new Map(); + this._requestsByChunk = new Map(); + this._promisesByRequest = new Map(); + this.progressiveDataLength = 0; + this.aborted = false; + this._loadedStreamCapability = Promise.withResolvers(); + } + sendRequest(begin, end) { + const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end); + if (!rangeReader.isStreamingSupported) { + rangeReader.onProgress = this.onProgress.bind(this); + } + let chunks = [], + loaded = 0; + return new Promise((resolve, reject) => { + const readChunk = ({ + value, + done + }) => { + try { + if (done) { + const chunkData = arrayBuffersToBytes(chunks); + chunks = null; + resolve(chunkData); + return; + } + loaded += value.byteLength; + if (rangeReader.isStreamingSupported) { + this.onProgress({ + loaded + }); + } + chunks.push(value); + rangeReader.read().then(readChunk, reject); + } catch (e) { + reject(e); + } + }; + rangeReader.read().then(readChunk, reject); + }).then(data => { + if (this.aborted) { + return; + } + this.onReceiveData({ + chunk: data, + begin + }); + }); + } + requestAllChunks(noFetch = false) { + if (!noFetch) { + const missingChunks = this.stream.getMissingChunks(); + this._requestChunks(missingChunks); + } + return this._loadedStreamCapability.promise; + } + _requestChunks(chunks) { + const requestId = this.currRequestId++; + const chunksNeeded = new Set(); + this._chunksNeededByRequest.set(requestId, chunksNeeded); + for (const chunk of chunks) { + if (!this.stream.hasChunk(chunk)) { + chunksNeeded.add(chunk); + } + } + if (chunksNeeded.size === 0) { + return Promise.resolve(); + } + const capability = Promise.withResolvers(); + this._promisesByRequest.set(requestId, capability); + const chunksToRequest = []; + for (const chunk of chunksNeeded) { + let requestIds = this._requestsByChunk.get(chunk); + if (!requestIds) { + requestIds = []; + this._requestsByChunk.set(chunk, requestIds); + chunksToRequest.push(chunk); + } + requestIds.push(requestId); + } + if (chunksToRequest.length > 0) { + const groupedChunksToRequest = this.groupChunks(chunksToRequest); + for (const groupedChunk of groupedChunksToRequest) { + const begin = groupedChunk.beginChunk * this.chunkSize; + const end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end).catch(capability.reject); + } + } + return capability.promise.catch(reason => { + if (this.aborted) { + return; + } + throw reason; + }); + } + getStream() { + return this.stream; + } + requestRange(begin, end) { + end = Math.min(end, this.length); + const beginChunk = this.getBeginChunk(begin); + const endChunk = this.getEndChunk(end); + const chunks = []; + for (let chunk = beginChunk; chunk < endChunk; ++chunk) { + chunks.push(chunk); + } + return this._requestChunks(chunks); + } + requestRanges(ranges = []) { + const chunksToRequest = []; + for (const range of ranges) { + const beginChunk = this.getBeginChunk(range.begin); + const endChunk = this.getEndChunk(range.end); + for (let chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!chunksToRequest.includes(chunk)) { + chunksToRequest.push(chunk); + } + } + } + chunksToRequest.sort((a, b) => a - b); + return this._requestChunks(chunksToRequest); + } + groupChunks(chunks) { + const groupedChunks = []; + let beginChunk = -1; + let prevChunk = -1; + for (let i = 0, ii = chunks.length; i < ii; ++i) { + const chunk = chunks[i]; + if (beginChunk < 0) { + beginChunk = chunk; + } + if (prevChunk >= 0 && prevChunk + 1 !== chunk) { + groupedChunks.push({ + beginChunk, + endChunk: prevChunk + 1 + }); + beginChunk = chunk; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ + beginChunk, + endChunk: chunk + 1 + }); + } + prevChunk = chunk; + } + return groupedChunks; + } + onProgress(args) { + this.msgHandler.send("DocProgress", { + loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded, + total: this.length + }); + } + onReceiveData(args) { + const chunk = args.chunk; + const isProgressive = args.begin === undefined; + const begin = isProgressive ? this.progressiveDataLength : args.begin; + const end = begin + chunk.byteLength; + const beginChunk = Math.floor(begin / this.chunkSize); + const endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize); + if (isProgressive) { + this.stream.onReceiveProgressiveData(chunk); + this.progressiveDataLength = end; + } else { + this.stream.onReceiveData(begin, chunk); + } + if (this.stream.isDataLoaded) { + this._loadedStreamCapability.resolve(this.stream); + } + const loadedRequests = []; + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + const requestIds = this._requestsByChunk.get(curChunk); + if (!requestIds) { + continue; + } + this._requestsByChunk.delete(curChunk); + for (const requestId of requestIds) { + const chunksNeeded = this._chunksNeededByRequest.get(requestId); + if (chunksNeeded.has(curChunk)) { + chunksNeeded.delete(curChunk); + } + if (chunksNeeded.size > 0) { + continue; + } + loadedRequests.push(requestId); + } + } + if (!this.disableAutoFetch && this._requestsByChunk.size === 0) { + let nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + const lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (Number.isInteger(nextEmptyChunk)) { + this._requestChunks([nextEmptyChunk]); + } + } + for (const requestId of loadedRequests) { + const capability = this._promisesByRequest.get(requestId); + this._promisesByRequest.delete(requestId); + capability.resolve(); + } + this.msgHandler.send("DocProgress", { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + } + onError(err) { + this._loadedStreamCapability.reject(err); + } + getBeginChunk(begin) { + return Math.floor(begin / this.chunkSize); + } + getEndChunk(end) { + return Math.floor((end - 1) / this.chunkSize) + 1; + } + abort(reason) { + this.aborted = true; + this.pdfNetworkStream?.cancelAllRequests(reason); + for (const capability of this._promisesByRequest.values()) { + capability.reject(reason); + } + } +} + +;// ./src/shared/image_utils.js + +function convertToRGBA(params) { + switch (params.kind) { + case ImageKind.GRAYSCALE_1BPP: + return convertBlackAndWhiteToRGBA(params); + case ImageKind.RGB_24BPP: + return convertRGBToRGBA(params); + } + return null; +} +function convertBlackAndWhiteToRGBA({ + src, + srcPos = 0, + dest, + width, + height, + nonBlackColor = 0xffffffff, + inverseDecode = false +}) { + const black = FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff; + const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor]; + const widthInSource = width >> 3; + const widthRemainder = width & 7; + const srcLength = src.length; + dest = new Uint32Array(dest.buffer); + let destPos = 0; + for (let i = 0; i < height; i++) { + for (const max = srcPos + widthInSource; srcPos < max; srcPos++) { + const elem = srcPos < srcLength ? src[srcPos] : 255; + dest[destPos++] = elem & 0b10000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1000 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b100 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b10 ? oneMapping : zeroMapping; + dest[destPos++] = elem & 0b1 ? oneMapping : zeroMapping; + } + if (widthRemainder === 0) { + continue; + } + const elem = srcPos < srcLength ? src[srcPos++] : 255; + for (let j = 0; j < widthRemainder; j++) { + dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; + } + } + return { + srcPos, + destPos + }; +} +function convertRGBToRGBA({ + src, + srcPos = 0, + dest, + destPos = 0, + width, + height +}) { + let i = 0; + const len = width * height * 3; + const len32 = len >> 2; + const src32 = new Uint32Array(src.buffer, srcPos, len32); + if (FeatureTest.isLittleEndian) { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 0xff000000; + dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 0xff000000; + dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 0xff000000; + dest[destPos + 3] = s3 >>> 8 | 0xff000000; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 0xff000000; + } + } else { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 0xff; + dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 0xff; + dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 0xff; + dest[destPos + 3] = s3 << 8 | 0xff; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 0xff; + } + } + return { + srcPos: srcPos + len, + destPos + }; +} +function grayToRGBA(src, dest) { + if (FeatureTest.isLittleEndian) { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 0x10101 | 0xff000000; + } + } else { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 0x1010100 | 0x000000ff; + } + } +} + +;// ./src/core/image_resizer.js + + + +const MIN_IMAGE_DIM = 2048; +const MAX_IMAGE_DIM = 65537; +const MAX_ERROR = 128; +class ImageResizer { + static #goodSquareLength = MIN_IMAGE_DIM; + static #isImageDecoderSupported = FeatureTest.isImageDecoderSupported; + constructor(imgData, isMask) { + this._imgData = imgData; + this._isMask = isMask; + } + static get canUseImageDecoder() { + return shadow(this, "canUseImageDecoder", this.#isImageDecoderSupported ? ImageDecoder.isTypeSupported("image/bmp") : Promise.resolve(false)); + } + static needsToBeResized(width, height) { + if (width <= this.#goodSquareLength && height <= this.#goodSquareLength) { + return false; + } + const { + MAX_DIM + } = this; + if (width > MAX_DIM || height > MAX_DIM) { + return true; + } + const area = width * height; + if (this._hasMaxArea) { + return area > this.MAX_AREA; + } + if (area < this.#goodSquareLength ** 2) { + return false; + } + if (this._areGoodDims(width, height)) { + this.#goodSquareLength = Math.max(this.#goodSquareLength, Math.floor(Math.sqrt(width * height))); + return false; + } + this.#goodSquareLength = this._guessMax(this.#goodSquareLength, MAX_DIM, MAX_ERROR, 0); + const maxArea = this.MAX_AREA = this.#goodSquareLength ** 2; + return area > maxArea; + } + static getReducePowerForJPX(width, height, componentsCount) { + const area = width * height; + const maxJPXArea = 2 ** 30 / (componentsCount * 4); + if (!this.needsToBeResized(width, height)) { + if (area > maxJPXArea) { + return Math.ceil(Math.log2(area / maxJPXArea)); + } + return 0; + } + const { + MAX_DIM, + MAX_AREA + } = this; + const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(area / Math.min(maxJPXArea, MAX_AREA))); + return Math.ceil(Math.log2(minFactor)); + } + static get MAX_DIM() { + return shadow(this, "MAX_DIM", this._guessMax(MIN_IMAGE_DIM, MAX_IMAGE_DIM, 0, 1)); + } + static get MAX_AREA() { + this._hasMaxArea = true; + return shadow(this, "MAX_AREA", this._guessMax(this.#goodSquareLength, this.MAX_DIM, MAX_ERROR, 0) ** 2); + } + static set MAX_AREA(area) { + if (area >= 0) { + this._hasMaxArea = true; + shadow(this, "MAX_AREA", area); + } + } + static setOptions({ + canvasMaxAreaInBytes = -1, + isImageDecoderSupported = false + }) { + if (!this._hasMaxArea) { + this.MAX_AREA = canvasMaxAreaInBytes >> 2; + } + this.#isImageDecoderSupported = isImageDecoderSupported; + } + static _areGoodDims(width, height) { + try { + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + ctx.fillRect(0, 0, 1, 1); + const opacity = ctx.getImageData(0, 0, 1, 1).data[3]; + canvas.width = canvas.height = 1; + return opacity !== 0; + } catch { + return false; + } + } + static _guessMax(start, end, tolerance, defaultHeight) { + while (start + tolerance + 1 < end) { + const middle = Math.floor((start + end) / 2); + const height = defaultHeight || middle; + if (this._areGoodDims(middle, height)) { + start = middle; + } else { + end = middle; + } + } + return start; + } + static async createImage(imgData, isMask = false) { + return new ImageResizer(imgData, isMask)._createImage(); + } + async _createImage() { + const { + _imgData: imgData + } = this; + const { + width, + height + } = imgData; + if (width * height * 4 > MAX_INT_32) { + const result = this.#rescaleImageData(); + if (result) { + return result; + } + } + const data = this._encodeBMP(); + let decoder, imagePromise; + if (await ImageResizer.canUseImageDecoder) { + decoder = new ImageDecoder({ + data, + type: "image/bmp", + preferAnimation: false, + transfer: [data.buffer] + }); + imagePromise = decoder.decode().catch(reason => { + warn(`BMP image decoding failed: ${reason}`); + return createImageBitmap(new Blob([this._encodeBMP().buffer], { + type: "image/bmp" + })); + }).finally(() => { + decoder.close(); + }); + } else { + imagePromise = createImageBitmap(new Blob([data.buffer], { + type: "image/bmp" + })); + } + const { + MAX_AREA, + MAX_DIM + } = ImageResizer; + const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(width * height / MAX_AREA)); + const firstFactor = Math.max(minFactor, 2); + const factor = Math.round(10 * (minFactor + 1.25)) / 10 / firstFactor; + const N = Math.floor(Math.log2(factor)); + const steps = new Array(N + 2).fill(2); + steps[0] = firstFactor; + steps.splice(-1, 1, factor / (1 << N)); + let newWidth = width; + let newHeight = height; + const result = await imagePromise; + let bitmap = result.image || result; + for (const step of steps) { + const prevWidth = newWidth; + const prevHeight = newHeight; + newWidth = Math.floor(newWidth / step) - 1; + newHeight = Math.floor(newHeight / step) - 1; + const canvas = new OffscreenCanvas(newWidth, newHeight); + const ctx = canvas.getContext("2d"); + ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + bitmap.close(); + bitmap = canvas.transferToImageBitmap(); + } + imgData.data = null; + imgData.bitmap = bitmap; + imgData.width = newWidth; + imgData.height = newHeight; + return imgData; + } + #rescaleImageData() { + const { + _imgData: imgData + } = this; + const { + data, + width, + height, + kind + } = imgData; + const rgbaSize = width * height * 4; + const K = Math.ceil(Math.log2(rgbaSize / MAX_INT_32)); + const newWidth = width >> K; + const newHeight = height >> K; + let rgbaData; + let maxHeight = height; + try { + rgbaData = new Uint8Array(rgbaSize); + } catch { + let n = Math.floor(Math.log2(rgbaSize + 1)); + while (true) { + try { + rgbaData = new Uint8Array(2 ** n - 1); + break; + } catch { + n -= 1; + } + } + maxHeight = Math.floor((2 ** n - 1) / (width * 4)); + const newSize = width * maxHeight * 4; + if (newSize < rgbaData.length) { + rgbaData = new Uint8Array(newSize); + } + } + const src32 = new Uint32Array(rgbaData.buffer); + const dest32 = new Uint32Array(newWidth * newHeight); + let srcPos = 0; + let newIndex = 0; + const step = Math.ceil(height / maxHeight); + const remainder = height % maxHeight === 0 ? height : height % maxHeight; + for (let k = 0; k < step; k++) { + const h = k < step - 1 ? maxHeight : remainder; + ({ + srcPos + } = convertToRGBA({ + kind, + src: data, + dest: src32, + width, + height: h, + inverseDecode: this._isMask, + srcPos + })); + for (let i = 0, ii = h >> K; i < ii; i++) { + const buf = src32.subarray((i << K) * width); + for (let j = 0; j < newWidth; j++) { + dest32[newIndex++] = buf[j << K]; + } + } + } + if (ImageResizer.needsToBeResized(newWidth, newHeight)) { + imgData.data = dest32; + imgData.width = newWidth; + imgData.height = newHeight; + imgData.kind = ImageKind.RGBA_32BPP; + return null; + } + const canvas = new OffscreenCanvas(newWidth, newHeight); + const ctx = canvas.getContext("2d", { + willReadFrequently: true + }); + ctx.putImageData(new ImageData(new Uint8ClampedArray(dest32.buffer), newWidth, newHeight), 0, 0); + imgData.data = null; + imgData.bitmap = canvas.transferToImageBitmap(); + imgData.width = newWidth; + imgData.height = newHeight; + return imgData; + } + _encodeBMP() { + const { + width, + height, + kind + } = this._imgData; + let data = this._imgData.data; + let bitPerPixel; + let colorTable = new Uint8Array(0); + let maskTable = colorTable; + let compression = 0; + switch (kind) { + case ImageKind.GRAYSCALE_1BPP: + { + bitPerPixel = 1; + colorTable = new Uint8Array(this._isMask ? [255, 255, 255, 255, 0, 0, 0, 0] : [0, 0, 0, 0, 255, 255, 255, 255]); + const rowLen = width + 7 >> 3; + const rowSize = rowLen + 3 & -4; + if (rowLen !== rowSize) { + const newData = new Uint8Array(rowSize * height); + let k = 0; + for (let i = 0, ii = height * rowLen; i < ii; i += rowLen, k += rowSize) { + newData.set(data.subarray(i, i + rowLen), k); + } + data = newData; + } + break; + } + case ImageKind.RGB_24BPP: + { + bitPerPixel = 24; + if (width & 3) { + const rowLen = 3 * width; + const rowSize = rowLen + 3 & -4; + const extraLen = rowSize - rowLen; + const newData = new Uint8Array(rowSize * height); + let k = 0; + for (let i = 0, ii = height * rowLen; i < ii; i += rowLen) { + const row = data.subarray(i, i + rowLen); + for (let j = 0; j < rowLen; j += 3) { + newData[k++] = row[j + 2]; + newData[k++] = row[j + 1]; + newData[k++] = row[j]; + } + k += extraLen; + } + data = newData; + } else { + for (let i = 0, ii = data.length; i < ii; i += 3) { + const tmp = data[i]; + data[i] = data[i + 2]; + data[i + 2] = tmp; + } + } + break; + } + case ImageKind.RGBA_32BPP: + bitPerPixel = 32; + compression = 3; + maskTable = new Uint8Array(4 + 4 + 4 + 4 + 52); + const view = new DataView(maskTable.buffer); + if (FeatureTest.isLittleEndian) { + view.setUint32(0, 0x000000ff, true); + view.setUint32(4, 0x0000ff00, true); + view.setUint32(8, 0x00ff0000, true); + view.setUint32(12, 0xff000000, true); + } else { + view.setUint32(0, 0xff000000, true); + view.setUint32(4, 0x00ff0000, true); + view.setUint32(8, 0x0000ff00, true); + view.setUint32(12, 0x000000ff, true); + } + break; + default: + throw new Error("invalid format"); + } + let i = 0; + const headerLength = 40 + maskTable.length; + const fileLength = 14 + headerLength + colorTable.length + data.length; + const bmpData = new Uint8Array(fileLength); + const view = new DataView(bmpData.buffer); + view.setUint16(i, 0x4d42, true); + i += 2; + view.setUint32(i, fileLength, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + view.setUint32(i, 14 + headerLength + colorTable.length, true); + i += 4; + view.setUint32(i, headerLength, true); + i += 4; + view.setInt32(i, width, true); + i += 4; + view.setInt32(i, -height, true); + i += 4; + view.setUint16(i, 1, true); + i += 2; + view.setUint16(i, bitPerPixel, true); + i += 2; + view.setUint32(i, compression, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + view.setInt32(i, 0, true); + i += 4; + view.setInt32(i, 0, true); + i += 4; + view.setUint32(i, colorTable.length / 4, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + bmpData.set(maskTable, i); + i += maskTable.length; + bmpData.set(colorTable, i); + i += colorTable.length; + bmpData.set(data, i); + return bmpData; + } +} + +;// ./src/core/decode_stream.js + + +const emptyBuffer = new Uint8Array(0); +class DecodeStream extends BaseStream { + constructor(maybeMinBufferLength) { + super(); + this._rawMinBufferLength = maybeMinBufferLength || 0; + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + get isEmpty() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + } + ensureBuffer(requested) { + const buffer = this.buffer; + if (requested <= buffer.byteLength) { + return buffer; + } + let size = this.minBufferLength; + while (size < requested) { + size *= 2; + } + const buffer2 = new Uint8Array(size); + buffer2.set(buffer); + return this.buffer = buffer2; + } + getByte() { + const pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + } + getBytes(length, decoderOptions = null) { + const pos = this.pos; + let end; + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + while (!this.eof && this.bufferLength < end) { + this.readBlock(decoderOptions); + } + const bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(decoderOptions); + } + end = this.bufferLength; + } + this.pos = end; + return this.buffer.subarray(pos, end); + } + async getImageData(length, decoderOptions) { + if (!this.canAsyncDecodeImageFromBuffer) { + if (this.isAsyncDecoder) { + return this.decodeImage(null, decoderOptions); + } + return this.getBytes(length, decoderOptions); + } + const data = await this.stream.asyncGetBytes(); + return this.decodeImage(data, decoderOptions); + } + reset() { + this.pos = 0; + } + makeSubStream(start, length, dict = null) { + if (length === undefined) { + while (!this.eof) { + this.readBlock(); + } + } else { + const end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + } + return new Stream(this.buffer, start, length, dict); + } + getBaseStreams() { + return this.stream ? this.stream.getBaseStreams() : null; + } + clone() { + while (!this.eof) { + this.readBlock(); + } + return new Stream(this.buffer, this.start, this.end - this.start, this.dict.clone()); + } +} +class StreamsSequenceStream extends DecodeStream { + constructor(streams, onError = null) { + streams = streams.filter(s => s instanceof BaseStream); + let maybeLength = 0; + for (const stream of streams) { + maybeLength += stream instanceof DecodeStream ? stream._rawMinBufferLength : stream.length; + } + super(maybeLength); + this.streams = streams; + this._onError = onError; + } + readBlock() { + const streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + const stream = streams.shift(); + let chunk; + try { + chunk = stream.getBytes(); + } catch (reason) { + if (this._onError) { + this._onError(reason, stream.dict?.objId); + return; + } + throw reason; + } + const bufferLength = this.bufferLength; + const newLength = bufferLength + chunk.length; + const buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + } + getBaseStreams() { + const baseStreamsBuf = []; + for (const stream of this.streams) { + const baseStreams = stream.getBaseStreams(); + if (baseStreams) { + baseStreamsBuf.push(...baseStreams); + } + } + return baseStreamsBuf.length > 0 ? baseStreamsBuf : null; + } +} + +;// ./src/core/colorspace_utils.js + + + + + +class ColorSpaceUtils { + static parse({ + cs, + xref, + resources = null, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache, + asyncIfNotCached = false + }) { + const options = { + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }; + let csName, csRef, parsedCS; + if (cs instanceof Ref) { + csRef = cs; + const cachedCS = globalColorSpaceCache.getByRef(csRef) || localColorSpaceCache.getByRef(csRef); + if (cachedCS) { + return cachedCS; + } + cs = xref.fetch(cs); + } + if (cs instanceof Name) { + csName = cs.name; + const cachedCS = localColorSpaceCache.getByName(csName); + if (cachedCS) { + return cachedCS; + } + } + try { + parsedCS = this.#parse(cs, options); + } catch (ex) { + if (asyncIfNotCached && !(ex instanceof MissingDataException)) { + return Promise.reject(ex); + } + throw ex; + } + if (csName || csRef) { + localColorSpaceCache.set(csName, csRef, parsedCS); + if (csRef) { + globalColorSpaceCache.set(null, csRef, parsedCS); + } + } + return asyncIfNotCached ? Promise.resolve(parsedCS) : parsedCS; + } + static #subParse(cs, options) { + const { + globalColorSpaceCache + } = options; + let csRef; + if (cs instanceof Ref) { + csRef = cs; + const cachedCS = globalColorSpaceCache.getByRef(csRef); + if (cachedCS) { + return cachedCS; + } + } + const parsedCS = this.#parse(cs, options); + if (csRef) { + globalColorSpaceCache.set(null, csRef, parsedCS); + } + return parsedCS; + } + static #parse(cs, options) { + const { + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache + } = options; + cs = xref.fetchIfRef(cs); + if (cs instanceof Name) { + switch (cs.name) { + case "G": + case "DeviceGray": + return this.gray; + case "RGB": + case "DeviceRGB": + return this.rgb; + case "DeviceRGBA": + return this.rgba; + case "CMYK": + case "DeviceCMYK": + return this.cmyk; + case "Pattern": + return new PatternCS(null); + default: + if (resources instanceof Dict) { + const colorSpaces = resources.get("ColorSpace"); + if (colorSpaces instanceof Dict) { + const resourcesCS = colorSpaces.get(cs.name); + if (resourcesCS) { + if (resourcesCS instanceof Name) { + return this.#parse(resourcesCS, options); + } + cs = resourcesCS; + break; + } + } + } + warn(`Unrecognized ColorSpace: ${cs.name}`); + return this.gray; + } + } + if (Array.isArray(cs)) { + const mode = xref.fetchIfRef(cs[0]).name; + let params, numComps, baseCS, whitePoint, blackPoint, gamma; + switch (mode) { + case "G": + case "DeviceGray": + return this.gray; + case "RGB": + case "DeviceRGB": + return this.rgb; + case "CMYK": + case "DeviceCMYK": + return this.cmyk; + case "CalGray": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + gamma = params.get("Gamma"); + return new CalGrayCS(whitePoint, blackPoint, gamma); + case "CalRGB": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + gamma = params.getArray("Gamma"); + const matrix = params.getArray("Matrix"); + return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); + case "ICCBased": + const isRef = cs[1] instanceof Ref; + if (isRef) { + const cachedCS = globalColorSpaceCache.getByRef(cs[1]); + if (cachedCS) { + return cachedCS; + } + } + const stream = xref.fetchIfRef(cs[1]); + const dict = stream.dict; + numComps = dict.get("N"); + if (IccColorSpace.isUsable) { + try { + const iccCS = new IccColorSpace(stream.getBytes(), "ICCBased", numComps); + if (isRef) { + globalColorSpaceCache.set(null, cs[1], iccCS); + } + return iccCS; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`ICCBased color space (${cs[1]}): "${ex}".`); + } + } + const altRaw = dict.getRaw("Alternate"); + if (altRaw) { + const altCS = this.#subParse(altRaw, options); + if (altCS.numComps === numComps) { + return altCS; + } + warn("ICCBased color space: Ignoring incorrect /Alternate entry."); + } + if (numComps === 1) { + return this.gray; + } else if (numComps === 3) { + return this.rgb; + } else if (numComps === 4) { + return this.cmyk; + } + break; + case "Pattern": + baseCS = cs[1] || null; + if (baseCS) { + baseCS = this.#subParse(baseCS, options); + } + return new PatternCS(baseCS); + case "I": + case "Indexed": + baseCS = this.#subParse(cs[1], options); + const hiVal = MathClamp(xref.fetchIfRef(cs[2]), 0, 255); + const lookup = xref.fetchIfRef(cs[3]); + return new IndexedCS(baseCS, hiVal, lookup); + case "Separation": + case "DeviceN": + const name = xref.fetchIfRef(cs[1]); + numComps = Array.isArray(name) ? name.length : 1; + baseCS = this.#subParse(cs[2], options); + const tintFn = pdfFunctionFactory.create(cs[3]); + return new AlternateCS(numComps, baseCS, tintFn); + case "Lab": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + const range = params.getArray("Range"); + return new LabCS(whitePoint, blackPoint, range); + default: + warn(`Unimplemented ColorSpace object: ${mode}`); + return this.gray; + } + } + warn(`Unrecognized ColorSpace object: ${cs}`); + return this.gray; + } + static get gray() { + return shadow(this, "gray", new DeviceGrayCS()); + } + static get rgb() { + return shadow(this, "rgb", new DeviceRgbCS()); + } + static get rgba() { + return shadow(this, "rgba", new DeviceRgbaCS()); + } + static get cmyk() { + if (CmykICCBasedCS.isUsable) { + try { + return shadow(this, "cmyk", new CmykICCBasedCS()); + } catch { + warn("CMYK fallback: DeviceCMYK"); + } + } + return shadow(this, "cmyk", new DeviceCmykCS()); + } +} + +;// ./src/core/jpg.js + + + + + +class JpegError extends BaseException { + constructor(msg) { + super(msg, "JpegError"); + } +} +class DNLMarkerError extends BaseException { + constructor(message, scanLines) { + super(message, "DNLMarkerError"); + this.scanLines = scanLines; + } +} +class EOIMarkerError extends BaseException { + constructor(msg) { + super(msg, "EOIMarkerError"); + } +} +const dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]); +const dctCos1 = 4017; +const dctSin1 = 799; +const dctCos3 = 3406; +const dctSin3 = 2276; +const dctCos6 = 1567; +const dctSin6 = 3784; +const dctSqrt2 = 5793; +const dctSqrt1d2 = 2896; +function buildHuffmanTable(codeLengths, values) { + let k = 0, + i, + j, + length = 16; + while (length > 0 && !codeLengths[length - 1]) { + length--; + } + const code = [{ + children: [], + index: 0 + }]; + let p = code[0], + q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; +} +function getBlockBufferOffset(component, row, col) { + return 64 * ((component.blocksPerLine + 1) * row + col); +} +function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) { + const mcusPerLine = frame.mcusPerLine; + const progressive = frame.progressive; + const startOffset = offset; + let bitsData = 0, + bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return bitsData >> bitsCount & 1; + } + bitsData = data[offset++]; + if (bitsData === 0xff) { + const nextByte = data[offset++]; + if (nextByte) { + if (nextByte === 0xdc && parseDNLMarker) { + offset += 2; + const scanLines = readUint16(data, offset); + offset += 2; + if (scanLines > 0 && scanLines !== frame.scanLines) { + throw new DNLMarkerError("Found DNL marker (0xFFDC) while parsing scan data", scanLines); + } + } else if (nextByte === 0xd9) { + if (parseDNLMarker) { + const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0); + if (maybeScanLines > 0 && Math.round(frame.scanLines / maybeScanLines) >= 5) { + throw new DNLMarkerError("Found EOI marker (0xFFD9) while parsing scan data, " + "possibly caused by incorrect `scanLines` parameter", maybeScanLines); + } + } + throw new EOIMarkerError("Found EOI marker (0xFFD9) while parsing scan data"); + } + throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`); + } + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + let node = tree; + while (true) { + node = node[readBit()]; + switch (typeof node) { + case "number": + return node; + case "object": + continue; + } + throw new JpegError("invalid huffman sequence"); + } + } + function receive(length) { + let n = 0; + while (length > 0) { + n = n << 1 | readBit(); + length--; + } + return n; + } + function receiveAndExtend(length) { + if (length === 1) { + return readBit() === 1 ? 1 : -1; + } + const n = receive(length); + if (n >= 1 << length - 1) { + return n; + } + return n + (-1 << length) + 1; + } + function decodeBaseline(component, blockOffset) { + const t = decodeHuffman(component.huffmanTableDC); + const diff = t === 0 ? 0 : receiveAndExtend(t); + component.blockData[blockOffset] = component.pred += diff; + let k = 1; + while (k < 64) { + const rs = decodeHuffman(component.huffmanTableAC); + const s = rs & 15, + r = rs >> 4; + if (s === 0) { + if (r < 15) { + break; + } + k += 16; + continue; + } + k += r; + const z = dctZigZag[k]; + component.blockData[blockOffset + z] = receiveAndExtend(s); + k++; + } + } + function decodeDCFirst(component, blockOffset) { + const t = decodeHuffman(component.huffmanTableDC); + const diff = t === 0 ? 0 : receiveAndExtend(t) << successive; + component.blockData[blockOffset] = component.pred += diff; + } + function decodeDCSuccessive(component, blockOffset) { + component.blockData[blockOffset] |= readBit() << successive; + } + let eobrun = 0; + function decodeACFirst(component, blockOffset) { + if (eobrun > 0) { + eobrun--; + return; + } + let k = spectralStart; + const e = spectralEnd; + while (k <= e) { + const rs = decodeHuffman(component.huffmanTableAC); + const s = rs & 15, + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + const z = dctZigZag[k]; + component.blockData[blockOffset + z] = receiveAndExtend(s) * (1 << successive); + k++; + } + } + let successiveACState = 0, + successiveACNextValue; + function decodeACSuccessive(component, blockOffset) { + let k = spectralStart; + const e = spectralEnd; + let r = 0; + let s; + let rs; + while (k <= e) { + const offsetZ = blockOffset + dctZigZag[k]; + const sign = component.blockData[offsetZ] < 0 ? -1 : 1; + switch (successiveACState) { + case 0: + rs = decodeHuffman(component.huffmanTableAC); + s = rs & 15; + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) { + throw new JpegError("invalid ACn encoding"); + } + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: + case 2: + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); + } else { + r--; + if (r === 0) { + successiveACState = successiveACState === 2 ? 3 : 0; + } + } + break; + case 3: + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); + } else { + component.blockData[offsetZ] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); + } + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) { + successiveACState = 0; + } + } + } + let blockRow = 0; + function decodeMcu(component, decode, mcu, row, col) { + const mcuRow = mcu / mcusPerLine | 0; + const mcuCol = mcu % mcusPerLine; + blockRow = mcuRow * component.v + row; + const blockCol = mcuCol * component.h + col; + const blockOffset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, blockOffset); + } + function decodeBlock(component, decode, mcu) { + blockRow = mcu / component.blocksPerLine | 0; + const blockCol = mcu % component.blocksPerLine; + const blockOffset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, blockOffset); + } + const componentsLength = components.length; + let component, i, j, k, n; + let decodeFn; + if (progressive) { + if (spectralStart === 0) { + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + } else { + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } + } else { + decodeFn = decodeBaseline; + } + let mcu = 0, + fileMarker; + const mcuExpected = componentsLength === 1 ? components[0].blocksPerLine * components[0].blocksPerColumn : mcusPerLine * frame.mcusPerColumn; + let h, v; + while (mcu <= mcuExpected) { + const mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected; + if (mcuToRead > 0) { + for (i = 0; i < componentsLength; i++) { + components[i].pred = 0; + } + eobrun = 0; + if (componentsLength === 1) { + component = components[0]; + for (n = 0; n < mcuToRead; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < mcuToRead; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + } + } + } + bitsCount = 0; + fileMarker = findNextFileMarker(data, offset); + if (!fileMarker) { + break; + } + if (fileMarker.invalid) { + const partialMsg = mcuToRead > 0 ? "unexpected" : "excessive"; + warn(`decodeScan - ${partialMsg} MCU data, current marker is: ${fileMarker.invalid}`); + offset = fileMarker.offset; + } + if (fileMarker.marker >= 0xffd0 && fileMarker.marker <= 0xffd7) { + offset += 2; + } else { + break; + } + } + return offset - startOffset; +} +function quantizeAndInverse(component, blockBufferOffset, p) { + const qt = component.quantizationTable, + blockData = component.blockData; + let v0, v1, v2, v3, v4, v5, v6, v7; + let p0, p1, p2, p3, p4, p5, p6, p7; + let t; + if (!qt) { + throw new JpegError("missing required Quantization Table."); + } + for (let row = 0; row < 64; row += 8) { + p0 = blockData[blockBufferOffset + row]; + p1 = blockData[blockBufferOffset + row + 1]; + p2 = blockData[blockBufferOffset + row + 2]; + p3 = blockData[blockBufferOffset + row + 3]; + p4 = blockData[blockBufferOffset + row + 4]; + p5 = blockData[blockBufferOffset + row + 5]; + p6 = blockData[blockBufferOffset + row + 6]; + p7 = blockData[blockBufferOffset + row + 7]; + p0 *= qt[row]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 512 >> 10; + p[row] = t; + p[row + 1] = t; + p[row + 2] = t; + p[row + 3] = t; + p[row + 4] = t; + p[row + 5] = t; + p[row + 6] = t; + p[row + 7] = t; + continue; + } + p1 *= qt[row + 1]; + p2 *= qt[row + 2]; + p3 *= qt[row + 3]; + p4 *= qt[row + 4]; + p5 *= qt[row + 5]; + p6 *= qt[row + 6]; + p7 *= qt[row + 7]; + v0 = dctSqrt2 * p0 + 128 >> 8; + v1 = dctSqrt2 * p4 + 128 >> 8; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8; + v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8; + v5 = p3 << 4; + v6 = p5 << 4; + v0 = v0 + v1 + 1 >> 1; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8; + v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p[row] = v0 + v7; + p[row + 7] = v0 - v7; + p[row + 1] = v1 + v6; + p[row + 6] = v1 - v6; + p[row + 2] = v2 + v5; + p[row + 5] = v2 - v5; + p[row + 3] = v3 + v4; + p[row + 4] = v3 - v4; + } + for (let col = 0; col < 8; ++col) { + p0 = p[col]; + p1 = p[col + 8]; + p2 = p[col + 16]; + p3 = p[col + 24]; + p4 = p[col + 32]; + p5 = p[col + 40]; + p6 = p[col + 48]; + p7 = p[col + 56]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 8192 >> 14; + if (t < -2040) { + t = 0; + } else if (t >= 2024) { + t = 255; + } else { + t = t + 2056 >> 4; + } + blockData[blockBufferOffset + col] = t; + blockData[blockBufferOffset + col + 8] = t; + blockData[blockBufferOffset + col + 16] = t; + blockData[blockBufferOffset + col + 24] = t; + blockData[blockBufferOffset + col + 32] = t; + blockData[blockBufferOffset + col + 40] = t; + blockData[blockBufferOffset + col + 48] = t; + blockData[blockBufferOffset + col + 56] = t; + continue; + } + v0 = dctSqrt2 * p0 + 2048 >> 12; + v1 = dctSqrt2 * p4 + 2048 >> 12; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12; + v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12; + v5 = p3; + v6 = p5; + v0 = (v0 + v1 + 1 >> 1) + 4112; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12; + v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p0 = v0 + v7; + p7 = v0 - v7; + p1 = v1 + v6; + p6 = v1 - v6; + p2 = v2 + v5; + p5 = v2 - v5; + p3 = v3 + v4; + p4 = v3 - v4; + if (p0 < 16) { + p0 = 0; + } else if (p0 >= 4080) { + p0 = 255; + } else { + p0 >>= 4; + } + if (p1 < 16) { + p1 = 0; + } else if (p1 >= 4080) { + p1 = 255; + } else { + p1 >>= 4; + } + if (p2 < 16) { + p2 = 0; + } else if (p2 >= 4080) { + p2 = 255; + } else { + p2 >>= 4; + } + if (p3 < 16) { + p3 = 0; + } else if (p3 >= 4080) { + p3 = 255; + } else { + p3 >>= 4; + } + if (p4 < 16) { + p4 = 0; + } else if (p4 >= 4080) { + p4 = 255; + } else { + p4 >>= 4; + } + if (p5 < 16) { + p5 = 0; + } else if (p5 >= 4080) { + p5 = 255; + } else { + p5 >>= 4; + } + if (p6 < 16) { + p6 = 0; + } else if (p6 >= 4080) { + p6 = 255; + } else { + p6 >>= 4; + } + if (p7 < 16) { + p7 = 0; + } else if (p7 >= 4080) { + p7 = 255; + } else { + p7 >>= 4; + } + blockData[blockBufferOffset + col] = p0; + blockData[blockBufferOffset + col + 8] = p1; + blockData[blockBufferOffset + col + 16] = p2; + blockData[blockBufferOffset + col + 24] = p3; + blockData[blockBufferOffset + col + 32] = p4; + blockData[blockBufferOffset + col + 40] = p5; + blockData[blockBufferOffset + col + 48] = p6; + blockData[blockBufferOffset + col + 56] = p7; + } +} +function buildComponentData(frame, component) { + const blocksPerLine = component.blocksPerLine; + const blocksPerColumn = component.blocksPerColumn; + const computationBuffer = new Int16Array(64); + for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) { + const offset = getBlockBufferOffset(component, blockRow, blockCol); + quantizeAndInverse(component, offset, computationBuffer); + } + } + return component.blockData; +} +function findNextFileMarker(data, currentPos, startPos = currentPos) { + const maxPos = data.length - 1; + let newPos = startPos < currentPos ? startPos : currentPos; + if (currentPos >= maxPos) { + return null; + } + const currentMarker = readUint16(data, currentPos); + if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) { + return { + invalid: null, + marker: currentMarker, + offset: currentPos + }; + } + let newMarker = readUint16(data, newPos); + while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) { + if (++newPos >= maxPos) { + return null; + } + newMarker = readUint16(data, newPos); + } + return { + invalid: currentMarker.toString(16), + marker: newMarker, + offset: newPos + }; +} +function prepareComponents(frame) { + const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); + const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); + for (const component of frame.components) { + const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH); + const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV); + const blocksPerLineForMcu = mcusPerLine * component.h; + const blocksPerColumnForMcu = mcusPerColumn * component.v; + const blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1); + component.blockData = new Int16Array(blocksBufferSize); + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + } + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; +} +function readDataBlock(data, offset) { + const length = readUint16(data, offset); + offset += 2; + let endOffset = offset + length - 2; + const fileMarker = findNextFileMarker(data, endOffset, offset); + if (fileMarker?.invalid) { + warn("readDataBlock - incorrect length, current marker is: " + fileMarker.invalid); + endOffset = fileMarker.offset; + } + const array = data.subarray(offset, endOffset); + return { + appData: array, + oldOffset: offset, + newOffset: offset + array.length + }; +} +function skipData(data, offset) { + const length = readUint16(data, offset); + offset += 2; + const endOffset = offset + length - 2; + const fileMarker = findNextFileMarker(data, endOffset, offset); + if (fileMarker?.invalid) { + return fileMarker.offset; + } + return endOffset; +} +class JpegImage { + constructor({ + decodeTransform = null, + colorTransform = -1 + } = {}) { + this._decodeTransform = decodeTransform; + this._colorTransform = colorTransform; + } + static canUseImageDecoder(data, colorTransform = -1) { + let exifOffsets = null; + let offset = 0; + let numComponents = null; + let fileMarker = readUint16(data, offset); + offset += 2; + if (fileMarker !== 0xffd8) { + throw new JpegError("SOI not found"); + } + fileMarker = readUint16(data, offset); + offset += 2; + markerLoop: while (fileMarker !== 0xffd9) { + switch (fileMarker) { + case 0xffe1: + const { + appData, + oldOffset, + newOffset + } = readDataBlock(data, offset); + offset = newOffset; + if (appData[0] === 0x45 && appData[1] === 0x78 && appData[2] === 0x69 && appData[3] === 0x66 && appData[4] === 0 && appData[5] === 0) { + if (exifOffsets) { + throw new JpegError("Duplicate EXIF-blocks found."); + } + exifOffsets = { + exifStart: oldOffset + 6, + exifEnd: newOffset + }; + } + fileMarker = readUint16(data, offset); + offset += 2; + continue; + case 0xffc0: + case 0xffc1: + case 0xffc2: + numComponents = data[offset + (2 + 1 + 2 + 2)]; + break markerLoop; + case 0xffff: + if (data[offset] !== 0xff) { + offset--; + } + break; + } + offset = skipData(data, offset); + fileMarker = readUint16(data, offset); + offset += 2; + } + if (numComponents === 4) { + return null; + } + if (numComponents === 3 && colorTransform === 0) { + return null; + } + return exifOffsets || {}; + } + parse(data, { + dnlScanLines = null + } = {}) { + let offset = 0; + let jfif = null; + let adobe = null; + let frame, resetInterval; + let numSOSMarkers = 0; + const quantizationTables = []; + const huffmanTablesAC = [], + huffmanTablesDC = []; + let fileMarker = readUint16(data, offset); + offset += 2; + if (fileMarker !== 0xffd8) { + throw new JpegError("SOI not found"); + } + fileMarker = readUint16(data, offset); + offset += 2; + markerLoop: while (fileMarker !== 0xffd9) { + let i, j, l; + switch (fileMarker) { + case 0xffe0: + case 0xffe1: + case 0xffe2: + case 0xffe3: + case 0xffe4: + case 0xffe5: + case 0xffe6: + case 0xffe7: + case 0xffe8: + case 0xffe9: + case 0xffea: + case 0xffeb: + case 0xffec: + case 0xffed: + case 0xffee: + case 0xffef: + case 0xfffe: + const { + appData, + newOffset + } = readDataBlock(data, offset); + offset = newOffset; + if (fileMarker === 0xffe0) { + if (appData[0] === 0x4a && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) { + jfif = { + version: { + major: appData[5], + minor: appData[6] + }, + densityUnits: appData[7], + xDensity: appData[8] << 8 | appData[9], + yDensity: appData[10] << 8 | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + if (fileMarker === 0xffee) { + if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6f && appData[3] === 0x62 && appData[4] === 0x65) { + adobe = { + version: appData[5] << 8 | appData[6], + flags0: appData[7] << 8 | appData[8], + flags1: appData[9] << 8 | appData[10], + transformCode: appData[11] + }; + } + } + break; + case 0xffdb: + const quantizationTablesLength = readUint16(data, offset); + offset += 2; + const quantizationTablesEnd = quantizationTablesLength + offset - 2; + let z; + while (offset < quantizationTablesEnd) { + const quantizationTableSpec = data[offset++]; + const tableData = new Uint16Array(64); + if (quantizationTableSpec >> 4 === 0) { + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if (quantizationTableSpec >> 4 === 1) { + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = readUint16(data, offset); + offset += 2; + } + } else { + throw new JpegError("DQT - invalid table spec"); + } + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + case 0xffc0: + case 0xffc1: + case 0xffc2: + if (frame) { + throw new JpegError("Only single frame JPEGs supported"); + } + offset += 2; + frame = {}; + frame.extended = fileMarker === 0xffc1; + frame.progressive = fileMarker === 0xffc2; + frame.precision = data[offset++]; + const sofScanLines = readUint16(data, offset); + offset += 2; + frame.scanLines = dnlScanLines || sofScanLines; + frame.samplesPerLine = readUint16(data, offset); + offset += 2; + frame.components = []; + frame.componentIds = {}; + const componentsCount = data[offset++]; + let maxH = 0, + maxV = 0; + for (i = 0; i < componentsCount; i++) { + const componentId = data[offset]; + const h = data[offset + 1] >> 4; + const v = data[offset + 1] & 15; + if (maxH < h) { + maxH = h; + } + if (maxV < v) { + maxV = v; + } + const qId = data[offset + 2]; + l = frame.components.push({ + h, + v, + quantizationId: qId, + quantizationTable: null + }); + frame.componentIds[componentId] = l - 1; + offset += 3; + } + frame.maxH = maxH; + frame.maxV = maxV; + prepareComponents(frame); + break; + case 0xffc4: + const huffmanLength = readUint16(data, offset); + offset += 2; + for (i = 2; i < huffmanLength;) { + const huffmanTableSpec = data[offset++]; + const codeLengths = new Uint8Array(16); + let codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += codeLengths[j] = data[offset]; + } + const huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) { + huffmanValues[j] = data[offset]; + } + i += 17 + codeLengthSum; + (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues); + } + break; + case 0xffdd: + offset += 2; + resetInterval = readUint16(data, offset); + offset += 2; + break; + case 0xffda: + const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines; + offset += 2; + const selectorsCount = data[offset++], + components = []; + for (i = 0; i < selectorsCount; i++) { + const index = data[offset++]; + const componentIndex = frame.componentIds[index]; + const component = frame.components[componentIndex]; + component.index = index; + const tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + const spectralStart = data[offset++], + spectralEnd = data[offset++], + successiveApproximation = data[offset++]; + try { + const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker); + offset += processed; + } catch (ex) { + if (ex instanceof DNLMarkerError) { + warn(`${ex.message} -- attempting to re-parse the JPEG image.`); + return this.parse(data, { + dnlScanLines: ex.scanLines + }); + } else if (ex instanceof EOIMarkerError) { + warn(`${ex.message} -- ignoring the rest of the image data.`); + break markerLoop; + } + throw ex; + } + break; + case 0xffdc: + offset += 4; + break; + case 0xffff: + if (data[offset] !== 0xff) { + offset--; + } + break; + default: + const nextFileMarker = findNextFileMarker(data, offset - 2, offset - 3); + if (nextFileMarker?.invalid) { + warn("JpegImage.parse - unexpected data, current marker is: " + nextFileMarker.invalid); + offset = nextFileMarker.offset; + break; + } + if (!nextFileMarker || offset >= data.length - 1) { + warn("JpegImage.parse - reached the end of the image data " + "without finding an EOI marker (0xFFD9)."); + break markerLoop; + } + throw new JpegError("JpegImage.parse - unknown marker: " + fileMarker.toString(16)); + } + fileMarker = readUint16(data, offset); + offset += 2; + } + if (!frame) { + throw new JpegError("JpegImage.parse - no frame data found."); + } + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (const component of frame.components) { + const quantizationTable = quantizationTables[component.quantizationId]; + if (quantizationTable) { + component.quantizationTable = quantizationTable; + } + this.components.push({ + index: component.index, + output: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn + }); + } + this.numComponents = this.components.length; + return undefined; + } + _getLinearizedBlockData(width, height, isSourcePDF = false) { + const scaleX = this.width / width, + scaleY = this.height / height; + let component, componentScaleX, componentScaleY, blocksPerScanline; + let x, y, i, j, k; + let index; + let offset = 0; + let output; + const numComponents = this.components.length; + const dataLength = width * height * numComponents; + const data = new Uint8ClampedArray(dataLength); + const xScaleBlockOffset = new Uint32Array(width); + const mask3LSB = 0xfffffff8; + let lastComponentScaleX; + for (i = 0; i < numComponents; i++) { + component = this.components[i]; + componentScaleX = component.scaleX * scaleX; + componentScaleY = component.scaleY * scaleY; + offset = i; + output = component.output; + blocksPerScanline = component.blocksPerLine + 1 << 3; + if (componentScaleX !== lastComponentScaleX) { + for (x = 0; x < width; x++) { + j = 0 | x * componentScaleX; + xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7; + } + lastComponentScaleX = componentScaleX; + } + for (y = 0; y < height; y++) { + j = 0 | y * componentScaleY; + index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3; + for (x = 0; x < width; x++) { + data[offset] = output[index + xScaleBlockOffset[x]]; + offset += numComponents; + } + } + } + let transform = this._decodeTransform; + if (!isSourcePDF && numComponents === 4 && !transform) { + transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]); + } + if (transform) { + for (i = 0; i < dataLength;) { + for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { + data[i] = (data[i] * transform[k] >> 8) + transform[k + 1]; + } + } + } + return data; + } + get _isColorConversionNeeded() { + if (this.adobe) { + return !!this.adobe.transformCode; + } + if (this.numComponents === 3) { + if (this._colorTransform === 0) { + return false; + } else if (this.components[0].index === 0x52 && this.components[1].index === 0x47 && this.components[2].index === 0x42) { + return false; + } + return true; + } + if (this._colorTransform === 1) { + return true; + } + return false; + } + _convertYccToRgb(data) { + let Y, Cb, Cr; + for (let i = 0, length = data.length; i < length; i += 3) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = Y - 179.456 + 1.402 * Cr; + data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr; + data[i + 2] = Y - 226.816 + 1.772 * Cb; + } + return data; + } + _convertYccToRgba(data, out) { + for (let i = 0, j = 0, length = data.length; i < length; i += 3, j += 4) { + const Y = data[i]; + const Cb = data[i + 1]; + const Cr = data[i + 2]; + out[j] = Y - 179.456 + 1.402 * Cr; + out[j + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr; + out[j + 2] = Y - 226.816 + 1.772 * Cb; + out[j + 3] = 255; + } + return out; + } + _convertYcckToRgb(data) { + this._convertYcckToCmyk(data); + return this._convertCmykToRgb(data); + } + _convertYcckToRgba(data) { + this._convertYcckToCmyk(data); + return this._convertCmykToRgba(data); + } + _convertYcckToCmyk(data) { + let Y, Cb, Cr; + for (let i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = 434.456 - Y - 1.402 * Cr; + data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr; + data[i + 2] = 481.816 - Y - 1.772 * Cb; + } + return data; + } + _convertCmykToRgb(data) { + const count = data.length / 4; + ColorSpaceUtils.cmyk.getRgbBuffer(data, 0, count, data, 0, 8, 0); + return data.subarray(0, count * 3); + } + _convertCmykToRgba(data) { + ColorSpaceUtils.cmyk.getRgbBuffer(data, 0, data.length / 4, data, 0, 8, 1); + if (ColorSpaceUtils.cmyk instanceof DeviceCmykCS) { + for (let i = 3, ii = data.length; i < ii; i += 4) { + data[i] = 255; + } + } + return data; + } + getData({ + width, + height, + forceRGBA = false, + forceRGB = false, + isSourcePDF = false + }) { + if (this.numComponents > 4) { + throw new JpegError("Unsupported color mode"); + } + const data = this._getLinearizedBlockData(width, height, isSourcePDF); + if (this.numComponents === 1 && (forceRGBA || forceRGB)) { + const len = data.length * (forceRGBA ? 4 : 3); + const rgbaData = new Uint8ClampedArray(len); + let offset = 0; + if (forceRGBA) { + grayToRGBA(data, new Uint32Array(rgbaData.buffer)); + } else { + for (const grayColor of data) { + rgbaData[offset++] = grayColor; + rgbaData[offset++] = grayColor; + rgbaData[offset++] = grayColor; + } + } + return rgbaData; + } else if (this.numComponents === 3 && this._isColorConversionNeeded) { + if (forceRGBA) { + const rgbaData = new Uint8ClampedArray(data.length / 3 * 4); + return this._convertYccToRgba(data, rgbaData); + } + return this._convertYccToRgb(data); + } else if (this.numComponents === 4) { + if (this._isColorConversionNeeded) { + if (forceRGBA) { + return this._convertYcckToRgba(data); + } + if (forceRGB) { + return this._convertYcckToRgb(data); + } + return this._convertYcckToCmyk(data); + } else if (forceRGBA) { + return this._convertCmykToRgba(data); + } else if (forceRGB) { + return this._convertCmykToRgb(data); + } + } + return data; + } +} + +;// ./src/core/jpeg_stream.js + + + + +class JpegStream extends DecodeStream { + static #isImageDecoderSupported = FeatureTest.isImageDecoderSupported; + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + static get canUseImageDecoder() { + return shadow(this, "canUseImageDecoder", this.#isImageDecoderSupported ? ImageDecoder.isTypeSupported("image/jpeg") : Promise.resolve(false)); + } + static setOptions({ + isImageDecoderSupported = false + }) { + this.#isImageDecoderSupported = isImageDecoderSupported; + } + get bytes() { + return shadow(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) {} + readBlock() { + this.decodeImage(); + } + get jpegOptions() { + const jpegOptions = { + decodeTransform: undefined, + colorTransform: undefined + }; + const decodeArr = this.dict.getArray("D", "Decode"); + if ((this.forceRGBA || this.forceRGB) && Array.isArray(decodeArr)) { + const bitsPerComponent = this.dict.get("BPC", "BitsPerComponent") || 8; + const decodeArrLength = decodeArr.length; + const transform = new Int32Array(decodeArrLength); + let transformNeeded = false; + const maxValue = (1 << bitsPerComponent) - 1; + for (let i = 0; i < decodeArrLength; i += 2) { + transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0; + transform[i + 1] = decodeArr[i] * maxValue | 0; + if (transform[i] !== 256 || transform[i + 1] !== 0) { + transformNeeded = true; + } + } + if (transformNeeded) { + jpegOptions.decodeTransform = transform; + } + } + if (this.params instanceof Dict) { + const colorTransform = this.params.get("ColorTransform"); + if (Number.isInteger(colorTransform)) { + jpegOptions.colorTransform = colorTransform; + } + } + return shadow(this, "jpegOptions", jpegOptions); + } + #skipUselessBytes(data) { + for (let i = 0, ii = data.length - 1; i < ii; i++) { + if (data[i] === 0xff && data[i + 1] === 0xd8) { + if (i > 0) { + data = data.subarray(i); + } + break; + } + } + return data; + } + decodeImage(bytes) { + if (this.eof) { + return this.buffer; + } + bytes = this.#skipUselessBytes(bytes || this.bytes); + const jpegImage = new JpegImage(this.jpegOptions); + jpegImage.parse(bytes); + const data = jpegImage.getData({ + width: this.drawWidth, + height: this.drawHeight, + forceRGBA: this.forceRGBA, + forceRGB: this.forceRGB, + isSourcePDF: true + }); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } + async getTransferableImage() { + if (!(await JpegStream.canUseImageDecoder)) { + return null; + } + const jpegOptions = this.jpegOptions; + if (jpegOptions.decodeTransform) { + return null; + } + let decoder; + try { + const bytes = this.canAsyncDecodeImageFromBuffer && (await this.stream.asyncGetBytes()) || this.bytes; + if (!bytes) { + return null; + } + let data = this.#skipUselessBytes(bytes); + const useImageDecoder = JpegImage.canUseImageDecoder(data, jpegOptions.colorTransform); + if (!useImageDecoder) { + return null; + } + if (useImageDecoder.exifStart) { + data = data.slice(); + data.fill(0x00, useImageDecoder.exifStart, useImageDecoder.exifEnd); + } + decoder = new ImageDecoder({ + data, + type: "image/jpeg", + preferAnimation: false + }); + return (await decoder.decode()).image; + } catch (reason) { + warn(`getTransferableImage - failed: "${reason}".`); + return null; + } finally { + decoder?.close(); + } + } +} + +;// ./external/openjpeg/openjpeg.js +async function OpenJPEG(moduleArg = {}) { + var moduleRtn; + var Module = moduleArg; + var ENVIRONMENT_IS_WEB = true; + var ENVIRONMENT_IS_WORKER = false; + var arguments_ = []; + var thisProgram = "./this.program"; + var quit_ = (status, toThrow) => { + throw toThrow; + }; + var _scriptName = import.meta.url; + var scriptDirectory = ""; + var readAsync, readBinary; + if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + try { + scriptDirectory = new URL(".", _scriptName).href; + } catch {} + readAsync = async url => { + var response = await fetch(url, { + credentials: "same-origin" + }); + if (response.ok) { + return response.arrayBuffer(); + } + throw new Error(response.status + " : " + response.url); + }; + } else {} + var out = console.log.bind(console); + var err = console.error.bind(console); + var wasmBinary; + var ABORT = false; + var EXITSTATUS; + var readyPromiseResolve, readyPromiseReject; + var wasmMemory; + var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + var HEAP64, HEAPU64; + var runtimeInitialized = false; + function updateMemoryViews() { + var b = wasmMemory.buffer; + HEAP8 = new Int8Array(b); + HEAP16 = new Int16Array(b); + HEAPU8 = new Uint8Array(b); + HEAPU16 = new Uint16Array(b); + HEAP32 = new Int32Array(b); + HEAPU32 = new Uint32Array(b); + HEAPF32 = new Float32Array(b); + HEAPF64 = new Float64Array(b); + HEAP64 = new BigInt64Array(b); + HEAPU64 = new BigUint64Array(b); + } + function preRun() { + if (Module["preRun"]) { + if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]]; + while (Module["preRun"].length) { + addOnPreRun(Module["preRun"].shift()); + } + } + callRuntimeCallbacks(onPreRuns); + } + function initRuntime() { + runtimeInitialized = true; + wasmExports["s"](); + } + function postRun() { + if (Module["postRun"]) { + if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]]; + while (Module["postRun"].length) { + addOnPostRun(Module["postRun"].shift()); + } + } + callRuntimeCallbacks(onPostRuns); + } + function abort(what) { + Module["onAbort"]?.(what); + what = "Aborted(" + what + ")"; + err(what); + ABORT = true; + what += ". Build with -sASSERTIONS for more info."; + var e = new WebAssembly.RuntimeError(what); + readyPromiseReject?.(e); + throw e; + } + var wasmBinaryFile; + function getWasmImports() { + return { + a: wasmImports + }; + } + async function createWasm() { + function receiveInstance(instance, module) { + wasmExports = instance.exports; + wasmMemory = wasmExports["r"]; + updateMemoryViews(); + assignWasmExports(wasmExports); + return wasmExports; + } + var info = getWasmImports(); + return new Promise((resolve, reject) => { + Module["instantiateWasm"](info, (mod, inst) => { + resolve(receiveInstance(mod, inst)); + }); + }); + } + class ExitStatus { + name = "ExitStatus"; + constructor(status) { + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + } + var callRuntimeCallbacks = callbacks => { + while (callbacks.length > 0) { + callbacks.shift()(Module); + } + }; + var onPostRuns = []; + var addOnPostRun = cb => onPostRuns.push(cb); + var onPreRuns = []; + var addOnPreRun = cb => onPreRuns.push(cb); + var noExitRuntime = true; + var __abort_js = () => abort(""); + var runtimeKeepaliveCounter = 0; + var __emscripten_runtime_keepalive_clear = () => { + noExitRuntime = false; + runtimeKeepaliveCounter = 0; + }; + var timers = {}; + var handleException = e => { + if (e instanceof ExitStatus || e == "unwind") { + return EXITSTATUS; + } + quit_(1, e); + }; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + var _proc_exit = code => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + Module["onExit"]?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + var exitJS = (status, implicit) => { + EXITSTATUS = status; + _proc_exit(status); + }; + var _exit = exitJS; + var maybeExit = () => { + if (!keepRuntimeAlive()) { + try { + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = func => { + if (ABORT) { + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + var _emscripten_get_now = () => performance.now(); + var __setitimer_js = (which, timeout_ms) => { + if (timers[which]) { + clearTimeout(timers[which].id); + delete timers[which]; + } + if (!timeout_ms) return 0; + var id = setTimeout(() => { + delete timers[which]; + callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now())); + }, timeout_ms); + timers[which] = { + id, + timeout_ms + }; + return 0; + }; + function _copy_pixels_1(compG_ptr, nb_pixels) { + compG_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + imageData.set(compG); + } + function _copy_pixels_3(compR_ptr, compG_ptr, compB_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 3); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[3 * i] = compR[i]; + imageData[3 * i + 1] = compG[i]; + imageData[3 * i + 2] = compB[i]; + } + } + function _copy_pixels_4(compR_ptr, compG_ptr, compB_ptr, compA_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + compA_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + const compA = HEAP32.subarray(compA_ptr, compA_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = compR[i]; + imageData[4 * i + 1] = compG[i]; + imageData[4 * i + 2] = compB[i]; + imageData[4 * i + 3] = compA[i]; + } + } + var getHeapMax = () => 2147483648; + var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment; + var growMemory = size => { + var oldHeapSize = wasmMemory.buffer.byteLength; + var pages = (size - oldHeapSize + 65535) / 65536 | 0; + try { + wasmMemory.grow(pages); + updateMemoryViews(); + return 1; + } catch (e) {} + }; + var _emscripten_resize_heap = requestedSize => { + var oldSize = HEAPU8.length; + requestedSize >>>= 0; + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + return false; + } + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + .2 / cutDown); + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); + var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)); + var replacement = growMemory(newSize); + if (replacement) { + return true; + } + } + return false; + }; + var ENV = {}; + var getExecutableName = () => thisProgram || "./this.program"; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + var lang = (typeof navigator == "object" && navigator.language || "C").replace("-", "_") + ".UTF-8"; + var env = { + USER: "web_user", + LOGNAME: "web_user", + PATH: "/", + PWD: "/", + HOME: "/home/web_user", + LANG: lang, + _: getExecutableName() + }; + for (var x in ENV) { + if (ENV[x] === undefined) delete env[x];else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + if (!(maxBytesToWrite > 0)) return 0; + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; + for (var i = 0; i < str.length; ++i) { + var u = str.codePointAt(i); + if (u <= 127) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 2047) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 192 | u >> 6; + heap[outIdx++] = 128 | u & 63; + } else if (u <= 65535) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 224 | u >> 12; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63; + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 240 | u >> 18; + heap[outIdx++] = 128 | u >> 12 & 63; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63; + i++; + } + } + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + var envp = 0; + for (var string of getEnvStrings()) { + var ptr = environ_buf + bufSize; + HEAPU32[__environ + envp >> 2] = ptr; + bufSize += stringToUTF8(string, ptr, Infinity) + 1; + envp += 4; + } + return 0; + }; + var lengthBytesUTF8 = str => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + if (c <= 127) { + len++; + } else if (c <= 2047) { + len += 2; + } else if (c >= 55296 && c <= 57343) { + len += 4; + ++i; + } else { + len += 3; + } + } + return len; + }; + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[penviron_count >> 2] = strings.length; + var bufSize = 0; + for (var string of strings) { + bufSize += lengthBytesUTF8(string) + 1; + } + HEAPU32[penviron_buf_size >> 2] = bufSize; + return 0; + }; + var INT53_MAX = 9007199254740992; + var INT53_MIN = -9007199254740992; + var bigintToI53Checked = num => num < INT53_MIN || num > INT53_MAX ? NaN : Number(num); + function _fd_seek(fd, offset, whence, newOffset) { + offset = bigintToI53Checked(offset); + return 70; + } + var printCharBuffers = [null, [], []]; + var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder() : undefined; + var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { + var maxIdx = idx + maxBytesToRead; + if (ignoreNul) return maxIdx; + while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx; + return idx; + }; + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => { + var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul); + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ""; + while (idx < endPtr) { + var u0 = heapOrArray[idx++]; + if (!(u0 & 128)) { + str += String.fromCharCode(u0); + continue; + } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 224) == 192) { + str += String.fromCharCode((u0 & 31) << 6 | u1); + continue; + } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 240) == 224) { + u0 = (u0 & 15) << 12 | u1 << 6 | u2; + } else { + u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63; + } + if (u0 < 65536) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 65536; + str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); + } + } + return str; + }; + var printChar = (stream, curr) => { + var buffer = printCharBuffers[stream]; + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer)); + buffer.length = 0; + } else { + buffer.push(curr); + } + }; + var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : ""; + var _fd_write = (fd, iov, iovcnt, pnum) => { + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[iov >> 2]; + var len = HEAPU32[iov + 4 >> 2]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr + j]); + } + num += len; + } + HEAPU32[pnum >> 2] = num; + return 0; + }; + function _gray_to_rgba(compG_ptr, nb_pixels) { + compG_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = imageData[4 * i + 1] = imageData[4 * i + 2] = compG[i]; + imageData[4 * i + 3] = 255; + } + } + function _graya_to_rgba(compG_ptr, compA_ptr, nb_pixels) { + compG_ptr >>= 2; + compA_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compA = HEAP32.subarray(compA_ptr, compA_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = imageData[4 * i + 1] = imageData[4 * i + 2] = compG[i]; + imageData[4 * i + 3] = compA[i]; + } + } + function _jsPrintWarning(message_ptr) { + const message = UTF8ToString(message_ptr); + (Module.warn || console.warn)(`OpenJPEG: ${message}`); + } + function _rgb_to_rgba(compR_ptr, compG_ptr, compB_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = compR[i]; + imageData[4 * i + 1] = compG[i]; + imageData[4 * i + 2] = compB[i]; + imageData[4 * i + 3] = 255; + } + } + function _storeErrorMessage(message_ptr) { + const message = UTF8ToString(message_ptr); + if (!Module.errorMessages) { + Module.errorMessages = message; + } else { + Module.errorMessages += "\n" + message; + } + } + var writeArrayToMemory = (array, buffer) => { + HEAP8.set(array, buffer); + }; + if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"]; + if (Module["print"]) out = Module["print"]; + if (Module["printErr"]) err = Module["printErr"]; + if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; + if (Module["arguments"]) arguments_ = Module["arguments"]; + if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; + if (Module["preInit"]) { + if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]]; + while (Module["preInit"].length > 0) { + Module["preInit"].shift()(); + } + } + Module["writeArrayToMemory"] = writeArrayToMemory; + var _malloc, _free, _jp2_decode, __emscripten_timeout; + function assignWasmExports(wasmExports) { + Module["_malloc"] = _malloc = wasmExports["t"]; + Module["_free"] = _free = wasmExports["u"]; + Module["_jp2_decode"] = _jp2_decode = wasmExports["v"]; + __emscripten_timeout = wasmExports["w"]; + } + var wasmImports = { + k: __abort_js, + j: __emscripten_runtime_keepalive_clear, + l: __setitimer_js, + f: _copy_pixels_1, + e: _copy_pixels_3, + d: _copy_pixels_4, + m: _emscripten_resize_heap, + o: _environ_get, + p: _environ_sizes_get, + n: _fd_seek, + b: _fd_write, + q: _gray_to_rgba, + h: _graya_to_rgba, + c: _jsPrintWarning, + i: _proc_exit, + g: _rgb_to_rgba, + a: _storeErrorMessage + }; + function run() { + preRun(); + function doRun() { + Module["calledRun"] = true; + if (ABORT) return; + initRuntime(); + readyPromiseResolve?.(Module); + Module["onRuntimeInitialized"]?.(); + postRun(); + } + if (Module["setStatus"]) { + Module["setStatus"]("Running..."); + setTimeout(() => { + setTimeout(() => Module["setStatus"](""), 1); + doRun(); + }, 1); + } else { + doRun(); + } + } + var wasmExports; + wasmExports = await createWasm(); + run(); + if (runtimeInitialized) { + moduleRtn = Module; + } else { + moduleRtn = new Promise((resolve, reject) => { + readyPromiseResolve = resolve; + readyPromiseReject = reject; + }); + } + return moduleRtn; +} +/* harmony default export */ const openjpeg = (OpenJPEG); +;// ./src/core/jpx.js + + + + +class JpxError extends BaseException { + constructor(msg) { + super(msg, "JpxError"); + } +} +class JpxImage { + static #buffer = null; + static #handler = null; + static #modulePromise = null; + static #useWasm = true; + static #useWorkerFetch = true; + static #wasmUrl = null; + static setOptions({ + handler, + useWasm, + useWorkerFetch, + wasmUrl + }) { + this.#useWasm = useWasm; + this.#useWorkerFetch = useWorkerFetch; + this.#wasmUrl = wasmUrl; + if (!useWorkerFetch) { + this.#handler = handler; + } + } + static async #getJsModule(fallbackCallback) { + const path = `${this.#wasmUrl}openjpeg_nowasm_fallback.js`; + let instance = null; + try { + const mod = await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + path); + instance = mod.default(); + } catch (e) { + warn(`JpxImage#getJsModule: ${e}`); + } + fallbackCallback(instance); + } + static async #instantiateWasm(fallbackCallback, imports, successCallback) { + const filename = "openjpeg.wasm"; + try { + if (!this.#buffer) { + if (this.#useWorkerFetch) { + this.#buffer = await fetchBinaryData(`${this.#wasmUrl}${filename}`); + } else { + this.#buffer = await this.#handler.sendWithPromise("FetchBinaryData", { + type: "wasmFactory", + filename + }); + } + } + const results = await WebAssembly.instantiate(this.#buffer, imports); + return successCallback(results.instance); + } catch (reason) { + warn(`JpxImage#instantiateWasm: ${reason}`); + this.#getJsModule(fallbackCallback); + return null; + } finally { + this.#handler = null; + } + } + static async decode(bytes, { + numComponents = 4, + isIndexedColormap = false, + smaskInData = false, + reducePower = 0 + } = {}) { + if (!this.#modulePromise) { + const { + promise, + resolve + } = Promise.withResolvers(); + const promises = [promise]; + if (!this.#useWasm) { + this.#getJsModule(resolve); + } else { + promises.push(openjpeg({ + warn: warn, + instantiateWasm: this.#instantiateWasm.bind(this, resolve) + })); + } + this.#modulePromise = Promise.race(promises); + } + const module = await this.#modulePromise; + if (!module) { + throw new JpxError("OpenJPEG failed to initialize"); + } + let ptr; + try { + const size = bytes.length; + ptr = module._malloc(size); + module.writeArrayToMemory(bytes, ptr); + const ret = module._jp2_decode(ptr, size, numComponents > 0 ? numComponents : 0, !!isIndexedColormap, !!smaskInData, reducePower); + if (ret) { + const { + errorMessages + } = module; + if (errorMessages) { + delete module.errorMessages; + throw new JpxError(errorMessages); + } + throw new JpxError("Unknown error"); + } + const { + imageData + } = module; + module.imageData = null; + return imageData; + } finally { + if (ptr) { + module._free(ptr); + } + } + } + static cleanup() { + this.#modulePromise = null; + } + static parseImageProperties(stream) { + let newByte = stream.getByte(); + while (newByte >= 0) { + const oldByte = newByte; + newByte = stream.getByte(); + const code = oldByte << 8 | newByte; + if (code === 0xff51) { + stream.skip(4); + const Xsiz = stream.getInt32() >>> 0; + const Ysiz = stream.getInt32() >>> 0; + const XOsiz = stream.getInt32() >>> 0; + const YOsiz = stream.getInt32() >>> 0; + stream.skip(16); + const Csiz = stream.getUint16(); + return { + width: Xsiz - XOsiz, + height: Ysiz - YOsiz, + bitsPerComponent: 8, + componentsCount: Csiz + }; + } + } + throw new JpxError("No size marker found in JPX stream"); + } +} + +;// ./src/core/operator_list.js + +function addState(parentState, pattern, checkFn, iterateFn, processFn) { + let state = parentState; + for (let i = 0, ii = pattern.length - 1; i < ii; i++) { + const item = pattern[i]; + state = state[item] ||= []; + } + state[pattern.at(-1)] = { + checkFn, + iterateFn, + processFn + }; +} +const InitialState = []; +addState(InitialState, [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], null, function iterateInlineImageGroup(context, i) { + const fnArray = context.fnArray; + const iFirstSave = context.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS.save; + case 1: + return fnArray[i] === OPS.transform; + case 2: + return fnArray[i] === OPS.paintInlineImageXObject; + case 3: + return fnArray[i] === OPS.restore; + } + throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`); +}, function foundInlineImageGroup(context, i) { + const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; + const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; + const MAX_WIDTH = 1000; + const IMAGE_PADDING = 1; + const fnArray = context.fnArray, + argsArray = context.argsArray; + const curr = context.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIIXO = curr - 1; + const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); + if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { + return i - (i - iFirstSave) % 4; + } + let maxX = 0; + const map = []; + let maxLineHeight = 0; + let currentX = IMAGE_PADDING, + currentY = IMAGE_PADDING; + for (let q = 0; q < count; q++) { + const transform = argsArray[iFirstTransform + (q << 2)]; + const img = argsArray[iFirstPIIXO + (q << 2)][0]; + if (currentX + img.width > MAX_WIDTH) { + maxX = Math.max(maxX, currentX); + currentY += maxLineHeight + 2 * IMAGE_PADDING; + currentX = 0; + maxLineHeight = 0; + } + map.push({ + transform, + x: currentX, + y: currentY, + w: img.width, + h: img.height + }); + currentX += img.width + 2 * IMAGE_PADDING; + maxLineHeight = Math.max(maxLineHeight, img.height); + } + const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; + const imgHeight = currentY + maxLineHeight + IMAGE_PADDING; + const imgData = new Uint8Array(imgWidth * imgHeight * 4); + const imgRowSize = imgWidth << 2; + for (let q = 0; q < count; q++) { + const data = argsArray[iFirstPIIXO + (q << 2)][0].data; + const rowSize = map[q].w << 2; + let dataOffset = 0; + let offset = map[q].x + map[q].y * imgWidth << 2; + imgData.set(data.subarray(0, rowSize), offset - imgRowSize); + for (let k = 0, kk = map[q].h; k < kk; k++) { + imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); + dataOffset += rowSize; + offset += imgRowSize; + } + imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); + while (offset >= 0) { + data[offset - 4] = data[offset]; + data[offset - 3] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 1] = data[offset + 3]; + data[offset + rowSize] = data[offset + rowSize - 4]; + data[offset + rowSize + 1] = data[offset + rowSize - 3]; + data[offset + rowSize + 2] = data[offset + rowSize - 2]; + data[offset + rowSize + 3] = data[offset + rowSize - 1]; + offset -= imgRowSize; + } + } + const img = { + width: imgWidth, + height: imgHeight + }; + if (context.isOffscreenCanvasSupported) { + const canvas = new OffscreenCanvas(imgWidth, imgHeight); + const ctx = canvas.getContext("2d"); + ctx.putImageData(new ImageData(new Uint8ClampedArray(imgData.buffer), imgWidth, imgHeight), 0, 0); + img.bitmap = canvas.transferToImageBitmap(); + img.data = null; + } else { + img.kind = ImageKind.RGBA_32BPP; + img.data = imgData; + } + fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [img, map]); + return iFirstSave + 1; +}); +addState(InitialState, [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], null, function iterateImageMaskGroup(context, i) { + const fnArray = context.fnArray; + const iFirstSave = context.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS.save; + case 1: + return fnArray[i] === OPS.transform; + case 2: + return fnArray[i] === OPS.paintImageMaskXObject; + case 3: + return fnArray[i] === OPS.restore; + } + throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`); +}, function foundImageMaskGroup(context, i) { + const MIN_IMAGES_IN_MASKS_BLOCK = 10; + const MAX_IMAGES_IN_MASKS_BLOCK = 100; + const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; + const fnArray = context.fnArray, + argsArray = context.argsArray; + const curr = context.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIMXO = curr - 1; + let count = Math.floor((i - iFirstSave) / 4); + if (count < MIN_IMAGES_IN_MASKS_BLOCK) { + return i - (i - iFirstSave) % 4; + } + let isSameImage = false; + let iTransform, transformArgs; + const firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; + const firstTransformArg0 = argsArray[iFirstTransform][0], + firstTransformArg1 = argsArray[iFirstTransform][1], + firstTransformArg2 = argsArray[iFirstTransform][2], + firstTransformArg3 = argsArray[iFirstTransform][3]; + if (firstTransformArg1 === firstTransformArg2) { + isSameImage = true; + iTransform = iFirstTransform + 4; + let iPIMXO = iFirstPIMXO + 4; + for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { + transformArgs = argsArray[iTransform]; + if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) { + if (q < MIN_IMAGES_IN_MASKS_BLOCK) { + isSameImage = false; + } else { + count = q; + } + break; + } + } + } + if (isSameImage) { + count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); + const positions = new Float32Array(count * 2); + iTransform = iFirstTransform; + for (let q = 0; q < count; q++, iTransform += 4) { + transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]); + } else { + count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); + const images = []; + for (let q = 0; q < count; q++) { + transformArgs = argsArray[iFirstTransform + (q << 2)]; + const maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; + images.push({ + data: maskParams.data, + width: maskParams.width, + height: maskParams.height, + interpolate: maskParams.interpolate, + count: maskParams.count, + transform: transformArgs + }); + } + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [images]); + } + return iFirstSave + 1; +}); +addState(InitialState, [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], function (context) { + const argsArray = context.argsArray; + const iFirstTransform = context.iCurr - 2; + return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0; +}, function iterateImageGroup(context, i) { + const fnArray = context.fnArray, + argsArray = context.argsArray; + const iFirstSave = context.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS.save; + case 1: + if (fnArray[i] !== OPS.transform) { + return false; + } + const iFirstTransform = context.iCurr - 2; + const firstTransformArg0 = argsArray[iFirstTransform][0]; + const firstTransformArg3 = argsArray[iFirstTransform][3]; + if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) { + return false; + } + return true; + case 2: + if (fnArray[i] !== OPS.paintImageXObject) { + return false; + } + const iFirstPIXO = context.iCurr - 1; + const firstPIXOArg0 = argsArray[iFirstPIXO][0]; + if (argsArray[i][0] !== firstPIXOArg0) { + return false; + } + return true; + case 3: + return fnArray[i] === OPS.restore; + } + throw new Error(`iterateImageGroup - invalid pos: ${pos}`); +}, function (context, i) { + const MIN_IMAGES_IN_BLOCK = 3; + const MAX_IMAGES_IN_BLOCK = 1000; + const fnArray = context.fnArray, + argsArray = context.argsArray; + const curr = context.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIXO = curr - 1; + const firstPIXOArg0 = argsArray[iFirstPIXO][0]; + const firstTransformArg0 = argsArray[iFirstTransform][0]; + const firstTransformArg3 = argsArray[iFirstTransform][3]; + const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK); + if (count < MIN_IMAGES_IN_BLOCK) { + return i - (i - iFirstSave) % 4; + } + const positions = new Float32Array(count * 2); + let iTransform = iFirstTransform; + for (let q = 0; q < count; q++, iTransform += 4) { + const transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions]; + fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, args); + return iFirstSave + 1; +}); +addState(InitialState, [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], null, function iterateShowTextGroup(context, i) { + const fnArray = context.fnArray, + argsArray = context.argsArray; + const iFirstSave = context.iCurr - 4; + const pos = (i - iFirstSave) % 5; + switch (pos) { + case 0: + return fnArray[i] === OPS.beginText; + case 1: + return fnArray[i] === OPS.setFont; + case 2: + return fnArray[i] === OPS.setTextMatrix; + case 3: + if (fnArray[i] !== OPS.showText) { + return false; + } + const iFirstSetFont = context.iCurr - 3; + const firstSetFontArg0 = argsArray[iFirstSetFont][0]; + const firstSetFontArg1 = argsArray[iFirstSetFont][1]; + if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) { + return false; + } + return true; + case 4: + return fnArray[i] === OPS.endText; + } + throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`); +}, function (context, i) { + const MIN_CHARS_IN_BLOCK = 3; + const MAX_CHARS_IN_BLOCK = 1000; + const fnArray = context.fnArray, + argsArray = context.argsArray; + const curr = context.iCurr; + const iFirstBeginText = curr - 4; + const iFirstSetFont = curr - 3; + const iFirstSetTextMatrix = curr - 2; + const iFirstShowText = curr - 1; + const iFirstEndText = curr; + const firstSetFontArg0 = argsArray[iFirstSetFont][0]; + const firstSetFontArg1 = argsArray[iFirstSetFont][1]; + let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); + if (count < MIN_CHARS_IN_BLOCK) { + return i - (i - iFirstBeginText) % 5; + } + let iFirst = iFirstBeginText; + if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { + count++; + iFirst -= 5; + } + let iEndText = iFirst + 4; + for (let q = 1; q < count; q++) { + fnArray.splice(iEndText, 3); + argsArray.splice(iEndText, 3); + iEndText += 2; + } + return iEndText + 1; +}); +addState(InitialState, [OPS.save, OPS.transform, OPS.constructPath, OPS.restore], context => { + const argsArray = context.argsArray; + const iFirstConstructPath = context.iCurr - 1; + const op = argsArray[iFirstConstructPath][0]; + if (op !== OPS.stroke && op !== OPS.closeStroke && op !== OPS.fillStroke && op !== OPS.eoFillStroke && op !== OPS.closeFillStroke && op !== OPS.closeEOFillStroke) { + return true; + } + const iFirstTransform = context.iCurr - 2; + const transform = argsArray[iFirstTransform]; + return transform[0] === 1 && transform[1] === 0 && transform[2] === 0 && transform[3] === 1; +}, () => false, (context, i) => { + const { + fnArray, + argsArray + } = context; + const curr = context.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstConstructPath = curr - 1; + const args = argsArray[iFirstConstructPath]; + const transform = argsArray[iFirstTransform]; + const [, [buffer], minMax] = args; + if (minMax) { + Util.scaleMinMax(transform, minMax); + for (let k = 0, kk = buffer.length; k < kk;) { + switch (buffer[k++]) { + case DrawOPS.moveTo: + case DrawOPS.lineTo: + Util.applyTransform(buffer, transform, k); + k += 2; + break; + case DrawOPS.curveTo: + Util.applyTransformToBezier(buffer, transform, k); + k += 6; + break; + } + } + } + fnArray.splice(iFirstSave, 4, OPS.constructPath); + argsArray.splice(iFirstSave, 4, args); + return iFirstSave + 1; +}); +class NullOptimizer { + constructor(queue) { + this.queue = queue; + } + _optimize() {} + push(fn, args) { + this.queue.fnArray.push(fn); + this.queue.argsArray.push(args); + this._optimize(); + } + flush() {} + reset() {} +} +class QueueOptimizer extends NullOptimizer { + constructor(queue) { + super(queue); + this.state = null; + this.context = { + iCurr: 0, + fnArray: queue.fnArray, + argsArray: queue.argsArray, + isOffscreenCanvasSupported: OperatorList.isOffscreenCanvasSupported + }; + this.match = null; + this.lastProcessed = 0; + } + _optimize() { + const fnArray = this.queue.fnArray; + let i = this.lastProcessed, + ii = fnArray.length; + let state = this.state; + let match = this.match; + if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) { + this.lastProcessed = ii; + return; + } + const context = this.context; + while (i < ii) { + if (match) { + const iterate = (0, match.iterateFn)(context, i); + if (iterate) { + i++; + continue; + } + i = (0, match.processFn)(context, i + 1); + ii = fnArray.length; + match = null; + state = null; + if (i >= ii) { + break; + } + } + state = (state || InitialState)[fnArray[i]]; + if (!state || Array.isArray(state)) { + i++; + continue; + } + context.iCurr = i; + i++; + if (state.checkFn && !(0, state.checkFn)(context)) { + state = null; + continue; + } + match = state; + state = null; + } + this.state = state; + this.match = match; + this.lastProcessed = i; + } + flush() { + while (this.match) { + const length = this.queue.fnArray.length; + this.lastProcessed = (0, this.match.processFn)(this.context, length); + this.match = null; + this.state = null; + this._optimize(); + } + } + reset() { + this.state = null; + this.match = null; + this.lastProcessed = 0; + } +} +class OperatorList { + static CHUNK_SIZE = 1000; + static CHUNK_SIZE_ABOUT = this.CHUNK_SIZE - 5; + static isOffscreenCanvasSupported = false; + constructor(intent = 0, streamSink) { + this._streamSink = streamSink; + this.fnArray = []; + this.argsArray = []; + this.optimizer = streamSink && !(intent & RenderingIntentFlag.OPLIST) ? new QueueOptimizer(this) : new NullOptimizer(this); + this.dependencies = new Set(); + this._totalLength = 0; + this.weight = 0; + this._resolved = streamSink ? null : Promise.resolve(); + } + static setOptions({ + isOffscreenCanvasSupported + }) { + this.isOffscreenCanvasSupported = isOffscreenCanvasSupported; + } + get length() { + return this.argsArray.length; + } + get ready() { + return this._resolved || this._streamSink.ready; + } + get totalLength() { + return this._totalLength + this.length; + } + addOp(fn, args) { + this.optimizer.push(fn, args); + this.weight++; + if (this._streamSink) { + if (this.weight >= OperatorList.CHUNK_SIZE) { + this.flush(); + } else if (this.weight >= OperatorList.CHUNK_SIZE_ABOUT && (fn === OPS.restore || fn === OPS.endText)) { + this.flush(); + } + } + } + addImageOps(fn, args, optionalContent, hasMask = false) { + if (hasMask) { + this.addOp(OPS.save); + this.addOp(OPS.setGState, [[["SMask", false]]]); + } + if (optionalContent !== undefined) { + this.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); + } + this.addOp(fn, args); + if (optionalContent !== undefined) { + this.addOp(OPS.endMarkedContent, []); + } + if (hasMask) { + this.addOp(OPS.restore); + } + } + addDependency(dependency) { + if (this.dependencies.has(dependency)) { + return; + } + this.dependencies.add(dependency); + this.addOp(OPS.dependency, [dependency]); + } + addDependencies(dependencies) { + for (const dependency of dependencies) { + this.addDependency(dependency); + } + } + addOpList(opList) { + if (!(opList instanceof OperatorList)) { + warn('addOpList - ignoring invalid "opList" parameter.'); + return; + } + for (const dependency of opList.dependencies) { + this.dependencies.add(dependency); + } + for (let i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + } + getIR() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + } + get _transfers() { + const transfers = []; + const { + fnArray, + argsArray, + length + } = this; + for (let i = 0; i < length; i++) { + switch (fnArray[i]) { + case OPS.paintInlineImageXObject: + case OPS.paintInlineImageXObjectGroup: + case OPS.paintImageMaskXObject: + { + const { + bitmap, + data + } = argsArray[i][0]; + if (bitmap || data?.buffer) { + transfers.push(bitmap || data.buffer); + } + break; + } + case OPS.constructPath: + { + const [, [data], minMax] = argsArray[i]; + if (data) { + transfers.push(data.buffer, minMax.buffer); + } + break; + } + case OPS.paintFormXObjectBegin: + const [matrix, bbox] = argsArray[i]; + if (matrix) { + transfers.push(matrix.buffer); + } + if (bbox) { + transfers.push(bbox.buffer); + } + break; + case OPS.setTextMatrix: + transfers.push(argsArray[i][0].buffer); + break; + } + } + return transfers; + } + flush(lastChunk = false, separateAnnots = null) { + this.optimizer.flush(); + const length = this.length; + this._totalLength += length; + this._streamSink.enqueue({ + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk, + separateAnnots, + length + }, 1, this._transfers); + this.dependencies.clear(); + this.fnArray.length = 0; + this.argsArray.length = 0; + this.weight = 0; + this.optimizer.reset(); + } +} + +;// ./src/core/binary_cmap.js + +function hexToInt(a, size) { + let n = 0; + for (let i = 0; i <= size; i++) { + n = n << 8 | a[i]; + } + return n >>> 0; +} +function hexToStr(a, size) { + if (size === 1) { + return String.fromCharCode(a[0], a[1]); + } + if (size === 3) { + return String.fromCharCode(a[0], a[1], a[2], a[3]); + } + return String.fromCharCode(...a.subarray(0, size + 1)); +} +function addHex(a, b, size) { + let c = 0; + for (let i = size; i >= 0; i--) { + c += a[i] + b[i]; + a[i] = c & 255; + c >>= 8; + } +} +function incHex(a, size) { + let c = 1; + for (let i = size; i >= 0 && c > 0; i--) { + c += a[i]; + a[i] = c & 255; + c >>= 8; + } +} +const MAX_NUM_SIZE = 16; +const MAX_ENCODED_NUM_SIZE = 19; +class BinaryCMapStream { + constructor(data) { + this.buffer = data; + this.pos = 0; + this.end = data.length; + this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); + } + readByte() { + if (this.pos >= this.end) { + return -1; + } + return this.buffer[this.pos++]; + } + readNumber() { + let n = 0; + let last; + do { + const b = this.readByte(); + if (b < 0) { + throw new FormatError("unexpected EOF in bcmap"); + } + last = !(b & 0x80); + n = n << 7 | b & 0x7f; + } while (!last); + return n; + } + readSigned() { + const n = this.readNumber(); + return n & 1 ? ~(n >>> 1) : n >>> 1; + } + readHex(num, size) { + num.set(this.buffer.subarray(this.pos, this.pos + size + 1)); + this.pos += size + 1; + } + readHexNumber(num, size) { + let last; + const stack = this.tmpBuf; + let sp = 0; + do { + const b = this.readByte(); + if (b < 0) { + throw new FormatError("unexpected EOF in bcmap"); + } + last = !(b & 0x80); + stack[sp++] = b & 0x7f; + } while (!last); + let i = size, + buffer = 0, + bufferSize = 0; + while (i >= 0) { + while (bufferSize < 8 && stack.length > 0) { + buffer |= stack[--sp] << bufferSize; + bufferSize += 7; + } + num[i] = buffer & 255; + i--; + buffer >>= 8; + bufferSize -= 8; + } + } + readHexSigned(num, size) { + this.readHexNumber(num, size); + const sign = num[size] & 1 ? 255 : 0; + let c = 0; + for (let i = 0; i <= size; i++) { + c = (c & 1) << 8 | num[i]; + num[i] = c >> 1 ^ sign; + } + } + readString() { + const len = this.readNumber(), + buf = new Array(len); + for (let i = 0; i < len; i++) { + buf[i] = this.readNumber(); + } + return String.fromCharCode(...buf); + } +} +class BinaryCMapReader { + async process(data, cMap, extend) { + const stream = new BinaryCMapStream(data); + const header = stream.readByte(); + cMap.vertical = !!(header & 1); + let useCMap = null; + const start = new Uint8Array(MAX_NUM_SIZE); + const end = new Uint8Array(MAX_NUM_SIZE); + const char = new Uint8Array(MAX_NUM_SIZE); + const charCode = new Uint8Array(MAX_NUM_SIZE); + const tmp = new Uint8Array(MAX_NUM_SIZE); + let code; + let b; + while ((b = stream.readByte()) >= 0) { + const type = b >> 5; + if (type === 7) { + switch (b & 0x1f) { + case 0: + stream.readString(); + break; + case 1: + useCMap = stream.readString(); + break; + } + continue; + } + const sequence = !!(b & 0x10); + const dataSize = b & 15; + if (dataSize + 1 > MAX_NUM_SIZE) { + throw new Error("BinaryCMapReader.process: Invalid dataSize."); + } + const ucs2DataSize = 1; + const subitemsCount = stream.readNumber(); + switch (type) { + case 0: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + } + break; + case 1: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + stream.readNumber(); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + stream.readNumber(); + } + break; + case 2: + stream.readHex(char, dataSize); + code = stream.readNumber(); + cMap.mapOne(hexToInt(char, dataSize), code); + for (let i = 1; i < subitemsCount; i++) { + incHex(char, dataSize); + if (!sequence) { + stream.readHexNumber(tmp, dataSize); + addHex(char, tmp, dataSize); + } + code = stream.readSigned() + (code + 1); + cMap.mapOne(hexToInt(char, dataSize), code); + } + break; + case 3: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + if (!sequence) { + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + } + break; + case 4: + stream.readHex(char, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(char, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(tmp, ucs2DataSize); + addHex(char, tmp, ucs2DataSize); + } + incHex(charCode, dataSize); + stream.readHexSigned(tmp, dataSize); + addHex(charCode, tmp, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + case 5: + stream.readHex(start, ucs2DataSize); + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(start, ucs2DataSize); + addHex(start, end, ucs2DataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + default: + throw new Error(`BinaryCMapReader.process - unknown type: ${type}`); + } + } + if (useCMap) { + return extend(useCMap); + } + return cMap; + } +} + +;// ./src/core/ascii_85_stream.js + + +class Ascii85Stream extends DecodeStream { + constructor(str, maybeLength) { + if (maybeLength) { + maybeLength *= 0.8; + } + super(maybeLength); + this.stream = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + } + readBlock() { + const TILDA_CHAR = 0x7e; + const Z_LOWER_CHAR = 0x7a; + const EOF = -1; + const str = this.stream; + let c = str.getByte(); + while (isWhiteSpace(c)) { + c = str.getByte(); + } + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + const bufferLength = this.bufferLength; + let buffer, i; + if (c === Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + const input = this.input; + input[0] = c; + for (i = 1; i < 5; ++i) { + c = str.getByte(); + while (isWhiteSpace(c)) { + c = str.getByte(); + } + input[i] = c; + if (c === EOF || c === TILDA_CHAR) { + break; + } + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + if (i < 5) { + for (; i < 5; ++i) { + input[i] = 0x21 + 84; + } + this.eof = true; + } + let t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input[i] - 0x21); + } + for (i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 0xff; + t >>= 8; + } + } + } +} + +;// ./src/core/ascii_hex_stream.js + +class AsciiHexStream extends DecodeStream { + constructor(str, maybeLength) { + if (maybeLength) { + maybeLength *= 0.5; + } + super(maybeLength); + this.stream = str; + this.dict = str.dict; + this.firstDigit = -1; + } + readBlock() { + const UPSTREAM_BLOCK_SIZE = 8000; + const bytes = this.stream.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + const maxDecodeLength = bytes.length + 1 >> 1; + const buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + let bufferLength = this.bufferLength; + let firstDigit = this.firstDigit; + for (const ch of bytes) { + let digit; + if (ch >= 0x30 && ch <= 0x39) { + digit = ch & 0x0f; + } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { + digit = (ch & 0x0f) + 9; + } else if (ch === 0x3e) { + this.eof = true; + break; + } else { + continue; + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = firstDigit << 4 | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + buffer[bufferLength++] = firstDigit << 4; + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + } +} + +;// ./src/core/ccitt.js + +const ccittEOL = -2; +const ccittEOF = -1; +const twoDimPass = 0; +const twoDimHoriz = 1; +const twoDimVert0 = 2; +const twoDimVertR1 = 3; +const twoDimVertL1 = 4; +const twoDimVertR2 = 5; +const twoDimVertL2 = 6; +const twoDimVertR3 = 7; +const twoDimVertL3 = 8; +const twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]]; +const whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]]; +const whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]]; +const blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]]; +const blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]]; +const blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]; +class CCITTFaxDecoder { + constructor(source, options = {}) { + if (typeof source?.next !== "function") { + throw new Error('CCITTFaxDecoder - invalid "source" parameter.'); + } + this.source = source; + this.eof = false; + this.encoding = options.K || 0; + this.eoline = options.EndOfLine || false; + this.byteAlign = options.EncodedByteAlign || false; + this.columns = options.Columns || 1728; + this.rows = options.Rows || 0; + this.eoblock = options.EndOfBlock ?? true; + this.black = options.BlackIs1 || false; + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + this.codingLine[0] = this.columns; + this.codingPos = 0; + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + this.rowsDone = false; + let code1; + while ((code1 = this._lookBits(12)) === 0) { + this._eatBits(1); + } + if (code1 === 1) { + this._eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this._lookBits(1); + this._eatBits(1); + } + } + readNextChar() { + if (this.eof) { + return -1; + } + const refLine = this.refLine; + const codingLine = this.codingLine; + const columns = this.columns; + let refPos, blackPixels, bits, i; + if (this.outputBits === 0) { + if (this.rowsDone) { + this.eof = true; + } + if (this.eof) { + return -1; + } + this.err = false; + let code1, code2, code3; + if (this.nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = this._getTwoDimCode(); + switch (code1) { + case twoDimPass: + this._addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) { + refPos += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += code3 = this._getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = this._getBlackCode(); + } while (code3 >= 64); + } + this._addPixels(codingLine[this.codingPos] + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this._addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR2: + this._addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this._addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVert0: + this._addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL3: + this._addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL2: + this._addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL1: + this._addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case ccittEOF: + this._addPixels(columns, 0); + this.eof = true; + break; + default: + info("bad 2d code"); + this._addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += code3 = this._getBlackCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + } + this._addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + let gotEOL = false; + if (this.byteAlign) { + this.inputBits &= ~7; + } + if (!this.eoblock && this.row === this.rows - 1) { + this.rowsDone = true; + } else { + code1 = this._lookBits(12); + if (this.eoline) { + while (code1 !== ccittEOF && code1 !== 1) { + this._eatBits(1); + code1 = this._lookBits(12); + } + } else { + while (code1 === 0) { + this._eatBits(1); + code1 = this._lookBits(12); + } + } + if (code1 === 1) { + this._eatBits(12); + gotEOL = true; + } else if (code1 === ccittEOF) { + this.eof = true; + } + } + if (!this.eof && this.encoding > 0 && !this.rowsDone) { + this.nextLine2D = !this._lookBits(1); + this._eatBits(1); + } + if (this.eoblock && gotEOL && this.byteAlign) { + code1 = this._lookBits(12); + if (code1 === 1) { + this._eatBits(12); + if (this.encoding > 0) { + this._lookBits(1); + this._eatBits(1); + } + if (this.encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = this._lookBits(12); + if (code1 !== 1) { + info("bad rtc code: " + code1); + } + this._eatBits(12); + if (this.encoding > 0) { + this._lookBits(1); + this._eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this._lookBits(13); + if (code1 === ccittEOF) { + this.eof = true; + return -1; + } + if (code1 >> 1 === 1) { + break; + } + this._eatBits(1); + } + this._eatBits(12); + if (this.encoding > 0) { + this._eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + this.outputBits = codingLine[0] > 0 ? codingLine[this.codingPos = 0] : codingLine[this.codingPos = 1]; + this.row++; + } + let c; + if (this.outputBits >= 8) { + c = this.codingPos & 1 ? 0 : 0xff; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } + } else { + bits = 8; + c = 0; + do { + if (typeof this.outputBits !== "number") { + throw new FormatError('Invalid /CCITTFaxDecode data, "outputBits" must be a number.'); + } + if (this.outputBits > bits) { + c <<= bits; + if (!(this.codingPos & 1)) { + c |= 0xff >> 8 - bits; + } + this.outputBits -= bits; + bits = 0; + } else { + c <<= this.outputBits; + if (!(this.codingPos & 1)) { + c |= 0xff >> 8 - this.outputBits; + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } else if (bits > 0) { + c <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + c ^= 0xff; + } + return c; + } + _addPixels(a1, blackPixels) { + const codingLine = this.codingLine; + let codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info("row is wrong length"); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + } + _addPixelsNeg(a1, blackPixels) { + const codingLine = this.codingLine; + let codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info("row is wrong length"); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info("invalid code"); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { + --codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + } + _findTableCode(start, end, table, limit) { + const limitValue = limit || 0; + for (let i = start; i <= end; ++i) { + let code = this._lookBits(i); + if (code === ccittEOF) { + return [true, 1, false]; + } + if (i < end) { + code <<= end - i; + } + if (!limitValue || code >= limitValue) { + const p = table[code - limitValue]; + if (p[0] === i) { + this._eatBits(i); + return [true, p[1], true]; + } + } + } + return [false, 0, false]; + } + _getTwoDimCode() { + let code = 0; + let p; + if (this.eoblock) { + code = this._lookBits(7); + p = twoDimTable[code]; + if (p?.[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + const result = this._findTableCode(1, 7, twoDimTable); + if (result[0] && result[2]) { + return result[1]; + } + } + info("Bad two dim code"); + return ccittEOF; + } + _getWhiteCode() { + let code = 0; + let p; + if (this.eoblock) { + code = this._lookBits(12); + if (code === ccittEOF) { + return 1; + } + p = code >> 5 === 0 ? whiteTable1[code] : whiteTable2[code >> 3]; + if (p[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + let result = this._findTableCode(1, 9, whiteTable2); + if (result[0]) { + return result[1]; + } + result = this._findTableCode(11, 12, whiteTable1); + if (result[0]) { + return result[1]; + } + } + info("bad white code"); + this._eatBits(1); + return 1; + } + _getBlackCode() { + let code, p; + if (this.eoblock) { + code = this._lookBits(13); + if (code === ccittEOF) { + return 1; + } + if (code >> 7 === 0) { + p = blackTable1[code]; + } else if (code >> 9 === 0 && code >> 7 !== 0) { + p = blackTable2[(code >> 1) - 64]; + } else { + p = blackTable3[code >> 7]; + } + if (p[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + let result = this._findTableCode(2, 6, blackTable3); + if (result[0]) { + return result[1]; + } + result = this._findTableCode(7, 12, blackTable2, 64); + if (result[0]) { + return result[1]; + } + result = this._findTableCode(10, 13, blackTable1); + if (result[0]) { + return result[1]; + } + } + info("bad black code"); + this._eatBits(1); + return 1; + } + _lookBits(n) { + let c; + while (this.inputBits < n) { + if ((c = this.source.next()) === -1) { + if (this.inputBits === 0) { + return ccittEOF; + } + return this.inputBuf << n - this.inputBits & 0xffff >> 16 - n; + } + this.inputBuf = this.inputBuf << 8 | c; + this.inputBits += 8; + } + return this.inputBuf >> this.inputBits - n & 0xffff >> 16 - n; + } + _eatBits(n) { + if ((this.inputBits -= n) < 0) { + this.inputBits = 0; + } + } +} + +;// ./src/core/ccitt_stream.js + + + +class CCITTFaxStream extends DecodeStream { + constructor(str, maybeLength, params) { + super(maybeLength); + this.stream = str; + this.dict = str.dict; + if (!(params instanceof Dict)) { + params = Dict.empty; + } + const source = { + next() { + return str.getByte(); + } + }; + this.ccittFaxDecoder = new CCITTFaxDecoder(source, { + K: params.get("K"), + EndOfLine: params.get("EndOfLine"), + EncodedByteAlign: params.get("EncodedByteAlign"), + Columns: params.get("Columns"), + Rows: params.get("Rows"), + EndOfBlock: params.get("EndOfBlock"), + BlackIs1: params.get("BlackIs1") + }); + } + readBlock() { + while (!this.eof) { + const c = this.ccittFaxDecoder.readNextChar(); + if (c === -1) { + this.eof = true; + return; + } + this.ensureBuffer(this.bufferLength + 1); + this.buffer[this.bufferLength++] = c; + } + } +} + +;// ./src/core/flate_stream.js + + + +const codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); +const lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]); +const distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]); +const fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9]; +const fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5]; +class FlateStream extends DecodeStream { + constructor(str, maybeLength) { + super(maybeLength); + this.stream = str; + this.dict = str.dict; + const cmf = str.getByte(); + const flg = str.getByte(); + if (cmf === -1 || flg === -1) { + throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`); + } + if ((cmf & 0x0f) !== 0x08) { + throw new FormatError(`Unknown compression method in flate stream: ${cmf}, ${flg}`); + } + if (((cmf << 8) + flg) % 31 !== 0) { + throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`); + } + if (flg & 0x20) { + throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`); + } + this.codeSize = 0; + this.codeBuf = 0; + } + async getImageData(length, _decoderOptions) { + const data = await this.asyncGetBytes(); + if (!data) { + return this.getBytes(length); + } + if (data.length <= length) { + return data; + } + return data.subarray(0, length); + } + async asyncGetBytes() { + this.stream.reset(); + const bytes = this.stream.getBytes(); + try { + const { + readable, + writable + } = new DecompressionStream("deflate"); + const writer = writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => {}); + const chunks = []; + let totalLength = 0; + for await (const chunk of readable) { + chunks.push(chunk); + totalLength += chunk.byteLength; + } + const data = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + data.set(chunk, offset); + offset += chunk.byteLength; + } + return data; + } catch { + this.stream = new Stream(bytes, 2, bytes.length, this.stream.dict); + this.reset(); + return null; + } + } + get isAsync() { + return true; + } + getBits(bits) { + const str = this.stream; + let codeSize = this.codeSize; + let codeBuf = this.codeBuf; + let b; + while (codeSize < bits) { + if ((b = str.getByte()) === -1) { + throw new FormatError("Bad encoding in flate stream"); + } + codeBuf |= b << codeSize; + codeSize += 8; + } + b = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + return b; + } + getCode(table) { + const str = this.stream; + const codes = table[0]; + const maxLen = table[1]; + let codeSize = this.codeSize; + let codeBuf = this.codeBuf; + let b; + while (codeSize < maxLen) { + if ((b = str.getByte()) === -1) { + break; + } + codeBuf |= b << codeSize; + codeSize += 8; + } + const code = codes[codeBuf & (1 << maxLen) - 1]; + const codeLen = code >> 16; + const codeVal = code & 0xffff; + if (codeLen < 1 || codeSize < codeLen) { + throw new FormatError("Bad encoding in flate stream"); + } + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + return codeVal; + } + generateHuffmanTable(lengths) { + const n = lengths.length; + let maxLen = 0; + let i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + const size = 1 << maxLen; + const codes = new Int32Array(size); + for (let len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (let val = 0; val < n; ++val) { + if (lengths[val] === len) { + let code2 = 0; + let t = code; + for (i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } + for (i = code2; i < size; i += skip) { + codes[i] = len << 16 | val; + } + ++code; + } + } + } + return [codes, maxLen]; + } + #endsStreamOnError(err) { + info(err); + this.eof = true; + } + readBlock() { + let buffer, hdr, len; + const str = this.stream; + try { + hdr = this.getBits(3); + } catch (ex) { + this.#endsStreamOnError(ex.message); + return; + } + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + if (hdr === 0) { + let b; + if ((b = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + let blockLen = b; + if ((b = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + blockLen |= b << 8; + if ((b = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + let check = b; + if ((b = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + check |= b << 8; + if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) { + throw new FormatError("Bad uncompressed block length in flate stream"); + } + this.codeBuf = 0; + this.codeSize = 0; + const bufferLength = this.bufferLength, + end = bufferLength + blockLen; + buffer = this.ensureBuffer(end); + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + const block = str.getBytes(blockLen); + buffer.set(block, bufferLength); + if (block.length < blockLen) { + this.eof = true; + } + } + return; + } + let litCodeTable; + let distCodeTable; + if (hdr === 1) { + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { + const numLitCodes = this.getBits(5) + 257; + const numDistCodes = this.getBits(5) + 1; + const numCodeLenCodes = this.getBits(4) + 4; + const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + let i; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + len = 0; + i = 0; + const codes = numLitCodes + numDistCodes; + const codeLengths = new Uint8Array(codes); + let bitsLength, bitsOffset, what; + while (i < codes) { + const code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; + bitsOffset = 3; + what = len; + } else if (code === 17) { + bitsLength = 3; + bitsOffset = 3; + what = len = 0; + } else if (code === 18) { + bitsLength = 7; + bitsOffset = 11; + what = len = 0; + } else { + codeLengths[i++] = len = code; + continue; + } + let repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + throw new FormatError("Unknown block type in flate stream"); + } + buffer = this.buffer; + let limit = buffer ? buffer.length : 0; + let pos = this.bufferLength; + while (true) { + let code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + let code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + const dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (let k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + } +} + +;// ./src/core/arithmetic_decoder.js +const QeTable = [{ + qe: 0x5601, + nmps: 1, + nlps: 1, + switchFlag: 1 +}, { + qe: 0x3401, + nmps: 2, + nlps: 6, + switchFlag: 0 +}, { + qe: 0x1801, + nmps: 3, + nlps: 9, + switchFlag: 0 +}, { + qe: 0x0ac1, + nmps: 4, + nlps: 12, + switchFlag: 0 +}, { + qe: 0x0521, + nmps: 5, + nlps: 29, + switchFlag: 0 +}, { + qe: 0x0221, + nmps: 38, + nlps: 33, + switchFlag: 0 +}, { + qe: 0x5601, + nmps: 7, + nlps: 6, + switchFlag: 1 +}, { + qe: 0x5401, + nmps: 8, + nlps: 14, + switchFlag: 0 +}, { + qe: 0x4801, + nmps: 9, + nlps: 14, + switchFlag: 0 +}, { + qe: 0x3801, + nmps: 10, + nlps: 14, + switchFlag: 0 +}, { + qe: 0x3001, + nmps: 11, + nlps: 17, + switchFlag: 0 +}, { + qe: 0x2401, + nmps: 12, + nlps: 18, + switchFlag: 0 +}, { + qe: 0x1c01, + nmps: 13, + nlps: 20, + switchFlag: 0 +}, { + qe: 0x1601, + nmps: 29, + nlps: 21, + switchFlag: 0 +}, { + qe: 0x5601, + nmps: 15, + nlps: 14, + switchFlag: 1 +}, { + qe: 0x5401, + nmps: 16, + nlps: 14, + switchFlag: 0 +}, { + qe: 0x5101, + nmps: 17, + nlps: 15, + switchFlag: 0 +}, { + qe: 0x4801, + nmps: 18, + nlps: 16, + switchFlag: 0 +}, { + qe: 0x3801, + nmps: 19, + nlps: 17, + switchFlag: 0 +}, { + qe: 0x3401, + nmps: 20, + nlps: 18, + switchFlag: 0 +}, { + qe: 0x3001, + nmps: 21, + nlps: 19, + switchFlag: 0 +}, { + qe: 0x2801, + nmps: 22, + nlps: 19, + switchFlag: 0 +}, { + qe: 0x2401, + nmps: 23, + nlps: 20, + switchFlag: 0 +}, { + qe: 0x2201, + nmps: 24, + nlps: 21, + switchFlag: 0 +}, { + qe: 0x1c01, + nmps: 25, + nlps: 22, + switchFlag: 0 +}, { + qe: 0x1801, + nmps: 26, + nlps: 23, + switchFlag: 0 +}, { + qe: 0x1601, + nmps: 27, + nlps: 24, + switchFlag: 0 +}, { + qe: 0x1401, + nmps: 28, + nlps: 25, + switchFlag: 0 +}, { + qe: 0x1201, + nmps: 29, + nlps: 26, + switchFlag: 0 +}, { + qe: 0x1101, + nmps: 30, + nlps: 27, + switchFlag: 0 +}, { + qe: 0x0ac1, + nmps: 31, + nlps: 28, + switchFlag: 0 +}, { + qe: 0x09c1, + nmps: 32, + nlps: 29, + switchFlag: 0 +}, { + qe: 0x08a1, + nmps: 33, + nlps: 30, + switchFlag: 0 +}, { + qe: 0x0521, + nmps: 34, + nlps: 31, + switchFlag: 0 +}, { + qe: 0x0441, + nmps: 35, + nlps: 32, + switchFlag: 0 +}, { + qe: 0x02a1, + nmps: 36, + nlps: 33, + switchFlag: 0 +}, { + qe: 0x0221, + nmps: 37, + nlps: 34, + switchFlag: 0 +}, { + qe: 0x0141, + nmps: 38, + nlps: 35, + switchFlag: 0 +}, { + qe: 0x0111, + nmps: 39, + nlps: 36, + switchFlag: 0 +}, { + qe: 0x0085, + nmps: 40, + nlps: 37, + switchFlag: 0 +}, { + qe: 0x0049, + nmps: 41, + nlps: 38, + switchFlag: 0 +}, { + qe: 0x0025, + nmps: 42, + nlps: 39, + switchFlag: 0 +}, { + qe: 0x0015, + nmps: 43, + nlps: 40, + switchFlag: 0 +}, { + qe: 0x0009, + nmps: 44, + nlps: 41, + switchFlag: 0 +}, { + qe: 0x0005, + nmps: 45, + nlps: 42, + switchFlag: 0 +}, { + qe: 0x0001, + nmps: 45, + nlps: 43, + switchFlag: 0 +}, { + qe: 0x5601, + nmps: 46, + nlps: 46, + switchFlag: 0 +}]; +class ArithmeticDecoder { + constructor(data, start, end) { + this.data = data; + this.bp = start; + this.dataEnd = end; + this.chigh = data[start]; + this.clow = 0; + this.byteIn(); + this.chigh = this.chigh << 7 & 0xffff | this.clow >> 9 & 0x7f; + this.clow = this.clow << 7 & 0xffff; + this.ct -= 7; + this.a = 0x8000; + } + byteIn() { + const data = this.data; + let bp = this.bp; + if (data[bp] === 0xff) { + if (data[bp + 1] > 0x8f) { + this.clow += 0xff00; + this.ct = 8; + } else { + bp++; + this.clow += data[bp] << 9; + this.ct = 7; + this.bp = bp; + } + } else { + bp++; + this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00; + this.ct = 8; + this.bp = bp; + } + if (this.clow > 0xffff) { + this.chigh += this.clow >> 16; + this.clow &= 0xffff; + } + } + readBit(contexts, pos) { + let cx_index = contexts[pos] >> 1, + cx_mps = contexts[pos] & 1; + const qeTableIcx = QeTable[cx_index]; + const qeIcx = qeTableIcx.qe; + let d; + let a = this.a - qeIcx; + if (this.chigh < qeIcx) { + if (a < qeIcx) { + a = qeIcx; + d = cx_mps; + cx_index = qeTableIcx.nmps; + } else { + a = qeIcx; + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } + } else { + this.chigh -= qeIcx; + if ((a & 0x8000) !== 0) { + this.a = a; + return cx_mps; + } + if (a < qeIcx) { + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } else { + d = cx_mps; + cx_index = qeTableIcx.nmps; + } + } + do { + if (this.ct === 0) { + this.byteIn(); + } + a <<= 1; + this.chigh = this.chigh << 1 & 0xffff | this.clow >> 15 & 1; + this.clow = this.clow << 1 & 0xffff; + this.ct--; + } while ((a & 0x8000) === 0); + this.a = a; + contexts[pos] = cx_index << 1 | cx_mps; + return d; + } +} + +;// ./src/core/jbig2.js + + + + +class Jbig2Error extends BaseException { + constructor(msg) { + super(msg, "Jbig2Error"); + } +} +class ContextCache { + getContexts(id) { + if (id in this) { + return this[id]; + } + return this[id] = new Int8Array(1 << 16); + } +} +class DecodingContext { + constructor(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + get decoder() { + const decoder = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow(this, "decoder", decoder); + } + get contextCache() { + const cache = new ContextCache(); + return shadow(this, "contextCache", cache); + } +} +function decodeInteger(contextCache, procedure, decoder) { + const contexts = contextCache.getContexts(procedure); + let prev = 1; + function readBits(length) { + let v = 0; + for (let i = 0; i < length; i++) { + const bit = decoder.readBit(contexts, prev); + prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256; + v = v << 1 | bit; + } + return v >>> 0; + } + const sign = readBits(1); + const value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2); + let signedValue; + if (sign === 0) { + signedValue = value; + } else if (value > 0) { + signedValue = -value; + } + if (signedValue >= MIN_INT_32 && signedValue <= MAX_INT_32) { + return signedValue; + } + return null; +} +function decodeIAID(contextCache, decoder, codeLength) { + const contexts = contextCache.getContexts("IAID"); + let prev = 1; + for (let i = 0; i < codeLength; i++) { + const bit = decoder.readBit(contexts, prev); + prev = prev << 1 | bit; + } + if (codeLength < 31) { + return prev & (1 << codeLength) - 1; + } + return prev & 0x7fffffff; +} +const SegmentTypes = ["SymbolDictionary", null, null, null, "IntermediateTextRegion", null, "ImmediateTextRegion", "ImmediateLosslessTextRegion", null, null, null, null, null, null, null, null, "PatternDictionary", null, null, null, "IntermediateHalftoneRegion", null, "ImmediateHalftoneRegion", "ImmediateLosslessHalftoneRegion", null, null, null, null, null, null, null, null, null, null, null, null, "IntermediateGenericRegion", null, "ImmediateGenericRegion", "ImmediateLosslessGenericRegion", "IntermediateGenericRefinementRegion", null, "ImmediateGenericRefinementRegion", "ImmediateLosslessGenericRefinementRegion", null, null, null, null, "PageInformation", "EndOfPage", "EndOfStripe", "EndOfFile", "Profiles", "Tables", null, null, null, null, null, null, null, null, "Extension"]; +const CodingTemplates = [[{ + x: -1, + y: -2 +}, { + x: 0, + y: -2 +}, { + x: 1, + y: -2 +}, { + x: -2, + y: -1 +}, { + x: -1, + y: -1 +}, { + x: 0, + y: -1 +}, { + x: 1, + y: -1 +}, { + x: 2, + y: -1 +}, { + x: -4, + y: 0 +}, { + x: -3, + y: 0 +}, { + x: -2, + y: 0 +}, { + x: -1, + y: 0 +}], [{ + x: -1, + y: -2 +}, { + x: 0, + y: -2 +}, { + x: 1, + y: -2 +}, { + x: 2, + y: -2 +}, { + x: -2, + y: -1 +}, { + x: -1, + y: -1 +}, { + x: 0, + y: -1 +}, { + x: 1, + y: -1 +}, { + x: 2, + y: -1 +}, { + x: -3, + y: 0 +}, { + x: -2, + y: 0 +}, { + x: -1, + y: 0 +}], [{ + x: -1, + y: -2 +}, { + x: 0, + y: -2 +}, { + x: 1, + y: -2 +}, { + x: -2, + y: -1 +}, { + x: -1, + y: -1 +}, { + x: 0, + y: -1 +}, { + x: 1, + y: -1 +}, { + x: -2, + y: 0 +}, { + x: -1, + y: 0 +}], [{ + x: -3, + y: -1 +}, { + x: -2, + y: -1 +}, { + x: -1, + y: -1 +}, { + x: 0, + y: -1 +}, { + x: 1, + y: -1 +}, { + x: -4, + y: 0 +}, { + x: -3, + y: 0 +}, { + x: -2, + y: 0 +}, { + x: -1, + y: 0 +}]]; +const RefinementTemplates = [{ + coding: [{ + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }], + reference: [{ + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }, { + x: 0, + y: 0 + }, { + x: 1, + y: 0 + }, { + x: -1, + y: 1 + }, { + x: 0, + y: 1 + }, { + x: 1, + y: 1 + }] +}, { + coding: [{ + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }], + reference: [{ + x: 0, + y: -1 + }, { + x: -1, + y: 0 + }, { + x: 0, + y: 0 + }, { + x: 1, + y: 0 + }, { + x: 0, + y: 1 + }, { + x: 1, + y: 1 + }] +}]; +const ReusedContexts = [0x9b25, 0x0795, 0x00e5, 0x0195]; +const RefinementReusedContexts = [0x0020, 0x0008]; +function decodeBitmapTemplate0(width, height, decodingContext) { + const decoder = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GB"); + const bitmap = []; + let contextLabel, i, j, pixel, row, row1, row2; + const OLD_PIXEL_MASK = 0x7bf7; + for (i = 0; i < height; i++) { + row = bitmap[i] = new Uint8Array(width); + row1 = i < 1 ? row : bitmap[i - 1]; + row2 = i < 2 ? row : bitmap[i - 2]; + contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4; + for (j = 0; j < width; j++) { + row[j] = pixel = decoder.readBit(contexts, contextLabel); + contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; + } + } + return bitmap; +} +function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) { + if (mmr) { + const input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); + return decodeMMRBitmap(input, width, height, false); + } + if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { + return decodeBitmapTemplate0(width, height, decodingContext); + } + const useskip = !!skip; + const template = CodingTemplates[templateIndex].concat(at); + template.sort((a, b) => a.y - b.y || a.x - b.x); + const templateLength = template.length; + const templateX = new Int8Array(templateLength); + const templateY = new Int8Array(templateLength); + const changingTemplateEntries = []; + let reuseMask = 0, + minX = 0, + maxX = 0, + minY = 0; + let c, k; + for (k = 0; k < templateLength; k++) { + templateX[k] = template[k].x; + templateY[k] = template[k].y; + minX = Math.min(minX, template[k].x); + maxX = Math.max(maxX, template[k].x); + minY = Math.min(minY, template[k].y); + if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) { + reuseMask |= 1 << templateLength - 1 - k; + } else { + changingTemplateEntries.push(k); + } + } + const changingEntriesLength = changingTemplateEntries.length; + const changingTemplateX = new Int8Array(changingEntriesLength); + const changingTemplateY = new Int8Array(changingEntriesLength); + const changingTemplateBit = new Uint16Array(changingEntriesLength); + for (c = 0; c < changingEntriesLength; c++) { + k = changingTemplateEntries[c]; + changingTemplateX[c] = template[k].x; + changingTemplateY[c] = template[k].y; + changingTemplateBit[c] = 1 << templateLength - 1 - k; + } + const sbb_left = -minX; + const sbb_top = -minY; + const sbb_right = width - maxX; + const pseudoPixelContext = ReusedContexts[templateIndex]; + let row = new Uint8Array(width); + const bitmap = []; + const decoder = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GB"); + let ltp = 0, + j, + i0, + j0, + contextLabel = 0, + bit, + shift; + for (let i = 0; i < height; i++) { + if (prediction) { + const sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + bitmap.push(row); + continue; + } + } + row = new Uint8Array(row); + bitmap.push(row); + for (j = 0; j < width; j++) { + if (useskip && skip[i][j]) { + row[j] = 0; + continue; + } + if (j >= sbb_left && j < sbb_right && i >= sbb_top) { + contextLabel = contextLabel << 1 & reuseMask; + for (k = 0; k < changingEntriesLength; k++) { + i0 = i + changingTemplateY[k]; + j0 = j + changingTemplateX[k]; + bit = bitmap[i0][j0]; + if (bit) { + bit = changingTemplateBit[k]; + contextLabel |= bit; + } + } + } else { + contextLabel = 0; + shift = templateLength - 1; + for (k = 0; k < templateLength; k++, shift--) { + j0 = j + templateX[k]; + if (j0 >= 0 && j0 < width) { + i0 = i + templateY[k]; + if (i0 >= 0) { + bit = bitmap[i0][j0]; + if (bit) { + contextLabel |= bit << shift; + } + } + } + } + } + const pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; +} +function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) { + let codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) { + codingTemplate = codingTemplate.concat([at[0]]); + } + const codingTemplateLength = codingTemplate.length; + const codingTemplateX = new Int32Array(codingTemplateLength); + const codingTemplateY = new Int32Array(codingTemplateLength); + let k; + for (k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + let referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) { + referenceTemplate = referenceTemplate.concat([at[1]]); + } + const referenceTemplateLength = referenceTemplate.length; + const referenceTemplateX = new Int32Array(referenceTemplateLength); + const referenceTemplateY = new Int32Array(referenceTemplateLength); + for (k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + const referenceWidth = referenceBitmap[0].length; + const referenceHeight = referenceBitmap.length; + const pseudoPixelContext = RefinementReusedContexts[templateIndex]; + const bitmap = []; + const decoder = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GR"); + let ltp = 0; + for (let i = 0; i < height; i++) { + if (prediction) { + const sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + throw new Jbig2Error("prediction is not supported"); + } + } + const row = new Uint8Array(width); + bitmap.push(row); + for (let j = 0; j < width; j++) { + let i0, j0; + let contextLabel = 0; + for (k = 0; k < codingTemplateLength; k++) { + i0 = i + codingTemplateY[k]; + j0 = j + codingTemplateX[k]; + if (i0 < 0 || j0 < 0 || j0 >= width) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | bitmap[i0][j0]; + } + } + for (k = 0; k < referenceTemplateLength; k++) { + i0 = i + referenceTemplateY[k] - offsetY; + j0 = j + referenceTemplateX[k] - offsetX; + if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | referenceBitmap[i0][j0]; + } + } + const pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; +} +function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) { + if (huffman && refinement) { + throw new Jbig2Error("symbol refinement with Huffman is not supported"); + } + const newSymbols = []; + let currentHeight = 0; + let symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + const decoder = decodingContext.decoder; + const contextCache = decodingContext.contextCache; + let tableB1, symbolWidths; + if (huffman) { + tableB1 = getStandardTable(1); + symbolWidths = []; + symbolCodeLength = Math.max(symbolCodeLength, 1); + } + while (newSymbols.length < numberOfNewSymbols) { + const deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, "IADH", decoder); + currentHeight += deltaHeight; + let currentWidth = 0, + totalWidth = 0; + const firstSymbol = huffman ? symbolWidths.length : 0; + while (true) { + const deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, "IADW", decoder); + if (deltaWidth === null) { + break; + } + currentWidth += deltaWidth; + totalWidth += currentWidth; + let bitmap; + if (refinement) { + const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder); + if (numberOfInstances > 1) { + bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput); + } else { + const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + const rdx = decodeInteger(contextCache, "IARDX", decoder); + const rdy = decodeInteger(contextCache, "IARDY", decoder); + const symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length]; + bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext); + } + newSymbols.push(bitmap); + } else if (huffman) { + symbolWidths.push(currentWidth); + } else { + bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext); + newSymbols.push(bitmap); + } + } + if (huffman && !refinement) { + const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput); + huffmanInput.byteAlign(); + let collectiveBitmap; + if (bitmapSize === 0) { + collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight); + } else { + const originalEnd = huffmanInput.end; + const bitmapEnd = huffmanInput.position + bitmapSize; + huffmanInput.end = bitmapEnd; + collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false); + huffmanInput.end = originalEnd; + huffmanInput.position = bitmapEnd; + } + const numberOfSymbolsDecoded = symbolWidths.length; + if (firstSymbol === numberOfSymbolsDecoded - 1) { + newSymbols.push(collectiveBitmap); + } else { + let i, + y, + xMin = 0, + xMax, + bitmapWidth, + symbolBitmap; + for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) { + bitmapWidth = symbolWidths[i]; + xMax = xMin + bitmapWidth; + symbolBitmap = []; + for (y = 0; y < currentHeight; y++) { + symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); + } + newSymbols.push(symbolBitmap); + xMin = xMax; + } + } + } + } + const exportedSymbols = [], + flags = []; + let currentFlag = false, + i, + ii; + const totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + let runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, "IAEX", decoder); + while (runLength--) { + flags.push(currentFlag); + } + currentFlag = !currentFlag; + } + for (i = 0, ii = symbols.length; i < ii; i++) { + if (flags[i]) { + exportedSymbols.push(symbols[i]); + } + } + for (let j = 0; j < numberOfNewSymbols; i++, j++) { + if (flags[i]) { + exportedSymbols.push(newSymbols[j]); + } + } + return exportedSymbols; +} +function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) { + if (huffman && refinement) { + throw new Jbig2Error("refinement with Huffman is not supported"); + } + const bitmap = []; + let i, row; + for (i = 0; i < height; i++) { + row = new Uint8Array(width); + if (defaultPixelValue) { + row.fill(defaultPixelValue); + } + bitmap.push(row); + } + const decoder = decodingContext.decoder; + const contextCache = decodingContext.contextCache; + let stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, "IADT", decoder); + let firstS = 0; + i = 0; + while (i < numberOfSymbolInstances) { + const deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, "IADT", decoder); + stripT += deltaT; + const deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, "IAFS", decoder); + firstS += deltaFirstS; + let currentS = firstS; + do { + let currentT = 0; + if (stripSize > 1) { + currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, "IAIT", decoder); + } + const t = stripSize * stripT + currentT; + const symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength); + const applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, "IARI", decoder)); + let symbolBitmap = inputSymbols[symbolId]; + let symbolWidth = symbolBitmap[0].length; + let symbolHeight = symbolBitmap.length; + if (applyRefinement) { + const rdw = decodeInteger(contextCache, "IARDW", decoder); + const rdh = decodeInteger(contextCache, "IARDH", decoder); + const rdx = decodeInteger(contextCache, "IARDX", decoder); + const rdy = decodeInteger(contextCache, "IARDY", decoder); + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext); + } + let increment = 0; + if (!transposed) { + if (referenceCorner > 1) { + currentS += symbolWidth - 1; + } else { + increment = symbolWidth - 1; + } + } else if (!(referenceCorner & 1)) { + currentS += symbolHeight - 1; + } else { + increment = symbolHeight - 1; + } + const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1); + const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0); + let s2, t2, symbolRow; + if (transposed) { + for (s2 = 0; s2 < symbolHeight; s2++) { + row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[s2]; + const maxWidth = Math.min(width - offsetT, symbolWidth); + switch (combinationOperator) { + case 0: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + } else { + for (t2 = 0; t2 < symbolHeight; t2++) { + row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + } + i++; + const deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, "IADS", decoder); + if (deltaS === null) { + break; + } + currentS += increment + deltaS + dsOffset; + } while (true); + } + return bitmap; +} +function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) { + const at = []; + if (!mmr) { + at.push({ + x: -patternWidth, + y: 0 + }); + if (template === 0) { + at.push({ + x: -3, + y: -1 + }, { + x: 2, + y: -2 + }, { + x: -2, + y: -2 + }); + } + } + const collectiveWidth = (maxPatternIndex + 1) * patternWidth; + const collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext); + const patterns = []; + for (let i = 0; i <= maxPatternIndex; i++) { + const patternBitmap = []; + const xMin = patternWidth * i; + const xMax = xMin + patternWidth; + for (let y = 0; y < patternHeight; y++) { + patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); + } + patterns.push(patternBitmap); + } + return patterns; +} +function decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) { + const skip = null; + if (enableSkip) { + throw new Jbig2Error("skip is not supported"); + } + if (combinationOperator !== 0) { + throw new Jbig2Error(`operator "${combinationOperator}" is not supported in halftone region`); + } + const regionBitmap = []; + let i, j, row; + for (i = 0; i < regionHeight; i++) { + row = new Uint8Array(regionWidth); + if (defaultPixelValue) { + row.fill(defaultPixelValue); + } + regionBitmap.push(row); + } + const numberOfPatterns = patterns.length; + const pattern0 = patterns[0]; + const patternWidth = pattern0[0].length, + patternHeight = pattern0.length; + const bitsPerValue = log2(numberOfPatterns); + const at = []; + if (!mmr) { + at.push({ + x: template <= 1 ? 3 : 2, + y: -1 + }); + if (template === 0) { + at.push({ + x: -3, + y: -1 + }, { + x: 2, + y: -2 + }, { + x: -2, + y: -2 + }); + } + } + const grayScaleBitPlanes = []; + let mmrInput, bitmap; + if (mmr) { + mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); + } + for (i = bitsPerValue - 1; i >= 0; i--) { + if (mmr) { + bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true); + } else { + bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext); + } + grayScaleBitPlanes[i] = bitmap; + } + let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow; + for (mg = 0; mg < gridHeight; mg++) { + for (ng = 0; ng < gridWidth; ng++) { + bit = 0; + patternIndex = 0; + for (j = bitsPerValue - 1; j >= 0; j--) { + bit ^= grayScaleBitPlanes[j][mg][ng]; + patternIndex |= bit << j; + } + patternBitmap = patterns[patternIndex]; + x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8; + y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8; + if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) { + for (i = 0; i < patternHeight; i++) { + regionRow = regionBitmap[y + i]; + patternRow = patternBitmap[i]; + for (j = 0; j < patternWidth; j++) { + regionRow[x + j] |= patternRow[j]; + } + } + } else { + let regionX, regionY; + for (i = 0; i < patternHeight; i++) { + regionY = y + i; + if (regionY < 0 || regionY >= regionHeight) { + continue; + } + regionRow = regionBitmap[regionY]; + patternRow = patternBitmap[i]; + for (j = 0; j < patternWidth; j++) { + regionX = x + j; + if (regionX >= 0 && regionX < regionWidth) { + regionRow[regionX] |= patternRow[j]; + } + } + } + } + } + } + return regionBitmap; +} +function readSegmentHeader(data, start) { + const segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + const flags = data[start + 4]; + const segmentType = flags & 0x3f; + if (!SegmentTypes[segmentType]) { + throw new Jbig2Error("invalid segment type: " + segmentType); + } + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 0x80); + const pageAssociationFieldSize = !!(flags & 0x40); + const referredFlags = data[start + 5]; + let referredToCount = referredFlags >> 5 & 7; + const retainBits = [referredFlags & 31]; + let position = start + 6; + if (referredFlags === 7) { + referredToCount = readUint32(data, position - 1) & 0x1fffffff; + position += 3; + let bytes = referredToCount + 7 >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags === 5 || referredFlags === 6) { + throw new Jbig2Error("invalid referred-to flags"); + } + segmentHeader.retainBits = retainBits; + let referredToSegmentNumberSize = 4; + if (segmentHeader.number <= 256) { + referredToSegmentNumberSize = 1; + } else if (segmentHeader.number <= 65536) { + referredToSegmentNumberSize = 2; + } + const referredTo = []; + let i, ii; + for (i = 0; i < referredToCount; i++) { + let number; + if (referredToSegmentNumberSize === 1) { + number = data[position]; + } else if (referredToSegmentNumberSize === 2) { + number = readUint16(data, position); + } else { + number = readUint32(data, position); + } + referredTo.push(number); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) { + segmentHeader.pageAssociation = data[position++]; + } else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + if (segmentHeader.length === 0xffffffff) { + if (segmentType === 38) { + const genericRegionInfo = readRegionSegmentInformation(data, position); + const genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength]; + const genericRegionMmr = !!(genericRegionSegmentFlags & 1); + const searchPatternLength = 6; + const searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 0xff; + searchPattern[1] = 0xac; + } + searchPattern[2] = genericRegionInfo.height >>> 24 & 0xff; + searchPattern[3] = genericRegionInfo.height >> 16 & 0xff; + searchPattern[4] = genericRegionInfo.height >> 8 & 0xff; + searchPattern[5] = genericRegionInfo.height & 0xff; + for (i = position, ii = data.length; i < ii; i++) { + let j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j === searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length === 0xffffffff) { + throw new Jbig2Error("segment end was not found"); + } + } else { + throw new Jbig2Error("invalid unknown segment length"); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; +} +function readSegments(header, data, start, end) { + const segments = []; + let position = start; + while (position < end) { + const segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + const segment = { + header: segmentHeader, + data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type === 51) { + break; + } + } + if (header.randomAccess) { + for (let i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; +} +function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; +} +const RegionSegmentInformationFieldLength = 17; +function processSegment(segment, visitor) { + const header = segment.header; + const data = segment.data, + end = segment.end; + let position = segment.start; + let args, at, i, atLength; + switch (header.type) { + case 0: + const dictionary = {}; + const dictionaryFlags = readUint16(data, position); + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3; + dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3; + dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1; + dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = dictionaryFlags >> 10 & 3; + dictionary.refinementTemplate = dictionaryFlags >> 12 & 1; + position += 2; + if (!dictionary.huffman) { + atLength = dictionary.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [dictionary, header.number, header.referredTo, data, position, end]; + break; + case 6: + case 7: + const textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3; + textRegion.stripSize = 1 << textRegion.logStripSize; + textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3; + textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1; + textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27; + textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1; + if (textRegion.huffman) { + const textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = textRegionHuffmanFlags & 3; + textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3; + textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3; + textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3; + textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3; + textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3; + textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3; + textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + args = [textRegion, header.referredTo, data, position, end]; + break; + case 16: + const patternDictionary = {}; + const patternDictionaryFlags = data[position++]; + patternDictionary.mmr = !!(patternDictionaryFlags & 1); + patternDictionary.template = patternDictionaryFlags >> 1 & 3; + patternDictionary.patternWidth = data[position++]; + patternDictionary.patternHeight = data[position++]; + patternDictionary.maxPatternIndex = readUint32(data, position); + position += 4; + args = [patternDictionary, header.number, data, position, end]; + break; + case 22: + case 23: + const halftoneRegion = {}; + halftoneRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const halftoneRegionFlags = data[position++]; + halftoneRegion.mmr = !!(halftoneRegionFlags & 1); + halftoneRegion.template = halftoneRegionFlags >> 1 & 3; + halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8); + halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7; + halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1; + halftoneRegion.gridWidth = readUint32(data, position); + position += 4; + halftoneRegion.gridHeight = readUint32(data, position); + position += 4; + halftoneRegion.gridOffsetX = readUint32(data, position) & 0xffffffff; + position += 4; + halftoneRegion.gridOffsetY = readUint32(data, position) & 0xffffffff; + position += 4; + halftoneRegion.gridVectorX = readUint16(data, position); + position += 2; + halftoneRegion.gridVectorY = readUint16(data, position); + position += 2; + args = [halftoneRegion, header.referredTo, data, position, end]; + break; + case 38: + case 39: + const genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = genericRegionSegmentFlags >> 1 & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + atLength = genericRegion.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [genericRegion, data, position, end]; + break; + case 48: + const pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height === 0xffffffff) { + delete pageInfo.height; + } + const pageSegmentFlags = data[position + 16]; + readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1; + pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: + break; + case 50: + break; + case 51: + break; + case 53: + args = [header.number, data, position, end]; + break; + case 62: + break; + default: + throw new Jbig2Error(`segment type ${header.typeName}(${header.type}) is not implemented`); + } + const callbackName = "on" + header.typeName; + if (callbackName in visitor) { + visitor[callbackName].apply(visitor, args); + } +} +function processSegments(segments, visitor) { + for (let i = 0, ii = segments.length; i < ii; i++) { + processSegment(segments[i], visitor); + } +} +function parseJbig2Chunks(chunks) { + const visitor = new SimpleSegmentVisitor(); + for (let i = 0, ii = chunks.length; i < ii; i++) { + const chunk = chunks[i]; + const segments = readSegments({}, chunk.data, chunk.start, chunk.end); + processSegments(segments, visitor); + } + return visitor.buffer; +} +class SimpleSegmentVisitor { + onPageInformation(info) { + this.currentPageInfo = info; + const rowSize = info.width + 7 >> 3; + const buffer = new Uint8ClampedArray(rowSize * info.height); + if (info.defaultPixelValue) { + buffer.fill(0xff); + } + this.buffer = buffer; + } + drawBitmap(regionInfo, bitmap) { + const pageInfo = this.currentPageInfo; + const width = regionInfo.width, + height = regionInfo.height; + const rowSize = pageInfo.width + 7 >> 3; + const combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator; + const buffer = this.buffer; + const mask0 = 128 >> (regionInfo.x & 7); + let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); + let i, j, mask, offset; + switch (combinationOperator) { + case 0: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] |= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + case 2: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] ^= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + onImmediateGenericRegion(region, data, start, end) { + const regionInfo = region.info; + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion(...arguments); + } + onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) { + let huffmanTables, huffmanInput; + if (dictionary.huffman) { + huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables); + huffmanInput = new Reader(data, start, end); + } + let symbols = this.symbols; + if (!symbols) { + this.symbols = symbols = {}; + } + const inputSymbols = []; + for (const referredSegment of referredSegments) { + const referredSymbols = symbols[referredSegment]; + if (referredSymbols) { + inputSymbols.push(...referredSymbols); + } + } + const decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput); + } + onImmediateTextRegion(region, referredSegments, data, start, end) { + const regionInfo = region.info; + let huffmanTables, huffmanInput; + const symbols = this.symbols; + const inputSymbols = []; + for (const referredSegment of referredSegments) { + const referredSymbols = symbols[referredSegment]; + if (referredSymbols) { + inputSymbols.push(...referredSymbols); + } + } + const symbolCodeLength = log2(inputSymbols.length); + if (region.huffman) { + huffmanInput = new Reader(data, start, end); + huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput); + } + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessTextRegion() { + this.onImmediateTextRegion(...arguments); + } + onPatternDictionary(dictionary, currentSegment, data, start, end) { + let patterns = this.patterns; + if (!patterns) { + this.patterns = patterns = {}; + } + const decodingContext = new DecodingContext(data, start, end); + patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext); + } + onImmediateHalftoneRegion(region, referredSegments, data, start, end) { + const patterns = this.patterns[referredSegments[0]]; + const regionInfo = region.info; + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessHalftoneRegion() { + this.onImmediateHalftoneRegion(...arguments); + } + onTables(currentSegment, data, start, end) { + let customTables = this.customTables; + if (!customTables) { + this.customTables = customTables = {}; + } + customTables[currentSegment] = decodeTablesSegment(data, start, end); + } +} +class HuffmanLine { + constructor(lineData) { + if (lineData.length === 2) { + this.isOOB = true; + this.rangeLow = 0; + this.prefixLength = lineData[0]; + this.rangeLength = 0; + this.prefixCode = lineData[1]; + this.isLowerRange = false; + } else { + this.isOOB = false; + this.rangeLow = lineData[0]; + this.prefixLength = lineData[1]; + this.rangeLength = lineData[2]; + this.prefixCode = lineData[3]; + this.isLowerRange = lineData[4] === "lower"; + } + } +} +class HuffmanTreeNode { + constructor(line) { + this.children = []; + if (line) { + this.isLeaf = true; + this.rangeLength = line.rangeLength; + this.rangeLow = line.rangeLow; + this.isLowerRange = line.isLowerRange; + this.isOOB = line.isOOB; + } else { + this.isLeaf = false; + } + } + buildTree(line, shift) { + const bit = line.prefixCode >> shift & 1; + if (shift <= 0) { + this.children[bit] = new HuffmanTreeNode(line); + } else { + let node = this.children[bit]; + if (!node) { + this.children[bit] = node = new HuffmanTreeNode(null); + } + node.buildTree(line, shift - 1); + } + } + decodeNode(reader) { + if (this.isLeaf) { + if (this.isOOB) { + return null; + } + const htOffset = reader.readBits(this.rangeLength); + return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset); + } + const node = this.children[reader.readBit()]; + if (!node) { + throw new Jbig2Error("invalid Huffman data"); + } + return node.decodeNode(reader); + } +} +class HuffmanTable { + constructor(lines, prefixCodesDone) { + if (!prefixCodesDone) { + this.assignPrefixCodes(lines); + } + this.rootNode = new HuffmanTreeNode(null); + for (let i = 0, ii = lines.length; i < ii; i++) { + const line = lines[i]; + if (line.prefixLength > 0) { + this.rootNode.buildTree(line, line.prefixLength - 1); + } + } + } + decode(reader) { + return this.rootNode.decodeNode(reader); + } + assignPrefixCodes(lines) { + const linesLength = lines.length; + let prefixLengthMax = 0; + for (let i = 0; i < linesLength; i++) { + prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength); + } + const histogram = new Uint32Array(prefixLengthMax + 1); + for (let i = 0; i < linesLength; i++) { + histogram[lines[i].prefixLength]++; + } + let currentLength = 1, + firstCode = 0, + currentCode, + currentTemp, + line; + histogram[0] = 0; + while (currentLength <= prefixLengthMax) { + firstCode = firstCode + histogram[currentLength - 1] << 1; + currentCode = firstCode; + currentTemp = 0; + while (currentTemp < linesLength) { + line = lines[currentTemp]; + if (line.prefixLength === currentLength) { + line.prefixCode = currentCode; + currentCode++; + } + currentTemp++; + } + currentLength++; + } + } +} +function decodeTablesSegment(data, start, end) { + const flags = data[start]; + const lowestValue = readUint32(data, start + 1) & 0xffffffff; + const highestValue = readUint32(data, start + 5) & 0xffffffff; + const reader = new Reader(data, start + 9, end); + const prefixSizeBits = (flags >> 1 & 7) + 1; + const rangeSizeBits = (flags >> 4 & 7) + 1; + const lines = []; + let prefixLength, + rangeLength, + currentRangeLow = lowestValue; + do { + prefixLength = reader.readBits(prefixSizeBits); + rangeLength = reader.readBits(rangeSizeBits); + lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0])); + currentRangeLow += 1 << rangeLength; + } while (currentRangeLow < highestValue); + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"])); + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0])); + if (flags & 1) { + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([prefixLength, 0])); + } + return new HuffmanTable(lines, false); +} +const standardTablesCache = {}; +function getStandardTable(number) { + let table = standardTablesCache[number]; + if (table) { + return table; + } + let lines; + switch (number) { + case 1: + lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]]; + break; + case 2: + lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [75, 6, 32, 0x3e], [6, 0x3f]]; + break; + case 3: + lines = [[-256, 8, 8, 0xfe], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [-257, 8, 32, 0xff, "lower"], [75, 7, 32, 0x7e], [6, 0x3e]]; + break; + case 4: + lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [76, 5, 32, 0x1f]]; + break; + case 5: + lines = [[-255, 7, 8, 0x7e], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [-256, 7, 32, 0x7f, "lower"], [76, 6, 32, 0x3e]]; + break; + case 6: + lines = [[-2048, 5, 10, 0x1c], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xa], [-128, 5, 6, 0x1d], [-64, 5, 5, 0x1e], [-32, 4, 5, 0xb], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xc], [1024, 4, 10, 0xd], [-2049, 6, 32, 0x3e, "lower"], [2048, 6, 32, 0x3f]]; + break; + case 7: + lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1a], [-64, 5, 5, 0x1b], [-32, 4, 5, 0xa], [0, 4, 5, 0xb], [32, 5, 5, 0x1c], [64, 5, 6, 0x1d], [128, 4, 7, 0xc], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1e, "lower"], [2048, 5, 32, 0x1f]]; + break; + case 8: + lines = [[-15, 8, 3, 0xfc], [-7, 9, 1, 0x1fc], [-5, 8, 1, 0xfd], [-3, 9, 0, 0x1fd], [-2, 7, 0, 0x7c], [-1, 4, 0, 0xa], [0, 2, 1, 0x0], [2, 5, 0, 0x1a], [3, 6, 0, 0x3a], [4, 3, 4, 0x4], [20, 6, 1, 0x3b], [22, 4, 4, 0xb], [38, 4, 5, 0xc], [70, 5, 6, 0x1b], [134, 5, 7, 0x1c], [262, 6, 7, 0x3c], [390, 7, 8, 0x7d], [646, 6, 10, 0x3d], [-16, 9, 32, 0x1fe, "lower"], [1670, 9, 32, 0x1ff], [2, 0x1]]; + break; + case 9: + lines = [[-31, 8, 4, 0xfc], [-15, 9, 2, 0x1fc], [-11, 8, 2, 0xfd], [-7, 9, 1, 0x1fd], [-5, 7, 1, 0x7c], [-3, 4, 1, 0xa], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1a], [5, 6, 1, 0x3a], [7, 3, 5, 0x4], [39, 6, 2, 0x3b], [43, 4, 5, 0xb], [75, 4, 6, 0xc], [139, 5, 7, 0x1b], [267, 5, 8, 0x1c], [523, 6, 8, 0x3c], [779, 7, 9, 0x7d], [1291, 6, 11, 0x3d], [-32, 9, 32, 0x1fe, "lower"], [3339, 9, 32, 0x1ff], [2, 0x0]]; + break; + case 10: + lines = [[-21, 7, 4, 0x7a], [-5, 8, 0, 0xfc], [-4, 7, 0, 0x7b], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7c], [5, 8, 0, 0xfd], [6, 2, 6, 0x1], [70, 5, 5, 0x1a], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3a], [582, 6, 9, 0x3b], [1094, 6, 10, 0x3c], [2118, 7, 11, 0x7d], [-22, 8, 32, 0xfe, "lower"], [4166, 8, 32, 0xff], [2, 0x2]]; + break; + case 11: + lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xc], [5, 4, 1, 0xd], [7, 5, 1, 0x1c], [9, 5, 2, 0x1d], [13, 6, 2, 0x3c], [17, 7, 2, 0x7a], [21, 7, 3, 0x7b], [29, 7, 4, 0x7c], [45, 7, 5, 0x7d], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]]; + break; + case 12: + lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1c], [6, 5, 1, 0x1d], [8, 6, 1, 0x3c], [10, 7, 0, 0x7a], [11, 7, 1, 0x7b], [13, 7, 2, 0x7c], [17, 7, 3, 0x7d], [25, 7, 4, 0x7e], [41, 8, 5, 0xfe], [73, 8, 32, 0xff]]; + break; + case 13: + lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xc], [4, 5, 0, 0x1c], [5, 4, 1, 0xd], [7, 3, 3, 0x5], [15, 6, 1, 0x3a], [17, 6, 2, 0x3b], [21, 6, 3, 0x3c], [29, 6, 4, 0x3d], [45, 6, 5, 0x3e], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]]; + break; + case 14: + lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]]; + break; + case 15: + lines = [[-24, 7, 4, 0x7c], [-8, 6, 2, 0x3c], [-4, 5, 1, 0x1c], [-2, 4, 0, 0xc], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xd], [3, 5, 1, 0x1d], [5, 6, 2, 0x3d], [9, 7, 4, 0x7d], [-25, 7, 32, 0x7e, "lower"], [25, 7, 32, 0x7f]]; + break; + default: + throw new Jbig2Error(`standard table B.${number} does not exist`); + } + for (let i = 0, ii = lines.length; i < ii; i++) { + lines[i] = new HuffmanLine(lines[i]); + } + table = new HuffmanTable(lines, true); + standardTablesCache[number] = table; + return table; +} +class Reader { + constructor(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + this.position = start; + this.shift = -1; + this.currentByte = 0; + } + readBit() { + if (this.shift < 0) { + if (this.position >= this.end) { + throw new Jbig2Error("end of data while reading bit"); + } + this.currentByte = this.data[this.position++]; + this.shift = 7; + } + const bit = this.currentByte >> this.shift & 1; + this.shift--; + return bit; + } + readBits(numBits) { + let result = 0, + i; + for (i = numBits - 1; i >= 0; i--) { + result |= this.readBit() << i; + } + return result; + } + byteAlign() { + this.shift = -1; + } + next() { + if (this.position >= this.end) { + return -1; + } + return this.data[this.position++]; + } +} +function getCustomHuffmanTable(index, referredTo, customTables) { + let currentIndex = 0; + for (let i = 0, ii = referredTo.length; i < ii; i++) { + const table = customTables[referredTo[i]]; + if (table) { + if (index === currentIndex) { + return table; + } + currentIndex++; + } + } + throw new Jbig2Error("can't find custom Huffman table"); +} +function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) { + const codes = []; + for (let i = 0; i <= 34; i++) { + const codeLength = reader.readBits(4); + codes.push(new HuffmanLine([i, codeLength, 0, 0])); + } + const runCodesTable = new HuffmanTable(codes, false); + codes.length = 0; + for (let i = 0; i < numberOfSymbols;) { + const codeLength = runCodesTable.decode(reader); + if (codeLength >= 32) { + let repeatedLength, numberOfRepeats, j; + switch (codeLength) { + case 32: + if (i === 0) { + throw new Jbig2Error("no previous value in symbol ID table"); + } + numberOfRepeats = reader.readBits(2) + 3; + repeatedLength = codes[i - 1].prefixLength; + break; + case 33: + numberOfRepeats = reader.readBits(3) + 3; + repeatedLength = 0; + break; + case 34: + numberOfRepeats = reader.readBits(7) + 11; + repeatedLength = 0; + break; + default: + throw new Jbig2Error("invalid code length in symbol ID table"); + } + for (j = 0; j < numberOfRepeats; j++) { + codes.push(new HuffmanLine([i, repeatedLength, 0, 0])); + i++; + } + } else { + codes.push(new HuffmanLine([i, codeLength, 0, 0])); + i++; + } + } + reader.byteAlign(); + const symbolIDTable = new HuffmanTable(codes, false); + let customIndex = 0, + tableFirstS, + tableDeltaS, + tableDeltaT; + switch (textRegion.huffmanFS) { + case 0: + case 1: + tableFirstS = getStandardTable(textRegion.huffmanFS + 6); + break; + case 3: + tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman FS selector"); + } + switch (textRegion.huffmanDS) { + case 0: + case 1: + case 2: + tableDeltaS = getStandardTable(textRegion.huffmanDS + 8); + break; + case 3: + tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DS selector"); + } + switch (textRegion.huffmanDT) { + case 0: + case 1: + case 2: + tableDeltaT = getStandardTable(textRegion.huffmanDT + 11); + break; + case 3: + tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DT selector"); + } + if (textRegion.refinement) { + throw new Jbig2Error("refinement with Huffman is not supported"); + } + return { + symbolIDTable, + tableFirstS, + tableDeltaS, + tableDeltaT + }; +} +function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) { + let customIndex = 0, + tableDeltaHeight, + tableDeltaWidth; + switch (dictionary.huffmanDHSelector) { + case 0: + case 1: + tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4); + break; + case 3: + tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DH selector"); + } + switch (dictionary.huffmanDWSelector) { + case 0: + case 1: + tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2); + break; + case 3: + tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DW selector"); + } + let tableBitmapSize, tableAggregateInstances; + if (dictionary.bitmapSizeSelector) { + tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + } else { + tableBitmapSize = getStandardTable(1); + } + if (dictionary.aggregationInstancesSelector) { + tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables); + } else { + tableAggregateInstances = getStandardTable(1); + } + return { + tableDeltaHeight, + tableDeltaWidth, + tableBitmapSize, + tableAggregateInstances + }; +} +function readUncompressedBitmap(reader, width, height) { + const bitmap = []; + for (let y = 0; y < height; y++) { + const row = new Uint8Array(width); + bitmap.push(row); + for (let x = 0; x < width; x++) { + row[x] = reader.readBit(); + } + reader.byteAlign(); + } + return bitmap; +} +function decodeMMRBitmap(input, width, height, endOfBlock) { + const params = { + K: -1, + Columns: width, + Rows: height, + BlackIs1: true, + EndOfBlock: endOfBlock + }; + const decoder = new CCITTFaxDecoder(input, params); + const bitmap = []; + let currentByte, + eof = false; + for (let y = 0; y < height; y++) { + const row = new Uint8Array(width); + bitmap.push(row); + let shift = -1; + for (let x = 0; x < width; x++) { + if (shift < 0) { + currentByte = decoder.readNextChar(); + if (currentByte === -1) { + currentByte = 0; + eof = true; + } + shift = 7; + } + row[x] = currentByte >> shift & 1; + shift--; + } + } + if (endOfBlock && !eof) { + const lookForEOFLimit = 5; + for (let i = 0; i < lookForEOFLimit; i++) { + if (decoder.readNextChar() === -1) { + break; + } + } + } + return bitmap; +} +class Jbig2Image { + parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + parse(data) { + throw new Error("Not implemented: Jbig2Image.parse"); + } +} + +;// ./src/core/jbig2_stream.js + + + + + +class Jbig2Stream extends DecodeStream { + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + get bytes() { + return shadow(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) {} + readBlock() { + this.decodeImage(); + } + decodeImage(bytes) { + if (this.eof) { + return this.buffer; + } + bytes ||= this.bytes; + const jbig2Image = new Jbig2Image(); + const chunks = []; + if (this.params instanceof Dict) { + const globalsStream = this.params.get("JBIG2Globals"); + if (globalsStream instanceof BaseStream) { + const globals = globalsStream.getBytes(); + chunks.push({ + data: globals, + start: 0, + end: globals.length + }); + } + } + chunks.push({ + data: bytes, + start: 0, + end: bytes.length + }); + const data = jbig2Image.parseChunks(chunks); + const dataLength = data.length; + for (let i = 0; i < dataLength; i++) { + data[i] ^= 0xff; + } + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } +} + +;// ./src/core/jpx_stream.js + + + +class JpxStream extends DecodeStream { + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + get bytes() { + return shadow(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) {} + readBlock(decoderOptions) { + unreachable("JpxStream.readBlock"); + } + get isAsyncDecoder() { + return true; + } + async decodeImage(bytes, decoderOptions) { + if (this.eof) { + return this.buffer; + } + bytes ||= this.bytes; + this.buffer = await JpxImage.decode(bytes, decoderOptions); + this.bufferLength = this.buffer.length; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } +} + +;// ./src/core/lzw_stream.js + +class LZWStream extends DecodeStream { + constructor(str, maybeLength, earlyChange) { + super(maybeLength); + this.stream = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + const maxLzwDictionarySize = 4096; + const lzwState = { + earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (let i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + } + readBits(n) { + let bitsCached = this.bitsCached; + let cachedData = this.cachedData; + while (bitsCached < n) { + const c = this.stream.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = cachedData << 8 | c; + bitsCached += 8; + } + this.bitsCached = bitsCached -= n; + this.cachedData = cachedData; + this.lastCode = null; + return cachedData >>> bitsCached & (1 << n) - 1; + } + readBlock() { + const blockSize = 512, + decodedSizeDelta = blockSize; + let estimatedDecodedSize = blockSize * 2; + let i, j, q; + const lzwState = this.lzwState; + if (!lzwState) { + return; + } + const earlyChange = lzwState.earlyChange; + let nextCode = lzwState.nextCode; + const dictionaryValues = lzwState.dictionaryValues; + const dictionaryLengths = lzwState.dictionaryLengths; + const dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + let codeLength = lzwState.codeLength; + let prevCode = lzwState.prevCode; + const currentSequence = lzwState.currentSequence; + let currentSequenceLength = lzwState.currentSequenceLength; + let decodedLength = 0; + let currentBufferLength = this.bufferLength; + let buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + for (i = 0; i < blockSize; i++) { + const code = this.readBits(codeLength); + const hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + this.bufferLength = currentBufferLength; + } +} + +;// ./src/core/predictor_stream.js + + + +class PredictorStream extends DecodeStream { + constructor(str, maybeLength, params) { + super(maybeLength); + if (!(params instanceof Dict)) { + return str; + } + const predictor = this.predictor = params.get("Predictor") || 1; + if (predictor <= 1) { + return str; + } + if (predictor !== 2 && (predictor < 10 || predictor > 15)) { + throw new FormatError(`Unsupported predictor: ${predictor}`); + } + this.readBlock = predictor === 2 ? this.readBlockTiff : this.readBlockPng; + this.stream = str; + this.dict = str.dict; + const colors = this.colors = params.get("Colors") || 1; + const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8; + const columns = this.columns = params.get("Columns") || 1; + this.pixBytes = colors * bits + 7 >> 3; + this.rowBytes = columns * colors * bits + 7 >> 3; + return this; + } + readBlockTiff() { + const rowBytes = this.rowBytes; + const bufferLength = this.bufferLength; + const buffer = this.ensureBuffer(bufferLength + rowBytes); + const bits = this.bits; + const colors = this.colors; + const rawBytes = this.stream.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + let inbuf = 0, + outbuf = 0; + let inbits = 0, + outbits = 0; + let pos = bufferLength; + let i; + if (bits === 1 && colors === 1) { + for (i = 0; i < rowBytes; ++i) { + let c = rawBytes[i] ^ inbuf; + c ^= c >> 1; + c ^= c >> 2; + c ^= c >> 4; + inbuf = (c & 1) << 7; + buffer[pos++] = c; + } + } else if (bits === 8) { + for (i = 0; i < colors; ++i) { + buffer[pos++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } + } else if (bits === 16) { + const bytesPerPixel = colors * 2; + for (i = 0; i < bytesPerPixel; ++i) { + buffer[pos++] = rawBytes[i]; + } + for (; i < rowBytes; i += 2) { + const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff); + buffer[pos++] = sum >> 8 & 0xff; + buffer[pos++] = sum & 0xff; + } + } else { + const compArray = new Uint8Array(colors + 1); + const bitMask = (1 << bits) - 1; + let j = 0, + k = bufferLength; + const columns = this.columns; + for (i = 0; i < columns; ++i) { + for (let kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = inbuf << 8 | rawBytes[j++] & 0xff; + inbits += 8; + } + compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask; + inbits -= bits; + outbuf = outbuf << bits | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer[k++] = outbuf >> outbits - 8 & 0xff; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1); + } + } + this.bufferLength += rowBytes; + } + readBlockPng() { + const rowBytes = this.rowBytes; + const pixBytes = this.pixBytes; + const predictor = this.stream.getByte(); + const rawBytes = this.stream.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + const bufferLength = this.bufferLength; + const buffer = this.ensureBuffer(bufferLength + rowBytes); + let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) { + prevRow = new Uint8Array(rowBytes); + } + let i, + j = bufferLength, + up, + c; + switch (predictor) { + case 0: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + break; + case 1: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff; + j++; + } + break; + case 2: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = prevRow[i] + rawBytes[i] & 0xff; + } + break; + case 3: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff; + j++; + } + break; + case 4: + for (i = 0; i < pixBytes; ++i) { + up = prevRow[i]; + c = rawBytes[i]; + buffer[j++] = up + c; + } + for (; i < rowBytes; ++i) { + up = prevRow[i]; + const upLeft = prevRow[i - pixBytes]; + const left = buffer[j - pixBytes]; + const p = left + up - upLeft; + let pa = p - left; + if (pa < 0) { + pa = -pa; + } + let pb = p - up; + if (pb < 0) { + pb = -pb; + } + let pc = p - upLeft; + if (pc < 0) { + pc = -pc; + } + c = rawBytes[i]; + if (pa <= pb && pa <= pc) { + buffer[j++] = left + c; + } else if (pb <= pc) { + buffer[j++] = up + c; + } else { + buffer[j++] = upLeft + c; + } + } + break; + default: + throw new FormatError(`Unsupported predictor: ${predictor}`); + } + this.bufferLength += rowBytes; + } +} + +;// ./src/core/run_length_stream.js + +class RunLengthStream extends DecodeStream { + constructor(str, maybeLength) { + super(maybeLength); + this.stream = str; + this.dict = str.dict; + } + readBlock() { + const repeatHeader = this.stream.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + let buffer; + let bufferLength = this.bufferLength; + let n = repeatHeader[0]; + if (n < 128) { + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + const source = this.stream.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer.fill(repeatHeader[1], bufferLength, bufferLength + n); + bufferLength += n; + } + this.bufferLength = bufferLength; + } +} + +;// ./src/core/parser.js + + + + + + + + + + + + + + +const MAX_LENGTH_TO_CACHE = 1000; +function getInlineImageCacheKey(bytes) { + const strBuf = [], + ii = bytes.length; + let i = 0; + while (i < ii - 1) { + strBuf.push(bytes[i++] << 8 | bytes[i++]); + } + if (i < ii) { + strBuf.push(bytes[i]); + } + return ii + "_" + String.fromCharCode.apply(null, strBuf); +} +class Parser { + constructor({ + lexer, + xref, + allowStreams = false, + recoveryMode = false + }) { + this.lexer = lexer; + this.xref = xref; + this.allowStreams = allowStreams; + this.recoveryMode = recoveryMode; + this.imageCache = Object.create(null); + this._imageId = 0; + this.refill(); + } + refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + } + shift() { + if (this.buf2 instanceof Cmd && this.buf2.cmd === "ID") { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + } + tryShift() { + try { + this.shift(); + return true; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + return false; + } + } + getObj(cipherTransform = null) { + const buf1 = this.buf1; + this.shift(); + if (buf1 instanceof Cmd) { + switch (buf1.cmd) { + case "BI": + return this.makeInlineImage(cipherTransform); + case "[": + const array = []; + while (!isCmd(this.buf1, "]") && this.buf1 !== EOF) { + array.push(this.getObj(cipherTransform)); + } + if (this.buf1 === EOF) { + if (this.recoveryMode) { + return array; + } + throw new ParserEOFException("End of file inside array."); + } + this.shift(); + return array; + case "<<": + const dict = new Dict(this.xref); + while (!isCmd(this.buf1, ">>") && this.buf1 !== EOF) { + if (!(this.buf1 instanceof Name)) { + info("Malformed dictionary: key must be a name object"); + this.shift(); + continue; + } + const key = this.buf1.name; + this.shift(); + if (this.buf1 === EOF) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + if (this.buf1 === EOF) { + if (this.recoveryMode) { + return dict; + } + throw new ParserEOFException("End of file inside dictionary."); + } + if (isCmd(this.buf2, "stream")) { + return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict; + } + this.shift(); + return dict; + default: + return buf1; + } + } + if (Number.isInteger(buf1)) { + if (Number.isInteger(this.buf1) && isCmd(this.buf2, "R")) { + const ref = Ref.get(buf1, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return buf1; + } + if (typeof buf1 === "string") { + if (cipherTransform) { + return cipherTransform.decryptString(buf1); + } + return buf1; + } + return buf1; + } + findDefaultInlineStreamEnd(stream) { + const E = 0x45, + I = 0x49, + SPACE = 0x20, + LF = 0xa, + CR = 0xd, + NUL = 0x0; + const { + knownCommands + } = this.lexer, + startPos = stream.pos, + n = 15; + let state = 0, + ch, + maybeEIPos; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = ch === E ? 1 : 0; + } else if (state === 1) { + state = ch === I ? 2 : 0; + } else { + if (ch === SPACE || ch === LF || ch === CR) { + maybeEIPos = stream.pos; + const followingBytes = stream.peekBytes(n); + const ii = followingBytes.length; + if (ii === 0) { + break; + } + for (let i = 0; i < ii; i++) { + ch = followingBytes[i]; + if (ch === NUL && followingBytes[i + 1] !== NUL) { + continue; + } + if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7f)) { + state = 0; + break; + } + } + if (state !== 2) { + continue; + } + if (!knownCommands) { + warn("findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined."); + continue; + } + const tmpLexer = new Lexer(new Stream(stream.peekBytes(5 * n)), knownCommands); + tmpLexer._hexStringWarn = () => {}; + let numArgs = 0; + while (true) { + const nextObj = tmpLexer.getObj(); + if (nextObj === EOF) { + state = 0; + break; + } + if (nextObj instanceof Cmd) { + const knownCommand = knownCommands[nextObj.cmd]; + if (!knownCommand) { + state = 0; + break; + } else if (knownCommand.variableArgs ? numArgs <= knownCommand.numArgs : numArgs === knownCommand.numArgs) { + break; + } + numArgs = 0; + continue; + } + numArgs++; + } + if (state === 2) { + break; + } + } else { + state = 0; + } + } + } + if (ch === -1) { + warn("findDefaultInlineStreamEnd: " + "Reached the end of the stream without finding a valid EI marker"); + if (maybeEIPos) { + warn('... trying to recover by using the last "EI" occurrence.'); + stream.skip(-(stream.pos - maybeEIPos)); + } + } + let endOffset = 4; + stream.skip(-endOffset); + ch = stream.peekByte(); + stream.skip(endOffset); + if (!isWhiteSpace(ch)) { + endOffset--; + } + return stream.pos - endOffset - startPos; + } + findDCTDecodeInlineStreamEnd(stream) { + const startPos = stream.pos; + let foundEOI = false, + b, + markerLength; + while ((b = stream.getByte()) !== -1) { + if (b !== 0xff) { + continue; + } + switch (stream.getByte()) { + case 0x00: + break; + case 0xff: + stream.skip(-1); + break; + case 0xd9: + foundEOI = true; + break; + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcd: + case 0xce: + case 0xcf: + case 0xc4: + case 0xcc: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: + case 0xec: + case 0xed: + case 0xee: + case 0xef: + case 0xfe: + markerLength = stream.getUint16(); + if (markerLength > 2) { + stream.skip(markerLength - 2); + } else { + stream.skip(-2); + } + break; + } + if (foundEOI) { + break; + } + } + const length = stream.pos - startPos; + if (b === -1) { + warn("Inline DCTDecode image stream: " + "EOI marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + findASCII85DecodeInlineStreamEnd(stream) { + const TILDE = 0x7e, + GT = 0x3e; + const startPos = stream.pos; + let ch; + while ((ch = stream.getByte()) !== -1) { + if (ch === TILDE) { + const tildePos = stream.pos; + ch = stream.peekByte(); + while (isWhiteSpace(ch)) { + stream.skip(); + ch = stream.peekByte(); + } + if (ch === GT) { + stream.skip(); + break; + } + if (stream.pos > tildePos) { + const maybeEI = stream.peekBytes(2); + if (maybeEI[0] === 0x45 && maybeEI[1] === 0x49) { + break; + } + } + } + } + const length = stream.pos - startPos; + if (ch === -1) { + warn("Inline ASCII85Decode image stream: " + "EOD marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + findASCIIHexDecodeInlineStreamEnd(stream) { + const GT = 0x3e; + const startPos = stream.pos; + let ch; + while ((ch = stream.getByte()) !== -1) { + if (ch === GT) { + break; + } + } + const length = stream.pos - startPos; + if (ch === -1) { + warn("Inline ASCIIHexDecode image stream: " + "EOD marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + inlineStreamSkipEI(stream) { + const E = 0x45, + I = 0x49; + let state = 0, + ch; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = ch === E ? 1 : 0; + } else if (state === 1) { + state = ch === I ? 2 : 0; + } else if (state === 2) { + break; + } + } + } + makeInlineImage(cipherTransform) { + const lexer = this.lexer; + const stream = lexer.stream; + const dictMap = Object.create(null); + let dictLength; + while (!isCmd(this.buf1, "ID") && this.buf1 !== EOF) { + if (!(this.buf1 instanceof Name)) { + throw new FormatError("Dictionary key must be a name object"); + } + const key = this.buf1.name; + this.shift(); + if (this.buf1 === EOF) { + break; + } + dictMap[key] = this.getObj(cipherTransform); + } + if (lexer.beginInlineImagePos !== -1) { + dictLength = stream.pos - lexer.beginInlineImagePos; + } + const filter = this.xref.fetchIfRef(dictMap.F || dictMap.Filter); + let filterName; + if (filter instanceof Name) { + filterName = filter.name; + } else if (Array.isArray(filter)) { + const filterZero = this.xref.fetchIfRef(filter[0]); + if (filterZero instanceof Name) { + filterName = filterZero.name; + } + } + const startPos = stream.pos; + let length; + switch (filterName) { + case "DCT": + case "DCTDecode": + length = this.findDCTDecodeInlineStreamEnd(stream); + break; + case "A85": + case "ASCII85Decode": + length = this.findASCII85DecodeInlineStreamEnd(stream); + break; + case "AHx": + case "ASCIIHexDecode": + length = this.findASCIIHexDecodeInlineStreamEnd(stream); + break; + default: + length = this.findDefaultInlineStreamEnd(stream); + } + let cacheKey; + if (length < MAX_LENGTH_TO_CACHE && dictLength > 0) { + const initialStreamPos = stream.pos; + stream.pos = lexer.beginInlineImagePos; + cacheKey = getInlineImageCacheKey(stream.getBytes(dictLength + length)); + stream.pos = initialStreamPos; + const cacheEntry = this.imageCache[cacheKey]; + if (cacheEntry !== undefined) { + this.buf2 = Cmd.get("EI"); + this.shift(); + cacheEntry.reset(); + return cacheEntry; + } + } + const dict = new Dict(this.xref); + for (const key in dictMap) { + dict.set(key, dictMap[key]); + } + let imageStream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) { + imageStream = cipherTransform.createStream(imageStream, length); + } + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + if (cacheKey !== undefined) { + imageStream.cacheKey = `inline_img_${++this._imageId}`; + this.imageCache[cacheKey] = imageStream; + } + this.buf2 = Cmd.get("EI"); + this.shift(); + return imageStream; + } + #findStreamLength(startPos) { + const { + stream + } = this.lexer; + stream.pos = startPos; + const SCAN_BLOCK_LENGTH = 2048; + const signatureLength = "endstream".length; + const END_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64]); + const endLength = END_SIGNATURE.length; + const PARTIAL_SIGNATURE = [new Uint8Array([0x73, 0x74, 0x72, 0x65, 0x61, 0x6d]), new Uint8Array([0x73, 0x74, 0x65, 0x61, 0x6d]), new Uint8Array([0x73, 0x74, 0x72, 0x65, 0x61])]; + const normalLength = signatureLength - endLength; + while (stream.pos < stream.end) { + const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); + const scanLength = scanBytes.length - signatureLength; + if (scanLength <= 0) { + break; + } + let pos = 0; + while (pos < scanLength) { + let j = 0; + while (j < endLength && scanBytes[pos + j] === END_SIGNATURE[j]) { + j++; + } + if (j >= endLength) { + let found = false; + for (const part of PARTIAL_SIGNATURE) { + const partLen = part.length; + let k = 0; + while (k < partLen && scanBytes[pos + j + k] === part[k]) { + k++; + } + if (k >= normalLength) { + found = true; + break; + } + if (k >= partLen) { + const lastByte = scanBytes[pos + j + k]; + if (isWhiteSpace(lastByte)) { + info(`Found "${bytesToString([...END_SIGNATURE, ...part])}" when ` + "searching for endstream command."); + found = true; + } + break; + } + } + if (found) { + stream.pos += pos; + return stream.pos - startPos; + } + } + pos++; + } + stream.pos += scanLength; + } + return -1; + } + makeStream(dict, cipherTransform) { + const lexer = this.lexer; + let stream = lexer.stream; + lexer.skipToNextLine(); + const startPos = stream.pos - 1; + let length = dict.get("Length"); + if (!Number.isInteger(length)) { + info(`Bad length "${length && length.toString()}" in stream.`); + length = 0; + } + stream.pos = startPos + length; + lexer.nextChar(); + if (this.tryShift() && isCmd(this.buf2, "endstream")) { + this.shift(); + } else { + length = this.#findStreamLength(startPos); + if (length < 0) { + throw new FormatError("Missing endstream command."); + } + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); + stream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) { + stream = cipherTransform.createStream(stream, length); + } + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + } + filter(stream, dict, length) { + let filter = dict.get("F", "Filter"); + let params = dict.get("DP", "DecodeParms"); + if (filter instanceof Name) { + if (Array.isArray(params)) { + warn("/DecodeParms should not be an Array, when /Filter is a Name."); + } + return this.makeFilter(stream, filter.name, length, params); + } + let maybeLength = length; + if (Array.isArray(filter)) { + const filterArray = filter; + const paramsArray = params; + for (let i = 0, ii = filterArray.length; i < ii; ++i) { + filter = this.xref.fetchIfRef(filterArray[i]); + if (!(filter instanceof Name)) { + throw new FormatError(`Bad filter name "${filter}"`); + } + params = null; + if (Array.isArray(paramsArray) && i in paramsArray) { + params = this.xref.fetchIfRef(paramsArray[i]); + } + stream = this.makeFilter(stream, filter.name, maybeLength, params); + maybeLength = null; + } + } + return stream; + } + makeFilter(stream, name, maybeLength, params) { + if (maybeLength === 0) { + warn(`Empty "${name}" stream.`); + return new NullStream(); + } + try { + switch (name) { + case "Fl": + case "FlateDecode": + if (params) { + return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params); + } + return new FlateStream(stream, maybeLength); + case "LZW": + case "LZWDecode": + let earlyChange = 1; + if (params) { + if (params.has("EarlyChange")) { + earlyChange = params.get("EarlyChange"); + } + return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params); + } + return new LZWStream(stream, maybeLength, earlyChange); + case "DCT": + case "DCTDecode": + return new JpegStream(stream, maybeLength, params); + case "JPX": + case "JPXDecode": + return new JpxStream(stream, maybeLength, params); + case "A85": + case "ASCII85Decode": + return new Ascii85Stream(stream, maybeLength); + case "AHx": + case "ASCIIHexDecode": + return new AsciiHexStream(stream, maybeLength); + case "CCF": + case "CCITTFaxDecode": + return new CCITTFaxStream(stream, maybeLength, params); + case "RL": + case "RunLengthDecode": + return new RunLengthStream(stream, maybeLength); + case "JBIG2Decode": + return new Jbig2Stream(stream, maybeLength, params); + } + warn(`Filter "${name}" is not supported.`); + return stream; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`Invalid stream: "${ex}"`); + return new NullStream(); + } + } +} +const specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; +function toHexDigit(ch) { + if (ch >= 0x30 && ch <= 0x39) { + return ch & 0x0f; + } + if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { + return (ch & 0x0f) + 9; + } + return -1; +} +class Lexer { + constructor(stream, knownCommands = null) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + this.knownCommands = knownCommands; + this._hexStringNumWarn = 0; + this.beginInlineImagePos = -1; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + peekChar() { + return this.stream.peekByte(); + } + getNumber() { + let ch = this.currentChar; + let eNotation = false; + let divideBy = 0; + let sign = 1; + if (ch === 0x2d) { + sign = -1; + ch = this.nextChar(); + if (ch === 0x2d) { + ch = this.nextChar(); + } + } else if (ch === 0x2b) { + ch = this.nextChar(); + } + if (ch === 0x0a || ch === 0x0d) { + do { + ch = this.nextChar(); + } while (ch === 0x0a || ch === 0x0d); + } + if (ch === 0x2e) { + divideBy = 10; + ch = this.nextChar(); + } + if (ch < 0x30 || ch > 0x39) { + const msg = `Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`; + if (isWhiteSpace(ch) || ch === 0x28 || ch === 0x3c || ch === -1) { + info(`Lexer.getNumber - "${msg}".`); + return 0; + } + throw new FormatError(msg); + } + let baseValue = ch - 0x30; + let powerValue = 0; + let powerValueSign = 1; + while ((ch = this.nextChar()) >= 0) { + if (ch >= 0x30 && ch <= 0x39) { + const currentDigit = ch - 0x30; + if (eNotation) { + powerValue = powerValue * 10 + currentDigit; + } else { + if (divideBy !== 0) { + divideBy *= 10; + } + baseValue = baseValue * 10 + currentDigit; + } + } else if (ch === 0x2e) { + if (divideBy === 0) { + divideBy = 1; + } else { + break; + } + } else if (ch === 0x2d) { + warn("Badly formatted number: minus sign in the middle"); + } else if (ch === 0x45 || ch === 0x65) { + ch = this.peekChar(); + if (ch === 0x2b || ch === 0x2d) { + powerValueSign = ch === 0x2d ? -1 : 1; + this.nextChar(); + } else if (ch < 0x30 || ch > 0x39) { + break; + } + eNotation = true; + } else { + break; + } + } + if (divideBy !== 0) { + baseValue /= divideBy; + } + if (eNotation) { + baseValue *= 10 ** (powerValueSign * powerValue); + } + return sign * baseValue; + } + getString() { + let numParen = 1; + let done = false; + const strBuf = this.strBuf; + strBuf.length = 0; + let ch = this.nextChar(); + while (true) { + let charBuffered = false; + switch (ch | 0) { + case -1: + warn("Unterminated string"); + done = true; + break; + case 0x28: + ++numParen; + strBuf.push("("); + break; + case 0x29: + if (--numParen === 0) { + this.nextChar(); + done = true; + } else { + strBuf.push(")"); + } + break; + case 0x5c: + ch = this.nextChar(); + switch (ch) { + case -1: + warn("Unterminated string"); + done = true; + break; + case 0x6e: + strBuf.push("\n"); + break; + case 0x72: + strBuf.push("\r"); + break; + case 0x74: + strBuf.push("\t"); + break; + case 0x62: + strBuf.push("\b"); + break; + case 0x66: + strBuf.push("\f"); + break; + case 0x5c: + case 0x28: + case 0x29: + strBuf.push(String.fromCharCode(ch)); + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + let x = ch & 0x0f; + ch = this.nextChar(); + charBuffered = true; + if (ch >= 0x30 && ch <= 0x37) { + x = (x << 3) + (ch & 0x0f); + ch = this.nextChar(); + if (ch >= 0x30 && ch <= 0x37) { + charBuffered = false; + x = (x << 3) + (ch & 0x0f); + } + } + strBuf.push(String.fromCharCode(x)); + break; + case 0x0d: + if (this.peekChar() === 0x0a) { + this.nextChar(); + } + break; + case 0x0a: + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch = this.nextChar(); + } + } + return strBuf.join(""); + } + getName() { + let ch, previousCh; + const strBuf = this.strBuf; + strBuf.length = 0; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + if (ch === 0x23) { + ch = this.nextChar(); + if (specialChars[ch]) { + warn("Lexer_getName: " + "NUMBER SIGN (#) should be followed by a hexadecimal number."); + strBuf.push("#"); + break; + } + const x = toHexDigit(ch); + if (x !== -1) { + previousCh = ch; + ch = this.nextChar(); + const x2 = toHexDigit(ch); + if (x2 === -1) { + warn(`Lexer_getName: Illegal digit (${String.fromCharCode(ch)}) ` + "in hexadecimal number."); + strBuf.push("#", String.fromCharCode(previousCh)); + if (specialChars[ch]) { + break; + } + strBuf.push(String.fromCharCode(ch)); + continue; + } + strBuf.push(String.fromCharCode(x << 4 | x2)); + } else { + strBuf.push("#", String.fromCharCode(ch)); + } + } else { + strBuf.push(String.fromCharCode(ch)); + } + } + if (strBuf.length > 127) { + warn(`Name token is longer than allowed by the spec: ${strBuf.length}`); + } + return Name.get(strBuf.join("")); + } + _hexStringWarn(ch) { + const MAX_HEX_STRING_NUM_WARN = 5; + if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) { + warn("getHexString - ignoring additional invalid characters."); + return; + } + if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) { + return; + } + warn(`getHexString - ignoring invalid character: ${ch}`); + } + getHexString() { + const strBuf = this.strBuf; + strBuf.length = 0; + let ch = this.currentChar; + let firstDigit = -1, + digit = -1; + this._hexStringNumWarn = 0; + while (true) { + if (ch < 0) { + warn("Unterminated hex string"); + break; + } else if (ch === 0x3e) { + this.nextChar(); + break; + } else if (specialChars[ch] === 1) { + ch = this.nextChar(); + continue; + } else { + digit = toHexDigit(ch); + if (digit === -1) { + this._hexStringWarn(ch); + } else if (firstDigit === -1) { + firstDigit = digit; + } else { + strBuf.push(String.fromCharCode(firstDigit << 4 | digit)); + firstDigit = -1; + } + ch = this.nextChar(); + } + } + if (firstDigit !== -1) { + strBuf.push(String.fromCharCode(firstDigit << 4)); + } + return strBuf.join(""); + } + getObj() { + let comment = false; + let ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0a || ch === 0x0d) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (specialChars[ch] !== 1) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x2b: + case 0x2d: + case 0x2e: + return this.getNumber(); + case 0x28: + return this.getString(); + case 0x2f: + return this.getName(); + case 0x5b: + this.nextChar(); + return Cmd.get("["); + case 0x5d: + this.nextChar(); + return Cmd.get("]"); + case 0x3c: + ch = this.nextChar(); + if (ch === 0x3c) { + this.nextChar(); + return Cmd.get("<<"); + } + return this.getHexString(); + case 0x3e: + ch = this.nextChar(); + if (ch === 0x3e) { + this.nextChar(); + return Cmd.get(">>"); + } + return Cmd.get(">"); + case 0x7b: + this.nextChar(); + return Cmd.get("{"); + case 0x7d: + this.nextChar(); + return Cmd.get("}"); + case 0x29: + this.nextChar(); + throw new FormatError(`Illegal character: ${ch}`); + } + let str = String.fromCharCode(ch); + if (ch < 0x20 || ch > 0x7f) { + const nextCh = this.peekChar(); + if (nextCh >= 0x20 && nextCh <= 0x7f) { + this.nextChar(); + return Cmd.get(str); + } + } + const knownCommands = this.knownCommands; + let knownCommandFound = knownCommands?.[str] !== undefined; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + const possibleCommand = str + String.fromCharCode(ch); + if (knownCommandFound && knownCommands[possibleCommand] === undefined) { + break; + } + if (str.length === 128) { + throw new FormatError(`Command token too long: ${str.length}`); + } + str = possibleCommand; + knownCommandFound = knownCommands?.[str] !== undefined; + } + if (str === "true") { + return true; + } + if (str === "false") { + return false; + } + if (str === "null") { + return null; + } + if (str === "BI") { + this.beginInlineImagePos = this.stream.pos; + } + return Cmd.get(str); + } + skipToNextLine() { + let ch = this.currentChar; + while (ch >= 0) { + if (ch === 0x0d) { + ch = this.nextChar(); + if (ch === 0x0a) { + this.nextChar(); + } + break; + } else if (ch === 0x0a) { + this.nextChar(); + break; + } + ch = this.nextChar(); + } + } +} +class Linearization { + static create(stream) { + function getInt(linDict, name, allowZeroValue = false) { + const obj = linDict.get(name); + if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { + return obj; + } + throw new Error(`The "${name}" parameter in the linearization ` + "dictionary is invalid."); + } + function getHints(linDict) { + const hints = linDict.get("H"); + let hintsLength; + if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) { + for (let index = 0; index < hintsLength; index++) { + const hint = hints[index]; + if (!(Number.isInteger(hint) && hint > 0)) { + throw new Error(`Hint (${index}) in the linearization dictionary is invalid.`); + } + } + return hints; + } + throw new Error("Hint array in the linearization dictionary is invalid."); + } + const parser = new Parser({ + lexer: new Lexer(stream), + xref: null + }); + const obj1 = parser.getObj(); + const obj2 = parser.getObj(); + const obj3 = parser.getObj(); + const linDict = parser.getObj(); + let obj, length; + if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && isCmd(obj3, "obj") && linDict instanceof Dict && typeof (obj = linDict.get("Linearized")) === "number" && obj > 0)) { + return null; + } else if ((length = getInt(linDict, "L")) !== stream.length) { + throw new Error('The "L" parameter in the linearization dictionary ' + "does not equal the stream length."); + } + return { + length, + hints: getHints(linDict), + objectNumberFirst: getInt(linDict, "O"), + endFirst: getInt(linDict, "E"), + numPages: getInt(linDict, "N"), + mainXRefEntriesOffset: getInt(linDict, "T"), + pageFirst: linDict.has("P") ? getInt(linDict, "P", true) : 0 + }; + } +} + +;// ./src/core/cmap.js + + + + + + + +const BUILT_IN_CMAPS = ["Adobe-GB1-UCS2", "Adobe-CNS1-UCS2", "Adobe-Japan1-UCS2", "Adobe-Korea1-UCS2", "78-EUC-H", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-CNS1-0", "Adobe-CNS1-1", "Adobe-CNS1-2", "Adobe-CNS1-3", "Adobe-CNS1-4", "Adobe-CNS1-5", "Adobe-CNS1-6", "Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2", "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Korea1-0", "Adobe-Korea1-1", "Adobe-Korea1-2", "B5-H", "B5-V", "B5pc-H", "B5pc-V", "CNS-EUC-H", "CNS-EUC-V", "CNS1-H", "CNS1-V", "CNS2-H", "CNS2-V", "ETHK-B5-H", "ETHK-B5-V", "ETen-B5-H", "ETen-B5-V", "ETenms-B5-H", "ETenms-B5-V", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "H", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V", "HKm471-B5-H", "HKm471-B5-V", "HKscs-B5-H", "HKscs-B5-V", "Hankaku", "Hiragana", "KSC-EUC-H", "KSC-EUC-V", "KSC-H", "KSC-Johab-H", "KSC-Johab-V", "KSC-V", "KSCms-UHC-H", "KSCms-UHC-HW-H", "KSCms-UHC-HW-V", "KSCms-UHC-V", "KSCpc-EUC-H", "KSCpc-EUC-V", "Katakana", "NWP-H", "NWP-V", "RKSJ-H", "RKSJ-V", "Roman", "UniCNS-UCS2-H", "UniCNS-UCS2-V", "UniCNS-UTF16-H", "UniCNS-UTF16-V", "UniCNS-UTF32-H", "UniCNS-UTF32-V", "UniCNS-UTF8-H", "UniCNS-UTF8-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "UniJIS-UCS2-H", "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V", "UniJIS-UCS2-V", "UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS-UTF32-H", "UniJIS-UTF32-V", "UniJIS-UTF8-H", "UniJIS-UTF8-V", "UniJIS2004-UTF16-H", "UniJIS2004-UTF16-V", "UniJIS2004-UTF32-H", "UniJIS2004-UTF32-V", "UniJIS2004-UTF8-H", "UniJIS2004-UTF8-V", "UniJISPro-UCS2-HW-V", "UniJISPro-UCS2-V", "UniJISPro-UTF8-V", "UniJISX0213-UTF32-H", "UniJISX0213-UTF32-V", "UniJISX02132004-UTF32-H", "UniJISX02132004-UTF32-V", "UniKS-UCS2-H", "UniKS-UCS2-V", "UniKS-UTF16-H", "UniKS-UTF16-V", "UniKS-UTF32-H", "UniKS-UTF32-V", "UniKS-UTF8-H", "UniKS-UTF8-V", "V", "WP-Symbol"]; +const MAX_MAP_RANGE = 2 ** 24 - 1; +class CMap { + constructor(builtInCMap = false) { + this.codespaceRanges = [[], [], [], []]; + this.numCodespaceRanges = 0; + this._map = []; + this.name = ""; + this.vertical = false; + this.useCMap = null; + this.builtInCMap = builtInCMap; + } + addCodespaceRange(n, low, high) { + this.codespaceRanges[n - 1].push(low, high); + this.numCodespaceRanges++; + } + mapCidRange(low, high, dstLow) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapCidRange - ignoring data above MAX_MAP_RANGE."); + } + while (low <= high) { + this._map[low++] = dstLow++; + } + } + mapBfRange(low, high, dstLow) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapBfRange - ignoring data above MAX_MAP_RANGE."); + } + const lastByte = dstLow.length - 1; + while (low <= high) { + this._map[low++] = dstLow; + const nextCharCode = dstLow.charCodeAt(lastByte) + 1; + if (nextCharCode > 0xff) { + dstLow = dstLow.substring(0, lastByte - 1) + String.fromCharCode(dstLow.charCodeAt(lastByte - 1) + 1) + "\x00"; + continue; + } + dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(nextCharCode); + } + } + mapBfRangeToArray(low, high, array) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapBfRangeToArray - ignoring data above MAX_MAP_RANGE."); + } + const ii = array.length; + let i = 0; + while (low <= high && i < ii) { + this._map[low] = array[i++]; + ++low; + } + } + mapOne(src, dst) { + this._map[src] = dst; + } + lookup(code) { + return this._map[code]; + } + contains(code) { + return this._map[code] !== undefined; + } + forEach(callback) { + const map = this._map; + const length = map.length; + if (length <= 0x10000) { + for (let i = 0; i < length; i++) { + if (map[i] !== undefined) { + callback(i, map[i]); + } + } + } else { + for (const i in map) { + callback(i, map[i]); + } + } + } + charCodeOf(value) { + const map = this._map; + if (map.length <= 0x10000) { + return map.indexOf(value); + } + for (const charCode in map) { + if (map[charCode] === value) { + return charCode | 0; + } + } + return -1; + } + getMap() { + return this._map; + } + readCharCode(str, offset, out) { + let c = 0; + const codespaceRanges = this.codespaceRanges; + for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { + c = (c << 8 | str.charCodeAt(offset + n)) >>> 0; + const codespaceRange = codespaceRanges[n]; + for (let k = 0, kk = codespaceRange.length; k < kk;) { + const low = codespaceRange[k++]; + const high = codespaceRange[k++]; + if (c >= low && c <= high) { + out.charcode = c; + out.length = n + 1; + return; + } + } + } + out.charcode = 0; + out.length = 1; + } + getCharCodeLength(charCode) { + const codespaceRanges = this.codespaceRanges; + for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { + const codespaceRange = codespaceRanges[n]; + for (let k = 0, kk = codespaceRange.length; k < kk;) { + const low = codespaceRange[k++]; + const high = codespaceRange[k++]; + if (charCode >= low && charCode <= high) { + return n + 1; + } + } + } + return 1; + } + get length() { + return this._map.length; + } + get isIdentityCMap() { + if (!(this.name === "Identity-H" || this.name === "Identity-V")) { + return false; + } + if (this._map.length !== 0x10000) { + return false; + } + for (let i = 0; i < 0x10000; i++) { + if (this._map[i] !== i) { + return false; + } + } + return true; + } +} +class IdentityCMap extends CMap { + constructor(vertical, n) { + super(); + this.vertical = vertical; + this.addCodespaceRange(n, 0, 0xffff); + } + mapCidRange(low, high, dstLow) { + unreachable("should not call mapCidRange"); + } + mapBfRange(low, high, dstLow) { + unreachable("should not call mapBfRange"); + } + mapBfRangeToArray(low, high, array) { + unreachable("should not call mapBfRangeToArray"); + } + mapOne(src, dst) { + unreachable("should not call mapCidOne"); + } + lookup(code) { + return Number.isInteger(code) && code <= 0xffff ? code : undefined; + } + contains(code) { + return Number.isInteger(code) && code <= 0xffff; + } + forEach(callback) { + for (let i = 0; i <= 0xffff; i++) { + callback(i, i); + } + } + charCodeOf(value) { + return Number.isInteger(value) && value <= 0xffff ? value : -1; + } + getMap() { + const map = new Array(0x10000); + for (let i = 0; i <= 0xffff; i++) { + map[i] = i; + } + return map; + } + get length() { + return 0x10000; + } + get isIdentityCMap() { + unreachable("should not access .isIdentityCMap"); + } +} +function strToInt(str) { + let a = 0; + for (let i = 0; i < str.length; i++) { + a = a << 8 | str.charCodeAt(i); + } + return a >>> 0; +} +function expectString(obj) { + if (typeof obj !== "string") { + throw new FormatError("Malformed CMap: expected string."); + } +} +function expectInt(obj) { + if (!Number.isInteger(obj)) { + throw new FormatError("Malformed CMap: expected int."); + } +} +function parseBfChar(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endbfchar")) { + return; + } + expectString(obj); + const src = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + const dst = obj; + cMap.mapOne(src, dst); + } +} +function parseBfRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endbfrange")) { + return; + } + expectString(obj); + const low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + const high = strToInt(obj); + obj = lexer.getObj(); + if (Number.isInteger(obj) || typeof obj === "string") { + const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj, "[")) { + obj = lexer.getObj(); + const array = []; + while (!isCmd(obj, "]") && obj !== EOF) { + array.push(obj); + obj = lexer.getObj(); + } + cMap.mapBfRangeToArray(low, high, array); + } else { + break; + } + } + throw new FormatError("Invalid bf range."); +} +function parseCidChar(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcidchar")) { + return; + } + expectString(obj); + const src = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + const dst = obj; + cMap.mapOne(src, dst); + } +} +function parseCidRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcidrange")) { + return; + } + expectString(obj); + const low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + const high = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + const dstLow = obj; + cMap.mapCidRange(low, high, dstLow); + } +} +function parseCodespaceRange(cMap, lexer) { + while (true) { + let obj = lexer.getObj(); + if (obj === EOF) { + break; + } + if (isCmd(obj, "endcodespacerange")) { + return; + } + if (typeof obj !== "string") { + break; + } + const low = strToInt(obj); + obj = lexer.getObj(); + if (typeof obj !== "string") { + break; + } + const high = strToInt(obj); + cMap.addCodespaceRange(obj.length, low, high); + } + throw new FormatError("Invalid codespace range."); +} +function parseWMode(cMap, lexer) { + const obj = lexer.getObj(); + if (Number.isInteger(obj)) { + cMap.vertical = !!obj; + } +} +function parseCMapName(cMap, lexer) { + const obj = lexer.getObj(); + if (obj instanceof Name) { + cMap.name = obj.name; + } +} +async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { + let previous, embeddedUseCMap; + objLoop: while (true) { + try { + const obj = lexer.getObj(); + if (obj === EOF) { + break; + } else if (obj instanceof Name) { + if (obj.name === "WMode") { + parseWMode(cMap, lexer); + } else if (obj.name === "CMapName") { + parseCMapName(cMap, lexer); + } + previous = obj; + } else if (obj instanceof Cmd) { + switch (obj.cmd) { + case "endcmap": + break objLoop; + case "usecmap": + if (previous instanceof Name) { + embeddedUseCMap = previous.name; + } + break; + case "begincodespacerange": + parseCodespaceRange(cMap, lexer); + break; + case "beginbfchar": + parseBfChar(cMap, lexer); + break; + case "begincidchar": + parseCidChar(cMap, lexer); + break; + case "beginbfrange": + parseBfRange(cMap, lexer); + break; + case "begincidrange": + parseCidRange(cMap, lexer); + break; + } + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Invalid cMap data: " + ex); + continue; + } + } + if (!useCMap && embeddedUseCMap) { + useCMap = embeddedUseCMap; + } + if (useCMap) { + return extendCMap(cMap, fetchBuiltInCMap, useCMap); + } + return cMap; +} +async function extendCMap(cMap, fetchBuiltInCMap, useCMap) { + cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap); + if (cMap.numCodespaceRanges === 0) { + const useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (let i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); + } + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + cMap.useCMap.forEach(function (key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, value); + } + }); + return cMap; +} +async function createBuiltInCMap(name, fetchBuiltInCMap) { + if (name === "Identity-H") { + return new IdentityCMap(false, 2); + } else if (name === "Identity-V") { + return new IdentityCMap(true, 2); + } + if (!BUILT_IN_CMAPS.includes(name)) { + throw new Error("Unknown CMap name: " + name); + } + if (!fetchBuiltInCMap) { + throw new Error("Built-in CMap parameters are not provided."); + } + const { + cMapData, + isCompressed + } = await fetchBuiltInCMap(name); + const cMap = new CMap(true); + if (isCompressed) { + return new BinaryCMapReader().process(cMapData, cMap, useCMap => extendCMap(cMap, fetchBuiltInCMap, useCMap)); + } + const lexer = new Lexer(new Stream(cMapData)); + return parseCMap(cMap, lexer, fetchBuiltInCMap, null); +} +class CMapFactory { + static async create({ + encoding, + fetchBuiltInCMap, + useCMap + }) { + if (encoding instanceof Name) { + return createBuiltInCMap(encoding.name, fetchBuiltInCMap); + } else if (encoding instanceof BaseStream) { + const parsedCMap = await parseCMap(new CMap(), new Lexer(encoding), fetchBuiltInCMap, useCMap); + if (parsedCMap.isIdentityCMap) { + return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); + } + return parsedCMap; + } + throw new Error("Encoding required."); + } +} + +;// ./src/core/encodings.js +const ExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "", "", "", "isuperior", "", "", "lsuperior", "msuperior", "nsuperior", "osuperior", "", "", "rsuperior", "ssuperior", "tsuperior", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdownsmall", "centoldstyle", "Lslashsmall", "", "", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "", "Dotaccentsmall", "", "", "Macronsmall", "", "", "figuredash", "hypheninferior", "", "", "Ogoneksmall", "Ringsmall", "Cedillasmall", "", "", "", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"]; +const MacExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "centoldstyle", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "", "threequartersemdash", "", "questionsmall", "", "", "", "", "Ethsmall", "", "", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "", "", "", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hypheninferior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "asuperior", "centsuperior", "", "", "", "", "Aacutesmall", "Agravesmall", "Acircumflexsmall", "Adieresissmall", "Atildesmall", "Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall", "Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall", "Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall", "Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall", "Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall", "", "eightsuperior", "fourinferior", "threeinferior", "sixinferior", "eightinferior", "seveninferior", "Scaronsmall", "", "centinferior", "twoinferior", "", "Dieresissmall", "", "Caronsmall", "osuperior", "fiveinferior", "", "commainferior", "periodinferior", "Yacutesmall", "", "dollarinferior", "", "", "Thornsmall", "", "nineinferior", "zeroinferior", "Zcaronsmall", "AEsmall", "Oslashsmall", "questiondownsmall", "oneinferior", "Lslashsmall", "", "", "", "", "", "", "Cedillasmall", "", "", "", "", "", "OEsmall", "figuredash", "hyphensuperior", "", "", "", "", "exclamdownsmall", "", "Ydieresissmall", "", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "ninesuperior", "zerosuperior", "", "esuperior", "rsuperior", "tsuperior", "", "", "isuperior", "ssuperior", "dsuperior", "", "", "", "", "", "lsuperior", "Ogoneksmall", "Brevesmall", "Macronsmall", "bsuperior", "nsuperior", "msuperior", "commasuperior", "periodsuperior", "Dotaccentsmall", "Ringsmall", "", "", "", ""]; +const MacRomanEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron"]; +const StandardEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "", "endash", "dagger", "daggerdbl", "periodcentered", "", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "", "questiondown", "", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "", "ring", "cedilla", "", "hungarumlaut", "ogonek", "caron", "emdash", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "AE", "", "ordfeminine", "", "", "", "", "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "", "", "ae", "", "", "", "dotlessi", "", "", "lslash", "oslash", "oe", "germandbls", "", "", "", ""]; +const WinAnsiEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet", "zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered", "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"]; +const SymbolSetEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "universal", "numbersign", "existential", "percent", "ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus", "comma", "minus", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi", "Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa", "Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau", "Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft", "therefore", "bracketright", "perpendicular", "underscore", "radicalex", "alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota", "phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho", "sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta", "braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal", "fraction", "infinity", "florin", "club", "diamond", "heart", "spade", "arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree", "plusminus", "second", "greaterequal", "multiply", "proportional", "partialdiff", "bullet", "divide", "notequal", "equivalence", "approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn", "aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply", "circleplus", "emptyset", "intersection", "union", "propersuperset", "reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element", "notelement", "angle", "gradient", "registerserif", "copyrightserif", "trademarkserif", "product", "radical", "dotmath", "logicalnot", "logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup", "arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans", "copyrightsans", "trademarksans", "summation", "parenlefttp", "parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex", "bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex", "", "angleright", "integral", "integraltp", "integralex", "integralbt", "parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp", "bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid", "bracerightbt", ""]; +const ZapfDingbatsEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117", "a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19", "a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7", "a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36", "a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46", "a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56", "a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75", "a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97", "a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205", "a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103", "a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120", "a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129", "a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138", "a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147", "a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156", "a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165", "a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173", "a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180", "a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185", "a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""]; +function getEncoding(encodingName) { + switch (encodingName) { + case "WinAnsiEncoding": + return WinAnsiEncoding; + case "StandardEncoding": + return StandardEncoding; + case "MacRomanEncoding": + return MacRomanEncoding; + case "SymbolSetEncoding": + return SymbolSetEncoding; + case "ZapfDingbatsEncoding": + return ZapfDingbatsEncoding; + case "ExpertEncoding": + return ExpertEncoding; + case "MacExpertEncoding": + return MacExpertEncoding; + default: + return null; + } +} + +;// ./src/core/glyphlist.js + +const getGlyphsUnicode = getLookupTableFactory(function (t) { + t.A = 0x0041; + t.AE = 0x00c6; + t.AEacute = 0x01fc; + t.AEmacron = 0x01e2; + t.AEsmall = 0xf7e6; + t.Aacute = 0x00c1; + t.Aacutesmall = 0xf7e1; + t.Abreve = 0x0102; + t.Abreveacute = 0x1eae; + t.Abrevecyrillic = 0x04d0; + t.Abrevedotbelow = 0x1eb6; + t.Abrevegrave = 0x1eb0; + t.Abrevehookabove = 0x1eb2; + t.Abrevetilde = 0x1eb4; + t.Acaron = 0x01cd; + t.Acircle = 0x24b6; + t.Acircumflex = 0x00c2; + t.Acircumflexacute = 0x1ea4; + t.Acircumflexdotbelow = 0x1eac; + t.Acircumflexgrave = 0x1ea6; + t.Acircumflexhookabove = 0x1ea8; + t.Acircumflexsmall = 0xf7e2; + t.Acircumflextilde = 0x1eaa; + t.Acute = 0xf6c9; + t.Acutesmall = 0xf7b4; + t.Acyrillic = 0x0410; + t.Adblgrave = 0x0200; + t.Adieresis = 0x00c4; + t.Adieresiscyrillic = 0x04d2; + t.Adieresismacron = 0x01de; + t.Adieresissmall = 0xf7e4; + t.Adotbelow = 0x1ea0; + t.Adotmacron = 0x01e0; + t.Agrave = 0x00c0; + t.Agravesmall = 0xf7e0; + t.Ahookabove = 0x1ea2; + t.Aiecyrillic = 0x04d4; + t.Ainvertedbreve = 0x0202; + t.Alpha = 0x0391; + t.Alphatonos = 0x0386; + t.Amacron = 0x0100; + t.Amonospace = 0xff21; + t.Aogonek = 0x0104; + t.Aring = 0x00c5; + t.Aringacute = 0x01fa; + t.Aringbelow = 0x1e00; + t.Aringsmall = 0xf7e5; + t.Asmall = 0xf761; + t.Atilde = 0x00c3; + t.Atildesmall = 0xf7e3; + t.Aybarmenian = 0x0531; + t.B = 0x0042; + t.Bcircle = 0x24b7; + t.Bdotaccent = 0x1e02; + t.Bdotbelow = 0x1e04; + t.Becyrillic = 0x0411; + t.Benarmenian = 0x0532; + t.Beta = 0x0392; + t.Bhook = 0x0181; + t.Blinebelow = 0x1e06; + t.Bmonospace = 0xff22; + t.Brevesmall = 0xf6f4; + t.Bsmall = 0xf762; + t.Btopbar = 0x0182; + t.C = 0x0043; + t.Caarmenian = 0x053e; + t.Cacute = 0x0106; + t.Caron = 0xf6ca; + t.Caronsmall = 0xf6f5; + t.Ccaron = 0x010c; + t.Ccedilla = 0x00c7; + t.Ccedillaacute = 0x1e08; + t.Ccedillasmall = 0xf7e7; + t.Ccircle = 0x24b8; + t.Ccircumflex = 0x0108; + t.Cdot = 0x010a; + t.Cdotaccent = 0x010a; + t.Cedillasmall = 0xf7b8; + t.Chaarmenian = 0x0549; + t.Cheabkhasiancyrillic = 0x04bc; + t.Checyrillic = 0x0427; + t.Chedescenderabkhasiancyrillic = 0x04be; + t.Chedescendercyrillic = 0x04b6; + t.Chedieresiscyrillic = 0x04f4; + t.Cheharmenian = 0x0543; + t.Chekhakassiancyrillic = 0x04cb; + t.Cheverticalstrokecyrillic = 0x04b8; + t.Chi = 0x03a7; + t.Chook = 0x0187; + t.Circumflexsmall = 0xf6f6; + t.Cmonospace = 0xff23; + t.Coarmenian = 0x0551; + t.Csmall = 0xf763; + t.D = 0x0044; + t.DZ = 0x01f1; + t.DZcaron = 0x01c4; + t.Daarmenian = 0x0534; + t.Dafrican = 0x0189; + t.Dcaron = 0x010e; + t.Dcedilla = 0x1e10; + t.Dcircle = 0x24b9; + t.Dcircumflexbelow = 0x1e12; + t.Dcroat = 0x0110; + t.Ddotaccent = 0x1e0a; + t.Ddotbelow = 0x1e0c; + t.Decyrillic = 0x0414; + t.Deicoptic = 0x03ee; + t.Delta = 0x2206; + t.Deltagreek = 0x0394; + t.Dhook = 0x018a; + t.Dieresis = 0xf6cb; + t.DieresisAcute = 0xf6cc; + t.DieresisGrave = 0xf6cd; + t.Dieresissmall = 0xf7a8; + t.Digammagreek = 0x03dc; + t.Djecyrillic = 0x0402; + t.Dlinebelow = 0x1e0e; + t.Dmonospace = 0xff24; + t.Dotaccentsmall = 0xf6f7; + t.Dslash = 0x0110; + t.Dsmall = 0xf764; + t.Dtopbar = 0x018b; + t.Dz = 0x01f2; + t.Dzcaron = 0x01c5; + t.Dzeabkhasiancyrillic = 0x04e0; + t.Dzecyrillic = 0x0405; + t.Dzhecyrillic = 0x040f; + t.E = 0x0045; + t.Eacute = 0x00c9; + t.Eacutesmall = 0xf7e9; + t.Ebreve = 0x0114; + t.Ecaron = 0x011a; + t.Ecedillabreve = 0x1e1c; + t.Echarmenian = 0x0535; + t.Ecircle = 0x24ba; + t.Ecircumflex = 0x00ca; + t.Ecircumflexacute = 0x1ebe; + t.Ecircumflexbelow = 0x1e18; + t.Ecircumflexdotbelow = 0x1ec6; + t.Ecircumflexgrave = 0x1ec0; + t.Ecircumflexhookabove = 0x1ec2; + t.Ecircumflexsmall = 0xf7ea; + t.Ecircumflextilde = 0x1ec4; + t.Ecyrillic = 0x0404; + t.Edblgrave = 0x0204; + t.Edieresis = 0x00cb; + t.Edieresissmall = 0xf7eb; + t.Edot = 0x0116; + t.Edotaccent = 0x0116; + t.Edotbelow = 0x1eb8; + t.Efcyrillic = 0x0424; + t.Egrave = 0x00c8; + t.Egravesmall = 0xf7e8; + t.Eharmenian = 0x0537; + t.Ehookabove = 0x1eba; + t.Eightroman = 0x2167; + t.Einvertedbreve = 0x0206; + t.Eiotifiedcyrillic = 0x0464; + t.Elcyrillic = 0x041b; + t.Elevenroman = 0x216a; + t.Emacron = 0x0112; + t.Emacronacute = 0x1e16; + t.Emacrongrave = 0x1e14; + t.Emcyrillic = 0x041c; + t.Emonospace = 0xff25; + t.Encyrillic = 0x041d; + t.Endescendercyrillic = 0x04a2; + t.Eng = 0x014a; + t.Enghecyrillic = 0x04a4; + t.Enhookcyrillic = 0x04c7; + t.Eogonek = 0x0118; + t.Eopen = 0x0190; + t.Epsilon = 0x0395; + t.Epsilontonos = 0x0388; + t.Ercyrillic = 0x0420; + t.Ereversed = 0x018e; + t.Ereversedcyrillic = 0x042d; + t.Escyrillic = 0x0421; + t.Esdescendercyrillic = 0x04aa; + t.Esh = 0x01a9; + t.Esmall = 0xf765; + t.Eta = 0x0397; + t.Etarmenian = 0x0538; + t.Etatonos = 0x0389; + t.Eth = 0x00d0; + t.Ethsmall = 0xf7f0; + t.Etilde = 0x1ebc; + t.Etildebelow = 0x1e1a; + t.Euro = 0x20ac; + t.Ezh = 0x01b7; + t.Ezhcaron = 0x01ee; + t.Ezhreversed = 0x01b8; + t.F = 0x0046; + t.Fcircle = 0x24bb; + t.Fdotaccent = 0x1e1e; + t.Feharmenian = 0x0556; + t.Feicoptic = 0x03e4; + t.Fhook = 0x0191; + t.Fitacyrillic = 0x0472; + t.Fiveroman = 0x2164; + t.Fmonospace = 0xff26; + t.Fourroman = 0x2163; + t.Fsmall = 0xf766; + t.G = 0x0047; + t.GBsquare = 0x3387; + t.Gacute = 0x01f4; + t.Gamma = 0x0393; + t.Gammaafrican = 0x0194; + t.Gangiacoptic = 0x03ea; + t.Gbreve = 0x011e; + t.Gcaron = 0x01e6; + t.Gcedilla = 0x0122; + t.Gcircle = 0x24bc; + t.Gcircumflex = 0x011c; + t.Gcommaaccent = 0x0122; + t.Gdot = 0x0120; + t.Gdotaccent = 0x0120; + t.Gecyrillic = 0x0413; + t.Ghadarmenian = 0x0542; + t.Ghemiddlehookcyrillic = 0x0494; + t.Ghestrokecyrillic = 0x0492; + t.Gheupturncyrillic = 0x0490; + t.Ghook = 0x0193; + t.Gimarmenian = 0x0533; + t.Gjecyrillic = 0x0403; + t.Gmacron = 0x1e20; + t.Gmonospace = 0xff27; + t.Grave = 0xf6ce; + t.Gravesmall = 0xf760; + t.Gsmall = 0xf767; + t.Gsmallhook = 0x029b; + t.Gstroke = 0x01e4; + t.H = 0x0048; + t.H18533 = 0x25cf; + t.H18543 = 0x25aa; + t.H18551 = 0x25ab; + t.H22073 = 0x25a1; + t.HPsquare = 0x33cb; + t.Haabkhasiancyrillic = 0x04a8; + t.Hadescendercyrillic = 0x04b2; + t.Hardsigncyrillic = 0x042a; + t.Hbar = 0x0126; + t.Hbrevebelow = 0x1e2a; + t.Hcedilla = 0x1e28; + t.Hcircle = 0x24bd; + t.Hcircumflex = 0x0124; + t.Hdieresis = 0x1e26; + t.Hdotaccent = 0x1e22; + t.Hdotbelow = 0x1e24; + t.Hmonospace = 0xff28; + t.Hoarmenian = 0x0540; + t.Horicoptic = 0x03e8; + t.Hsmall = 0xf768; + t.Hungarumlaut = 0xf6cf; + t.Hungarumlautsmall = 0xf6f8; + t.Hzsquare = 0x3390; + t.I = 0x0049; + t.IAcyrillic = 0x042f; + t.IJ = 0x0132; + t.IUcyrillic = 0x042e; + t.Iacute = 0x00cd; + t.Iacutesmall = 0xf7ed; + t.Ibreve = 0x012c; + t.Icaron = 0x01cf; + t.Icircle = 0x24be; + t.Icircumflex = 0x00ce; + t.Icircumflexsmall = 0xf7ee; + t.Icyrillic = 0x0406; + t.Idblgrave = 0x0208; + t.Idieresis = 0x00cf; + t.Idieresisacute = 0x1e2e; + t.Idieresiscyrillic = 0x04e4; + t.Idieresissmall = 0xf7ef; + t.Idot = 0x0130; + t.Idotaccent = 0x0130; + t.Idotbelow = 0x1eca; + t.Iebrevecyrillic = 0x04d6; + t.Iecyrillic = 0x0415; + t.Ifraktur = 0x2111; + t.Igrave = 0x00cc; + t.Igravesmall = 0xf7ec; + t.Ihookabove = 0x1ec8; + t.Iicyrillic = 0x0418; + t.Iinvertedbreve = 0x020a; + t.Iishortcyrillic = 0x0419; + t.Imacron = 0x012a; + t.Imacroncyrillic = 0x04e2; + t.Imonospace = 0xff29; + t.Iniarmenian = 0x053b; + t.Iocyrillic = 0x0401; + t.Iogonek = 0x012e; + t.Iota = 0x0399; + t.Iotaafrican = 0x0196; + t.Iotadieresis = 0x03aa; + t.Iotatonos = 0x038a; + t.Ismall = 0xf769; + t.Istroke = 0x0197; + t.Itilde = 0x0128; + t.Itildebelow = 0x1e2c; + t.Izhitsacyrillic = 0x0474; + t.Izhitsadblgravecyrillic = 0x0476; + t.J = 0x004a; + t.Jaarmenian = 0x0541; + t.Jcircle = 0x24bf; + t.Jcircumflex = 0x0134; + t.Jecyrillic = 0x0408; + t.Jheharmenian = 0x054b; + t.Jmonospace = 0xff2a; + t.Jsmall = 0xf76a; + t.K = 0x004b; + t.KBsquare = 0x3385; + t.KKsquare = 0x33cd; + t.Kabashkircyrillic = 0x04a0; + t.Kacute = 0x1e30; + t.Kacyrillic = 0x041a; + t.Kadescendercyrillic = 0x049a; + t.Kahookcyrillic = 0x04c3; + t.Kappa = 0x039a; + t.Kastrokecyrillic = 0x049e; + t.Kaverticalstrokecyrillic = 0x049c; + t.Kcaron = 0x01e8; + t.Kcedilla = 0x0136; + t.Kcircle = 0x24c0; + t.Kcommaaccent = 0x0136; + t.Kdotbelow = 0x1e32; + t.Keharmenian = 0x0554; + t.Kenarmenian = 0x053f; + t.Khacyrillic = 0x0425; + t.Kheicoptic = 0x03e6; + t.Khook = 0x0198; + t.Kjecyrillic = 0x040c; + t.Klinebelow = 0x1e34; + t.Kmonospace = 0xff2b; + t.Koppacyrillic = 0x0480; + t.Koppagreek = 0x03de; + t.Ksicyrillic = 0x046e; + t.Ksmall = 0xf76b; + t.L = 0x004c; + t.LJ = 0x01c7; + t.LL = 0xf6bf; + t.Lacute = 0x0139; + t.Lambda = 0x039b; + t.Lcaron = 0x013d; + t.Lcedilla = 0x013b; + t.Lcircle = 0x24c1; + t.Lcircumflexbelow = 0x1e3c; + t.Lcommaaccent = 0x013b; + t.Ldot = 0x013f; + t.Ldotaccent = 0x013f; + t.Ldotbelow = 0x1e36; + t.Ldotbelowmacron = 0x1e38; + t.Liwnarmenian = 0x053c; + t.Lj = 0x01c8; + t.Ljecyrillic = 0x0409; + t.Llinebelow = 0x1e3a; + t.Lmonospace = 0xff2c; + t.Lslash = 0x0141; + t.Lslashsmall = 0xf6f9; + t.Lsmall = 0xf76c; + t.M = 0x004d; + t.MBsquare = 0x3386; + t.Macron = 0xf6d0; + t.Macronsmall = 0xf7af; + t.Macute = 0x1e3e; + t.Mcircle = 0x24c2; + t.Mdotaccent = 0x1e40; + t.Mdotbelow = 0x1e42; + t.Menarmenian = 0x0544; + t.Mmonospace = 0xff2d; + t.Msmall = 0xf76d; + t.Mturned = 0x019c; + t.Mu = 0x039c; + t.N = 0x004e; + t.NJ = 0x01ca; + t.Nacute = 0x0143; + t.Ncaron = 0x0147; + t.Ncedilla = 0x0145; + t.Ncircle = 0x24c3; + t.Ncircumflexbelow = 0x1e4a; + t.Ncommaaccent = 0x0145; + t.Ndotaccent = 0x1e44; + t.Ndotbelow = 0x1e46; + t.Nhookleft = 0x019d; + t.Nineroman = 0x2168; + t.Nj = 0x01cb; + t.Njecyrillic = 0x040a; + t.Nlinebelow = 0x1e48; + t.Nmonospace = 0xff2e; + t.Nowarmenian = 0x0546; + t.Nsmall = 0xf76e; + t.Ntilde = 0x00d1; + t.Ntildesmall = 0xf7f1; + t.Nu = 0x039d; + t.O = 0x004f; + t.OE = 0x0152; + t.OEsmall = 0xf6fa; + t.Oacute = 0x00d3; + t.Oacutesmall = 0xf7f3; + t.Obarredcyrillic = 0x04e8; + t.Obarreddieresiscyrillic = 0x04ea; + t.Obreve = 0x014e; + t.Ocaron = 0x01d1; + t.Ocenteredtilde = 0x019f; + t.Ocircle = 0x24c4; + t.Ocircumflex = 0x00d4; + t.Ocircumflexacute = 0x1ed0; + t.Ocircumflexdotbelow = 0x1ed8; + t.Ocircumflexgrave = 0x1ed2; + t.Ocircumflexhookabove = 0x1ed4; + t.Ocircumflexsmall = 0xf7f4; + t.Ocircumflextilde = 0x1ed6; + t.Ocyrillic = 0x041e; + t.Odblacute = 0x0150; + t.Odblgrave = 0x020c; + t.Odieresis = 0x00d6; + t.Odieresiscyrillic = 0x04e6; + t.Odieresissmall = 0xf7f6; + t.Odotbelow = 0x1ecc; + t.Ogoneksmall = 0xf6fb; + t.Ograve = 0x00d2; + t.Ogravesmall = 0xf7f2; + t.Oharmenian = 0x0555; + t.Ohm = 0x2126; + t.Ohookabove = 0x1ece; + t.Ohorn = 0x01a0; + t.Ohornacute = 0x1eda; + t.Ohorndotbelow = 0x1ee2; + t.Ohorngrave = 0x1edc; + t.Ohornhookabove = 0x1ede; + t.Ohorntilde = 0x1ee0; + t.Ohungarumlaut = 0x0150; + t.Oi = 0x01a2; + t.Oinvertedbreve = 0x020e; + t.Omacron = 0x014c; + t.Omacronacute = 0x1e52; + t.Omacrongrave = 0x1e50; + t.Omega = 0x2126; + t.Omegacyrillic = 0x0460; + t.Omegagreek = 0x03a9; + t.Omegaroundcyrillic = 0x047a; + t.Omegatitlocyrillic = 0x047c; + t.Omegatonos = 0x038f; + t.Omicron = 0x039f; + t.Omicrontonos = 0x038c; + t.Omonospace = 0xff2f; + t.Oneroman = 0x2160; + t.Oogonek = 0x01ea; + t.Oogonekmacron = 0x01ec; + t.Oopen = 0x0186; + t.Oslash = 0x00d8; + t.Oslashacute = 0x01fe; + t.Oslashsmall = 0xf7f8; + t.Osmall = 0xf76f; + t.Ostrokeacute = 0x01fe; + t.Otcyrillic = 0x047e; + t.Otilde = 0x00d5; + t.Otildeacute = 0x1e4c; + t.Otildedieresis = 0x1e4e; + t.Otildesmall = 0xf7f5; + t.P = 0x0050; + t.Pacute = 0x1e54; + t.Pcircle = 0x24c5; + t.Pdotaccent = 0x1e56; + t.Pecyrillic = 0x041f; + t.Peharmenian = 0x054a; + t.Pemiddlehookcyrillic = 0x04a6; + t.Phi = 0x03a6; + t.Phook = 0x01a4; + t.Pi = 0x03a0; + t.Piwrarmenian = 0x0553; + t.Pmonospace = 0xff30; + t.Psi = 0x03a8; + t.Psicyrillic = 0x0470; + t.Psmall = 0xf770; + t.Q = 0x0051; + t.Qcircle = 0x24c6; + t.Qmonospace = 0xff31; + t.Qsmall = 0xf771; + t.R = 0x0052; + t.Raarmenian = 0x054c; + t.Racute = 0x0154; + t.Rcaron = 0x0158; + t.Rcedilla = 0x0156; + t.Rcircle = 0x24c7; + t.Rcommaaccent = 0x0156; + t.Rdblgrave = 0x0210; + t.Rdotaccent = 0x1e58; + t.Rdotbelow = 0x1e5a; + t.Rdotbelowmacron = 0x1e5c; + t.Reharmenian = 0x0550; + t.Rfraktur = 0x211c; + t.Rho = 0x03a1; + t.Ringsmall = 0xf6fc; + t.Rinvertedbreve = 0x0212; + t.Rlinebelow = 0x1e5e; + t.Rmonospace = 0xff32; + t.Rsmall = 0xf772; + t.Rsmallinverted = 0x0281; + t.Rsmallinvertedsuperior = 0x02b6; + t.S = 0x0053; + t.SF010000 = 0x250c; + t.SF020000 = 0x2514; + t.SF030000 = 0x2510; + t.SF040000 = 0x2518; + t.SF050000 = 0x253c; + t.SF060000 = 0x252c; + t.SF070000 = 0x2534; + t.SF080000 = 0x251c; + t.SF090000 = 0x2524; + t.SF100000 = 0x2500; + t.SF110000 = 0x2502; + t.SF190000 = 0x2561; + t.SF200000 = 0x2562; + t.SF210000 = 0x2556; + t.SF220000 = 0x2555; + t.SF230000 = 0x2563; + t.SF240000 = 0x2551; + t.SF250000 = 0x2557; + t.SF260000 = 0x255d; + t.SF270000 = 0x255c; + t.SF280000 = 0x255b; + t.SF360000 = 0x255e; + t.SF370000 = 0x255f; + t.SF380000 = 0x255a; + t.SF390000 = 0x2554; + t.SF400000 = 0x2569; + t.SF410000 = 0x2566; + t.SF420000 = 0x2560; + t.SF430000 = 0x2550; + t.SF440000 = 0x256c; + t.SF450000 = 0x2567; + t.SF460000 = 0x2568; + t.SF470000 = 0x2564; + t.SF480000 = 0x2565; + t.SF490000 = 0x2559; + t.SF500000 = 0x2558; + t.SF510000 = 0x2552; + t.SF520000 = 0x2553; + t.SF530000 = 0x256b; + t.SF540000 = 0x256a; + t.Sacute = 0x015a; + t.Sacutedotaccent = 0x1e64; + t.Sampigreek = 0x03e0; + t.Scaron = 0x0160; + t.Scarondotaccent = 0x1e66; + t.Scaronsmall = 0xf6fd; + t.Scedilla = 0x015e; + t.Schwa = 0x018f; + t.Schwacyrillic = 0x04d8; + t.Schwadieresiscyrillic = 0x04da; + t.Scircle = 0x24c8; + t.Scircumflex = 0x015c; + t.Scommaaccent = 0x0218; + t.Sdotaccent = 0x1e60; + t.Sdotbelow = 0x1e62; + t.Sdotbelowdotaccent = 0x1e68; + t.Seharmenian = 0x054d; + t.Sevenroman = 0x2166; + t.Shaarmenian = 0x0547; + t.Shacyrillic = 0x0428; + t.Shchacyrillic = 0x0429; + t.Sheicoptic = 0x03e2; + t.Shhacyrillic = 0x04ba; + t.Shimacoptic = 0x03ec; + t.Sigma = 0x03a3; + t.Sixroman = 0x2165; + t.Smonospace = 0xff33; + t.Softsigncyrillic = 0x042c; + t.Ssmall = 0xf773; + t.Stigmagreek = 0x03da; + t.T = 0x0054; + t.Tau = 0x03a4; + t.Tbar = 0x0166; + t.Tcaron = 0x0164; + t.Tcedilla = 0x0162; + t.Tcircle = 0x24c9; + t.Tcircumflexbelow = 0x1e70; + t.Tcommaaccent = 0x0162; + t.Tdotaccent = 0x1e6a; + t.Tdotbelow = 0x1e6c; + t.Tecyrillic = 0x0422; + t.Tedescendercyrillic = 0x04ac; + t.Tenroman = 0x2169; + t.Tetsecyrillic = 0x04b4; + t.Theta = 0x0398; + t.Thook = 0x01ac; + t.Thorn = 0x00de; + t.Thornsmall = 0xf7fe; + t.Threeroman = 0x2162; + t.Tildesmall = 0xf6fe; + t.Tiwnarmenian = 0x054f; + t.Tlinebelow = 0x1e6e; + t.Tmonospace = 0xff34; + t.Toarmenian = 0x0539; + t.Tonefive = 0x01bc; + t.Tonesix = 0x0184; + t.Tonetwo = 0x01a7; + t.Tretroflexhook = 0x01ae; + t.Tsecyrillic = 0x0426; + t.Tshecyrillic = 0x040b; + t.Tsmall = 0xf774; + t.Twelveroman = 0x216b; + t.Tworoman = 0x2161; + t.U = 0x0055; + t.Uacute = 0x00da; + t.Uacutesmall = 0xf7fa; + t.Ubreve = 0x016c; + t.Ucaron = 0x01d3; + t.Ucircle = 0x24ca; + t.Ucircumflex = 0x00db; + t.Ucircumflexbelow = 0x1e76; + t.Ucircumflexsmall = 0xf7fb; + t.Ucyrillic = 0x0423; + t.Udblacute = 0x0170; + t.Udblgrave = 0x0214; + t.Udieresis = 0x00dc; + t.Udieresisacute = 0x01d7; + t.Udieresisbelow = 0x1e72; + t.Udieresiscaron = 0x01d9; + t.Udieresiscyrillic = 0x04f0; + t.Udieresisgrave = 0x01db; + t.Udieresismacron = 0x01d5; + t.Udieresissmall = 0xf7fc; + t.Udotbelow = 0x1ee4; + t.Ugrave = 0x00d9; + t.Ugravesmall = 0xf7f9; + t.Uhookabove = 0x1ee6; + t.Uhorn = 0x01af; + t.Uhornacute = 0x1ee8; + t.Uhorndotbelow = 0x1ef0; + t.Uhorngrave = 0x1eea; + t.Uhornhookabove = 0x1eec; + t.Uhorntilde = 0x1eee; + t.Uhungarumlaut = 0x0170; + t.Uhungarumlautcyrillic = 0x04f2; + t.Uinvertedbreve = 0x0216; + t.Ukcyrillic = 0x0478; + t.Umacron = 0x016a; + t.Umacroncyrillic = 0x04ee; + t.Umacrondieresis = 0x1e7a; + t.Umonospace = 0xff35; + t.Uogonek = 0x0172; + t.Upsilon = 0x03a5; + t.Upsilon1 = 0x03d2; + t.Upsilonacutehooksymbolgreek = 0x03d3; + t.Upsilonafrican = 0x01b1; + t.Upsilondieresis = 0x03ab; + t.Upsilondieresishooksymbolgreek = 0x03d4; + t.Upsilonhooksymbol = 0x03d2; + t.Upsilontonos = 0x038e; + t.Uring = 0x016e; + t.Ushortcyrillic = 0x040e; + t.Usmall = 0xf775; + t.Ustraightcyrillic = 0x04ae; + t.Ustraightstrokecyrillic = 0x04b0; + t.Utilde = 0x0168; + t.Utildeacute = 0x1e78; + t.Utildebelow = 0x1e74; + t.V = 0x0056; + t.Vcircle = 0x24cb; + t.Vdotbelow = 0x1e7e; + t.Vecyrillic = 0x0412; + t.Vewarmenian = 0x054e; + t.Vhook = 0x01b2; + t.Vmonospace = 0xff36; + t.Voarmenian = 0x0548; + t.Vsmall = 0xf776; + t.Vtilde = 0x1e7c; + t.W = 0x0057; + t.Wacute = 0x1e82; + t.Wcircle = 0x24cc; + t.Wcircumflex = 0x0174; + t.Wdieresis = 0x1e84; + t.Wdotaccent = 0x1e86; + t.Wdotbelow = 0x1e88; + t.Wgrave = 0x1e80; + t.Wmonospace = 0xff37; + t.Wsmall = 0xf777; + t.X = 0x0058; + t.Xcircle = 0x24cd; + t.Xdieresis = 0x1e8c; + t.Xdotaccent = 0x1e8a; + t.Xeharmenian = 0x053d; + t.Xi = 0x039e; + t.Xmonospace = 0xff38; + t.Xsmall = 0xf778; + t.Y = 0x0059; + t.Yacute = 0x00dd; + t.Yacutesmall = 0xf7fd; + t.Yatcyrillic = 0x0462; + t.Ycircle = 0x24ce; + t.Ycircumflex = 0x0176; + t.Ydieresis = 0x0178; + t.Ydieresissmall = 0xf7ff; + t.Ydotaccent = 0x1e8e; + t.Ydotbelow = 0x1ef4; + t.Yericyrillic = 0x042b; + t.Yerudieresiscyrillic = 0x04f8; + t.Ygrave = 0x1ef2; + t.Yhook = 0x01b3; + t.Yhookabove = 0x1ef6; + t.Yiarmenian = 0x0545; + t.Yicyrillic = 0x0407; + t.Yiwnarmenian = 0x0552; + t.Ymonospace = 0xff39; + t.Ysmall = 0xf779; + t.Ytilde = 0x1ef8; + t.Yusbigcyrillic = 0x046a; + t.Yusbigiotifiedcyrillic = 0x046c; + t.Yuslittlecyrillic = 0x0466; + t.Yuslittleiotifiedcyrillic = 0x0468; + t.Z = 0x005a; + t.Zaarmenian = 0x0536; + t.Zacute = 0x0179; + t.Zcaron = 0x017d; + t.Zcaronsmall = 0xf6ff; + t.Zcircle = 0x24cf; + t.Zcircumflex = 0x1e90; + t.Zdot = 0x017b; + t.Zdotaccent = 0x017b; + t.Zdotbelow = 0x1e92; + t.Zecyrillic = 0x0417; + t.Zedescendercyrillic = 0x0498; + t.Zedieresiscyrillic = 0x04de; + t.Zeta = 0x0396; + t.Zhearmenian = 0x053a; + t.Zhebrevecyrillic = 0x04c1; + t.Zhecyrillic = 0x0416; + t.Zhedescendercyrillic = 0x0496; + t.Zhedieresiscyrillic = 0x04dc; + t.Zlinebelow = 0x1e94; + t.Zmonospace = 0xff3a; + t.Zsmall = 0xf77a; + t.Zstroke = 0x01b5; + t.a = 0x0061; + t.aabengali = 0x0986; + t.aacute = 0x00e1; + t.aadeva = 0x0906; + t.aagujarati = 0x0a86; + t.aagurmukhi = 0x0a06; + t.aamatragurmukhi = 0x0a3e; + t.aarusquare = 0x3303; + t.aavowelsignbengali = 0x09be; + t.aavowelsigndeva = 0x093e; + t.aavowelsigngujarati = 0x0abe; + t.abbreviationmarkarmenian = 0x055f; + t.abbreviationsigndeva = 0x0970; + t.abengali = 0x0985; + t.abopomofo = 0x311a; + t.abreve = 0x0103; + t.abreveacute = 0x1eaf; + t.abrevecyrillic = 0x04d1; + t.abrevedotbelow = 0x1eb7; + t.abrevegrave = 0x1eb1; + t.abrevehookabove = 0x1eb3; + t.abrevetilde = 0x1eb5; + t.acaron = 0x01ce; + t.acircle = 0x24d0; + t.acircumflex = 0x00e2; + t.acircumflexacute = 0x1ea5; + t.acircumflexdotbelow = 0x1ead; + t.acircumflexgrave = 0x1ea7; + t.acircumflexhookabove = 0x1ea9; + t.acircumflextilde = 0x1eab; + t.acute = 0x00b4; + t.acutebelowcmb = 0x0317; + t.acutecmb = 0x0301; + t.acutecomb = 0x0301; + t.acutedeva = 0x0954; + t.acutelowmod = 0x02cf; + t.acutetonecmb = 0x0341; + t.acyrillic = 0x0430; + t.adblgrave = 0x0201; + t.addakgurmukhi = 0x0a71; + t.adeva = 0x0905; + t.adieresis = 0x00e4; + t.adieresiscyrillic = 0x04d3; + t.adieresismacron = 0x01df; + t.adotbelow = 0x1ea1; + t.adotmacron = 0x01e1; + t.ae = 0x00e6; + t.aeacute = 0x01fd; + t.aekorean = 0x3150; + t.aemacron = 0x01e3; + t.afii00208 = 0x2015; + t.afii08941 = 0x20a4; + t.afii10017 = 0x0410; + t.afii10018 = 0x0411; + t.afii10019 = 0x0412; + t.afii10020 = 0x0413; + t.afii10021 = 0x0414; + t.afii10022 = 0x0415; + t.afii10023 = 0x0401; + t.afii10024 = 0x0416; + t.afii10025 = 0x0417; + t.afii10026 = 0x0418; + t.afii10027 = 0x0419; + t.afii10028 = 0x041a; + t.afii10029 = 0x041b; + t.afii10030 = 0x041c; + t.afii10031 = 0x041d; + t.afii10032 = 0x041e; + t.afii10033 = 0x041f; + t.afii10034 = 0x0420; + t.afii10035 = 0x0421; + t.afii10036 = 0x0422; + t.afii10037 = 0x0423; + t.afii10038 = 0x0424; + t.afii10039 = 0x0425; + t.afii10040 = 0x0426; + t.afii10041 = 0x0427; + t.afii10042 = 0x0428; + t.afii10043 = 0x0429; + t.afii10044 = 0x042a; + t.afii10045 = 0x042b; + t.afii10046 = 0x042c; + t.afii10047 = 0x042d; + t.afii10048 = 0x042e; + t.afii10049 = 0x042f; + t.afii10050 = 0x0490; + t.afii10051 = 0x0402; + t.afii10052 = 0x0403; + t.afii10053 = 0x0404; + t.afii10054 = 0x0405; + t.afii10055 = 0x0406; + t.afii10056 = 0x0407; + t.afii10057 = 0x0408; + t.afii10058 = 0x0409; + t.afii10059 = 0x040a; + t.afii10060 = 0x040b; + t.afii10061 = 0x040c; + t.afii10062 = 0x040e; + t.afii10063 = 0xf6c4; + t.afii10064 = 0xf6c5; + t.afii10065 = 0x0430; + t.afii10066 = 0x0431; + t.afii10067 = 0x0432; + t.afii10068 = 0x0433; + t.afii10069 = 0x0434; + t.afii10070 = 0x0435; + t.afii10071 = 0x0451; + t.afii10072 = 0x0436; + t.afii10073 = 0x0437; + t.afii10074 = 0x0438; + t.afii10075 = 0x0439; + t.afii10076 = 0x043a; + t.afii10077 = 0x043b; + t.afii10078 = 0x043c; + t.afii10079 = 0x043d; + t.afii10080 = 0x043e; + t.afii10081 = 0x043f; + t.afii10082 = 0x0440; + t.afii10083 = 0x0441; + t.afii10084 = 0x0442; + t.afii10085 = 0x0443; + t.afii10086 = 0x0444; + t.afii10087 = 0x0445; + t.afii10088 = 0x0446; + t.afii10089 = 0x0447; + t.afii10090 = 0x0448; + t.afii10091 = 0x0449; + t.afii10092 = 0x044a; + t.afii10093 = 0x044b; + t.afii10094 = 0x044c; + t.afii10095 = 0x044d; + t.afii10096 = 0x044e; + t.afii10097 = 0x044f; + t.afii10098 = 0x0491; + t.afii10099 = 0x0452; + t.afii10100 = 0x0453; + t.afii10101 = 0x0454; + t.afii10102 = 0x0455; + t.afii10103 = 0x0456; + t.afii10104 = 0x0457; + t.afii10105 = 0x0458; + t.afii10106 = 0x0459; + t.afii10107 = 0x045a; + t.afii10108 = 0x045b; + t.afii10109 = 0x045c; + t.afii10110 = 0x045e; + t.afii10145 = 0x040f; + t.afii10146 = 0x0462; + t.afii10147 = 0x0472; + t.afii10148 = 0x0474; + t.afii10192 = 0xf6c6; + t.afii10193 = 0x045f; + t.afii10194 = 0x0463; + t.afii10195 = 0x0473; + t.afii10196 = 0x0475; + t.afii10831 = 0xf6c7; + t.afii10832 = 0xf6c8; + t.afii10846 = 0x04d9; + t.afii299 = 0x200e; + t.afii300 = 0x200f; + t.afii301 = 0x200d; + t.afii57381 = 0x066a; + t.afii57388 = 0x060c; + t.afii57392 = 0x0660; + t.afii57393 = 0x0661; + t.afii57394 = 0x0662; + t.afii57395 = 0x0663; + t.afii57396 = 0x0664; + t.afii57397 = 0x0665; + t.afii57398 = 0x0666; + t.afii57399 = 0x0667; + t.afii57400 = 0x0668; + t.afii57401 = 0x0669; + t.afii57403 = 0x061b; + t.afii57407 = 0x061f; + t.afii57409 = 0x0621; + t.afii57410 = 0x0622; + t.afii57411 = 0x0623; + t.afii57412 = 0x0624; + t.afii57413 = 0x0625; + t.afii57414 = 0x0626; + t.afii57415 = 0x0627; + t.afii57416 = 0x0628; + t.afii57417 = 0x0629; + t.afii57418 = 0x062a; + t.afii57419 = 0x062b; + t.afii57420 = 0x062c; + t.afii57421 = 0x062d; + t.afii57422 = 0x062e; + t.afii57423 = 0x062f; + t.afii57424 = 0x0630; + t.afii57425 = 0x0631; + t.afii57426 = 0x0632; + t.afii57427 = 0x0633; + t.afii57428 = 0x0634; + t.afii57429 = 0x0635; + t.afii57430 = 0x0636; + t.afii57431 = 0x0637; + t.afii57432 = 0x0638; + t.afii57433 = 0x0639; + t.afii57434 = 0x063a; + t.afii57440 = 0x0640; + t.afii57441 = 0x0641; + t.afii57442 = 0x0642; + t.afii57443 = 0x0643; + t.afii57444 = 0x0644; + t.afii57445 = 0x0645; + t.afii57446 = 0x0646; + t.afii57448 = 0x0648; + t.afii57449 = 0x0649; + t.afii57450 = 0x064a; + t.afii57451 = 0x064b; + t.afii57452 = 0x064c; + t.afii57453 = 0x064d; + t.afii57454 = 0x064e; + t.afii57455 = 0x064f; + t.afii57456 = 0x0650; + t.afii57457 = 0x0651; + t.afii57458 = 0x0652; + t.afii57470 = 0x0647; + t.afii57505 = 0x06a4; + t.afii57506 = 0x067e; + t.afii57507 = 0x0686; + t.afii57508 = 0x0698; + t.afii57509 = 0x06af; + t.afii57511 = 0x0679; + t.afii57512 = 0x0688; + t.afii57513 = 0x0691; + t.afii57514 = 0x06ba; + t.afii57519 = 0x06d2; + t.afii57534 = 0x06d5; + t.afii57636 = 0x20aa; + t.afii57645 = 0x05be; + t.afii57658 = 0x05c3; + t.afii57664 = 0x05d0; + t.afii57665 = 0x05d1; + t.afii57666 = 0x05d2; + t.afii57667 = 0x05d3; + t.afii57668 = 0x05d4; + t.afii57669 = 0x05d5; + t.afii57670 = 0x05d6; + t.afii57671 = 0x05d7; + t.afii57672 = 0x05d8; + t.afii57673 = 0x05d9; + t.afii57674 = 0x05da; + t.afii57675 = 0x05db; + t.afii57676 = 0x05dc; + t.afii57677 = 0x05dd; + t.afii57678 = 0x05de; + t.afii57679 = 0x05df; + t.afii57680 = 0x05e0; + t.afii57681 = 0x05e1; + t.afii57682 = 0x05e2; + t.afii57683 = 0x05e3; + t.afii57684 = 0x05e4; + t.afii57685 = 0x05e5; + t.afii57686 = 0x05e6; + t.afii57687 = 0x05e7; + t.afii57688 = 0x05e8; + t.afii57689 = 0x05e9; + t.afii57690 = 0x05ea; + t.afii57694 = 0xfb2a; + t.afii57695 = 0xfb2b; + t.afii57700 = 0xfb4b; + t.afii57705 = 0xfb1f; + t.afii57716 = 0x05f0; + t.afii57717 = 0x05f1; + t.afii57718 = 0x05f2; + t.afii57723 = 0xfb35; + t.afii57793 = 0x05b4; + t.afii57794 = 0x05b5; + t.afii57795 = 0x05b6; + t.afii57796 = 0x05bb; + t.afii57797 = 0x05b8; + t.afii57798 = 0x05b7; + t.afii57799 = 0x05b0; + t.afii57800 = 0x05b2; + t.afii57801 = 0x05b1; + t.afii57802 = 0x05b3; + t.afii57803 = 0x05c2; + t.afii57804 = 0x05c1; + t.afii57806 = 0x05b9; + t.afii57807 = 0x05bc; + t.afii57839 = 0x05bd; + t.afii57841 = 0x05bf; + t.afii57842 = 0x05c0; + t.afii57929 = 0x02bc; + t.afii61248 = 0x2105; + t.afii61289 = 0x2113; + t.afii61352 = 0x2116; + t.afii61573 = 0x202c; + t.afii61574 = 0x202d; + t.afii61575 = 0x202e; + t.afii61664 = 0x200c; + t.afii63167 = 0x066d; + t.afii64937 = 0x02bd; + t.agrave = 0x00e0; + t.agujarati = 0x0a85; + t.agurmukhi = 0x0a05; + t.ahiragana = 0x3042; + t.ahookabove = 0x1ea3; + t.aibengali = 0x0990; + t.aibopomofo = 0x311e; + t.aideva = 0x0910; + t.aiecyrillic = 0x04d5; + t.aigujarati = 0x0a90; + t.aigurmukhi = 0x0a10; + t.aimatragurmukhi = 0x0a48; + t.ainarabic = 0x0639; + t.ainfinalarabic = 0xfeca; + t.aininitialarabic = 0xfecb; + t.ainmedialarabic = 0xfecc; + t.ainvertedbreve = 0x0203; + t.aivowelsignbengali = 0x09c8; + t.aivowelsigndeva = 0x0948; + t.aivowelsigngujarati = 0x0ac8; + t.akatakana = 0x30a2; + t.akatakanahalfwidth = 0xff71; + t.akorean = 0x314f; + t.alef = 0x05d0; + t.alefarabic = 0x0627; + t.alefdageshhebrew = 0xfb30; + t.aleffinalarabic = 0xfe8e; + t.alefhamzaabovearabic = 0x0623; + t.alefhamzaabovefinalarabic = 0xfe84; + t.alefhamzabelowarabic = 0x0625; + t.alefhamzabelowfinalarabic = 0xfe88; + t.alefhebrew = 0x05d0; + t.aleflamedhebrew = 0xfb4f; + t.alefmaddaabovearabic = 0x0622; + t.alefmaddaabovefinalarabic = 0xfe82; + t.alefmaksuraarabic = 0x0649; + t.alefmaksurafinalarabic = 0xfef0; + t.alefmaksurainitialarabic = 0xfef3; + t.alefmaksuramedialarabic = 0xfef4; + t.alefpatahhebrew = 0xfb2e; + t.alefqamatshebrew = 0xfb2f; + t.aleph = 0x2135; + t.allequal = 0x224c; + t.alpha = 0x03b1; + t.alphatonos = 0x03ac; + t.amacron = 0x0101; + t.amonospace = 0xff41; + t.ampersand = 0x0026; + t.ampersandmonospace = 0xff06; + t.ampersandsmall = 0xf726; + t.amsquare = 0x33c2; + t.anbopomofo = 0x3122; + t.angbopomofo = 0x3124; + t.angbracketleft = 0x3008; + t.angbracketright = 0x3009; + t.angkhankhuthai = 0x0e5a; + t.angle = 0x2220; + t.anglebracketleft = 0x3008; + t.anglebracketleftvertical = 0xfe3f; + t.anglebracketright = 0x3009; + t.anglebracketrightvertical = 0xfe40; + t.angleleft = 0x2329; + t.angleright = 0x232a; + t.angstrom = 0x212b; + t.anoteleia = 0x0387; + t.anudattadeva = 0x0952; + t.anusvarabengali = 0x0982; + t.anusvaradeva = 0x0902; + t.anusvaragujarati = 0x0a82; + t.aogonek = 0x0105; + t.apaatosquare = 0x3300; + t.aparen = 0x249c; + t.apostrophearmenian = 0x055a; + t.apostrophemod = 0x02bc; + t.apple = 0xf8ff; + t.approaches = 0x2250; + t.approxequal = 0x2248; + t.approxequalorimage = 0x2252; + t.approximatelyequal = 0x2245; + t.araeaekorean = 0x318e; + t.araeakorean = 0x318d; + t.arc = 0x2312; + t.arighthalfring = 0x1e9a; + t.aring = 0x00e5; + t.aringacute = 0x01fb; + t.aringbelow = 0x1e01; + t.arrowboth = 0x2194; + t.arrowdashdown = 0x21e3; + t.arrowdashleft = 0x21e0; + t.arrowdashright = 0x21e2; + t.arrowdashup = 0x21e1; + t.arrowdblboth = 0x21d4; + t.arrowdbldown = 0x21d3; + t.arrowdblleft = 0x21d0; + t.arrowdblright = 0x21d2; + t.arrowdblup = 0x21d1; + t.arrowdown = 0x2193; + t.arrowdownleft = 0x2199; + t.arrowdownright = 0x2198; + t.arrowdownwhite = 0x21e9; + t.arrowheaddownmod = 0x02c5; + t.arrowheadleftmod = 0x02c2; + t.arrowheadrightmod = 0x02c3; + t.arrowheadupmod = 0x02c4; + t.arrowhorizex = 0xf8e7; + t.arrowleft = 0x2190; + t.arrowleftdbl = 0x21d0; + t.arrowleftdblstroke = 0x21cd; + t.arrowleftoverright = 0x21c6; + t.arrowleftwhite = 0x21e6; + t.arrowright = 0x2192; + t.arrowrightdblstroke = 0x21cf; + t.arrowrightheavy = 0x279e; + t.arrowrightoverleft = 0x21c4; + t.arrowrightwhite = 0x21e8; + t.arrowtableft = 0x21e4; + t.arrowtabright = 0x21e5; + t.arrowup = 0x2191; + t.arrowupdn = 0x2195; + t.arrowupdnbse = 0x21a8; + t.arrowupdownbase = 0x21a8; + t.arrowupleft = 0x2196; + t.arrowupleftofdown = 0x21c5; + t.arrowupright = 0x2197; + t.arrowupwhite = 0x21e7; + t.arrowvertex = 0xf8e6; + t.asciicircum = 0x005e; + t.asciicircummonospace = 0xff3e; + t.asciitilde = 0x007e; + t.asciitildemonospace = 0xff5e; + t.ascript = 0x0251; + t.ascriptturned = 0x0252; + t.asmallhiragana = 0x3041; + t.asmallkatakana = 0x30a1; + t.asmallkatakanahalfwidth = 0xff67; + t.asterisk = 0x002a; + t.asteriskaltonearabic = 0x066d; + t.asteriskarabic = 0x066d; + t.asteriskmath = 0x2217; + t.asteriskmonospace = 0xff0a; + t.asterisksmall = 0xfe61; + t.asterism = 0x2042; + t.asuperior = 0xf6e9; + t.asymptoticallyequal = 0x2243; + t.at = 0x0040; + t.atilde = 0x00e3; + t.atmonospace = 0xff20; + t.atsmall = 0xfe6b; + t.aturned = 0x0250; + t.aubengali = 0x0994; + t.aubopomofo = 0x3120; + t.audeva = 0x0914; + t.augujarati = 0x0a94; + t.augurmukhi = 0x0a14; + t.aulengthmarkbengali = 0x09d7; + t.aumatragurmukhi = 0x0a4c; + t.auvowelsignbengali = 0x09cc; + t.auvowelsigndeva = 0x094c; + t.auvowelsigngujarati = 0x0acc; + t.avagrahadeva = 0x093d; + t.aybarmenian = 0x0561; + t.ayin = 0x05e2; + t.ayinaltonehebrew = 0xfb20; + t.ayinhebrew = 0x05e2; + t.b = 0x0062; + t.babengali = 0x09ac; + t.backslash = 0x005c; + t.backslashmonospace = 0xff3c; + t.badeva = 0x092c; + t.bagujarati = 0x0aac; + t.bagurmukhi = 0x0a2c; + t.bahiragana = 0x3070; + t.bahtthai = 0x0e3f; + t.bakatakana = 0x30d0; + t.bar = 0x007c; + t.barmonospace = 0xff5c; + t.bbopomofo = 0x3105; + t.bcircle = 0x24d1; + t.bdotaccent = 0x1e03; + t.bdotbelow = 0x1e05; + t.beamedsixteenthnotes = 0x266c; + t.because = 0x2235; + t.becyrillic = 0x0431; + t.beharabic = 0x0628; + t.behfinalarabic = 0xfe90; + t.behinitialarabic = 0xfe91; + t.behiragana = 0x3079; + t.behmedialarabic = 0xfe92; + t.behmeeminitialarabic = 0xfc9f; + t.behmeemisolatedarabic = 0xfc08; + t.behnoonfinalarabic = 0xfc6d; + t.bekatakana = 0x30d9; + t.benarmenian = 0x0562; + t.bet = 0x05d1; + t.beta = 0x03b2; + t.betasymbolgreek = 0x03d0; + t.betdagesh = 0xfb31; + t.betdageshhebrew = 0xfb31; + t.bethebrew = 0x05d1; + t.betrafehebrew = 0xfb4c; + t.bhabengali = 0x09ad; + t.bhadeva = 0x092d; + t.bhagujarati = 0x0aad; + t.bhagurmukhi = 0x0a2d; + t.bhook = 0x0253; + t.bihiragana = 0x3073; + t.bikatakana = 0x30d3; + t.bilabialclick = 0x0298; + t.bindigurmukhi = 0x0a02; + t.birusquare = 0x3331; + t.blackcircle = 0x25cf; + t.blackdiamond = 0x25c6; + t.blackdownpointingtriangle = 0x25bc; + t.blackleftpointingpointer = 0x25c4; + t.blackleftpointingtriangle = 0x25c0; + t.blacklenticularbracketleft = 0x3010; + t.blacklenticularbracketleftvertical = 0xfe3b; + t.blacklenticularbracketright = 0x3011; + t.blacklenticularbracketrightvertical = 0xfe3c; + t.blacklowerlefttriangle = 0x25e3; + t.blacklowerrighttriangle = 0x25e2; + t.blackrectangle = 0x25ac; + t.blackrightpointingpointer = 0x25ba; + t.blackrightpointingtriangle = 0x25b6; + t.blacksmallsquare = 0x25aa; + t.blacksmilingface = 0x263b; + t.blacksquare = 0x25a0; + t.blackstar = 0x2605; + t.blackupperlefttriangle = 0x25e4; + t.blackupperrighttriangle = 0x25e5; + t.blackuppointingsmalltriangle = 0x25b4; + t.blackuppointingtriangle = 0x25b2; + t.blank = 0x2423; + t.blinebelow = 0x1e07; + t.block = 0x2588; + t.bmonospace = 0xff42; + t.bobaimaithai = 0x0e1a; + t.bohiragana = 0x307c; + t.bokatakana = 0x30dc; + t.bparen = 0x249d; + t.bqsquare = 0x33c3; + t.braceex = 0xf8f4; + t.braceleft = 0x007b; + t.braceleftbt = 0xf8f3; + t.braceleftmid = 0xf8f2; + t.braceleftmonospace = 0xff5b; + t.braceleftsmall = 0xfe5b; + t.bracelefttp = 0xf8f1; + t.braceleftvertical = 0xfe37; + t.braceright = 0x007d; + t.bracerightbt = 0xf8fe; + t.bracerightmid = 0xf8fd; + t.bracerightmonospace = 0xff5d; + t.bracerightsmall = 0xfe5c; + t.bracerighttp = 0xf8fc; + t.bracerightvertical = 0xfe38; + t.bracketleft = 0x005b; + t.bracketleftbt = 0xf8f0; + t.bracketleftex = 0xf8ef; + t.bracketleftmonospace = 0xff3b; + t.bracketlefttp = 0xf8ee; + t.bracketright = 0x005d; + t.bracketrightbt = 0xf8fb; + t.bracketrightex = 0xf8fa; + t.bracketrightmonospace = 0xff3d; + t.bracketrighttp = 0xf8f9; + t.breve = 0x02d8; + t.brevebelowcmb = 0x032e; + t.brevecmb = 0x0306; + t.breveinvertedbelowcmb = 0x032f; + t.breveinvertedcmb = 0x0311; + t.breveinverteddoublecmb = 0x0361; + t.bridgebelowcmb = 0x032a; + t.bridgeinvertedbelowcmb = 0x033a; + t.brokenbar = 0x00a6; + t.bstroke = 0x0180; + t.bsuperior = 0xf6ea; + t.btopbar = 0x0183; + t.buhiragana = 0x3076; + t.bukatakana = 0x30d6; + t.bullet = 0x2022; + t.bulletinverse = 0x25d8; + t.bulletoperator = 0x2219; + t.bullseye = 0x25ce; + t.c = 0x0063; + t.caarmenian = 0x056e; + t.cabengali = 0x099a; + t.cacute = 0x0107; + t.cadeva = 0x091a; + t.cagujarati = 0x0a9a; + t.cagurmukhi = 0x0a1a; + t.calsquare = 0x3388; + t.candrabindubengali = 0x0981; + t.candrabinducmb = 0x0310; + t.candrabindudeva = 0x0901; + t.candrabindugujarati = 0x0a81; + t.capslock = 0x21ea; + t.careof = 0x2105; + t.caron = 0x02c7; + t.caronbelowcmb = 0x032c; + t.caroncmb = 0x030c; + t.carriagereturn = 0x21b5; + t.cbopomofo = 0x3118; + t.ccaron = 0x010d; + t.ccedilla = 0x00e7; + t.ccedillaacute = 0x1e09; + t.ccircle = 0x24d2; + t.ccircumflex = 0x0109; + t.ccurl = 0x0255; + t.cdot = 0x010b; + t.cdotaccent = 0x010b; + t.cdsquare = 0x33c5; + t.cedilla = 0x00b8; + t.cedillacmb = 0x0327; + t.cent = 0x00a2; + t.centigrade = 0x2103; + t.centinferior = 0xf6df; + t.centmonospace = 0xffe0; + t.centoldstyle = 0xf7a2; + t.centsuperior = 0xf6e0; + t.chaarmenian = 0x0579; + t.chabengali = 0x099b; + t.chadeva = 0x091b; + t.chagujarati = 0x0a9b; + t.chagurmukhi = 0x0a1b; + t.chbopomofo = 0x3114; + t.cheabkhasiancyrillic = 0x04bd; + t.checkmark = 0x2713; + t.checyrillic = 0x0447; + t.chedescenderabkhasiancyrillic = 0x04bf; + t.chedescendercyrillic = 0x04b7; + t.chedieresiscyrillic = 0x04f5; + t.cheharmenian = 0x0573; + t.chekhakassiancyrillic = 0x04cc; + t.cheverticalstrokecyrillic = 0x04b9; + t.chi = 0x03c7; + t.chieuchacirclekorean = 0x3277; + t.chieuchaparenkorean = 0x3217; + t.chieuchcirclekorean = 0x3269; + t.chieuchkorean = 0x314a; + t.chieuchparenkorean = 0x3209; + t.chochangthai = 0x0e0a; + t.chochanthai = 0x0e08; + t.chochingthai = 0x0e09; + t.chochoethai = 0x0e0c; + t.chook = 0x0188; + t.cieucacirclekorean = 0x3276; + t.cieucaparenkorean = 0x3216; + t.cieuccirclekorean = 0x3268; + t.cieuckorean = 0x3148; + t.cieucparenkorean = 0x3208; + t.cieucuparenkorean = 0x321c; + t.circle = 0x25cb; + t.circlecopyrt = 0x00a9; + t.circlemultiply = 0x2297; + t.circleot = 0x2299; + t.circleplus = 0x2295; + t.circlepostalmark = 0x3036; + t.circlewithlefthalfblack = 0x25d0; + t.circlewithrighthalfblack = 0x25d1; + t.circumflex = 0x02c6; + t.circumflexbelowcmb = 0x032d; + t.circumflexcmb = 0x0302; + t.clear = 0x2327; + t.clickalveolar = 0x01c2; + t.clickdental = 0x01c0; + t.clicklateral = 0x01c1; + t.clickretroflex = 0x01c3; + t.club = 0x2663; + t.clubsuitblack = 0x2663; + t.clubsuitwhite = 0x2667; + t.cmcubedsquare = 0x33a4; + t.cmonospace = 0xff43; + t.cmsquaredsquare = 0x33a0; + t.coarmenian = 0x0581; + t.colon = 0x003a; + t.colonmonetary = 0x20a1; + t.colonmonospace = 0xff1a; + t.colonsign = 0x20a1; + t.colonsmall = 0xfe55; + t.colontriangularhalfmod = 0x02d1; + t.colontriangularmod = 0x02d0; + t.comma = 0x002c; + t.commaabovecmb = 0x0313; + t.commaaboverightcmb = 0x0315; + t.commaaccent = 0xf6c3; + t.commaarabic = 0x060c; + t.commaarmenian = 0x055d; + t.commainferior = 0xf6e1; + t.commamonospace = 0xff0c; + t.commareversedabovecmb = 0x0314; + t.commareversedmod = 0x02bd; + t.commasmall = 0xfe50; + t.commasuperior = 0xf6e2; + t.commaturnedabovecmb = 0x0312; + t.commaturnedmod = 0x02bb; + t.compass = 0x263c; + t.congruent = 0x2245; + t.contourintegral = 0x222e; + t.control = 0x2303; + t.controlACK = 0x0006; + t.controlBEL = 0x0007; + t.controlBS = 0x0008; + t.controlCAN = 0x0018; + t.controlCR = 0x000d; + t.controlDC1 = 0x0011; + t.controlDC2 = 0x0012; + t.controlDC3 = 0x0013; + t.controlDC4 = 0x0014; + t.controlDEL = 0x007f; + t.controlDLE = 0x0010; + t.controlEM = 0x0019; + t.controlENQ = 0x0005; + t.controlEOT = 0x0004; + t.controlESC = 0x001b; + t.controlETB = 0x0017; + t.controlETX = 0x0003; + t.controlFF = 0x000c; + t.controlFS = 0x001c; + t.controlGS = 0x001d; + t.controlHT = 0x0009; + t.controlLF = 0x000a; + t.controlNAK = 0x0015; + t.controlNULL = 0x0000; + t.controlRS = 0x001e; + t.controlSI = 0x000f; + t.controlSO = 0x000e; + t.controlSOT = 0x0002; + t.controlSTX = 0x0001; + t.controlSUB = 0x001a; + t.controlSYN = 0x0016; + t.controlUS = 0x001f; + t.controlVT = 0x000b; + t.copyright = 0x00a9; + t.copyrightsans = 0xf8e9; + t.copyrightserif = 0xf6d9; + t.cornerbracketleft = 0x300c; + t.cornerbracketlefthalfwidth = 0xff62; + t.cornerbracketleftvertical = 0xfe41; + t.cornerbracketright = 0x300d; + t.cornerbracketrighthalfwidth = 0xff63; + t.cornerbracketrightvertical = 0xfe42; + t.corporationsquare = 0x337f; + t.cosquare = 0x33c7; + t.coverkgsquare = 0x33c6; + t.cparen = 0x249e; + t.cruzeiro = 0x20a2; + t.cstretched = 0x0297; + t.curlyand = 0x22cf; + t.curlyor = 0x22ce; + t.currency = 0x00a4; + t.cyrBreve = 0xf6d1; + t.cyrFlex = 0xf6d2; + t.cyrbreve = 0xf6d4; + t.cyrflex = 0xf6d5; + t.d = 0x0064; + t.daarmenian = 0x0564; + t.dabengali = 0x09a6; + t.dadarabic = 0x0636; + t.dadeva = 0x0926; + t.dadfinalarabic = 0xfebe; + t.dadinitialarabic = 0xfebf; + t.dadmedialarabic = 0xfec0; + t.dagesh = 0x05bc; + t.dageshhebrew = 0x05bc; + t.dagger = 0x2020; + t.daggerdbl = 0x2021; + t.dagujarati = 0x0aa6; + t.dagurmukhi = 0x0a26; + t.dahiragana = 0x3060; + t.dakatakana = 0x30c0; + t.dalarabic = 0x062f; + t.dalet = 0x05d3; + t.daletdagesh = 0xfb33; + t.daletdageshhebrew = 0xfb33; + t.dalethebrew = 0x05d3; + t.dalfinalarabic = 0xfeaa; + t.dammaarabic = 0x064f; + t.dammalowarabic = 0x064f; + t.dammatanaltonearabic = 0x064c; + t.dammatanarabic = 0x064c; + t.danda = 0x0964; + t.dargahebrew = 0x05a7; + t.dargalefthebrew = 0x05a7; + t.dasiapneumatacyrilliccmb = 0x0485; + t.dblGrave = 0xf6d3; + t.dblanglebracketleft = 0x300a; + t.dblanglebracketleftvertical = 0xfe3d; + t.dblanglebracketright = 0x300b; + t.dblanglebracketrightvertical = 0xfe3e; + t.dblarchinvertedbelowcmb = 0x032b; + t.dblarrowleft = 0x21d4; + t.dblarrowright = 0x21d2; + t.dbldanda = 0x0965; + t.dblgrave = 0xf6d6; + t.dblgravecmb = 0x030f; + t.dblintegral = 0x222c; + t.dbllowline = 0x2017; + t.dbllowlinecmb = 0x0333; + t.dbloverlinecmb = 0x033f; + t.dblprimemod = 0x02ba; + t.dblverticalbar = 0x2016; + t.dblverticallineabovecmb = 0x030e; + t.dbopomofo = 0x3109; + t.dbsquare = 0x33c8; + t.dcaron = 0x010f; + t.dcedilla = 0x1e11; + t.dcircle = 0x24d3; + t.dcircumflexbelow = 0x1e13; + t.dcroat = 0x0111; + t.ddabengali = 0x09a1; + t.ddadeva = 0x0921; + t.ddagujarati = 0x0aa1; + t.ddagurmukhi = 0x0a21; + t.ddalarabic = 0x0688; + t.ddalfinalarabic = 0xfb89; + t.dddhadeva = 0x095c; + t.ddhabengali = 0x09a2; + t.ddhadeva = 0x0922; + t.ddhagujarati = 0x0aa2; + t.ddhagurmukhi = 0x0a22; + t.ddotaccent = 0x1e0b; + t.ddotbelow = 0x1e0d; + t.decimalseparatorarabic = 0x066b; + t.decimalseparatorpersian = 0x066b; + t.decyrillic = 0x0434; + t.degree = 0x00b0; + t.dehihebrew = 0x05ad; + t.dehiragana = 0x3067; + t.deicoptic = 0x03ef; + t.dekatakana = 0x30c7; + t.deleteleft = 0x232b; + t.deleteright = 0x2326; + t.delta = 0x03b4; + t.deltaturned = 0x018d; + t.denominatorminusonenumeratorbengali = 0x09f8; + t.dezh = 0x02a4; + t.dhabengali = 0x09a7; + t.dhadeva = 0x0927; + t.dhagujarati = 0x0aa7; + t.dhagurmukhi = 0x0a27; + t.dhook = 0x0257; + t.dialytikatonos = 0x0385; + t.dialytikatonoscmb = 0x0344; + t.diamond = 0x2666; + t.diamondsuitwhite = 0x2662; + t.dieresis = 0x00a8; + t.dieresisacute = 0xf6d7; + t.dieresisbelowcmb = 0x0324; + t.dieresiscmb = 0x0308; + t.dieresisgrave = 0xf6d8; + t.dieresistonos = 0x0385; + t.dihiragana = 0x3062; + t.dikatakana = 0x30c2; + t.dittomark = 0x3003; + t.divide = 0x00f7; + t.divides = 0x2223; + t.divisionslash = 0x2215; + t.djecyrillic = 0x0452; + t.dkshade = 0x2593; + t.dlinebelow = 0x1e0f; + t.dlsquare = 0x3397; + t.dmacron = 0x0111; + t.dmonospace = 0xff44; + t.dnblock = 0x2584; + t.dochadathai = 0x0e0e; + t.dodekthai = 0x0e14; + t.dohiragana = 0x3069; + t.dokatakana = 0x30c9; + t.dollar = 0x0024; + t.dollarinferior = 0xf6e3; + t.dollarmonospace = 0xff04; + t.dollaroldstyle = 0xf724; + t.dollarsmall = 0xfe69; + t.dollarsuperior = 0xf6e4; + t.dong = 0x20ab; + t.dorusquare = 0x3326; + t.dotaccent = 0x02d9; + t.dotaccentcmb = 0x0307; + t.dotbelowcmb = 0x0323; + t.dotbelowcomb = 0x0323; + t.dotkatakana = 0x30fb; + t.dotlessi = 0x0131; + t.dotlessj = 0xf6be; + t.dotlessjstrokehook = 0x0284; + t.dotmath = 0x22c5; + t.dottedcircle = 0x25cc; + t.doubleyodpatah = 0xfb1f; + t.doubleyodpatahhebrew = 0xfb1f; + t.downtackbelowcmb = 0x031e; + t.downtackmod = 0x02d5; + t.dparen = 0x249f; + t.dsuperior = 0xf6eb; + t.dtail = 0x0256; + t.dtopbar = 0x018c; + t.duhiragana = 0x3065; + t.dukatakana = 0x30c5; + t.dz = 0x01f3; + t.dzaltone = 0x02a3; + t.dzcaron = 0x01c6; + t.dzcurl = 0x02a5; + t.dzeabkhasiancyrillic = 0x04e1; + t.dzecyrillic = 0x0455; + t.dzhecyrillic = 0x045f; + t.e = 0x0065; + t.eacute = 0x00e9; + t.earth = 0x2641; + t.ebengali = 0x098f; + t.ebopomofo = 0x311c; + t.ebreve = 0x0115; + t.ecandradeva = 0x090d; + t.ecandragujarati = 0x0a8d; + t.ecandravowelsigndeva = 0x0945; + t.ecandravowelsigngujarati = 0x0ac5; + t.ecaron = 0x011b; + t.ecedillabreve = 0x1e1d; + t.echarmenian = 0x0565; + t.echyiwnarmenian = 0x0587; + t.ecircle = 0x24d4; + t.ecircumflex = 0x00ea; + t.ecircumflexacute = 0x1ebf; + t.ecircumflexbelow = 0x1e19; + t.ecircumflexdotbelow = 0x1ec7; + t.ecircumflexgrave = 0x1ec1; + t.ecircumflexhookabove = 0x1ec3; + t.ecircumflextilde = 0x1ec5; + t.ecyrillic = 0x0454; + t.edblgrave = 0x0205; + t.edeva = 0x090f; + t.edieresis = 0x00eb; + t.edot = 0x0117; + t.edotaccent = 0x0117; + t.edotbelow = 0x1eb9; + t.eegurmukhi = 0x0a0f; + t.eematragurmukhi = 0x0a47; + t.efcyrillic = 0x0444; + t.egrave = 0x00e8; + t.egujarati = 0x0a8f; + t.eharmenian = 0x0567; + t.ehbopomofo = 0x311d; + t.ehiragana = 0x3048; + t.ehookabove = 0x1ebb; + t.eibopomofo = 0x311f; + t.eight = 0x0038; + t.eightarabic = 0x0668; + t.eightbengali = 0x09ee; + t.eightcircle = 0x2467; + t.eightcircleinversesansserif = 0x2791; + t.eightdeva = 0x096e; + t.eighteencircle = 0x2471; + t.eighteenparen = 0x2485; + t.eighteenperiod = 0x2499; + t.eightgujarati = 0x0aee; + t.eightgurmukhi = 0x0a6e; + t.eighthackarabic = 0x0668; + t.eighthangzhou = 0x3028; + t.eighthnotebeamed = 0x266b; + t.eightideographicparen = 0x3227; + t.eightinferior = 0x2088; + t.eightmonospace = 0xff18; + t.eightoldstyle = 0xf738; + t.eightparen = 0x247b; + t.eightperiod = 0x248f; + t.eightpersian = 0x06f8; + t.eightroman = 0x2177; + t.eightsuperior = 0x2078; + t.eightthai = 0x0e58; + t.einvertedbreve = 0x0207; + t.eiotifiedcyrillic = 0x0465; + t.ekatakana = 0x30a8; + t.ekatakanahalfwidth = 0xff74; + t.ekonkargurmukhi = 0x0a74; + t.ekorean = 0x3154; + t.elcyrillic = 0x043b; + t.element = 0x2208; + t.elevencircle = 0x246a; + t.elevenparen = 0x247e; + t.elevenperiod = 0x2492; + t.elevenroman = 0x217a; + t.ellipsis = 0x2026; + t.ellipsisvertical = 0x22ee; + t.emacron = 0x0113; + t.emacronacute = 0x1e17; + t.emacrongrave = 0x1e15; + t.emcyrillic = 0x043c; + t.emdash = 0x2014; + t.emdashvertical = 0xfe31; + t.emonospace = 0xff45; + t.emphasismarkarmenian = 0x055b; + t.emptyset = 0x2205; + t.enbopomofo = 0x3123; + t.encyrillic = 0x043d; + t.endash = 0x2013; + t.endashvertical = 0xfe32; + t.endescendercyrillic = 0x04a3; + t.eng = 0x014b; + t.engbopomofo = 0x3125; + t.enghecyrillic = 0x04a5; + t.enhookcyrillic = 0x04c8; + t.enspace = 0x2002; + t.eogonek = 0x0119; + t.eokorean = 0x3153; + t.eopen = 0x025b; + t.eopenclosed = 0x029a; + t.eopenreversed = 0x025c; + t.eopenreversedclosed = 0x025e; + t.eopenreversedhook = 0x025d; + t.eparen = 0x24a0; + t.epsilon = 0x03b5; + t.epsilontonos = 0x03ad; + t.equal = 0x003d; + t.equalmonospace = 0xff1d; + t.equalsmall = 0xfe66; + t.equalsuperior = 0x207c; + t.equivalence = 0x2261; + t.erbopomofo = 0x3126; + t.ercyrillic = 0x0440; + t.ereversed = 0x0258; + t.ereversedcyrillic = 0x044d; + t.escyrillic = 0x0441; + t.esdescendercyrillic = 0x04ab; + t.esh = 0x0283; + t.eshcurl = 0x0286; + t.eshortdeva = 0x090e; + t.eshortvowelsigndeva = 0x0946; + t.eshreversedloop = 0x01aa; + t.eshsquatreversed = 0x0285; + t.esmallhiragana = 0x3047; + t.esmallkatakana = 0x30a7; + t.esmallkatakanahalfwidth = 0xff6a; + t.estimated = 0x212e; + t.esuperior = 0xf6ec; + t.eta = 0x03b7; + t.etarmenian = 0x0568; + t.etatonos = 0x03ae; + t.eth = 0x00f0; + t.etilde = 0x1ebd; + t.etildebelow = 0x1e1b; + t.etnahtafoukhhebrew = 0x0591; + t.etnahtafoukhlefthebrew = 0x0591; + t.etnahtahebrew = 0x0591; + t.etnahtalefthebrew = 0x0591; + t.eturned = 0x01dd; + t.eukorean = 0x3161; + t.euro = 0x20ac; + t.evowelsignbengali = 0x09c7; + t.evowelsigndeva = 0x0947; + t.evowelsigngujarati = 0x0ac7; + t.exclam = 0x0021; + t.exclamarmenian = 0x055c; + t.exclamdbl = 0x203c; + t.exclamdown = 0x00a1; + t.exclamdownsmall = 0xf7a1; + t.exclammonospace = 0xff01; + t.exclamsmall = 0xf721; + t.existential = 0x2203; + t.ezh = 0x0292; + t.ezhcaron = 0x01ef; + t.ezhcurl = 0x0293; + t.ezhreversed = 0x01b9; + t.ezhtail = 0x01ba; + t.f = 0x0066; + t.fadeva = 0x095e; + t.fagurmukhi = 0x0a5e; + t.fahrenheit = 0x2109; + t.fathaarabic = 0x064e; + t.fathalowarabic = 0x064e; + t.fathatanarabic = 0x064b; + t.fbopomofo = 0x3108; + t.fcircle = 0x24d5; + t.fdotaccent = 0x1e1f; + t.feharabic = 0x0641; + t.feharmenian = 0x0586; + t.fehfinalarabic = 0xfed2; + t.fehinitialarabic = 0xfed3; + t.fehmedialarabic = 0xfed4; + t.feicoptic = 0x03e5; + t.female = 0x2640; + t.ff = 0xfb00; + t.f_f = 0xfb00; + t.ffi = 0xfb03; + t.f_f_i = 0xfb03; + t.ffl = 0xfb04; + t.f_f_l = 0xfb04; + t.fi = 0xfb01; + t.f_i = 0xfb01; + t.fifteencircle = 0x246e; + t.fifteenparen = 0x2482; + t.fifteenperiod = 0x2496; + t.figuredash = 0x2012; + t.filledbox = 0x25a0; + t.filledrect = 0x25ac; + t.finalkaf = 0x05da; + t.finalkafdagesh = 0xfb3a; + t.finalkafdageshhebrew = 0xfb3a; + t.finalkafhebrew = 0x05da; + t.finalmem = 0x05dd; + t.finalmemhebrew = 0x05dd; + t.finalnun = 0x05df; + t.finalnunhebrew = 0x05df; + t.finalpe = 0x05e3; + t.finalpehebrew = 0x05e3; + t.finaltsadi = 0x05e5; + t.finaltsadihebrew = 0x05e5; + t.firsttonechinese = 0x02c9; + t.fisheye = 0x25c9; + t.fitacyrillic = 0x0473; + t.five = 0x0035; + t.fivearabic = 0x0665; + t.fivebengali = 0x09eb; + t.fivecircle = 0x2464; + t.fivecircleinversesansserif = 0x278e; + t.fivedeva = 0x096b; + t.fiveeighths = 0x215d; + t.fivegujarati = 0x0aeb; + t.fivegurmukhi = 0x0a6b; + t.fivehackarabic = 0x0665; + t.fivehangzhou = 0x3025; + t.fiveideographicparen = 0x3224; + t.fiveinferior = 0x2085; + t.fivemonospace = 0xff15; + t.fiveoldstyle = 0xf735; + t.fiveparen = 0x2478; + t.fiveperiod = 0x248c; + t.fivepersian = 0x06f5; + t.fiveroman = 0x2174; + t.fivesuperior = 0x2075; + t.fivethai = 0x0e55; + t.fl = 0xfb02; + t.f_l = 0xfb02; + t.florin = 0x0192; + t.fmonospace = 0xff46; + t.fmsquare = 0x3399; + t.fofanthai = 0x0e1f; + t.fofathai = 0x0e1d; + t.fongmanthai = 0x0e4f; + t.forall = 0x2200; + t.four = 0x0034; + t.fourarabic = 0x0664; + t.fourbengali = 0x09ea; + t.fourcircle = 0x2463; + t.fourcircleinversesansserif = 0x278d; + t.fourdeva = 0x096a; + t.fourgujarati = 0x0aea; + t.fourgurmukhi = 0x0a6a; + t.fourhackarabic = 0x0664; + t.fourhangzhou = 0x3024; + t.fourideographicparen = 0x3223; + t.fourinferior = 0x2084; + t.fourmonospace = 0xff14; + t.fournumeratorbengali = 0x09f7; + t.fouroldstyle = 0xf734; + t.fourparen = 0x2477; + t.fourperiod = 0x248b; + t.fourpersian = 0x06f4; + t.fourroman = 0x2173; + t.foursuperior = 0x2074; + t.fourteencircle = 0x246d; + t.fourteenparen = 0x2481; + t.fourteenperiod = 0x2495; + t.fourthai = 0x0e54; + t.fourthtonechinese = 0x02cb; + t.fparen = 0x24a1; + t.fraction = 0x2044; + t.franc = 0x20a3; + t.g = 0x0067; + t.gabengali = 0x0997; + t.gacute = 0x01f5; + t.gadeva = 0x0917; + t.gafarabic = 0x06af; + t.gaffinalarabic = 0xfb93; + t.gafinitialarabic = 0xfb94; + t.gafmedialarabic = 0xfb95; + t.gagujarati = 0x0a97; + t.gagurmukhi = 0x0a17; + t.gahiragana = 0x304c; + t.gakatakana = 0x30ac; + t.gamma = 0x03b3; + t.gammalatinsmall = 0x0263; + t.gammasuperior = 0x02e0; + t.gangiacoptic = 0x03eb; + t.gbopomofo = 0x310d; + t.gbreve = 0x011f; + t.gcaron = 0x01e7; + t.gcedilla = 0x0123; + t.gcircle = 0x24d6; + t.gcircumflex = 0x011d; + t.gcommaaccent = 0x0123; + t.gdot = 0x0121; + t.gdotaccent = 0x0121; + t.gecyrillic = 0x0433; + t.gehiragana = 0x3052; + t.gekatakana = 0x30b2; + t.geometricallyequal = 0x2251; + t.gereshaccenthebrew = 0x059c; + t.gereshhebrew = 0x05f3; + t.gereshmuqdamhebrew = 0x059d; + t.germandbls = 0x00df; + t.gershayimaccenthebrew = 0x059e; + t.gershayimhebrew = 0x05f4; + t.getamark = 0x3013; + t.ghabengali = 0x0998; + t.ghadarmenian = 0x0572; + t.ghadeva = 0x0918; + t.ghagujarati = 0x0a98; + t.ghagurmukhi = 0x0a18; + t.ghainarabic = 0x063a; + t.ghainfinalarabic = 0xfece; + t.ghaininitialarabic = 0xfecf; + t.ghainmedialarabic = 0xfed0; + t.ghemiddlehookcyrillic = 0x0495; + t.ghestrokecyrillic = 0x0493; + t.gheupturncyrillic = 0x0491; + t.ghhadeva = 0x095a; + t.ghhagurmukhi = 0x0a5a; + t.ghook = 0x0260; + t.ghzsquare = 0x3393; + t.gihiragana = 0x304e; + t.gikatakana = 0x30ae; + t.gimarmenian = 0x0563; + t.gimel = 0x05d2; + t.gimeldagesh = 0xfb32; + t.gimeldageshhebrew = 0xfb32; + t.gimelhebrew = 0x05d2; + t.gjecyrillic = 0x0453; + t.glottalinvertedstroke = 0x01be; + t.glottalstop = 0x0294; + t.glottalstopinverted = 0x0296; + t.glottalstopmod = 0x02c0; + t.glottalstopreversed = 0x0295; + t.glottalstopreversedmod = 0x02c1; + t.glottalstopreversedsuperior = 0x02e4; + t.glottalstopstroke = 0x02a1; + t.glottalstopstrokereversed = 0x02a2; + t.gmacron = 0x1e21; + t.gmonospace = 0xff47; + t.gohiragana = 0x3054; + t.gokatakana = 0x30b4; + t.gparen = 0x24a2; + t.gpasquare = 0x33ac; + t.gradient = 0x2207; + t.grave = 0x0060; + t.gravebelowcmb = 0x0316; + t.gravecmb = 0x0300; + t.gravecomb = 0x0300; + t.gravedeva = 0x0953; + t.gravelowmod = 0x02ce; + t.gravemonospace = 0xff40; + t.gravetonecmb = 0x0340; + t.greater = 0x003e; + t.greaterequal = 0x2265; + t.greaterequalorless = 0x22db; + t.greatermonospace = 0xff1e; + t.greaterorequivalent = 0x2273; + t.greaterorless = 0x2277; + t.greateroverequal = 0x2267; + t.greatersmall = 0xfe65; + t.gscript = 0x0261; + t.gstroke = 0x01e5; + t.guhiragana = 0x3050; + t.guillemotleft = 0x00ab; + t.guillemotright = 0x00bb; + t.guilsinglleft = 0x2039; + t.guilsinglright = 0x203a; + t.gukatakana = 0x30b0; + t.guramusquare = 0x3318; + t.gysquare = 0x33c9; + t.h = 0x0068; + t.haabkhasiancyrillic = 0x04a9; + t.haaltonearabic = 0x06c1; + t.habengali = 0x09b9; + t.hadescendercyrillic = 0x04b3; + t.hadeva = 0x0939; + t.hagujarati = 0x0ab9; + t.hagurmukhi = 0x0a39; + t.haharabic = 0x062d; + t.hahfinalarabic = 0xfea2; + t.hahinitialarabic = 0xfea3; + t.hahiragana = 0x306f; + t.hahmedialarabic = 0xfea4; + t.haitusquare = 0x332a; + t.hakatakana = 0x30cf; + t.hakatakanahalfwidth = 0xff8a; + t.halantgurmukhi = 0x0a4d; + t.hamzaarabic = 0x0621; + t.hamzalowarabic = 0x0621; + t.hangulfiller = 0x3164; + t.hardsigncyrillic = 0x044a; + t.harpoonleftbarbup = 0x21bc; + t.harpoonrightbarbup = 0x21c0; + t.hasquare = 0x33ca; + t.hatafpatah = 0x05b2; + t.hatafpatah16 = 0x05b2; + t.hatafpatah23 = 0x05b2; + t.hatafpatah2f = 0x05b2; + t.hatafpatahhebrew = 0x05b2; + t.hatafpatahnarrowhebrew = 0x05b2; + t.hatafpatahquarterhebrew = 0x05b2; + t.hatafpatahwidehebrew = 0x05b2; + t.hatafqamats = 0x05b3; + t.hatafqamats1b = 0x05b3; + t.hatafqamats28 = 0x05b3; + t.hatafqamats34 = 0x05b3; + t.hatafqamatshebrew = 0x05b3; + t.hatafqamatsnarrowhebrew = 0x05b3; + t.hatafqamatsquarterhebrew = 0x05b3; + t.hatafqamatswidehebrew = 0x05b3; + t.hatafsegol = 0x05b1; + t.hatafsegol17 = 0x05b1; + t.hatafsegol24 = 0x05b1; + t.hatafsegol30 = 0x05b1; + t.hatafsegolhebrew = 0x05b1; + t.hatafsegolnarrowhebrew = 0x05b1; + t.hatafsegolquarterhebrew = 0x05b1; + t.hatafsegolwidehebrew = 0x05b1; + t.hbar = 0x0127; + t.hbopomofo = 0x310f; + t.hbrevebelow = 0x1e2b; + t.hcedilla = 0x1e29; + t.hcircle = 0x24d7; + t.hcircumflex = 0x0125; + t.hdieresis = 0x1e27; + t.hdotaccent = 0x1e23; + t.hdotbelow = 0x1e25; + t.he = 0x05d4; + t.heart = 0x2665; + t.heartsuitblack = 0x2665; + t.heartsuitwhite = 0x2661; + t.hedagesh = 0xfb34; + t.hedageshhebrew = 0xfb34; + t.hehaltonearabic = 0x06c1; + t.heharabic = 0x0647; + t.hehebrew = 0x05d4; + t.hehfinalaltonearabic = 0xfba7; + t.hehfinalalttwoarabic = 0xfeea; + t.hehfinalarabic = 0xfeea; + t.hehhamzaabovefinalarabic = 0xfba5; + t.hehhamzaaboveisolatedarabic = 0xfba4; + t.hehinitialaltonearabic = 0xfba8; + t.hehinitialarabic = 0xfeeb; + t.hehiragana = 0x3078; + t.hehmedialaltonearabic = 0xfba9; + t.hehmedialarabic = 0xfeec; + t.heiseierasquare = 0x337b; + t.hekatakana = 0x30d8; + t.hekatakanahalfwidth = 0xff8d; + t.hekutaarusquare = 0x3336; + t.henghook = 0x0267; + t.herutusquare = 0x3339; + t.het = 0x05d7; + t.hethebrew = 0x05d7; + t.hhook = 0x0266; + t.hhooksuperior = 0x02b1; + t.hieuhacirclekorean = 0x327b; + t.hieuhaparenkorean = 0x321b; + t.hieuhcirclekorean = 0x326d; + t.hieuhkorean = 0x314e; + t.hieuhparenkorean = 0x320d; + t.hihiragana = 0x3072; + t.hikatakana = 0x30d2; + t.hikatakanahalfwidth = 0xff8b; + t.hiriq = 0x05b4; + t.hiriq14 = 0x05b4; + t.hiriq21 = 0x05b4; + t.hiriq2d = 0x05b4; + t.hiriqhebrew = 0x05b4; + t.hiriqnarrowhebrew = 0x05b4; + t.hiriqquarterhebrew = 0x05b4; + t.hiriqwidehebrew = 0x05b4; + t.hlinebelow = 0x1e96; + t.hmonospace = 0xff48; + t.hoarmenian = 0x0570; + t.hohipthai = 0x0e2b; + t.hohiragana = 0x307b; + t.hokatakana = 0x30db; + t.hokatakanahalfwidth = 0xff8e; + t.holam = 0x05b9; + t.holam19 = 0x05b9; + t.holam26 = 0x05b9; + t.holam32 = 0x05b9; + t.holamhebrew = 0x05b9; + t.holamnarrowhebrew = 0x05b9; + t.holamquarterhebrew = 0x05b9; + t.holamwidehebrew = 0x05b9; + t.honokhukthai = 0x0e2e; + t.hookabovecomb = 0x0309; + t.hookcmb = 0x0309; + t.hookpalatalizedbelowcmb = 0x0321; + t.hookretroflexbelowcmb = 0x0322; + t.hoonsquare = 0x3342; + t.horicoptic = 0x03e9; + t.horizontalbar = 0x2015; + t.horncmb = 0x031b; + t.hotsprings = 0x2668; + t.house = 0x2302; + t.hparen = 0x24a3; + t.hsuperior = 0x02b0; + t.hturned = 0x0265; + t.huhiragana = 0x3075; + t.huiitosquare = 0x3333; + t.hukatakana = 0x30d5; + t.hukatakanahalfwidth = 0xff8c; + t.hungarumlaut = 0x02dd; + t.hungarumlautcmb = 0x030b; + t.hv = 0x0195; + t.hyphen = 0x002d; + t.hypheninferior = 0xf6e5; + t.hyphenmonospace = 0xff0d; + t.hyphensmall = 0xfe63; + t.hyphensuperior = 0xf6e6; + t.hyphentwo = 0x2010; + t.i = 0x0069; + t.iacute = 0x00ed; + t.iacyrillic = 0x044f; + t.ibengali = 0x0987; + t.ibopomofo = 0x3127; + t.ibreve = 0x012d; + t.icaron = 0x01d0; + t.icircle = 0x24d8; + t.icircumflex = 0x00ee; + t.icyrillic = 0x0456; + t.idblgrave = 0x0209; + t.ideographearthcircle = 0x328f; + t.ideographfirecircle = 0x328b; + t.ideographicallianceparen = 0x323f; + t.ideographiccallparen = 0x323a; + t.ideographiccentrecircle = 0x32a5; + t.ideographicclose = 0x3006; + t.ideographiccomma = 0x3001; + t.ideographiccommaleft = 0xff64; + t.ideographiccongratulationparen = 0x3237; + t.ideographiccorrectcircle = 0x32a3; + t.ideographicearthparen = 0x322f; + t.ideographicenterpriseparen = 0x323d; + t.ideographicexcellentcircle = 0x329d; + t.ideographicfestivalparen = 0x3240; + t.ideographicfinancialcircle = 0x3296; + t.ideographicfinancialparen = 0x3236; + t.ideographicfireparen = 0x322b; + t.ideographichaveparen = 0x3232; + t.ideographichighcircle = 0x32a4; + t.ideographiciterationmark = 0x3005; + t.ideographiclaborcircle = 0x3298; + t.ideographiclaborparen = 0x3238; + t.ideographicleftcircle = 0x32a7; + t.ideographiclowcircle = 0x32a6; + t.ideographicmedicinecircle = 0x32a9; + t.ideographicmetalparen = 0x322e; + t.ideographicmoonparen = 0x322a; + t.ideographicnameparen = 0x3234; + t.ideographicperiod = 0x3002; + t.ideographicprintcircle = 0x329e; + t.ideographicreachparen = 0x3243; + t.ideographicrepresentparen = 0x3239; + t.ideographicresourceparen = 0x323e; + t.ideographicrightcircle = 0x32a8; + t.ideographicsecretcircle = 0x3299; + t.ideographicselfparen = 0x3242; + t.ideographicsocietyparen = 0x3233; + t.ideographicspace = 0x3000; + t.ideographicspecialparen = 0x3235; + t.ideographicstockparen = 0x3231; + t.ideographicstudyparen = 0x323b; + t.ideographicsunparen = 0x3230; + t.ideographicsuperviseparen = 0x323c; + t.ideographicwaterparen = 0x322c; + t.ideographicwoodparen = 0x322d; + t.ideographiczero = 0x3007; + t.ideographmetalcircle = 0x328e; + t.ideographmooncircle = 0x328a; + t.ideographnamecircle = 0x3294; + t.ideographsuncircle = 0x3290; + t.ideographwatercircle = 0x328c; + t.ideographwoodcircle = 0x328d; + t.ideva = 0x0907; + t.idieresis = 0x00ef; + t.idieresisacute = 0x1e2f; + t.idieresiscyrillic = 0x04e5; + t.idotbelow = 0x1ecb; + t.iebrevecyrillic = 0x04d7; + t.iecyrillic = 0x0435; + t.ieungacirclekorean = 0x3275; + t.ieungaparenkorean = 0x3215; + t.ieungcirclekorean = 0x3267; + t.ieungkorean = 0x3147; + t.ieungparenkorean = 0x3207; + t.igrave = 0x00ec; + t.igujarati = 0x0a87; + t.igurmukhi = 0x0a07; + t.ihiragana = 0x3044; + t.ihookabove = 0x1ec9; + t.iibengali = 0x0988; + t.iicyrillic = 0x0438; + t.iideva = 0x0908; + t.iigujarati = 0x0a88; + t.iigurmukhi = 0x0a08; + t.iimatragurmukhi = 0x0a40; + t.iinvertedbreve = 0x020b; + t.iishortcyrillic = 0x0439; + t.iivowelsignbengali = 0x09c0; + t.iivowelsigndeva = 0x0940; + t.iivowelsigngujarati = 0x0ac0; + t.ij = 0x0133; + t.ikatakana = 0x30a4; + t.ikatakanahalfwidth = 0xff72; + t.ikorean = 0x3163; + t.ilde = 0x02dc; + t.iluyhebrew = 0x05ac; + t.imacron = 0x012b; + t.imacroncyrillic = 0x04e3; + t.imageorapproximatelyequal = 0x2253; + t.imatragurmukhi = 0x0a3f; + t.imonospace = 0xff49; + t.increment = 0x2206; + t.infinity = 0x221e; + t.iniarmenian = 0x056b; + t.integral = 0x222b; + t.integralbottom = 0x2321; + t.integralbt = 0x2321; + t.integralex = 0xf8f5; + t.integraltop = 0x2320; + t.integraltp = 0x2320; + t.intersection = 0x2229; + t.intisquare = 0x3305; + t.invbullet = 0x25d8; + t.invcircle = 0x25d9; + t.invsmileface = 0x263b; + t.iocyrillic = 0x0451; + t.iogonek = 0x012f; + t.iota = 0x03b9; + t.iotadieresis = 0x03ca; + t.iotadieresistonos = 0x0390; + t.iotalatin = 0x0269; + t.iotatonos = 0x03af; + t.iparen = 0x24a4; + t.irigurmukhi = 0x0a72; + t.ismallhiragana = 0x3043; + t.ismallkatakana = 0x30a3; + t.ismallkatakanahalfwidth = 0xff68; + t.issharbengali = 0x09fa; + t.istroke = 0x0268; + t.isuperior = 0xf6ed; + t.iterationhiragana = 0x309d; + t.iterationkatakana = 0x30fd; + t.itilde = 0x0129; + t.itildebelow = 0x1e2d; + t.iubopomofo = 0x3129; + t.iucyrillic = 0x044e; + t.ivowelsignbengali = 0x09bf; + t.ivowelsigndeva = 0x093f; + t.ivowelsigngujarati = 0x0abf; + t.izhitsacyrillic = 0x0475; + t.izhitsadblgravecyrillic = 0x0477; + t.j = 0x006a; + t.jaarmenian = 0x0571; + t.jabengali = 0x099c; + t.jadeva = 0x091c; + t.jagujarati = 0x0a9c; + t.jagurmukhi = 0x0a1c; + t.jbopomofo = 0x3110; + t.jcaron = 0x01f0; + t.jcircle = 0x24d9; + t.jcircumflex = 0x0135; + t.jcrossedtail = 0x029d; + t.jdotlessstroke = 0x025f; + t.jecyrillic = 0x0458; + t.jeemarabic = 0x062c; + t.jeemfinalarabic = 0xfe9e; + t.jeeminitialarabic = 0xfe9f; + t.jeemmedialarabic = 0xfea0; + t.jeharabic = 0x0698; + t.jehfinalarabic = 0xfb8b; + t.jhabengali = 0x099d; + t.jhadeva = 0x091d; + t.jhagujarati = 0x0a9d; + t.jhagurmukhi = 0x0a1d; + t.jheharmenian = 0x057b; + t.jis = 0x3004; + t.jmonospace = 0xff4a; + t.jparen = 0x24a5; + t.jsuperior = 0x02b2; + t.k = 0x006b; + t.kabashkircyrillic = 0x04a1; + t.kabengali = 0x0995; + t.kacute = 0x1e31; + t.kacyrillic = 0x043a; + t.kadescendercyrillic = 0x049b; + t.kadeva = 0x0915; + t.kaf = 0x05db; + t.kafarabic = 0x0643; + t.kafdagesh = 0xfb3b; + t.kafdageshhebrew = 0xfb3b; + t.kaffinalarabic = 0xfeda; + t.kafhebrew = 0x05db; + t.kafinitialarabic = 0xfedb; + t.kafmedialarabic = 0xfedc; + t.kafrafehebrew = 0xfb4d; + t.kagujarati = 0x0a95; + t.kagurmukhi = 0x0a15; + t.kahiragana = 0x304b; + t.kahookcyrillic = 0x04c4; + t.kakatakana = 0x30ab; + t.kakatakanahalfwidth = 0xff76; + t.kappa = 0x03ba; + t.kappasymbolgreek = 0x03f0; + t.kapyeounmieumkorean = 0x3171; + t.kapyeounphieuphkorean = 0x3184; + t.kapyeounpieupkorean = 0x3178; + t.kapyeounssangpieupkorean = 0x3179; + t.karoriisquare = 0x330d; + t.kashidaautoarabic = 0x0640; + t.kashidaautonosidebearingarabic = 0x0640; + t.kasmallkatakana = 0x30f5; + t.kasquare = 0x3384; + t.kasraarabic = 0x0650; + t.kasratanarabic = 0x064d; + t.kastrokecyrillic = 0x049f; + t.katahiraprolongmarkhalfwidth = 0xff70; + t.kaverticalstrokecyrillic = 0x049d; + t.kbopomofo = 0x310e; + t.kcalsquare = 0x3389; + t.kcaron = 0x01e9; + t.kcedilla = 0x0137; + t.kcircle = 0x24da; + t.kcommaaccent = 0x0137; + t.kdotbelow = 0x1e33; + t.keharmenian = 0x0584; + t.kehiragana = 0x3051; + t.kekatakana = 0x30b1; + t.kekatakanahalfwidth = 0xff79; + t.kenarmenian = 0x056f; + t.kesmallkatakana = 0x30f6; + t.kgreenlandic = 0x0138; + t.khabengali = 0x0996; + t.khacyrillic = 0x0445; + t.khadeva = 0x0916; + t.khagujarati = 0x0a96; + t.khagurmukhi = 0x0a16; + t.khaharabic = 0x062e; + t.khahfinalarabic = 0xfea6; + t.khahinitialarabic = 0xfea7; + t.khahmedialarabic = 0xfea8; + t.kheicoptic = 0x03e7; + t.khhadeva = 0x0959; + t.khhagurmukhi = 0x0a59; + t.khieukhacirclekorean = 0x3278; + t.khieukhaparenkorean = 0x3218; + t.khieukhcirclekorean = 0x326a; + t.khieukhkorean = 0x314b; + t.khieukhparenkorean = 0x320a; + t.khokhaithai = 0x0e02; + t.khokhonthai = 0x0e05; + t.khokhuatthai = 0x0e03; + t.khokhwaithai = 0x0e04; + t.khomutthai = 0x0e5b; + t.khook = 0x0199; + t.khorakhangthai = 0x0e06; + t.khzsquare = 0x3391; + t.kihiragana = 0x304d; + t.kikatakana = 0x30ad; + t.kikatakanahalfwidth = 0xff77; + t.kiroguramusquare = 0x3315; + t.kiromeetorusquare = 0x3316; + t.kirosquare = 0x3314; + t.kiyeokacirclekorean = 0x326e; + t.kiyeokaparenkorean = 0x320e; + t.kiyeokcirclekorean = 0x3260; + t.kiyeokkorean = 0x3131; + t.kiyeokparenkorean = 0x3200; + t.kiyeoksioskorean = 0x3133; + t.kjecyrillic = 0x045c; + t.klinebelow = 0x1e35; + t.klsquare = 0x3398; + t.kmcubedsquare = 0x33a6; + t.kmonospace = 0xff4b; + t.kmsquaredsquare = 0x33a2; + t.kohiragana = 0x3053; + t.kohmsquare = 0x33c0; + t.kokaithai = 0x0e01; + t.kokatakana = 0x30b3; + t.kokatakanahalfwidth = 0xff7a; + t.kooposquare = 0x331e; + t.koppacyrillic = 0x0481; + t.koreanstandardsymbol = 0x327f; + t.koroniscmb = 0x0343; + t.kparen = 0x24a6; + t.kpasquare = 0x33aa; + t.ksicyrillic = 0x046f; + t.ktsquare = 0x33cf; + t.kturned = 0x029e; + t.kuhiragana = 0x304f; + t.kukatakana = 0x30af; + t.kukatakanahalfwidth = 0xff78; + t.kvsquare = 0x33b8; + t.kwsquare = 0x33be; + t.l = 0x006c; + t.labengali = 0x09b2; + t.lacute = 0x013a; + t.ladeva = 0x0932; + t.lagujarati = 0x0ab2; + t.lagurmukhi = 0x0a32; + t.lakkhangyaothai = 0x0e45; + t.lamaleffinalarabic = 0xfefc; + t.lamalefhamzaabovefinalarabic = 0xfef8; + t.lamalefhamzaaboveisolatedarabic = 0xfef7; + t.lamalefhamzabelowfinalarabic = 0xfefa; + t.lamalefhamzabelowisolatedarabic = 0xfef9; + t.lamalefisolatedarabic = 0xfefb; + t.lamalefmaddaabovefinalarabic = 0xfef6; + t.lamalefmaddaaboveisolatedarabic = 0xfef5; + t.lamarabic = 0x0644; + t.lambda = 0x03bb; + t.lambdastroke = 0x019b; + t.lamed = 0x05dc; + t.lameddagesh = 0xfb3c; + t.lameddageshhebrew = 0xfb3c; + t.lamedhebrew = 0x05dc; + t.lamfinalarabic = 0xfede; + t.lamhahinitialarabic = 0xfcca; + t.laminitialarabic = 0xfedf; + t.lamjeeminitialarabic = 0xfcc9; + t.lamkhahinitialarabic = 0xfccb; + t.lamlamhehisolatedarabic = 0xfdf2; + t.lammedialarabic = 0xfee0; + t.lammeemhahinitialarabic = 0xfd88; + t.lammeeminitialarabic = 0xfccc; + t.largecircle = 0x25ef; + t.lbar = 0x019a; + t.lbelt = 0x026c; + t.lbopomofo = 0x310c; + t.lcaron = 0x013e; + t.lcedilla = 0x013c; + t.lcircle = 0x24db; + t.lcircumflexbelow = 0x1e3d; + t.lcommaaccent = 0x013c; + t.ldot = 0x0140; + t.ldotaccent = 0x0140; + t.ldotbelow = 0x1e37; + t.ldotbelowmacron = 0x1e39; + t.leftangleabovecmb = 0x031a; + t.lefttackbelowcmb = 0x0318; + t.less = 0x003c; + t.lessequal = 0x2264; + t.lessequalorgreater = 0x22da; + t.lessmonospace = 0xff1c; + t.lessorequivalent = 0x2272; + t.lessorgreater = 0x2276; + t.lessoverequal = 0x2266; + t.lesssmall = 0xfe64; + t.lezh = 0x026e; + t.lfblock = 0x258c; + t.lhookretroflex = 0x026d; + t.lira = 0x20a4; + t.liwnarmenian = 0x056c; + t.lj = 0x01c9; + t.ljecyrillic = 0x0459; + t.ll = 0xf6c0; + t.lladeva = 0x0933; + t.llagujarati = 0x0ab3; + t.llinebelow = 0x1e3b; + t.llladeva = 0x0934; + t.llvocalicbengali = 0x09e1; + t.llvocalicdeva = 0x0961; + t.llvocalicvowelsignbengali = 0x09e3; + t.llvocalicvowelsigndeva = 0x0963; + t.lmiddletilde = 0x026b; + t.lmonospace = 0xff4c; + t.lmsquare = 0x33d0; + t.lochulathai = 0x0e2c; + t.logicaland = 0x2227; + t.logicalnot = 0x00ac; + t.logicalnotreversed = 0x2310; + t.logicalor = 0x2228; + t.lolingthai = 0x0e25; + t.longs = 0x017f; + t.lowlinecenterline = 0xfe4e; + t.lowlinecmb = 0x0332; + t.lowlinedashed = 0xfe4d; + t.lozenge = 0x25ca; + t.lparen = 0x24a7; + t.lslash = 0x0142; + t.lsquare = 0x2113; + t.lsuperior = 0xf6ee; + t.ltshade = 0x2591; + t.luthai = 0x0e26; + t.lvocalicbengali = 0x098c; + t.lvocalicdeva = 0x090c; + t.lvocalicvowelsignbengali = 0x09e2; + t.lvocalicvowelsigndeva = 0x0962; + t.lxsquare = 0x33d3; + t.m = 0x006d; + t.mabengali = 0x09ae; + t.macron = 0x00af; + t.macronbelowcmb = 0x0331; + t.macroncmb = 0x0304; + t.macronlowmod = 0x02cd; + t.macronmonospace = 0xffe3; + t.macute = 0x1e3f; + t.madeva = 0x092e; + t.magujarati = 0x0aae; + t.magurmukhi = 0x0a2e; + t.mahapakhhebrew = 0x05a4; + t.mahapakhlefthebrew = 0x05a4; + t.mahiragana = 0x307e; + t.maichattawalowleftthai = 0xf895; + t.maichattawalowrightthai = 0xf894; + t.maichattawathai = 0x0e4b; + t.maichattawaupperleftthai = 0xf893; + t.maieklowleftthai = 0xf88c; + t.maieklowrightthai = 0xf88b; + t.maiekthai = 0x0e48; + t.maiekupperleftthai = 0xf88a; + t.maihanakatleftthai = 0xf884; + t.maihanakatthai = 0x0e31; + t.maitaikhuleftthai = 0xf889; + t.maitaikhuthai = 0x0e47; + t.maitholowleftthai = 0xf88f; + t.maitholowrightthai = 0xf88e; + t.maithothai = 0x0e49; + t.maithoupperleftthai = 0xf88d; + t.maitrilowleftthai = 0xf892; + t.maitrilowrightthai = 0xf891; + t.maitrithai = 0x0e4a; + t.maitriupperleftthai = 0xf890; + t.maiyamokthai = 0x0e46; + t.makatakana = 0x30de; + t.makatakanahalfwidth = 0xff8f; + t.male = 0x2642; + t.mansyonsquare = 0x3347; + t.maqafhebrew = 0x05be; + t.mars = 0x2642; + t.masoracirclehebrew = 0x05af; + t.masquare = 0x3383; + t.mbopomofo = 0x3107; + t.mbsquare = 0x33d4; + t.mcircle = 0x24dc; + t.mcubedsquare = 0x33a5; + t.mdotaccent = 0x1e41; + t.mdotbelow = 0x1e43; + t.meemarabic = 0x0645; + t.meemfinalarabic = 0xfee2; + t.meeminitialarabic = 0xfee3; + t.meemmedialarabic = 0xfee4; + t.meemmeeminitialarabic = 0xfcd1; + t.meemmeemisolatedarabic = 0xfc48; + t.meetorusquare = 0x334d; + t.mehiragana = 0x3081; + t.meizierasquare = 0x337e; + t.mekatakana = 0x30e1; + t.mekatakanahalfwidth = 0xff92; + t.mem = 0x05de; + t.memdagesh = 0xfb3e; + t.memdageshhebrew = 0xfb3e; + t.memhebrew = 0x05de; + t.menarmenian = 0x0574; + t.merkhahebrew = 0x05a5; + t.merkhakefulahebrew = 0x05a6; + t.merkhakefulalefthebrew = 0x05a6; + t.merkhalefthebrew = 0x05a5; + t.mhook = 0x0271; + t.mhzsquare = 0x3392; + t.middledotkatakanahalfwidth = 0xff65; + t.middot = 0x00b7; + t.mieumacirclekorean = 0x3272; + t.mieumaparenkorean = 0x3212; + t.mieumcirclekorean = 0x3264; + t.mieumkorean = 0x3141; + t.mieumpansioskorean = 0x3170; + t.mieumparenkorean = 0x3204; + t.mieumpieupkorean = 0x316e; + t.mieumsioskorean = 0x316f; + t.mihiragana = 0x307f; + t.mikatakana = 0x30df; + t.mikatakanahalfwidth = 0xff90; + t.minus = 0x2212; + t.minusbelowcmb = 0x0320; + t.minuscircle = 0x2296; + t.minusmod = 0x02d7; + t.minusplus = 0x2213; + t.minute = 0x2032; + t.miribaarusquare = 0x334a; + t.mirisquare = 0x3349; + t.mlonglegturned = 0x0270; + t.mlsquare = 0x3396; + t.mmcubedsquare = 0x33a3; + t.mmonospace = 0xff4d; + t.mmsquaredsquare = 0x339f; + t.mohiragana = 0x3082; + t.mohmsquare = 0x33c1; + t.mokatakana = 0x30e2; + t.mokatakanahalfwidth = 0xff93; + t.molsquare = 0x33d6; + t.momathai = 0x0e21; + t.moverssquare = 0x33a7; + t.moverssquaredsquare = 0x33a8; + t.mparen = 0x24a8; + t.mpasquare = 0x33ab; + t.mssquare = 0x33b3; + t.msuperior = 0xf6ef; + t.mturned = 0x026f; + t.mu = 0x00b5; + t.mu1 = 0x00b5; + t.muasquare = 0x3382; + t.muchgreater = 0x226b; + t.muchless = 0x226a; + t.mufsquare = 0x338c; + t.mugreek = 0x03bc; + t.mugsquare = 0x338d; + t.muhiragana = 0x3080; + t.mukatakana = 0x30e0; + t.mukatakanahalfwidth = 0xff91; + t.mulsquare = 0x3395; + t.multiply = 0x00d7; + t.mumsquare = 0x339b; + t.munahhebrew = 0x05a3; + t.munahlefthebrew = 0x05a3; + t.musicalnote = 0x266a; + t.musicalnotedbl = 0x266b; + t.musicflatsign = 0x266d; + t.musicsharpsign = 0x266f; + t.mussquare = 0x33b2; + t.muvsquare = 0x33b6; + t.muwsquare = 0x33bc; + t.mvmegasquare = 0x33b9; + t.mvsquare = 0x33b7; + t.mwmegasquare = 0x33bf; + t.mwsquare = 0x33bd; + t.n = 0x006e; + t.nabengali = 0x09a8; + t.nabla = 0x2207; + t.nacute = 0x0144; + t.nadeva = 0x0928; + t.nagujarati = 0x0aa8; + t.nagurmukhi = 0x0a28; + t.nahiragana = 0x306a; + t.nakatakana = 0x30ca; + t.nakatakanahalfwidth = 0xff85; + t.napostrophe = 0x0149; + t.nasquare = 0x3381; + t.nbopomofo = 0x310b; + t.nbspace = 0x00a0; + t.ncaron = 0x0148; + t.ncedilla = 0x0146; + t.ncircle = 0x24dd; + t.ncircumflexbelow = 0x1e4b; + t.ncommaaccent = 0x0146; + t.ndotaccent = 0x1e45; + t.ndotbelow = 0x1e47; + t.nehiragana = 0x306d; + t.nekatakana = 0x30cd; + t.nekatakanahalfwidth = 0xff88; + t.newsheqelsign = 0x20aa; + t.nfsquare = 0x338b; + t.ngabengali = 0x0999; + t.ngadeva = 0x0919; + t.ngagujarati = 0x0a99; + t.ngagurmukhi = 0x0a19; + t.ngonguthai = 0x0e07; + t.nhiragana = 0x3093; + t.nhookleft = 0x0272; + t.nhookretroflex = 0x0273; + t.nieunacirclekorean = 0x326f; + t.nieunaparenkorean = 0x320f; + t.nieuncieuckorean = 0x3135; + t.nieuncirclekorean = 0x3261; + t.nieunhieuhkorean = 0x3136; + t.nieunkorean = 0x3134; + t.nieunpansioskorean = 0x3168; + t.nieunparenkorean = 0x3201; + t.nieunsioskorean = 0x3167; + t.nieuntikeutkorean = 0x3166; + t.nihiragana = 0x306b; + t.nikatakana = 0x30cb; + t.nikatakanahalfwidth = 0xff86; + t.nikhahitleftthai = 0xf899; + t.nikhahitthai = 0x0e4d; + t.nine = 0x0039; + t.ninearabic = 0x0669; + t.ninebengali = 0x09ef; + t.ninecircle = 0x2468; + t.ninecircleinversesansserif = 0x2792; + t.ninedeva = 0x096f; + t.ninegujarati = 0x0aef; + t.ninegurmukhi = 0x0a6f; + t.ninehackarabic = 0x0669; + t.ninehangzhou = 0x3029; + t.nineideographicparen = 0x3228; + t.nineinferior = 0x2089; + t.ninemonospace = 0xff19; + t.nineoldstyle = 0xf739; + t.nineparen = 0x247c; + t.nineperiod = 0x2490; + t.ninepersian = 0x06f9; + t.nineroman = 0x2178; + t.ninesuperior = 0x2079; + t.nineteencircle = 0x2472; + t.nineteenparen = 0x2486; + t.nineteenperiod = 0x249a; + t.ninethai = 0x0e59; + t.nj = 0x01cc; + t.njecyrillic = 0x045a; + t.nkatakana = 0x30f3; + t.nkatakanahalfwidth = 0xff9d; + t.nlegrightlong = 0x019e; + t.nlinebelow = 0x1e49; + t.nmonospace = 0xff4e; + t.nmsquare = 0x339a; + t.nnabengali = 0x09a3; + t.nnadeva = 0x0923; + t.nnagujarati = 0x0aa3; + t.nnagurmukhi = 0x0a23; + t.nnnadeva = 0x0929; + t.nohiragana = 0x306e; + t.nokatakana = 0x30ce; + t.nokatakanahalfwidth = 0xff89; + t.nonbreakingspace = 0x00a0; + t.nonenthai = 0x0e13; + t.nonuthai = 0x0e19; + t.noonarabic = 0x0646; + t.noonfinalarabic = 0xfee6; + t.noonghunnaarabic = 0x06ba; + t.noonghunnafinalarabic = 0xfb9f; + t.nooninitialarabic = 0xfee7; + t.noonjeeminitialarabic = 0xfcd2; + t.noonjeemisolatedarabic = 0xfc4b; + t.noonmedialarabic = 0xfee8; + t.noonmeeminitialarabic = 0xfcd5; + t.noonmeemisolatedarabic = 0xfc4e; + t.noonnoonfinalarabic = 0xfc8d; + t.notcontains = 0x220c; + t.notelement = 0x2209; + t.notelementof = 0x2209; + t.notequal = 0x2260; + t.notgreater = 0x226f; + t.notgreaternorequal = 0x2271; + t.notgreaternorless = 0x2279; + t.notidentical = 0x2262; + t.notless = 0x226e; + t.notlessnorequal = 0x2270; + t.notparallel = 0x2226; + t.notprecedes = 0x2280; + t.notsubset = 0x2284; + t.notsucceeds = 0x2281; + t.notsuperset = 0x2285; + t.nowarmenian = 0x0576; + t.nparen = 0x24a9; + t.nssquare = 0x33b1; + t.nsuperior = 0x207f; + t.ntilde = 0x00f1; + t.nu = 0x03bd; + t.nuhiragana = 0x306c; + t.nukatakana = 0x30cc; + t.nukatakanahalfwidth = 0xff87; + t.nuktabengali = 0x09bc; + t.nuktadeva = 0x093c; + t.nuktagujarati = 0x0abc; + t.nuktagurmukhi = 0x0a3c; + t.numbersign = 0x0023; + t.numbersignmonospace = 0xff03; + t.numbersignsmall = 0xfe5f; + t.numeralsigngreek = 0x0374; + t.numeralsignlowergreek = 0x0375; + t.numero = 0x2116; + t.nun = 0x05e0; + t.nundagesh = 0xfb40; + t.nundageshhebrew = 0xfb40; + t.nunhebrew = 0x05e0; + t.nvsquare = 0x33b5; + t.nwsquare = 0x33bb; + t.nyabengali = 0x099e; + t.nyadeva = 0x091e; + t.nyagujarati = 0x0a9e; + t.nyagurmukhi = 0x0a1e; + t.o = 0x006f; + t.oacute = 0x00f3; + t.oangthai = 0x0e2d; + t.obarred = 0x0275; + t.obarredcyrillic = 0x04e9; + t.obarreddieresiscyrillic = 0x04eb; + t.obengali = 0x0993; + t.obopomofo = 0x311b; + t.obreve = 0x014f; + t.ocandradeva = 0x0911; + t.ocandragujarati = 0x0a91; + t.ocandravowelsigndeva = 0x0949; + t.ocandravowelsigngujarati = 0x0ac9; + t.ocaron = 0x01d2; + t.ocircle = 0x24de; + t.ocircumflex = 0x00f4; + t.ocircumflexacute = 0x1ed1; + t.ocircumflexdotbelow = 0x1ed9; + t.ocircumflexgrave = 0x1ed3; + t.ocircumflexhookabove = 0x1ed5; + t.ocircumflextilde = 0x1ed7; + t.ocyrillic = 0x043e; + t.odblacute = 0x0151; + t.odblgrave = 0x020d; + t.odeva = 0x0913; + t.odieresis = 0x00f6; + t.odieresiscyrillic = 0x04e7; + t.odotbelow = 0x1ecd; + t.oe = 0x0153; + t.oekorean = 0x315a; + t.ogonek = 0x02db; + t.ogonekcmb = 0x0328; + t.ograve = 0x00f2; + t.ogujarati = 0x0a93; + t.oharmenian = 0x0585; + t.ohiragana = 0x304a; + t.ohookabove = 0x1ecf; + t.ohorn = 0x01a1; + t.ohornacute = 0x1edb; + t.ohorndotbelow = 0x1ee3; + t.ohorngrave = 0x1edd; + t.ohornhookabove = 0x1edf; + t.ohorntilde = 0x1ee1; + t.ohungarumlaut = 0x0151; + t.oi = 0x01a3; + t.oinvertedbreve = 0x020f; + t.okatakana = 0x30aa; + t.okatakanahalfwidth = 0xff75; + t.okorean = 0x3157; + t.olehebrew = 0x05ab; + t.omacron = 0x014d; + t.omacronacute = 0x1e53; + t.omacrongrave = 0x1e51; + t.omdeva = 0x0950; + t.omega = 0x03c9; + t.omega1 = 0x03d6; + t.omegacyrillic = 0x0461; + t.omegalatinclosed = 0x0277; + t.omegaroundcyrillic = 0x047b; + t.omegatitlocyrillic = 0x047d; + t.omegatonos = 0x03ce; + t.omgujarati = 0x0ad0; + t.omicron = 0x03bf; + t.omicrontonos = 0x03cc; + t.omonospace = 0xff4f; + t.one = 0x0031; + t.onearabic = 0x0661; + t.onebengali = 0x09e7; + t.onecircle = 0x2460; + t.onecircleinversesansserif = 0x278a; + t.onedeva = 0x0967; + t.onedotenleader = 0x2024; + t.oneeighth = 0x215b; + t.onefitted = 0xf6dc; + t.onegujarati = 0x0ae7; + t.onegurmukhi = 0x0a67; + t.onehackarabic = 0x0661; + t.onehalf = 0x00bd; + t.onehangzhou = 0x3021; + t.oneideographicparen = 0x3220; + t.oneinferior = 0x2081; + t.onemonospace = 0xff11; + t.onenumeratorbengali = 0x09f4; + t.oneoldstyle = 0xf731; + t.oneparen = 0x2474; + t.oneperiod = 0x2488; + t.onepersian = 0x06f1; + t.onequarter = 0x00bc; + t.oneroman = 0x2170; + t.onesuperior = 0x00b9; + t.onethai = 0x0e51; + t.onethird = 0x2153; + t.oogonek = 0x01eb; + t.oogonekmacron = 0x01ed; + t.oogurmukhi = 0x0a13; + t.oomatragurmukhi = 0x0a4b; + t.oopen = 0x0254; + t.oparen = 0x24aa; + t.openbullet = 0x25e6; + t.option = 0x2325; + t.ordfeminine = 0x00aa; + t.ordmasculine = 0x00ba; + t.orthogonal = 0x221f; + t.oshortdeva = 0x0912; + t.oshortvowelsigndeva = 0x094a; + t.oslash = 0x00f8; + t.oslashacute = 0x01ff; + t.osmallhiragana = 0x3049; + t.osmallkatakana = 0x30a9; + t.osmallkatakanahalfwidth = 0xff6b; + t.ostrokeacute = 0x01ff; + t.osuperior = 0xf6f0; + t.otcyrillic = 0x047f; + t.otilde = 0x00f5; + t.otildeacute = 0x1e4d; + t.otildedieresis = 0x1e4f; + t.oubopomofo = 0x3121; + t.overline = 0x203e; + t.overlinecenterline = 0xfe4a; + t.overlinecmb = 0x0305; + t.overlinedashed = 0xfe49; + t.overlinedblwavy = 0xfe4c; + t.overlinewavy = 0xfe4b; + t.overscore = 0x00af; + t.ovowelsignbengali = 0x09cb; + t.ovowelsigndeva = 0x094b; + t.ovowelsigngujarati = 0x0acb; + t.p = 0x0070; + t.paampssquare = 0x3380; + t.paasentosquare = 0x332b; + t.pabengali = 0x09aa; + t.pacute = 0x1e55; + t.padeva = 0x092a; + t.pagedown = 0x21df; + t.pageup = 0x21de; + t.pagujarati = 0x0aaa; + t.pagurmukhi = 0x0a2a; + t.pahiragana = 0x3071; + t.paiyannoithai = 0x0e2f; + t.pakatakana = 0x30d1; + t.palatalizationcyrilliccmb = 0x0484; + t.palochkacyrillic = 0x04c0; + t.pansioskorean = 0x317f; + t.paragraph = 0x00b6; + t.parallel = 0x2225; + t.parenleft = 0x0028; + t.parenleftaltonearabic = 0xfd3e; + t.parenleftbt = 0xf8ed; + t.parenleftex = 0xf8ec; + t.parenleftinferior = 0x208d; + t.parenleftmonospace = 0xff08; + t.parenleftsmall = 0xfe59; + t.parenleftsuperior = 0x207d; + t.parenlefttp = 0xf8eb; + t.parenleftvertical = 0xfe35; + t.parenright = 0x0029; + t.parenrightaltonearabic = 0xfd3f; + t.parenrightbt = 0xf8f8; + t.parenrightex = 0xf8f7; + t.parenrightinferior = 0x208e; + t.parenrightmonospace = 0xff09; + t.parenrightsmall = 0xfe5a; + t.parenrightsuperior = 0x207e; + t.parenrighttp = 0xf8f6; + t.parenrightvertical = 0xfe36; + t.partialdiff = 0x2202; + t.paseqhebrew = 0x05c0; + t.pashtahebrew = 0x0599; + t.pasquare = 0x33a9; + t.patah = 0x05b7; + t.patah11 = 0x05b7; + t.patah1d = 0x05b7; + t.patah2a = 0x05b7; + t.patahhebrew = 0x05b7; + t.patahnarrowhebrew = 0x05b7; + t.patahquarterhebrew = 0x05b7; + t.patahwidehebrew = 0x05b7; + t.pazerhebrew = 0x05a1; + t.pbopomofo = 0x3106; + t.pcircle = 0x24df; + t.pdotaccent = 0x1e57; + t.pe = 0x05e4; + t.pecyrillic = 0x043f; + t.pedagesh = 0xfb44; + t.pedageshhebrew = 0xfb44; + t.peezisquare = 0x333b; + t.pefinaldageshhebrew = 0xfb43; + t.peharabic = 0x067e; + t.peharmenian = 0x057a; + t.pehebrew = 0x05e4; + t.pehfinalarabic = 0xfb57; + t.pehinitialarabic = 0xfb58; + t.pehiragana = 0x307a; + t.pehmedialarabic = 0xfb59; + t.pekatakana = 0x30da; + t.pemiddlehookcyrillic = 0x04a7; + t.perafehebrew = 0xfb4e; + t.percent = 0x0025; + t.percentarabic = 0x066a; + t.percentmonospace = 0xff05; + t.percentsmall = 0xfe6a; + t.period = 0x002e; + t.periodarmenian = 0x0589; + t.periodcentered = 0x00b7; + t.periodhalfwidth = 0xff61; + t.periodinferior = 0xf6e7; + t.periodmonospace = 0xff0e; + t.periodsmall = 0xfe52; + t.periodsuperior = 0xf6e8; + t.perispomenigreekcmb = 0x0342; + t.perpendicular = 0x22a5; + t.perthousand = 0x2030; + t.peseta = 0x20a7; + t.pfsquare = 0x338a; + t.phabengali = 0x09ab; + t.phadeva = 0x092b; + t.phagujarati = 0x0aab; + t.phagurmukhi = 0x0a2b; + t.phi = 0x03c6; + t.phi1 = 0x03d5; + t.phieuphacirclekorean = 0x327a; + t.phieuphaparenkorean = 0x321a; + t.phieuphcirclekorean = 0x326c; + t.phieuphkorean = 0x314d; + t.phieuphparenkorean = 0x320c; + t.philatin = 0x0278; + t.phinthuthai = 0x0e3a; + t.phisymbolgreek = 0x03d5; + t.phook = 0x01a5; + t.phophanthai = 0x0e1e; + t.phophungthai = 0x0e1c; + t.phosamphaothai = 0x0e20; + t.pi = 0x03c0; + t.pieupacirclekorean = 0x3273; + t.pieupaparenkorean = 0x3213; + t.pieupcieuckorean = 0x3176; + t.pieupcirclekorean = 0x3265; + t.pieupkiyeokkorean = 0x3172; + t.pieupkorean = 0x3142; + t.pieupparenkorean = 0x3205; + t.pieupsioskiyeokkorean = 0x3174; + t.pieupsioskorean = 0x3144; + t.pieupsiostikeutkorean = 0x3175; + t.pieupthieuthkorean = 0x3177; + t.pieuptikeutkorean = 0x3173; + t.pihiragana = 0x3074; + t.pikatakana = 0x30d4; + t.pisymbolgreek = 0x03d6; + t.piwrarmenian = 0x0583; + t.planckover2pi = 0x210f; + t.planckover2pi1 = 0x210f; + t.plus = 0x002b; + t.plusbelowcmb = 0x031f; + t.pluscircle = 0x2295; + t.plusminus = 0x00b1; + t.plusmod = 0x02d6; + t.plusmonospace = 0xff0b; + t.plussmall = 0xfe62; + t.plussuperior = 0x207a; + t.pmonospace = 0xff50; + t.pmsquare = 0x33d8; + t.pohiragana = 0x307d; + t.pointingindexdownwhite = 0x261f; + t.pointingindexleftwhite = 0x261c; + t.pointingindexrightwhite = 0x261e; + t.pointingindexupwhite = 0x261d; + t.pokatakana = 0x30dd; + t.poplathai = 0x0e1b; + t.postalmark = 0x3012; + t.postalmarkface = 0x3020; + t.pparen = 0x24ab; + t.precedes = 0x227a; + t.prescription = 0x211e; + t.primemod = 0x02b9; + t.primereversed = 0x2035; + t.product = 0x220f; + t.projective = 0x2305; + t.prolongedkana = 0x30fc; + t.propellor = 0x2318; + t.propersubset = 0x2282; + t.propersuperset = 0x2283; + t.proportion = 0x2237; + t.proportional = 0x221d; + t.psi = 0x03c8; + t.psicyrillic = 0x0471; + t.psilipneumatacyrilliccmb = 0x0486; + t.pssquare = 0x33b0; + t.puhiragana = 0x3077; + t.pukatakana = 0x30d7; + t.pvsquare = 0x33b4; + t.pwsquare = 0x33ba; + t.q = 0x0071; + t.qadeva = 0x0958; + t.qadmahebrew = 0x05a8; + t.qafarabic = 0x0642; + t.qaffinalarabic = 0xfed6; + t.qafinitialarabic = 0xfed7; + t.qafmedialarabic = 0xfed8; + t.qamats = 0x05b8; + t.qamats10 = 0x05b8; + t.qamats1a = 0x05b8; + t.qamats1c = 0x05b8; + t.qamats27 = 0x05b8; + t.qamats29 = 0x05b8; + t.qamats33 = 0x05b8; + t.qamatsde = 0x05b8; + t.qamatshebrew = 0x05b8; + t.qamatsnarrowhebrew = 0x05b8; + t.qamatsqatanhebrew = 0x05b8; + t.qamatsqatannarrowhebrew = 0x05b8; + t.qamatsqatanquarterhebrew = 0x05b8; + t.qamatsqatanwidehebrew = 0x05b8; + t.qamatsquarterhebrew = 0x05b8; + t.qamatswidehebrew = 0x05b8; + t.qarneyparahebrew = 0x059f; + t.qbopomofo = 0x3111; + t.qcircle = 0x24e0; + t.qhook = 0x02a0; + t.qmonospace = 0xff51; + t.qof = 0x05e7; + t.qofdagesh = 0xfb47; + t.qofdageshhebrew = 0xfb47; + t.qofhebrew = 0x05e7; + t.qparen = 0x24ac; + t.quarternote = 0x2669; + t.qubuts = 0x05bb; + t.qubuts18 = 0x05bb; + t.qubuts25 = 0x05bb; + t.qubuts31 = 0x05bb; + t.qubutshebrew = 0x05bb; + t.qubutsnarrowhebrew = 0x05bb; + t.qubutsquarterhebrew = 0x05bb; + t.qubutswidehebrew = 0x05bb; + t.question = 0x003f; + t.questionarabic = 0x061f; + t.questionarmenian = 0x055e; + t.questiondown = 0x00bf; + t.questiondownsmall = 0xf7bf; + t.questiongreek = 0x037e; + t.questionmonospace = 0xff1f; + t.questionsmall = 0xf73f; + t.quotedbl = 0x0022; + t.quotedblbase = 0x201e; + t.quotedblleft = 0x201c; + t.quotedblmonospace = 0xff02; + t.quotedblprime = 0x301e; + t.quotedblprimereversed = 0x301d; + t.quotedblright = 0x201d; + t.quoteleft = 0x2018; + t.quoteleftreversed = 0x201b; + t.quotereversed = 0x201b; + t.quoteright = 0x2019; + t.quoterightn = 0x0149; + t.quotesinglbase = 0x201a; + t.quotesingle = 0x0027; + t.quotesinglemonospace = 0xff07; + t.r = 0x0072; + t.raarmenian = 0x057c; + t.rabengali = 0x09b0; + t.racute = 0x0155; + t.radeva = 0x0930; + t.radical = 0x221a; + t.radicalex = 0xf8e5; + t.radoverssquare = 0x33ae; + t.radoverssquaredsquare = 0x33af; + t.radsquare = 0x33ad; + t.rafe = 0x05bf; + t.rafehebrew = 0x05bf; + t.ragujarati = 0x0ab0; + t.ragurmukhi = 0x0a30; + t.rahiragana = 0x3089; + t.rakatakana = 0x30e9; + t.rakatakanahalfwidth = 0xff97; + t.ralowerdiagonalbengali = 0x09f1; + t.ramiddlediagonalbengali = 0x09f0; + t.ramshorn = 0x0264; + t.ratio = 0x2236; + t.rbopomofo = 0x3116; + t.rcaron = 0x0159; + t.rcedilla = 0x0157; + t.rcircle = 0x24e1; + t.rcommaaccent = 0x0157; + t.rdblgrave = 0x0211; + t.rdotaccent = 0x1e59; + t.rdotbelow = 0x1e5b; + t.rdotbelowmacron = 0x1e5d; + t.referencemark = 0x203b; + t.reflexsubset = 0x2286; + t.reflexsuperset = 0x2287; + t.registered = 0x00ae; + t.registersans = 0xf8e8; + t.registerserif = 0xf6da; + t.reharabic = 0x0631; + t.reharmenian = 0x0580; + t.rehfinalarabic = 0xfeae; + t.rehiragana = 0x308c; + t.rekatakana = 0x30ec; + t.rekatakanahalfwidth = 0xff9a; + t.resh = 0x05e8; + t.reshdageshhebrew = 0xfb48; + t.reshhebrew = 0x05e8; + t.reversedtilde = 0x223d; + t.reviahebrew = 0x0597; + t.reviamugrashhebrew = 0x0597; + t.revlogicalnot = 0x2310; + t.rfishhook = 0x027e; + t.rfishhookreversed = 0x027f; + t.rhabengali = 0x09dd; + t.rhadeva = 0x095d; + t.rho = 0x03c1; + t.rhook = 0x027d; + t.rhookturned = 0x027b; + t.rhookturnedsuperior = 0x02b5; + t.rhosymbolgreek = 0x03f1; + t.rhotichookmod = 0x02de; + t.rieulacirclekorean = 0x3271; + t.rieulaparenkorean = 0x3211; + t.rieulcirclekorean = 0x3263; + t.rieulhieuhkorean = 0x3140; + t.rieulkiyeokkorean = 0x313a; + t.rieulkiyeoksioskorean = 0x3169; + t.rieulkorean = 0x3139; + t.rieulmieumkorean = 0x313b; + t.rieulpansioskorean = 0x316c; + t.rieulparenkorean = 0x3203; + t.rieulphieuphkorean = 0x313f; + t.rieulpieupkorean = 0x313c; + t.rieulpieupsioskorean = 0x316b; + t.rieulsioskorean = 0x313d; + t.rieulthieuthkorean = 0x313e; + t.rieultikeutkorean = 0x316a; + t.rieulyeorinhieuhkorean = 0x316d; + t.rightangle = 0x221f; + t.righttackbelowcmb = 0x0319; + t.righttriangle = 0x22bf; + t.rihiragana = 0x308a; + t.rikatakana = 0x30ea; + t.rikatakanahalfwidth = 0xff98; + t.ring = 0x02da; + t.ringbelowcmb = 0x0325; + t.ringcmb = 0x030a; + t.ringhalfleft = 0x02bf; + t.ringhalfleftarmenian = 0x0559; + t.ringhalfleftbelowcmb = 0x031c; + t.ringhalfleftcentered = 0x02d3; + t.ringhalfright = 0x02be; + t.ringhalfrightbelowcmb = 0x0339; + t.ringhalfrightcentered = 0x02d2; + t.rinvertedbreve = 0x0213; + t.rittorusquare = 0x3351; + t.rlinebelow = 0x1e5f; + t.rlongleg = 0x027c; + t.rlonglegturned = 0x027a; + t.rmonospace = 0xff52; + t.rohiragana = 0x308d; + t.rokatakana = 0x30ed; + t.rokatakanahalfwidth = 0xff9b; + t.roruathai = 0x0e23; + t.rparen = 0x24ad; + t.rrabengali = 0x09dc; + t.rradeva = 0x0931; + t.rragurmukhi = 0x0a5c; + t.rreharabic = 0x0691; + t.rrehfinalarabic = 0xfb8d; + t.rrvocalicbengali = 0x09e0; + t.rrvocalicdeva = 0x0960; + t.rrvocalicgujarati = 0x0ae0; + t.rrvocalicvowelsignbengali = 0x09c4; + t.rrvocalicvowelsigndeva = 0x0944; + t.rrvocalicvowelsigngujarati = 0x0ac4; + t.rsuperior = 0xf6f1; + t.rtblock = 0x2590; + t.rturned = 0x0279; + t.rturnedsuperior = 0x02b4; + t.ruhiragana = 0x308b; + t.rukatakana = 0x30eb; + t.rukatakanahalfwidth = 0xff99; + t.rupeemarkbengali = 0x09f2; + t.rupeesignbengali = 0x09f3; + t.rupiah = 0xf6dd; + t.ruthai = 0x0e24; + t.rvocalicbengali = 0x098b; + t.rvocalicdeva = 0x090b; + t.rvocalicgujarati = 0x0a8b; + t.rvocalicvowelsignbengali = 0x09c3; + t.rvocalicvowelsigndeva = 0x0943; + t.rvocalicvowelsigngujarati = 0x0ac3; + t.s = 0x0073; + t.sabengali = 0x09b8; + t.sacute = 0x015b; + t.sacutedotaccent = 0x1e65; + t.sadarabic = 0x0635; + t.sadeva = 0x0938; + t.sadfinalarabic = 0xfeba; + t.sadinitialarabic = 0xfebb; + t.sadmedialarabic = 0xfebc; + t.sagujarati = 0x0ab8; + t.sagurmukhi = 0x0a38; + t.sahiragana = 0x3055; + t.sakatakana = 0x30b5; + t.sakatakanahalfwidth = 0xff7b; + t.sallallahoualayhewasallamarabic = 0xfdfa; + t.samekh = 0x05e1; + t.samekhdagesh = 0xfb41; + t.samekhdageshhebrew = 0xfb41; + t.samekhhebrew = 0x05e1; + t.saraaathai = 0x0e32; + t.saraaethai = 0x0e41; + t.saraaimaimalaithai = 0x0e44; + t.saraaimaimuanthai = 0x0e43; + t.saraamthai = 0x0e33; + t.saraathai = 0x0e30; + t.saraethai = 0x0e40; + t.saraiileftthai = 0xf886; + t.saraiithai = 0x0e35; + t.saraileftthai = 0xf885; + t.saraithai = 0x0e34; + t.saraothai = 0x0e42; + t.saraueeleftthai = 0xf888; + t.saraueethai = 0x0e37; + t.saraueleftthai = 0xf887; + t.sarauethai = 0x0e36; + t.sarauthai = 0x0e38; + t.sarauuthai = 0x0e39; + t.sbopomofo = 0x3119; + t.scaron = 0x0161; + t.scarondotaccent = 0x1e67; + t.scedilla = 0x015f; + t.schwa = 0x0259; + t.schwacyrillic = 0x04d9; + t.schwadieresiscyrillic = 0x04db; + t.schwahook = 0x025a; + t.scircle = 0x24e2; + t.scircumflex = 0x015d; + t.scommaaccent = 0x0219; + t.sdotaccent = 0x1e61; + t.sdotbelow = 0x1e63; + t.sdotbelowdotaccent = 0x1e69; + t.seagullbelowcmb = 0x033c; + t.second = 0x2033; + t.secondtonechinese = 0x02ca; + t.section = 0x00a7; + t.seenarabic = 0x0633; + t.seenfinalarabic = 0xfeb2; + t.seeninitialarabic = 0xfeb3; + t.seenmedialarabic = 0xfeb4; + t.segol = 0x05b6; + t.segol13 = 0x05b6; + t.segol1f = 0x05b6; + t.segol2c = 0x05b6; + t.segolhebrew = 0x05b6; + t.segolnarrowhebrew = 0x05b6; + t.segolquarterhebrew = 0x05b6; + t.segoltahebrew = 0x0592; + t.segolwidehebrew = 0x05b6; + t.seharmenian = 0x057d; + t.sehiragana = 0x305b; + t.sekatakana = 0x30bb; + t.sekatakanahalfwidth = 0xff7e; + t.semicolon = 0x003b; + t.semicolonarabic = 0x061b; + t.semicolonmonospace = 0xff1b; + t.semicolonsmall = 0xfe54; + t.semivoicedmarkkana = 0x309c; + t.semivoicedmarkkanahalfwidth = 0xff9f; + t.sentisquare = 0x3322; + t.sentosquare = 0x3323; + t.seven = 0x0037; + t.sevenarabic = 0x0667; + t.sevenbengali = 0x09ed; + t.sevencircle = 0x2466; + t.sevencircleinversesansserif = 0x2790; + t.sevendeva = 0x096d; + t.seveneighths = 0x215e; + t.sevengujarati = 0x0aed; + t.sevengurmukhi = 0x0a6d; + t.sevenhackarabic = 0x0667; + t.sevenhangzhou = 0x3027; + t.sevenideographicparen = 0x3226; + t.seveninferior = 0x2087; + t.sevenmonospace = 0xff17; + t.sevenoldstyle = 0xf737; + t.sevenparen = 0x247a; + t.sevenperiod = 0x248e; + t.sevenpersian = 0x06f7; + t.sevenroman = 0x2176; + t.sevensuperior = 0x2077; + t.seventeencircle = 0x2470; + t.seventeenparen = 0x2484; + t.seventeenperiod = 0x2498; + t.seventhai = 0x0e57; + t.sfthyphen = 0x00ad; + t.shaarmenian = 0x0577; + t.shabengali = 0x09b6; + t.shacyrillic = 0x0448; + t.shaddaarabic = 0x0651; + t.shaddadammaarabic = 0xfc61; + t.shaddadammatanarabic = 0xfc5e; + t.shaddafathaarabic = 0xfc60; + t.shaddakasraarabic = 0xfc62; + t.shaddakasratanarabic = 0xfc5f; + t.shade = 0x2592; + t.shadedark = 0x2593; + t.shadelight = 0x2591; + t.shademedium = 0x2592; + t.shadeva = 0x0936; + t.shagujarati = 0x0ab6; + t.shagurmukhi = 0x0a36; + t.shalshelethebrew = 0x0593; + t.shbopomofo = 0x3115; + t.shchacyrillic = 0x0449; + t.sheenarabic = 0x0634; + t.sheenfinalarabic = 0xfeb6; + t.sheeninitialarabic = 0xfeb7; + t.sheenmedialarabic = 0xfeb8; + t.sheicoptic = 0x03e3; + t.sheqel = 0x20aa; + t.sheqelhebrew = 0x20aa; + t.sheva = 0x05b0; + t.sheva115 = 0x05b0; + t.sheva15 = 0x05b0; + t.sheva22 = 0x05b0; + t.sheva2e = 0x05b0; + t.shevahebrew = 0x05b0; + t.shevanarrowhebrew = 0x05b0; + t.shevaquarterhebrew = 0x05b0; + t.shevawidehebrew = 0x05b0; + t.shhacyrillic = 0x04bb; + t.shimacoptic = 0x03ed; + t.shin = 0x05e9; + t.shindagesh = 0xfb49; + t.shindageshhebrew = 0xfb49; + t.shindageshshindot = 0xfb2c; + t.shindageshshindothebrew = 0xfb2c; + t.shindageshsindot = 0xfb2d; + t.shindageshsindothebrew = 0xfb2d; + t.shindothebrew = 0x05c1; + t.shinhebrew = 0x05e9; + t.shinshindot = 0xfb2a; + t.shinshindothebrew = 0xfb2a; + t.shinsindot = 0xfb2b; + t.shinsindothebrew = 0xfb2b; + t.shook = 0x0282; + t.sigma = 0x03c3; + t.sigma1 = 0x03c2; + t.sigmafinal = 0x03c2; + t.sigmalunatesymbolgreek = 0x03f2; + t.sihiragana = 0x3057; + t.sikatakana = 0x30b7; + t.sikatakanahalfwidth = 0xff7c; + t.siluqhebrew = 0x05bd; + t.siluqlefthebrew = 0x05bd; + t.similar = 0x223c; + t.sindothebrew = 0x05c2; + t.siosacirclekorean = 0x3274; + t.siosaparenkorean = 0x3214; + t.sioscieuckorean = 0x317e; + t.sioscirclekorean = 0x3266; + t.sioskiyeokkorean = 0x317a; + t.sioskorean = 0x3145; + t.siosnieunkorean = 0x317b; + t.siosparenkorean = 0x3206; + t.siospieupkorean = 0x317d; + t.siostikeutkorean = 0x317c; + t.six = 0x0036; + t.sixarabic = 0x0666; + t.sixbengali = 0x09ec; + t.sixcircle = 0x2465; + t.sixcircleinversesansserif = 0x278f; + t.sixdeva = 0x096c; + t.sixgujarati = 0x0aec; + t.sixgurmukhi = 0x0a6c; + t.sixhackarabic = 0x0666; + t.sixhangzhou = 0x3026; + t.sixideographicparen = 0x3225; + t.sixinferior = 0x2086; + t.sixmonospace = 0xff16; + t.sixoldstyle = 0xf736; + t.sixparen = 0x2479; + t.sixperiod = 0x248d; + t.sixpersian = 0x06f6; + t.sixroman = 0x2175; + t.sixsuperior = 0x2076; + t.sixteencircle = 0x246f; + t.sixteencurrencydenominatorbengali = 0x09f9; + t.sixteenparen = 0x2483; + t.sixteenperiod = 0x2497; + t.sixthai = 0x0e56; + t.slash = 0x002f; + t.slashmonospace = 0xff0f; + t.slong = 0x017f; + t.slongdotaccent = 0x1e9b; + t.smileface = 0x263a; + t.smonospace = 0xff53; + t.sofpasuqhebrew = 0x05c3; + t.softhyphen = 0x00ad; + t.softsigncyrillic = 0x044c; + t.sohiragana = 0x305d; + t.sokatakana = 0x30bd; + t.sokatakanahalfwidth = 0xff7f; + t.soliduslongoverlaycmb = 0x0338; + t.solidusshortoverlaycmb = 0x0337; + t.sorusithai = 0x0e29; + t.sosalathai = 0x0e28; + t.sosothai = 0x0e0b; + t.sosuathai = 0x0e2a; + t.space = 0x0020; + t.spacehackarabic = 0x0020; + t.spade = 0x2660; + t.spadesuitblack = 0x2660; + t.spadesuitwhite = 0x2664; + t.sparen = 0x24ae; + t.squarebelowcmb = 0x033b; + t.squarecc = 0x33c4; + t.squarecm = 0x339d; + t.squarediagonalcrosshatchfill = 0x25a9; + t.squarehorizontalfill = 0x25a4; + t.squarekg = 0x338f; + t.squarekm = 0x339e; + t.squarekmcapital = 0x33ce; + t.squareln = 0x33d1; + t.squarelog = 0x33d2; + t.squaremg = 0x338e; + t.squaremil = 0x33d5; + t.squaremm = 0x339c; + t.squaremsquared = 0x33a1; + t.squareorthogonalcrosshatchfill = 0x25a6; + t.squareupperlefttolowerrightfill = 0x25a7; + t.squareupperrighttolowerleftfill = 0x25a8; + t.squareverticalfill = 0x25a5; + t.squarewhitewithsmallblack = 0x25a3; + t.srsquare = 0x33db; + t.ssabengali = 0x09b7; + t.ssadeva = 0x0937; + t.ssagujarati = 0x0ab7; + t.ssangcieuckorean = 0x3149; + t.ssanghieuhkorean = 0x3185; + t.ssangieungkorean = 0x3180; + t.ssangkiyeokkorean = 0x3132; + t.ssangnieunkorean = 0x3165; + t.ssangpieupkorean = 0x3143; + t.ssangsioskorean = 0x3146; + t.ssangtikeutkorean = 0x3138; + t.ssuperior = 0xf6f2; + t.sterling = 0x00a3; + t.sterlingmonospace = 0xffe1; + t.strokelongoverlaycmb = 0x0336; + t.strokeshortoverlaycmb = 0x0335; + t.subset = 0x2282; + t.subsetnotequal = 0x228a; + t.subsetorequal = 0x2286; + t.succeeds = 0x227b; + t.suchthat = 0x220b; + t.suhiragana = 0x3059; + t.sukatakana = 0x30b9; + t.sukatakanahalfwidth = 0xff7d; + t.sukunarabic = 0x0652; + t.summation = 0x2211; + t.sun = 0x263c; + t.superset = 0x2283; + t.supersetnotequal = 0x228b; + t.supersetorequal = 0x2287; + t.svsquare = 0x33dc; + t.syouwaerasquare = 0x337c; + t.t = 0x0074; + t.tabengali = 0x09a4; + t.tackdown = 0x22a4; + t.tackleft = 0x22a3; + t.tadeva = 0x0924; + t.tagujarati = 0x0aa4; + t.tagurmukhi = 0x0a24; + t.taharabic = 0x0637; + t.tahfinalarabic = 0xfec2; + t.tahinitialarabic = 0xfec3; + t.tahiragana = 0x305f; + t.tahmedialarabic = 0xfec4; + t.taisyouerasquare = 0x337d; + t.takatakana = 0x30bf; + t.takatakanahalfwidth = 0xff80; + t.tatweelarabic = 0x0640; + t.tau = 0x03c4; + t.tav = 0x05ea; + t.tavdages = 0xfb4a; + t.tavdagesh = 0xfb4a; + t.tavdageshhebrew = 0xfb4a; + t.tavhebrew = 0x05ea; + t.tbar = 0x0167; + t.tbopomofo = 0x310a; + t.tcaron = 0x0165; + t.tccurl = 0x02a8; + t.tcedilla = 0x0163; + t.tcheharabic = 0x0686; + t.tchehfinalarabic = 0xfb7b; + t.tchehinitialarabic = 0xfb7c; + t.tchehmedialarabic = 0xfb7d; + t.tcircle = 0x24e3; + t.tcircumflexbelow = 0x1e71; + t.tcommaaccent = 0x0163; + t.tdieresis = 0x1e97; + t.tdotaccent = 0x1e6b; + t.tdotbelow = 0x1e6d; + t.tecyrillic = 0x0442; + t.tedescendercyrillic = 0x04ad; + t.teharabic = 0x062a; + t.tehfinalarabic = 0xfe96; + t.tehhahinitialarabic = 0xfca2; + t.tehhahisolatedarabic = 0xfc0c; + t.tehinitialarabic = 0xfe97; + t.tehiragana = 0x3066; + t.tehjeeminitialarabic = 0xfca1; + t.tehjeemisolatedarabic = 0xfc0b; + t.tehmarbutaarabic = 0x0629; + t.tehmarbutafinalarabic = 0xfe94; + t.tehmedialarabic = 0xfe98; + t.tehmeeminitialarabic = 0xfca4; + t.tehmeemisolatedarabic = 0xfc0e; + t.tehnoonfinalarabic = 0xfc73; + t.tekatakana = 0x30c6; + t.tekatakanahalfwidth = 0xff83; + t.telephone = 0x2121; + t.telephoneblack = 0x260e; + t.telishagedolahebrew = 0x05a0; + t.telishaqetanahebrew = 0x05a9; + t.tencircle = 0x2469; + t.tenideographicparen = 0x3229; + t.tenparen = 0x247d; + t.tenperiod = 0x2491; + t.tenroman = 0x2179; + t.tesh = 0x02a7; + t.tet = 0x05d8; + t.tetdagesh = 0xfb38; + t.tetdageshhebrew = 0xfb38; + t.tethebrew = 0x05d8; + t.tetsecyrillic = 0x04b5; + t.tevirhebrew = 0x059b; + t.tevirlefthebrew = 0x059b; + t.thabengali = 0x09a5; + t.thadeva = 0x0925; + t.thagujarati = 0x0aa5; + t.thagurmukhi = 0x0a25; + t.thalarabic = 0x0630; + t.thalfinalarabic = 0xfeac; + t.thanthakhatlowleftthai = 0xf898; + t.thanthakhatlowrightthai = 0xf897; + t.thanthakhatthai = 0x0e4c; + t.thanthakhatupperleftthai = 0xf896; + t.theharabic = 0x062b; + t.thehfinalarabic = 0xfe9a; + t.thehinitialarabic = 0xfe9b; + t.thehmedialarabic = 0xfe9c; + t.thereexists = 0x2203; + t.therefore = 0x2234; + t.theta = 0x03b8; + t.theta1 = 0x03d1; + t.thetasymbolgreek = 0x03d1; + t.thieuthacirclekorean = 0x3279; + t.thieuthaparenkorean = 0x3219; + t.thieuthcirclekorean = 0x326b; + t.thieuthkorean = 0x314c; + t.thieuthparenkorean = 0x320b; + t.thirteencircle = 0x246c; + t.thirteenparen = 0x2480; + t.thirteenperiod = 0x2494; + t.thonangmonthothai = 0x0e11; + t.thook = 0x01ad; + t.thophuthaothai = 0x0e12; + t.thorn = 0x00fe; + t.thothahanthai = 0x0e17; + t.thothanthai = 0x0e10; + t.thothongthai = 0x0e18; + t.thothungthai = 0x0e16; + t.thousandcyrillic = 0x0482; + t.thousandsseparatorarabic = 0x066c; + t.thousandsseparatorpersian = 0x066c; + t.three = 0x0033; + t.threearabic = 0x0663; + t.threebengali = 0x09e9; + t.threecircle = 0x2462; + t.threecircleinversesansserif = 0x278c; + t.threedeva = 0x0969; + t.threeeighths = 0x215c; + t.threegujarati = 0x0ae9; + t.threegurmukhi = 0x0a69; + t.threehackarabic = 0x0663; + t.threehangzhou = 0x3023; + t.threeideographicparen = 0x3222; + t.threeinferior = 0x2083; + t.threemonospace = 0xff13; + t.threenumeratorbengali = 0x09f6; + t.threeoldstyle = 0xf733; + t.threeparen = 0x2476; + t.threeperiod = 0x248a; + t.threepersian = 0x06f3; + t.threequarters = 0x00be; + t.threequartersemdash = 0xf6de; + t.threeroman = 0x2172; + t.threesuperior = 0x00b3; + t.threethai = 0x0e53; + t.thzsquare = 0x3394; + t.tihiragana = 0x3061; + t.tikatakana = 0x30c1; + t.tikatakanahalfwidth = 0xff81; + t.tikeutacirclekorean = 0x3270; + t.tikeutaparenkorean = 0x3210; + t.tikeutcirclekorean = 0x3262; + t.tikeutkorean = 0x3137; + t.tikeutparenkorean = 0x3202; + t.tilde = 0x02dc; + t.tildebelowcmb = 0x0330; + t.tildecmb = 0x0303; + t.tildecomb = 0x0303; + t.tildedoublecmb = 0x0360; + t.tildeoperator = 0x223c; + t.tildeoverlaycmb = 0x0334; + t.tildeverticalcmb = 0x033e; + t.timescircle = 0x2297; + t.tipehahebrew = 0x0596; + t.tipehalefthebrew = 0x0596; + t.tippigurmukhi = 0x0a70; + t.titlocyrilliccmb = 0x0483; + t.tiwnarmenian = 0x057f; + t.tlinebelow = 0x1e6f; + t.tmonospace = 0xff54; + t.toarmenian = 0x0569; + t.tohiragana = 0x3068; + t.tokatakana = 0x30c8; + t.tokatakanahalfwidth = 0xff84; + t.tonebarextrahighmod = 0x02e5; + t.tonebarextralowmod = 0x02e9; + t.tonebarhighmod = 0x02e6; + t.tonebarlowmod = 0x02e8; + t.tonebarmidmod = 0x02e7; + t.tonefive = 0x01bd; + t.tonesix = 0x0185; + t.tonetwo = 0x01a8; + t.tonos = 0x0384; + t.tonsquare = 0x3327; + t.topatakthai = 0x0e0f; + t.tortoiseshellbracketleft = 0x3014; + t.tortoiseshellbracketleftsmall = 0xfe5d; + t.tortoiseshellbracketleftvertical = 0xfe39; + t.tortoiseshellbracketright = 0x3015; + t.tortoiseshellbracketrightsmall = 0xfe5e; + t.tortoiseshellbracketrightvertical = 0xfe3a; + t.totaothai = 0x0e15; + t.tpalatalhook = 0x01ab; + t.tparen = 0x24af; + t.trademark = 0x2122; + t.trademarksans = 0xf8ea; + t.trademarkserif = 0xf6db; + t.tretroflexhook = 0x0288; + t.triagdn = 0x25bc; + t.triaglf = 0x25c4; + t.triagrt = 0x25ba; + t.triagup = 0x25b2; + t.ts = 0x02a6; + t.tsadi = 0x05e6; + t.tsadidagesh = 0xfb46; + t.tsadidageshhebrew = 0xfb46; + t.tsadihebrew = 0x05e6; + t.tsecyrillic = 0x0446; + t.tsere = 0x05b5; + t.tsere12 = 0x05b5; + t.tsere1e = 0x05b5; + t.tsere2b = 0x05b5; + t.tserehebrew = 0x05b5; + t.tserenarrowhebrew = 0x05b5; + t.tserequarterhebrew = 0x05b5; + t.tserewidehebrew = 0x05b5; + t.tshecyrillic = 0x045b; + t.tsuperior = 0xf6f3; + t.ttabengali = 0x099f; + t.ttadeva = 0x091f; + t.ttagujarati = 0x0a9f; + t.ttagurmukhi = 0x0a1f; + t.tteharabic = 0x0679; + t.ttehfinalarabic = 0xfb67; + t.ttehinitialarabic = 0xfb68; + t.ttehmedialarabic = 0xfb69; + t.tthabengali = 0x09a0; + t.tthadeva = 0x0920; + t.tthagujarati = 0x0aa0; + t.tthagurmukhi = 0x0a20; + t.tturned = 0x0287; + t.tuhiragana = 0x3064; + t.tukatakana = 0x30c4; + t.tukatakanahalfwidth = 0xff82; + t.tusmallhiragana = 0x3063; + t.tusmallkatakana = 0x30c3; + t.tusmallkatakanahalfwidth = 0xff6f; + t.twelvecircle = 0x246b; + t.twelveparen = 0x247f; + t.twelveperiod = 0x2493; + t.twelveroman = 0x217b; + t.twentycircle = 0x2473; + t.twentyhangzhou = 0x5344; + t.twentyparen = 0x2487; + t.twentyperiod = 0x249b; + t.two = 0x0032; + t.twoarabic = 0x0662; + t.twobengali = 0x09e8; + t.twocircle = 0x2461; + t.twocircleinversesansserif = 0x278b; + t.twodeva = 0x0968; + t.twodotenleader = 0x2025; + t.twodotleader = 0x2025; + t.twodotleadervertical = 0xfe30; + t.twogujarati = 0x0ae8; + t.twogurmukhi = 0x0a68; + t.twohackarabic = 0x0662; + t.twohangzhou = 0x3022; + t.twoideographicparen = 0x3221; + t.twoinferior = 0x2082; + t.twomonospace = 0xff12; + t.twonumeratorbengali = 0x09f5; + t.twooldstyle = 0xf732; + t.twoparen = 0x2475; + t.twoperiod = 0x2489; + t.twopersian = 0x06f2; + t.tworoman = 0x2171; + t.twostroke = 0x01bb; + t.twosuperior = 0x00b2; + t.twothai = 0x0e52; + t.twothirds = 0x2154; + t.u = 0x0075; + t.uacute = 0x00fa; + t.ubar = 0x0289; + t.ubengali = 0x0989; + t.ubopomofo = 0x3128; + t.ubreve = 0x016d; + t.ucaron = 0x01d4; + t.ucircle = 0x24e4; + t.ucircumflex = 0x00fb; + t.ucircumflexbelow = 0x1e77; + t.ucyrillic = 0x0443; + t.udattadeva = 0x0951; + t.udblacute = 0x0171; + t.udblgrave = 0x0215; + t.udeva = 0x0909; + t.udieresis = 0x00fc; + t.udieresisacute = 0x01d8; + t.udieresisbelow = 0x1e73; + t.udieresiscaron = 0x01da; + t.udieresiscyrillic = 0x04f1; + t.udieresisgrave = 0x01dc; + t.udieresismacron = 0x01d6; + t.udotbelow = 0x1ee5; + t.ugrave = 0x00f9; + t.ugujarati = 0x0a89; + t.ugurmukhi = 0x0a09; + t.uhiragana = 0x3046; + t.uhookabove = 0x1ee7; + t.uhorn = 0x01b0; + t.uhornacute = 0x1ee9; + t.uhorndotbelow = 0x1ef1; + t.uhorngrave = 0x1eeb; + t.uhornhookabove = 0x1eed; + t.uhorntilde = 0x1eef; + t.uhungarumlaut = 0x0171; + t.uhungarumlautcyrillic = 0x04f3; + t.uinvertedbreve = 0x0217; + t.ukatakana = 0x30a6; + t.ukatakanahalfwidth = 0xff73; + t.ukcyrillic = 0x0479; + t.ukorean = 0x315c; + t.umacron = 0x016b; + t.umacroncyrillic = 0x04ef; + t.umacrondieresis = 0x1e7b; + t.umatragurmukhi = 0x0a41; + t.umonospace = 0xff55; + t.underscore = 0x005f; + t.underscoredbl = 0x2017; + t.underscoremonospace = 0xff3f; + t.underscorevertical = 0xfe33; + t.underscorewavy = 0xfe4f; + t.union = 0x222a; + t.universal = 0x2200; + t.uogonek = 0x0173; + t.uparen = 0x24b0; + t.upblock = 0x2580; + t.upperdothebrew = 0x05c4; + t.upsilon = 0x03c5; + t.upsilondieresis = 0x03cb; + t.upsilondieresistonos = 0x03b0; + t.upsilonlatin = 0x028a; + t.upsilontonos = 0x03cd; + t.uptackbelowcmb = 0x031d; + t.uptackmod = 0x02d4; + t.uragurmukhi = 0x0a73; + t.uring = 0x016f; + t.ushortcyrillic = 0x045e; + t.usmallhiragana = 0x3045; + t.usmallkatakana = 0x30a5; + t.usmallkatakanahalfwidth = 0xff69; + t.ustraightcyrillic = 0x04af; + t.ustraightstrokecyrillic = 0x04b1; + t.utilde = 0x0169; + t.utildeacute = 0x1e79; + t.utildebelow = 0x1e75; + t.uubengali = 0x098a; + t.uudeva = 0x090a; + t.uugujarati = 0x0a8a; + t.uugurmukhi = 0x0a0a; + t.uumatragurmukhi = 0x0a42; + t.uuvowelsignbengali = 0x09c2; + t.uuvowelsigndeva = 0x0942; + t.uuvowelsigngujarati = 0x0ac2; + t.uvowelsignbengali = 0x09c1; + t.uvowelsigndeva = 0x0941; + t.uvowelsigngujarati = 0x0ac1; + t.v = 0x0076; + t.vadeva = 0x0935; + t.vagujarati = 0x0ab5; + t.vagurmukhi = 0x0a35; + t.vakatakana = 0x30f7; + t.vav = 0x05d5; + t.vavdagesh = 0xfb35; + t.vavdagesh65 = 0xfb35; + t.vavdageshhebrew = 0xfb35; + t.vavhebrew = 0x05d5; + t.vavholam = 0xfb4b; + t.vavholamhebrew = 0xfb4b; + t.vavvavhebrew = 0x05f0; + t.vavyodhebrew = 0x05f1; + t.vcircle = 0x24e5; + t.vdotbelow = 0x1e7f; + t.vecyrillic = 0x0432; + t.veharabic = 0x06a4; + t.vehfinalarabic = 0xfb6b; + t.vehinitialarabic = 0xfb6c; + t.vehmedialarabic = 0xfb6d; + t.vekatakana = 0x30f9; + t.venus = 0x2640; + t.verticalbar = 0x007c; + t.verticallineabovecmb = 0x030d; + t.verticallinebelowcmb = 0x0329; + t.verticallinelowmod = 0x02cc; + t.verticallinemod = 0x02c8; + t.vewarmenian = 0x057e; + t.vhook = 0x028b; + t.vikatakana = 0x30f8; + t.viramabengali = 0x09cd; + t.viramadeva = 0x094d; + t.viramagujarati = 0x0acd; + t.visargabengali = 0x0983; + t.visargadeva = 0x0903; + t.visargagujarati = 0x0a83; + t.vmonospace = 0xff56; + t.voarmenian = 0x0578; + t.voicediterationhiragana = 0x309e; + t.voicediterationkatakana = 0x30fe; + t.voicedmarkkana = 0x309b; + t.voicedmarkkanahalfwidth = 0xff9e; + t.vokatakana = 0x30fa; + t.vparen = 0x24b1; + t.vtilde = 0x1e7d; + t.vturned = 0x028c; + t.vuhiragana = 0x3094; + t.vukatakana = 0x30f4; + t.w = 0x0077; + t.wacute = 0x1e83; + t.waekorean = 0x3159; + t.wahiragana = 0x308f; + t.wakatakana = 0x30ef; + t.wakatakanahalfwidth = 0xff9c; + t.wakorean = 0x3158; + t.wasmallhiragana = 0x308e; + t.wasmallkatakana = 0x30ee; + t.wattosquare = 0x3357; + t.wavedash = 0x301c; + t.wavyunderscorevertical = 0xfe34; + t.wawarabic = 0x0648; + t.wawfinalarabic = 0xfeee; + t.wawhamzaabovearabic = 0x0624; + t.wawhamzaabovefinalarabic = 0xfe86; + t.wbsquare = 0x33dd; + t.wcircle = 0x24e6; + t.wcircumflex = 0x0175; + t.wdieresis = 0x1e85; + t.wdotaccent = 0x1e87; + t.wdotbelow = 0x1e89; + t.wehiragana = 0x3091; + t.weierstrass = 0x2118; + t.wekatakana = 0x30f1; + t.wekorean = 0x315e; + t.weokorean = 0x315d; + t.wgrave = 0x1e81; + t.whitebullet = 0x25e6; + t.whitecircle = 0x25cb; + t.whitecircleinverse = 0x25d9; + t.whitecornerbracketleft = 0x300e; + t.whitecornerbracketleftvertical = 0xfe43; + t.whitecornerbracketright = 0x300f; + t.whitecornerbracketrightvertical = 0xfe44; + t.whitediamond = 0x25c7; + t.whitediamondcontainingblacksmalldiamond = 0x25c8; + t.whitedownpointingsmalltriangle = 0x25bf; + t.whitedownpointingtriangle = 0x25bd; + t.whiteleftpointingsmalltriangle = 0x25c3; + t.whiteleftpointingtriangle = 0x25c1; + t.whitelenticularbracketleft = 0x3016; + t.whitelenticularbracketright = 0x3017; + t.whiterightpointingsmalltriangle = 0x25b9; + t.whiterightpointingtriangle = 0x25b7; + t.whitesmallsquare = 0x25ab; + t.whitesmilingface = 0x263a; + t.whitesquare = 0x25a1; + t.whitestar = 0x2606; + t.whitetelephone = 0x260f; + t.whitetortoiseshellbracketleft = 0x3018; + t.whitetortoiseshellbracketright = 0x3019; + t.whiteuppointingsmalltriangle = 0x25b5; + t.whiteuppointingtriangle = 0x25b3; + t.wihiragana = 0x3090; + t.wikatakana = 0x30f0; + t.wikorean = 0x315f; + t.wmonospace = 0xff57; + t.wohiragana = 0x3092; + t.wokatakana = 0x30f2; + t.wokatakanahalfwidth = 0xff66; + t.won = 0x20a9; + t.wonmonospace = 0xffe6; + t.wowaenthai = 0x0e27; + t.wparen = 0x24b2; + t.wring = 0x1e98; + t.wsuperior = 0x02b7; + t.wturned = 0x028d; + t.wynn = 0x01bf; + t.x = 0x0078; + t.xabovecmb = 0x033d; + t.xbopomofo = 0x3112; + t.xcircle = 0x24e7; + t.xdieresis = 0x1e8d; + t.xdotaccent = 0x1e8b; + t.xeharmenian = 0x056d; + t.xi = 0x03be; + t.xmonospace = 0xff58; + t.xparen = 0x24b3; + t.xsuperior = 0x02e3; + t.y = 0x0079; + t.yaadosquare = 0x334e; + t.yabengali = 0x09af; + t.yacute = 0x00fd; + t.yadeva = 0x092f; + t.yaekorean = 0x3152; + t.yagujarati = 0x0aaf; + t.yagurmukhi = 0x0a2f; + t.yahiragana = 0x3084; + t.yakatakana = 0x30e4; + t.yakatakanahalfwidth = 0xff94; + t.yakorean = 0x3151; + t.yamakkanthai = 0x0e4e; + t.yasmallhiragana = 0x3083; + t.yasmallkatakana = 0x30e3; + t.yasmallkatakanahalfwidth = 0xff6c; + t.yatcyrillic = 0x0463; + t.ycircle = 0x24e8; + t.ycircumflex = 0x0177; + t.ydieresis = 0x00ff; + t.ydotaccent = 0x1e8f; + t.ydotbelow = 0x1ef5; + t.yeharabic = 0x064a; + t.yehbarreearabic = 0x06d2; + t.yehbarreefinalarabic = 0xfbaf; + t.yehfinalarabic = 0xfef2; + t.yehhamzaabovearabic = 0x0626; + t.yehhamzaabovefinalarabic = 0xfe8a; + t.yehhamzaaboveinitialarabic = 0xfe8b; + t.yehhamzaabovemedialarabic = 0xfe8c; + t.yehinitialarabic = 0xfef3; + t.yehmedialarabic = 0xfef4; + t.yehmeeminitialarabic = 0xfcdd; + t.yehmeemisolatedarabic = 0xfc58; + t.yehnoonfinalarabic = 0xfc94; + t.yehthreedotsbelowarabic = 0x06d1; + t.yekorean = 0x3156; + t.yen = 0x00a5; + t.yenmonospace = 0xffe5; + t.yeokorean = 0x3155; + t.yeorinhieuhkorean = 0x3186; + t.yerahbenyomohebrew = 0x05aa; + t.yerahbenyomolefthebrew = 0x05aa; + t.yericyrillic = 0x044b; + t.yerudieresiscyrillic = 0x04f9; + t.yesieungkorean = 0x3181; + t.yesieungpansioskorean = 0x3183; + t.yesieungsioskorean = 0x3182; + t.yetivhebrew = 0x059a; + t.ygrave = 0x1ef3; + t.yhook = 0x01b4; + t.yhookabove = 0x1ef7; + t.yiarmenian = 0x0575; + t.yicyrillic = 0x0457; + t.yikorean = 0x3162; + t.yinyang = 0x262f; + t.yiwnarmenian = 0x0582; + t.ymonospace = 0xff59; + t.yod = 0x05d9; + t.yoddagesh = 0xfb39; + t.yoddageshhebrew = 0xfb39; + t.yodhebrew = 0x05d9; + t.yodyodhebrew = 0x05f2; + t.yodyodpatahhebrew = 0xfb1f; + t.yohiragana = 0x3088; + t.yoikorean = 0x3189; + t.yokatakana = 0x30e8; + t.yokatakanahalfwidth = 0xff96; + t.yokorean = 0x315b; + t.yosmallhiragana = 0x3087; + t.yosmallkatakana = 0x30e7; + t.yosmallkatakanahalfwidth = 0xff6e; + t.yotgreek = 0x03f3; + t.yoyaekorean = 0x3188; + t.yoyakorean = 0x3187; + t.yoyakthai = 0x0e22; + t.yoyingthai = 0x0e0d; + t.yparen = 0x24b4; + t.ypogegrammeni = 0x037a; + t.ypogegrammenigreekcmb = 0x0345; + t.yr = 0x01a6; + t.yring = 0x1e99; + t.ysuperior = 0x02b8; + t.ytilde = 0x1ef9; + t.yturned = 0x028e; + t.yuhiragana = 0x3086; + t.yuikorean = 0x318c; + t.yukatakana = 0x30e6; + t.yukatakanahalfwidth = 0xff95; + t.yukorean = 0x3160; + t.yusbigcyrillic = 0x046b; + t.yusbigiotifiedcyrillic = 0x046d; + t.yuslittlecyrillic = 0x0467; + t.yuslittleiotifiedcyrillic = 0x0469; + t.yusmallhiragana = 0x3085; + t.yusmallkatakana = 0x30e5; + t.yusmallkatakanahalfwidth = 0xff6d; + t.yuyekorean = 0x318b; + t.yuyeokorean = 0x318a; + t.yyabengali = 0x09df; + t.yyadeva = 0x095f; + t.z = 0x007a; + t.zaarmenian = 0x0566; + t.zacute = 0x017a; + t.zadeva = 0x095b; + t.zagurmukhi = 0x0a5b; + t.zaharabic = 0x0638; + t.zahfinalarabic = 0xfec6; + t.zahinitialarabic = 0xfec7; + t.zahiragana = 0x3056; + t.zahmedialarabic = 0xfec8; + t.zainarabic = 0x0632; + t.zainfinalarabic = 0xfeb0; + t.zakatakana = 0x30b6; + t.zaqefgadolhebrew = 0x0595; + t.zaqefqatanhebrew = 0x0594; + t.zarqahebrew = 0x0598; + t.zayin = 0x05d6; + t.zayindagesh = 0xfb36; + t.zayindageshhebrew = 0xfb36; + t.zayinhebrew = 0x05d6; + t.zbopomofo = 0x3117; + t.zcaron = 0x017e; + t.zcircle = 0x24e9; + t.zcircumflex = 0x1e91; + t.zcurl = 0x0291; + t.zdot = 0x017c; + t.zdotaccent = 0x017c; + t.zdotbelow = 0x1e93; + t.zecyrillic = 0x0437; + t.zedescendercyrillic = 0x0499; + t.zedieresiscyrillic = 0x04df; + t.zehiragana = 0x305c; + t.zekatakana = 0x30bc; + t.zero = 0x0030; + t.zeroarabic = 0x0660; + t.zerobengali = 0x09e6; + t.zerodeva = 0x0966; + t.zerogujarati = 0x0ae6; + t.zerogurmukhi = 0x0a66; + t.zerohackarabic = 0x0660; + t.zeroinferior = 0x2080; + t.zeromonospace = 0xff10; + t.zerooldstyle = 0xf730; + t.zeropersian = 0x06f0; + t.zerosuperior = 0x2070; + t.zerothai = 0x0e50; + t.zerowidthjoiner = 0xfeff; + t.zerowidthnonjoiner = 0x200c; + t.zerowidthspace = 0x200b; + t.zeta = 0x03b6; + t.zhbopomofo = 0x3113; + t.zhearmenian = 0x056a; + t.zhebrevecyrillic = 0x04c2; + t.zhecyrillic = 0x0436; + t.zhedescendercyrillic = 0x0497; + t.zhedieresiscyrillic = 0x04dd; + t.zihiragana = 0x3058; + t.zikatakana = 0x30b8; + t.zinorhebrew = 0x05ae; + t.zlinebelow = 0x1e95; + t.zmonospace = 0xff5a; + t.zohiragana = 0x305e; + t.zokatakana = 0x30be; + t.zparen = 0x24b5; + t.zretroflexhook = 0x0290; + t.zstroke = 0x01b6; + t.zuhiragana = 0x305a; + t.zukatakana = 0x30ba; + t[".notdef"] = 0x0000; + t.angbracketleftbig = 0x2329; + t.angbracketleftBig = 0x2329; + t.angbracketleftbigg = 0x2329; + t.angbracketleftBigg = 0x2329; + t.angbracketrightBig = 0x232a; + t.angbracketrightbig = 0x232a; + t.angbracketrightBigg = 0x232a; + t.angbracketrightbigg = 0x232a; + t.arrowhookleft = 0x21aa; + t.arrowhookright = 0x21a9; + t.arrowlefttophalf = 0x21bc; + t.arrowleftbothalf = 0x21bd; + t.arrownortheast = 0x2197; + t.arrownorthwest = 0x2196; + t.arrowrighttophalf = 0x21c0; + t.arrowrightbothalf = 0x21c1; + t.arrowsoutheast = 0x2198; + t.arrowsouthwest = 0x2199; + t.backslashbig = 0x2216; + t.backslashBig = 0x2216; + t.backslashBigg = 0x2216; + t.backslashbigg = 0x2216; + t.bardbl = 0x2016; + t.bracehtipdownleft = 0xfe37; + t.bracehtipdownright = 0xfe37; + t.bracehtipupleft = 0xfe38; + t.bracehtipupright = 0xfe38; + t.braceleftBig = 0x007b; + t.braceleftbig = 0x007b; + t.braceleftbigg = 0x007b; + t.braceleftBigg = 0x007b; + t.bracerightBig = 0x007d; + t.bracerightbig = 0x007d; + t.bracerightbigg = 0x007d; + t.bracerightBigg = 0x007d; + t.bracketleftbig = 0x005b; + t.bracketleftBig = 0x005b; + t.bracketleftbigg = 0x005b; + t.bracketleftBigg = 0x005b; + t.bracketrightBig = 0x005d; + t.bracketrightbig = 0x005d; + t.bracketrightbigg = 0x005d; + t.bracketrightBigg = 0x005d; + t.ceilingleftbig = 0x2308; + t.ceilingleftBig = 0x2308; + t.ceilingleftBigg = 0x2308; + t.ceilingleftbigg = 0x2308; + t.ceilingrightbig = 0x2309; + t.ceilingrightBig = 0x2309; + t.ceilingrightbigg = 0x2309; + t.ceilingrightBigg = 0x2309; + t.circledotdisplay = 0x2299; + t.circledottext = 0x2299; + t.circlemultiplydisplay = 0x2297; + t.circlemultiplytext = 0x2297; + t.circleplusdisplay = 0x2295; + t.circleplustext = 0x2295; + t.contintegraldisplay = 0x222e; + t.contintegraltext = 0x222e; + t.coproductdisplay = 0x2210; + t.coproducttext = 0x2210; + t.floorleftBig = 0x230a; + t.floorleftbig = 0x230a; + t.floorleftbigg = 0x230a; + t.floorleftBigg = 0x230a; + t.floorrightbig = 0x230b; + t.floorrightBig = 0x230b; + t.floorrightBigg = 0x230b; + t.floorrightbigg = 0x230b; + t.hatwide = 0x0302; + t.hatwider = 0x0302; + t.hatwidest = 0x0302; + t.intercal = 0x1d40; + t.integraldisplay = 0x222b; + t.integraltext = 0x222b; + t.intersectiondisplay = 0x22c2; + t.intersectiontext = 0x22c2; + t.logicalanddisplay = 0x2227; + t.logicalandtext = 0x2227; + t.logicalordisplay = 0x2228; + t.logicalortext = 0x2228; + t.parenleftBig = 0x0028; + t.parenleftbig = 0x0028; + t.parenleftBigg = 0x0028; + t.parenleftbigg = 0x0028; + t.parenrightBig = 0x0029; + t.parenrightbig = 0x0029; + t.parenrightBigg = 0x0029; + t.parenrightbigg = 0x0029; + t.prime = 0x2032; + t.productdisplay = 0x220f; + t.producttext = 0x220f; + t.radicalbig = 0x221a; + t.radicalBig = 0x221a; + t.radicalBigg = 0x221a; + t.radicalbigg = 0x221a; + t.radicalbt = 0x221a; + t.radicaltp = 0x221a; + t.radicalvertex = 0x221a; + t.slashbig = 0x002f; + t.slashBig = 0x002f; + t.slashBigg = 0x002f; + t.slashbigg = 0x002f; + t.summationdisplay = 0x2211; + t.summationtext = 0x2211; + t.tildewide = 0x02dc; + t.tildewider = 0x02dc; + t.tildewidest = 0x02dc; + t.uniondisplay = 0x22c3; + t.unionmultidisplay = 0x228e; + t.unionmultitext = 0x228e; + t.unionsqdisplay = 0x2294; + t.unionsqtext = 0x2294; + t.uniontext = 0x22c3; + t.vextenddouble = 0x2225; + t.vextendsingle = 0x2223; +}); +const getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) { + t.space = 0x0020; + t.a1 = 0x2701; + t.a2 = 0x2702; + t.a202 = 0x2703; + t.a3 = 0x2704; + t.a4 = 0x260e; + t.a5 = 0x2706; + t.a119 = 0x2707; + t.a118 = 0x2708; + t.a117 = 0x2709; + t.a11 = 0x261b; + t.a12 = 0x261e; + t.a13 = 0x270c; + t.a14 = 0x270d; + t.a15 = 0x270e; + t.a16 = 0x270f; + t.a105 = 0x2710; + t.a17 = 0x2711; + t.a18 = 0x2712; + t.a19 = 0x2713; + t.a20 = 0x2714; + t.a21 = 0x2715; + t.a22 = 0x2716; + t.a23 = 0x2717; + t.a24 = 0x2718; + t.a25 = 0x2719; + t.a26 = 0x271a; + t.a27 = 0x271b; + t.a28 = 0x271c; + t.a6 = 0x271d; + t.a7 = 0x271e; + t.a8 = 0x271f; + t.a9 = 0x2720; + t.a10 = 0x2721; + t.a29 = 0x2722; + t.a30 = 0x2723; + t.a31 = 0x2724; + t.a32 = 0x2725; + t.a33 = 0x2726; + t.a34 = 0x2727; + t.a35 = 0x2605; + t.a36 = 0x2729; + t.a37 = 0x272a; + t.a38 = 0x272b; + t.a39 = 0x272c; + t.a40 = 0x272d; + t.a41 = 0x272e; + t.a42 = 0x272f; + t.a43 = 0x2730; + t.a44 = 0x2731; + t.a45 = 0x2732; + t.a46 = 0x2733; + t.a47 = 0x2734; + t.a48 = 0x2735; + t.a49 = 0x2736; + t.a50 = 0x2737; + t.a51 = 0x2738; + t.a52 = 0x2739; + t.a53 = 0x273a; + t.a54 = 0x273b; + t.a55 = 0x273c; + t.a56 = 0x273d; + t.a57 = 0x273e; + t.a58 = 0x273f; + t.a59 = 0x2740; + t.a60 = 0x2741; + t.a61 = 0x2742; + t.a62 = 0x2743; + t.a63 = 0x2744; + t.a64 = 0x2745; + t.a65 = 0x2746; + t.a66 = 0x2747; + t.a67 = 0x2748; + t.a68 = 0x2749; + t.a69 = 0x274a; + t.a70 = 0x274b; + t.a71 = 0x25cf; + t.a72 = 0x274d; + t.a73 = 0x25a0; + t.a74 = 0x274f; + t.a203 = 0x2750; + t.a75 = 0x2751; + t.a204 = 0x2752; + t.a76 = 0x25b2; + t.a77 = 0x25bc; + t.a78 = 0x25c6; + t.a79 = 0x2756; + t.a81 = 0x25d7; + t.a82 = 0x2758; + t.a83 = 0x2759; + t.a84 = 0x275a; + t.a97 = 0x275b; + t.a98 = 0x275c; + t.a99 = 0x275d; + t.a100 = 0x275e; + t.a101 = 0x2761; + t.a102 = 0x2762; + t.a103 = 0x2763; + t.a104 = 0x2764; + t.a106 = 0x2765; + t.a107 = 0x2766; + t.a108 = 0x2767; + t.a112 = 0x2663; + t.a111 = 0x2666; + t.a110 = 0x2665; + t.a109 = 0x2660; + t.a120 = 0x2460; + t.a121 = 0x2461; + t.a122 = 0x2462; + t.a123 = 0x2463; + t.a124 = 0x2464; + t.a125 = 0x2465; + t.a126 = 0x2466; + t.a127 = 0x2467; + t.a128 = 0x2468; + t.a129 = 0x2469; + t.a130 = 0x2776; + t.a131 = 0x2777; + t.a132 = 0x2778; + t.a133 = 0x2779; + t.a134 = 0x277a; + t.a135 = 0x277b; + t.a136 = 0x277c; + t.a137 = 0x277d; + t.a138 = 0x277e; + t.a139 = 0x277f; + t.a140 = 0x2780; + t.a141 = 0x2781; + t.a142 = 0x2782; + t.a143 = 0x2783; + t.a144 = 0x2784; + t.a145 = 0x2785; + t.a146 = 0x2786; + t.a147 = 0x2787; + t.a148 = 0x2788; + t.a149 = 0x2789; + t.a150 = 0x278a; + t.a151 = 0x278b; + t.a152 = 0x278c; + t.a153 = 0x278d; + t.a154 = 0x278e; + t.a155 = 0x278f; + t.a156 = 0x2790; + t.a157 = 0x2791; + t.a158 = 0x2792; + t.a159 = 0x2793; + t.a160 = 0x2794; + t.a161 = 0x2192; + t.a163 = 0x2194; + t.a164 = 0x2195; + t.a196 = 0x2798; + t.a165 = 0x2799; + t.a192 = 0x279a; + t.a166 = 0x279b; + t.a167 = 0x279c; + t.a168 = 0x279d; + t.a169 = 0x279e; + t.a170 = 0x279f; + t.a171 = 0x27a0; + t.a172 = 0x27a1; + t.a173 = 0x27a2; + t.a162 = 0x27a3; + t.a174 = 0x27a4; + t.a175 = 0x27a5; + t.a176 = 0x27a6; + t.a177 = 0x27a7; + t.a178 = 0x27a8; + t.a179 = 0x27a9; + t.a193 = 0x27aa; + t.a180 = 0x27ab; + t.a199 = 0x27ac; + t.a181 = 0x27ad; + t.a200 = 0x27ae; + t.a182 = 0x27af; + t.a201 = 0x27b1; + t.a183 = 0x27b2; + t.a184 = 0x27b3; + t.a197 = 0x27b4; + t.a185 = 0x27b5; + t.a194 = 0x27b6; + t.a198 = 0x27b7; + t.a186 = 0x27b8; + t.a195 = 0x27b9; + t.a187 = 0x27ba; + t.a188 = 0x27bb; + t.a189 = 0x27bc; + t.a190 = 0x27bd; + t.a191 = 0x27be; + t.a89 = 0x2768; + t.a90 = 0x2769; + t.a93 = 0x276a; + t.a94 = 0x276b; + t.a91 = 0x276c; + t.a92 = 0x276d; + t.a205 = 0x276e; + t.a85 = 0x276f; + t.a206 = 0x2770; + t.a86 = 0x2771; + t.a87 = 0x2772; + t.a88 = 0x2773; + t.a95 = 0x2774; + t.a96 = 0x2775; + t[".notdef"] = 0x0000; +}); + +;// ./src/core/unicode.js + +const getSpecialPUASymbols = getLookupTableFactory(function (t) { + t[63721] = 0x00a9; + t[63193] = 0x00a9; + t[63720] = 0x00ae; + t[63194] = 0x00ae; + t[63722] = 0x2122; + t[63195] = 0x2122; + t[63729] = 0x23a7; + t[63730] = 0x23a8; + t[63731] = 0x23a9; + t[63740] = 0x23ab; + t[63741] = 0x23ac; + t[63742] = 0x23ad; + t[63726] = 0x23a1; + t[63727] = 0x23a2; + t[63728] = 0x23a3; + t[63737] = 0x23a4; + t[63738] = 0x23a5; + t[63739] = 0x23a6; + t[63723] = 0x239b; + t[63724] = 0x239c; + t[63725] = 0x239d; + t[63734] = 0x239e; + t[63735] = 0x239f; + t[63736] = 0x23a0; +}); +function mapSpecialUnicodeValues(code) { + if (code >= 0xfff0 && code <= 0xffff) { + return 0; + } else if (code >= 0xf600 && code <= 0xf8ff) { + return getSpecialPUASymbols()[code] || code; + } else if (code === 0x00ad) { + return 0x002d; + } + return code; +} +function getUnicodeForGlyph(name, glyphsUnicodeMap) { + let unicode = glyphsUnicodeMap[name]; + if (unicode !== undefined) { + return unicode; + } + if (!name) { + return -1; + } + if (name[0] === "u") { + const nameLen = name.length; + let hexStr; + if (nameLen === 7 && name[1] === "n" && name[2] === "i") { + hexStr = name.substring(3); + } else if (nameLen >= 5 && nameLen <= 7) { + hexStr = name.substring(1); + } else { + return -1; + } + if (hexStr === hexStr.toUpperCase()) { + unicode = parseInt(hexStr, 16); + if (unicode >= 0) { + return unicode; + } + } + } + return -1; +} +const UnicodeRanges = [[0x0000, 0x007f], [0x0080, 0x00ff], [0x0100, 0x017f], [0x0180, 0x024f], [0x0250, 0x02af, 0x1d00, 0x1d7f, 0x1d80, 0x1dbf], [0x02b0, 0x02ff, 0xa700, 0xa71f], [0x0300, 0x036f, 0x1dc0, 0x1dff], [0x0370, 0x03ff], [0x2c80, 0x2cff], [0x0400, 0x04ff, 0x0500, 0x052f, 0x2de0, 0x2dff, 0xa640, 0xa69f], [0x0530, 0x058f], [0x0590, 0x05ff], [0xa500, 0xa63f], [0x0600, 0x06ff, 0x0750, 0x077f], [0x07c0, 0x07ff], [0x0900, 0x097f], [0x0980, 0x09ff], [0x0a00, 0x0a7f], [0x0a80, 0x0aff], [0x0b00, 0x0b7f], [0x0b80, 0x0bff], [0x0c00, 0x0c7f], [0x0c80, 0x0cff], [0x0d00, 0x0d7f], [0x0e00, 0x0e7f], [0x0e80, 0x0eff], [0x10a0, 0x10ff, 0x2d00, 0x2d2f], [0x1b00, 0x1b7f], [0x1100, 0x11ff], [0x1e00, 0x1eff, 0x2c60, 0x2c7f, 0xa720, 0xa7ff], [0x1f00, 0x1fff], [0x2000, 0x206f, 0x2e00, 0x2e7f], [0x2070, 0x209f], [0x20a0, 0x20cf], [0x20d0, 0x20ff], [0x2100, 0x214f], [0x2150, 0x218f], [0x2190, 0x21ff, 0x27f0, 0x27ff, 0x2900, 0x297f, 0x2b00, 0x2bff], [0x2200, 0x22ff, 0x2a00, 0x2aff, 0x27c0, 0x27ef, 0x2980, 0x29ff], [0x2300, 0x23ff], [0x2400, 0x243f], [0x2440, 0x245f], [0x2460, 0x24ff], [0x2500, 0x257f], [0x2580, 0x259f], [0x25a0, 0x25ff], [0x2600, 0x26ff], [0x2700, 0x27bf], [0x3000, 0x303f], [0x3040, 0x309f], [0x30a0, 0x30ff, 0x31f0, 0x31ff], [0x3100, 0x312f, 0x31a0, 0x31bf], [0x3130, 0x318f], [0xa840, 0xa87f], [0x3200, 0x32ff], [0x3300, 0x33ff], [0xac00, 0xd7af], [0xd800, 0xdfff], [0x10900, 0x1091f], [0x4e00, 0x9fff, 0x2e80, 0x2eff, 0x2f00, 0x2fdf, 0x2ff0, 0x2fff, 0x3400, 0x4dbf, 0x20000, 0x2a6df, 0x3190, 0x319f], [0xe000, 0xf8ff], [0x31c0, 0x31ef, 0xf900, 0xfaff, 0x2f800, 0x2fa1f], [0xfb00, 0xfb4f], [0xfb50, 0xfdff], [0xfe20, 0xfe2f], [0xfe10, 0xfe1f], [0xfe50, 0xfe6f], [0xfe70, 0xfeff], [0xff00, 0xffef], [0xfff0, 0xffff], [0x0f00, 0x0fff], [0x0700, 0x074f], [0x0780, 0x07bf], [0x0d80, 0x0dff], [0x1000, 0x109f], [0x1200, 0x137f, 0x1380, 0x139f, 0x2d80, 0x2ddf], [0x13a0, 0x13ff], [0x1400, 0x167f], [0x1680, 0x169f], [0x16a0, 0x16ff], [0x1780, 0x17ff], [0x1800, 0x18af], [0x2800, 0x28ff], [0xa000, 0xa48f], [0x1700, 0x171f, 0x1720, 0x173f, 0x1740, 0x175f, 0x1760, 0x177f], [0x10300, 0x1032f], [0x10330, 0x1034f], [0x10400, 0x1044f], [0x1d000, 0x1d0ff, 0x1d100, 0x1d1ff, 0x1d200, 0x1d24f], [0x1d400, 0x1d7ff], [0xff000, 0xffffd], [0xfe00, 0xfe0f, 0xe0100, 0xe01ef], [0xe0000, 0xe007f], [0x1900, 0x194f], [0x1950, 0x197f], [0x1980, 0x19df], [0x1a00, 0x1a1f], [0x2c00, 0x2c5f], [0x2d30, 0x2d7f], [0x4dc0, 0x4dff], [0xa800, 0xa82f], [0x10000, 0x1007f, 0x10080, 0x100ff, 0x10100, 0x1013f], [0x10140, 0x1018f], [0x10380, 0x1039f], [0x103a0, 0x103df], [0x10450, 0x1047f], [0x10480, 0x104af], [0x10800, 0x1083f], [0x10a00, 0x10a5f], [0x1d300, 0x1d35f], [0x12000, 0x123ff, 0x12400, 0x1247f], [0x1d360, 0x1d37f], [0x1b80, 0x1bbf], [0x1c00, 0x1c4f], [0x1c50, 0x1c7f], [0xa880, 0xa8df], [0xa900, 0xa92f], [0xa930, 0xa95f], [0xaa00, 0xaa5f], [0x10190, 0x101cf], [0x101d0, 0x101ff], [0x102a0, 0x102df, 0x10280, 0x1029f, 0x10920, 0x1093f], [0x1f030, 0x1f09f, 0x1f000, 0x1f02f]]; +function getUnicodeRangeFor(value, lastPosition = -1) { + if (lastPosition !== -1) { + const range = UnicodeRanges[lastPosition]; + for (let i = 0, ii = range.length; i < ii; i += 2) { + if (value >= range[i] && value <= range[i + 1]) { + return lastPosition; + } + } + } + for (let i = 0, ii = UnicodeRanges.length; i < ii; i++) { + const range = UnicodeRanges[i]; + for (let j = 0, jj = range.length; j < jj; j += 2) { + if (value >= range[j] && value <= range[j + 1]) { + return i; + } + } + } + return -1; +} +const SpecialCharRegExp = new RegExp("^(\\s)|(\\p{Mn})|(\\p{Cf})$", "u"); +const CategoryCache = new Map(); +function getCharUnicodeCategory(char) { + const cachedCategory = CategoryCache.get(char); + if (cachedCategory) { + return cachedCategory; + } + const groups = char.match(SpecialCharRegExp); + const category = { + isWhitespace: !!groups?.[1], + isZeroWidthDiacritic: !!groups?.[2], + isInvisibleFormatMark: !!groups?.[3] + }; + CategoryCache.set(char, category); + return category; +} +function clearUnicodeCaches() { + CategoryCache.clear(); +} + +;// ./src/core/fonts_utils.js + + + + + +const SEAC_ANALYSIS_ENABLED = true; +const FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 +}; +const MacStandardGlyphOrdering = [".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", "dcroat"]; +function recoverGlyphName(name, glyphsUnicodeMap) { + if (glyphsUnicodeMap[name] !== undefined) { + return name; + } + const unicode = getUnicodeForGlyph(name, glyphsUnicodeMap); + if (unicode !== -1) { + for (const key in glyphsUnicodeMap) { + if (glyphsUnicodeMap[key] === unicode) { + return key; + } + } + } + info("Unable to recover a standard glyph name for: " + name); + return name; +} +function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { + const charCodeToGlyphId = Object.create(null); + let glyphId, charCode, baseEncoding; + const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + if (properties.isInternalFont) { + baseEncoding = builtInEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } else if (properties.baseEncodingName) { + baseEncoding = getEncoding(properties.baseEncodingName); + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } else if (isSymbolicFont) { + for (charCode in builtInEncoding) { + charCodeToGlyphId[charCode] = builtInEncoding[charCode]; + } + } else { + baseEncoding = StandardEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } + const differences = properties.differences; + let glyphsUnicodeMap; + if (differences) { + for (charCode in differences) { + const glyphName = differences[charCode]; + glyphId = glyphNames.indexOf(glyphName); + if (glyphId === -1) { + if (!glyphsUnicodeMap) { + glyphsUnicodeMap = getGlyphsUnicode(); + } + const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + if (standardGlyphName !== glyphName) { + glyphId = glyphNames.indexOf(standardGlyphName); + } + } + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } + return charCodeToGlyphId; +} +function normalizeFontName(name) { + return name.replaceAll(/[,_]/g, "-").replaceAll(/\s/g, ""); +} +const getVerticalPresentationForm = getLookupTableFactory(t => { + t[0x2013] = 0xfe32; + t[0x2014] = 0xfe31; + t[0x2025] = 0xfe30; + t[0x2026] = 0xfe19; + t[0x3001] = 0xfe11; + t[0x3002] = 0xfe12; + t[0x3008] = 0xfe3f; + t[0x3009] = 0xfe40; + t[0x300a] = 0xfe3d; + t[0x300b] = 0xfe3e; + t[0x300c] = 0xfe41; + t[0x300d] = 0xfe42; + t[0x300e] = 0xfe43; + t[0x300f] = 0xfe44; + t[0x3010] = 0xfe3b; + t[0x3011] = 0xfe3c; + t[0x3014] = 0xfe39; + t[0x3015] = 0xfe3a; + t[0x3016] = 0xfe17; + t[0x3017] = 0xfe18; + t[0xfe4f] = 0xfe34; + t[0xff01] = 0xfe15; + t[0xff08] = 0xfe35; + t[0xff09] = 0xfe36; + t[0xff0c] = 0xfe10; + t[0xff1a] = 0xfe13; + t[0xff1b] = 0xfe14; + t[0xff1f] = 0xfe16; + t[0xff3b] = 0xfe47; + t[0xff3d] = 0xfe48; + t[0xff3f] = 0xfe33; + t[0xff5b] = 0xfe37; + t[0xff5d] = 0xfe38; +}); +const MAX_SIZE_TO_COMPILE = 1000; +function compileType3Glyph({ + data: img, + width, + height +}) { + if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) { + return null; + } + const POINT_TO_PROCESS_LIMIT = 1000; + const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + const width1 = width + 1; + const points = new Uint8Array(width1 * (height + 1)); + let i, j, j0; + const lineSize = width + 7 & ~7; + const data = new Uint8Array(lineSize * height); + let pos = 0; + for (const elem of img) { + let mask = 128; + while (mask > 0) { + data[pos++] = elem & mask ? 0 : 255; + mask >>= 1; + } + } + let count = 0; + pos = 0; + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + pos++; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + pos = lineSize * (height - 1); + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + const pathBuf = []; + const { + a, + b, + c, + d, + e, + f + } = new DOMMatrix().scaleSelf(1 / width, -1 / height).translateSelf(0, -height); + for (i = 0; count && i <= height; i++) { + let p = i * width1; + const end = p + width; + while (p < end && !points[p]) { + p++; + } + if (p === end) { + continue; + } + let x = p % width1; + let y = i; + pathBuf.push(DrawOPS.moveTo, a * x + c * y + e, b * x + d * y + f); + const p0 = p; + let type = points[p]; + do { + const step = steps[type]; + do { + p += step; + } while (!points[p]); + const pp = points[p]; + if (pp !== 5 && pp !== 10) { + type = pp; + points[p] = 0; + } else { + type = pp & 0x33 * type >> 4; + points[p] &= type >> 2 | type << 2; + } + x = p % width1; + y = p / width1 | 0; + pathBuf.push(DrawOPS.lineTo, a * x + c * y + e, b * x + d * y + f); + if (!points[p]) { + --count; + } + } while (p0 !== p); + --i; + } + return [OPS.rawFillPath, [new Float32Array(pathBuf)], new Float32Array([0, 0, width, height])]; +} + +;// ./src/core/charsets.js +const ISOAdobeCharset = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron"]; +const ExpertCharset = [".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"]; +const ExpertSubsetCharset = [".notdef", "space", "dollaroldstyle", "dollarsuperior", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "hyphensuperior", "colonmonetary", "onefitted", "rupiah", "centoldstyle", "figuredash", "hypheninferior", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior"]; + +;// ./src/core/cff_parser.js + + + + +const MAX_SUBR_NESTING = 10; +const CFFStandardStrings = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"]; +const NUM_STANDARD_CFF_STRINGS = 391; +const CharstringValidationData = [null, { + id: "hstem", + min: 2, + stackClearing: true, + stem: true +}, null, { + id: "vstem", + min: 2, + stackClearing: true, + stem: true +}, { + id: "vmoveto", + min: 1, + stackClearing: true +}, { + id: "rlineto", + min: 2, + resetStack: true +}, { + id: "hlineto", + min: 1, + resetStack: true +}, { + id: "vlineto", + min: 1, + resetStack: true +}, { + id: "rrcurveto", + min: 6, + resetStack: true +}, null, { + id: "callsubr", + min: 1, + undefStack: true +}, { + id: "return", + min: 0, + undefStack: true +}, null, null, { + id: "endchar", + min: 0, + stackClearing: true +}, null, null, null, { + id: "hstemhm", + min: 2, + stackClearing: true, + stem: true +}, { + id: "hintmask", + min: 0, + stackClearing: true +}, { + id: "cntrmask", + min: 0, + stackClearing: true +}, { + id: "rmoveto", + min: 2, + stackClearing: true +}, { + id: "hmoveto", + min: 1, + stackClearing: true +}, { + id: "vstemhm", + min: 2, + stackClearing: true, + stem: true +}, { + id: "rcurveline", + min: 8, + resetStack: true +}, { + id: "rlinecurve", + min: 8, + resetStack: true +}, { + id: "vvcurveto", + min: 4, + resetStack: true +}, { + id: "hhcurveto", + min: 4, + resetStack: true +}, null, { + id: "callgsubr", + min: 1, + undefStack: true +}, { + id: "vhcurveto", + min: 4, + resetStack: true +}, { + id: "hvcurveto", + min: 4, + resetStack: true +}]; +const CharstringValidationData12 = [null, null, null, { + id: "and", + min: 2, + stackDelta: -1 +}, { + id: "or", + min: 2, + stackDelta: -1 +}, { + id: "not", + min: 1, + stackDelta: 0 +}, null, null, null, { + id: "abs", + min: 1, + stackDelta: 0 +}, { + id: "add", + min: 2, + stackDelta: -1, + stackFn(stack, index) { + stack[index - 2] = stack[index - 2] + stack[index - 1]; + } +}, { + id: "sub", + min: 2, + stackDelta: -1, + stackFn(stack, index) { + stack[index - 2] = stack[index - 2] - stack[index - 1]; + } +}, { + id: "div", + min: 2, + stackDelta: -1, + stackFn(stack, index) { + stack[index - 2] = stack[index - 2] / stack[index - 1]; + } +}, null, { + id: "neg", + min: 1, + stackDelta: 0, + stackFn(stack, index) { + stack[index - 1] = -stack[index - 1]; + } +}, { + id: "eq", + min: 2, + stackDelta: -1 +}, null, null, { + id: "drop", + min: 1, + stackDelta: -1 +}, null, { + id: "put", + min: 2, + stackDelta: -2 +}, { + id: "get", + min: 1, + stackDelta: 0 +}, { + id: "ifelse", + min: 4, + stackDelta: -3 +}, { + id: "random", + min: 0, + stackDelta: 1 +}, { + id: "mul", + min: 2, + stackDelta: -1, + stackFn(stack, index) { + stack[index - 2] = stack[index - 2] * stack[index - 1]; + } +}, null, { + id: "sqrt", + min: 1, + stackDelta: 0 +}, { + id: "dup", + min: 1, + stackDelta: 1 +}, { + id: "exch", + min: 2, + stackDelta: 0 +}, { + id: "index", + min: 2, + stackDelta: 0 +}, { + id: "roll", + min: 3, + stackDelta: -2 +}, null, null, null, { + id: "hflex", + min: 7, + resetStack: true +}, { + id: "flex", + min: 13, + resetStack: true +}, { + id: "hflex1", + min: 9, + resetStack: true +}, { + id: "flex1", + min: 11, + resetStack: true +}]; +class CFFParser { + constructor(file, properties, seacAnalysisEnabled) { + this.bytes = file.getBytes(); + this.properties = properties; + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + } + parse() { + const properties = this.properties; + const cff = new CFF(); + this.cff = cff; + const header = this.parseHeader(); + const nameIndex = this.parseIndex(header.endPos); + const topDictIndex = this.parseIndex(nameIndex.endPos); + const stringIndex = this.parseIndex(topDictIndex.endPos); + const globalSubrIndex = this.parseIndex(stringIndex.endPos); + const topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + const topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + this.parsePrivateDict(cff.topDict); + cff.isCIDFont = topDict.hasName("ROS"); + const charStringOffset = topDict.getByName("CharStrings"); + const charStringIndex = this.parseIndex(charStringOffset).obj; + const fontMatrix = topDict.getByName("FontMatrix"); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + const fontBBox = topDict.getByName("FontBBox"); + if (fontBBox) { + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + } + let charset, encoding; + if (cff.isCIDFont) { + const fdArrayIndex = this.parseIndex(topDict.getByName("FDArray")).obj; + for (let i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + const dictRaw = fdArrayIndex.get(i); + const fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + encoding = null; + charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName("FDSelect"), charStringIndex.count); + } else { + charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName("Encoding"), properties, cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + const charStringsAndSeacs = this.parseCharStrings({ + charStrings: charStringIndex, + localSubrIndex: topDict.privateDict.subrsIndex, + globalSubrIndex: globalSubrIndex.obj, + fdSelect: cff.fdSelect, + fdArray: cff.fdArray, + privateDict: topDict.privateDict + }); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + cff.widths = charStringsAndSeacs.widths; + return cff; + } + parseHeader() { + let bytes = this.bytes; + const bytesLength = bytes.length; + let offset = 0; + while (offset < bytesLength && bytes[offset] !== 1) { + ++offset; + } + if (offset >= bytesLength) { + throw new FormatError("Invalid CFF header"); + } + if (offset !== 0) { + info("cff data is shifted"); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + const major = bytes[0]; + const minor = bytes[1]; + const hdrSize = bytes[2]; + const offSize = bytes[3]; + const header = new CFFHeader(major, minor, hdrSize, offSize); + return { + obj: header, + endPos: hdrSize + }; + } + parseDict(dict) { + let pos = 0; + function parseOperand() { + let value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(); + } else if (value === 28) { + value = readInt16(dict, pos); + pos += 2; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return (value - 247) * 256 + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } + warn('CFFParser_parseDict: "' + value + '" is a reserved command.'); + return NaN; + } + function parseFloatOperand() { + let str = ""; + const eof = 15; + const lookup = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "E", "E-", null, "-"]; + const length = dict.length; + while (pos < length) { + const b = dict[pos++]; + const b1 = b >> 4; + const b2 = b & 15; + if (b1 === eof) { + break; + } + str += lookup[b1]; + if (b2 === eof) { + break; + } + str += lookup[b2]; + } + return parseFloat(str); + } + let operands = []; + const entries = []; + pos = 0; + const end = dict.length; + while (pos < end) { + let b = dict[pos]; + if (b <= 21) { + if (b === 12) { + b = b << 8 | dict[++pos]; + } + entries.push([b, operands]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + } + parseIndex(pos) { + const cffIndex = new CFFIndex(); + const bytes = this.bytes; + const count = bytes[pos++] << 8 | bytes[pos++]; + const offsets = []; + let end = pos; + let i, ii; + if (count !== 0) { + const offsetSize = bytes[pos++]; + const startPos = pos + (count + 1) * offsetSize - 1; + for (i = 0, ii = count + 1; i < ii; ++i) { + let offset = 0; + for (let j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (i = 0, ii = offsets.length - 1; i < ii; ++i) { + const offsetStart = offsets[i]; + const offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return { + obj: cffIndex, + endPos: end + }; + } + parseNameIndex(index) { + const names = []; + for (let i = 0, ii = index.count; i < ii; ++i) { + const name = index.get(i); + names.push(bytesToString(name)); + } + return names; + } + parseStringIndex(index) { + const strings = new CFFStrings(); + for (let i = 0, ii = index.count; i < ii; ++i) { + const data = index.get(i); + strings.add(bytesToString(data)); + } + return strings; + } + createDict(Type, dict, strings) { + const cffDict = new Type(strings); + for (const [key, value] of dict) { + cffDict.setByKey(key, value); + } + return cffDict; + } + parseCharString(state, data, localSubrIndex, globalSubrIndex) { + if (!data || state.callDepth > MAX_SUBR_NESTING) { + return false; + } + let stackSize = state.stackSize; + const stack = state.stack; + let length = data.length; + for (let j = 0; j < length;) { + const value = data[j++]; + let validationCommand = null; + if (value === 12) { + const q = data[j++]; + if (q === 0) { + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { + stack[stackSize] = readInt16(data, j); + j += 2; + stackSize++; + } else if (value === 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (this.seacAnalysisEnabled) { + state.seac = stack.slice(stackSize, stackSize + 4); + return false; + } + } + validationCommand = CharstringValidationData[value]; + } else if (value >= 32 && value <= 246) { + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { + stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108; + j++; + stackSize++; + } else if (value === 255) { + stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value === 19 || value === 20) { + state.hints += stackSize >> 1; + if (state.hints === 0) { + data.copyWithin(j - 1, j, -1); + j -= 1; + length -= 1; + continue; + } + j += state.hints + 7 >> 3; + stackSize %= 2; + validationCommand = CharstringValidationData[value]; + } else if (value === 10 || value === 29) { + const subrsIndex = value === 10 ? localSubrIndex : globalSubrIndex; + if (!subrsIndex) { + validationCommand = CharstringValidationData[value]; + warn("Missing subrsIndex for " + validationCommand.id); + return false; + } + let bias = 32768; + if (subrsIndex.count < 1240) { + bias = 107; + } else if (subrsIndex.count < 33900) { + bias = 1131; + } + const subrNumber = stack[--stackSize] + bias; + if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) { + validationCommand = CharstringValidationData[value]; + warn("Out of bounds subrIndex for " + validationCommand.id); + return false; + } + state.stackSize = stackSize; + state.callDepth++; + const valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex); + if (!valid) { + return false; + } + state.callDepth--; + stackSize = state.stackSize; + continue; + } else if (value === 11) { + state.stackSize = stackSize; + return true; + } else if (value === 0 && j === data.length) { + data[j - 1] = 14; + validationCommand = CharstringValidationData[14]; + } else if (value === 9) { + data.copyWithin(j - 1, j, -1); + j -= 1; + length -= 1; + continue; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + state.hints += stackSize >> 1; + if (value === 3 || value === 23) { + state.hasVStems = true; + } else if (state.hasVStems && (value === 1 || value === 18)) { + warn("CFF stem hints are in wrong order"); + data[j - 1] = value === 1 ? 3 : 23; + } + } + if ("min" in validationCommand) { + if (!state.undefStack && stackSize < validationCommand.min) { + warn("Not enough parameters for " + validationCommand.id + "; actual: " + stackSize + ", expected: " + validationCommand.min); + if (stackSize === 0) { + data[j - 1] = 14; + return true; + } + return false; + } + } + if (state.firstStackClearing && validationCommand.stackClearing) { + state.firstStackClearing = false; + stackSize -= validationCommand.min; + if (stackSize >= 2 && validationCommand.stem) { + stackSize %= 2; + } else if (stackSize > 1) { + warn("Found too many parameters for stack-clearing command"); + } + if (stackSize > 0) { + state.width = stack[stackSize - 1]; + } + } + if ("stackDelta" in validationCommand) { + if ("stackFn" in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.stackClearing) { + stackSize = 0; + } else if (validationCommand.resetStack) { + stackSize = 0; + state.undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + state.undefStack = true; + state.firstStackClearing = false; + } + } + } + if (length < data.length) { + data.fill(14, length); + } + state.stackSize = stackSize; + return true; + } + parseCharStrings({ + charStrings, + localSubrIndex, + globalSubrIndex, + fdSelect, + fdArray, + privateDict + }) { + const seacs = []; + const widths = []; + const count = charStrings.count; + for (let i = 0; i < count; i++) { + const charstring = charStrings.get(i); + const state = { + callDepth: 0, + stackSize: 0, + stack: [], + undefStack: true, + hints: 0, + firstStackClearing: true, + seac: null, + width: null, + hasVStems: false + }; + let valid = true; + let localSubrToUse = null; + let privateDictToUse = privateDict; + if (fdSelect && fdArray.length) { + const fdIndex = fdSelect.getFDIndex(i); + if (fdIndex === -1) { + warn("Glyph index is not in fd select."); + valid = false; + } + if (fdIndex >= fdArray.length) { + warn("Invalid fd index for glyph index."); + valid = false; + } + if (valid) { + privateDictToUse = fdArray[fdIndex].privateDict; + localSubrToUse = privateDictToUse.subrsIndex; + } + } else if (localSubrIndex) { + localSubrToUse = localSubrIndex; + } + if (valid) { + valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex); + } + if (state.width !== null) { + const nominalWidth = privateDictToUse.getByName("nominalWidthX"); + widths[i] = nominalWidth + state.width; + } else { + const defaultWidth = privateDictToUse.getByName("defaultWidthX"); + widths[i] = defaultWidth; + } + if (state.seac !== null) { + seacs[i] = state.seac; + } + if (!valid) { + charStrings.set(i, new Uint8Array([14])); + } + } + return { + charStrings, + seacs, + widths + }; + } + emptyPrivateDictionary(parentDict) { + const privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings); + parentDict.setByKey(18, [0, 0]); + parentDict.privateDict = privateDict; + } + parsePrivateDict(parentDict) { + if (!parentDict.hasName("Private")) { + this.emptyPrivateDictionary(parentDict); + return; + } + const privateOffset = parentDict.getByName("Private"); + if (!Array.isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName("Private"); + return; + } + const size = privateOffset[0]; + const offset = privateOffset[1]; + if (size === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + const privateDictEnd = offset + size; + const dictData = this.bytes.subarray(offset, privateDictEnd); + const dict = this.parseDict(dictData); + const privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings); + parentDict.privateDict = privateDict; + if (privateDict.getByName("ExpansionFactor") === 0) { + privateDict.setByName("ExpansionFactor", 0.06); + } + if (!privateDict.getByName("Subrs")) { + return; + } + const subrsOffset = privateDict.getByName("Subrs"); + const relativeOffset = offset + subrsOffset; + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + const subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + } + parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset); + } else if (pos === 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset); + } else if (pos === 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset); + } + const bytes = this.bytes; + const start = pos; + const format = bytes[pos++]; + const charset = [cid ? 0 : ".notdef"]; + let id, count, i; + length -= 1; + switch (format) { + case 0: + for (i = 0; i < length; i++) { + id = bytes[pos++] << 8 | bytes[pos++]; + charset.push(cid ? id : strings.get(id)); + } + break; + case 1: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + case 2: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + default: + throw new FormatError("Unknown charset format"); + } + const end = pos; + const raw = bytes.subarray(start, end); + return new CFFCharset(false, format, charset, raw); + } + parseEncoding(pos, properties, strings, charset) { + const encoding = Object.create(null); + const bytes = this.bytes; + let predefined = false; + let format, i, ii; + let raw = null; + function readSupplement() { + const supplementsCount = bytes[pos++]; + for (i = 0; i < supplementsCount; i++) { + const code = bytes[pos++]; + const sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + if (pos === 0 || pos === 1) { + predefined = true; + format = pos; + const baseEncoding = pos ? ExpertEncoding : StandardEncoding; + for (i = 0, ii = charset.length; i < ii; i++) { + const index = baseEncoding.indexOf(charset[i]); + if (index !== -1) { + encoding[index] = i; + } + } + } else { + const dataStart = pos; + format = bytes[pos++]; + switch (format & 0x7f) { + case 0: + const glyphsCount = bytes[pos++]; + for (i = 1; i <= glyphsCount; i++) { + encoding[bytes[pos++]] = i; + } + break; + case 1: + const rangesCount = bytes[pos++]; + let gid = 1; + for (i = 0; i < rangesCount; i++) { + const start = bytes[pos++]; + const left = bytes[pos++]; + for (let j = start; j <= start + left; j++) { + encoding[j] = gid++; + } + } + break; + default: + throw new FormatError(`Unknown encoding format: ${format} in CFF`); + } + const dataEnd = pos; + if (format & 0x80) { + bytes[dataStart] &= 0x7f; + readSupplement(); + } + raw = bytes.subarray(dataStart, dataEnd); + } + format &= 0x7f; + return new CFFEncoding(predefined, format, encoding, raw); + } + parseFDSelect(pos, length) { + const bytes = this.bytes; + const format = bytes[pos++]; + const fdSelect = []; + let i; + switch (format) { + case 0: + for (i = 0; i < length; ++i) { + const id = bytes[pos++]; + fdSelect.push(id); + } + break; + case 3: + const rangesCount = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i < rangesCount; ++i) { + let first = bytes[pos++] << 8 | bytes[pos++]; + if (i === 0 && first !== 0) { + warn("parseFDSelect: The first range must have a first GID of 0" + " -- trying to recover."); + first = 0; + } + const fdIndex = bytes[pos++]; + const next = bytes[pos] << 8 | bytes[pos + 1]; + for (let j = first; j < next; ++j) { + fdSelect.push(fdIndex); + } + } + pos += 2; + break; + default: + throw new FormatError(`parseFDSelect: Unknown format "${format}".`); + } + if (fdSelect.length !== length) { + throw new FormatError("parseFDSelect: Invalid font data."); + } + return new CFFFDSelect(format, fdSelect); + } +} +class CFF { + constructor() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + this.isCIDFont = false; + } + duplicateFirstGlyph() { + if (this.charStrings.count >= 65535) { + warn("Not enough space in charstrings to duplicate first glyph."); + return; + } + const glyphZero = this.charStrings.get(0); + this.charStrings.add(glyphZero); + if (this.isCIDFont) { + this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]); + } + } + hasGlyphId(id) { + if (id < 0 || id >= this.charStrings.count) { + return false; + } + const glyph = this.charStrings.get(id); + return glyph.length > 0; + } +} +class CFFHeader { + constructor(major, minor, hdrSize, offSize) { + this.major = major; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } +} +class CFFStrings { + constructor() { + this.strings = []; + } + get(index) { + if (index >= 0 && index <= NUM_STANDARD_CFF_STRINGS - 1) { + return CFFStandardStrings[index]; + } + if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) { + return this.strings[index - NUM_STANDARD_CFF_STRINGS]; + } + return CFFStandardStrings[0]; + } + getSID(str) { + let index = CFFStandardStrings.indexOf(str); + if (index !== -1) { + return index; + } + index = this.strings.indexOf(str); + if (index !== -1) { + return index + NUM_STANDARD_CFF_STRINGS; + } + return -1; + } + add(value) { + this.strings.push(value); + } + get count() { + return this.strings.length; + } +} +class CFFIndex { + constructor() { + this.objects = []; + this.length = 0; + } + add(data) { + this.length += data.length; + this.objects.push(data); + } + set(index, data) { + this.length += data.length - this.objects[index].length; + this.objects[index] = data; + } + get(index) { + return this.objects[index]; + } + get count() { + return this.objects.length; + } +} +class CFFDict { + constructor(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = Object.create(null); + } + setByKey(key, value) { + if (!(key in this.keyToNameMap)) { + return false; + } + if (value.length === 0) { + return true; + } + for (const val of value) { + if (isNaN(val)) { + warn(`Invalid CFFDict value: "${value}" for key "${key}".`); + return true; + } + } + const type = this.types[key]; + if (type === "num" || type === "sid" || type === "offset") { + value = value[0]; + } + this.values[key] = value; + return true; + } + setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + throw new FormatError(`Invalid dictionary name "${name}"`); + } + this.values[this.nameToKeyMap[name]] = value; + } + hasName(name) { + return this.nameToKeyMap[name] in this.values; + } + getByName(name) { + if (!(name in this.nameToKeyMap)) { + throw new FormatError(`Invalid dictionary name ${name}"`); + } + const key = this.nameToKeyMap[name]; + if (!(key in this.values)) { + return this.defaults[key]; + } + return this.values[key]; + } + removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + static createTables(layout) { + const tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (const entry of layout) { + const key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + } +} +const CFFTopDictLayout = [[[12, 30], "ROS", ["sid", "sid", "num"], null], [[12, 20], "SyntheticBase", "num", null], [0, "version", "sid", null], [1, "Notice", "sid", null], [[12, 0], "Copyright", "sid", null], [2, "FullName", "sid", null], [3, "FamilyName", "sid", null], [4, "Weight", "sid", null], [[12, 1], "isFixedPitch", "num", 0], [[12, 2], "ItalicAngle", "num", 0], [[12, 3], "UnderlinePosition", "num", -100], [[12, 4], "UnderlineThickness", "num", 50], [[12, 5], "PaintType", "num", 0], [[12, 6], "CharstringType", "num", 2], [[12, 7], "FontMatrix", ["num", "num", "num", "num", "num", "num"], [0.001, 0, 0, 0.001, 0, 0]], [13, "UniqueID", "num", null], [5, "FontBBox", ["num", "num", "num", "num"], [0, 0, 0, 0]], [[12, 8], "StrokeWidth", "num", 0], [14, "XUID", "array", null], [15, "charset", "offset", 0], [16, "Encoding", "offset", 0], [17, "CharStrings", "offset", 0], [18, "Private", ["offset", "offset"], null], [[12, 21], "PostScript", "sid", null], [[12, 22], "BaseFontName", "sid", null], [[12, 23], "BaseFontBlend", "delta", null], [[12, 31], "CIDFontVersion", "num", 0], [[12, 32], "CIDFontRevision", "num", 0], [[12, 33], "CIDFontType", "num", 0], [[12, 34], "CIDCount", "num", 8720], [[12, 35], "UIDBase", "num", null], [[12, 37], "FDSelect", "offset", null], [[12, 36], "FDArray", "offset", null], [[12, 38], "FontName", "sid", null]]; +class CFFTopDict extends CFFDict { + static get tables() { + return shadow(this, "tables", this.createTables(CFFTopDictLayout)); + } + constructor(strings) { + super(CFFTopDict.tables, strings); + this.privateDict = null; + } +} +const CFFPrivateDictLayout = [[6, "BlueValues", "delta", null], [7, "OtherBlues", "delta", null], [8, "FamilyBlues", "delta", null], [9, "FamilyOtherBlues", "delta", null], [[12, 9], "BlueScale", "num", 0.039625], [[12, 10], "BlueShift", "num", 7], [[12, 11], "BlueFuzz", "num", 1], [10, "StdHW", "num", null], [11, "StdVW", "num", null], [[12, 12], "StemSnapH", "delta", null], [[12, 13], "StemSnapV", "delta", null], [[12, 14], "ForceBold", "num", 0], [[12, 17], "LanguageGroup", "num", 0], [[12, 18], "ExpansionFactor", "num", 0.06], [[12, 19], "initialRandomSeed", "num", 0], [20, "defaultWidthX", "num", 0], [21, "nominalWidthX", "num", 0], [19, "Subrs", "offset", null]]; +class CFFPrivateDict extends CFFDict { + static get tables() { + return shadow(this, "tables", this.createTables(CFFPrivateDictLayout)); + } + constructor(strings) { + super(CFFPrivateDict.tables, strings); + this.subrsIndex = null; + } +} +const CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 +}; +class CFFCharset { + constructor(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } +} +class CFFEncoding { + constructor(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } +} +class CFFFDSelect { + constructor(format, fdSelect) { + this.format = format; + this.fdSelect = fdSelect; + } + getFDIndex(glyphIndex) { + if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) { + return -1; + } + return this.fdSelect[glyphIndex]; + } +} +class CFFOffsetTracker { + constructor() { + this.offsets = Object.create(null); + } + isTracking(key) { + return key in this.offsets; + } + track(key, location) { + if (key in this.offsets) { + throw new FormatError(`Already tracking location of ${key}`); + } + this.offsets[key] = location; + } + offset(value) { + for (const key in this.offsets) { + this.offsets[key] += value; + } + } + setEntryLocation(key, values, output) { + if (!(key in this.offsets)) { + throw new FormatError(`Not tracking location of ${key}`); + } + const data = output.data; + const dataOffset = this.offsets[key]; + const size = 5; + for (let i = 0, ii = values.length; i < ii; ++i) { + const offset0 = i * size + dataOffset; + const offset1 = offset0 + 1; + const offset2 = offset0 + 2; + const offset3 = offset0 + 3; + const offset4 = offset0 + 4; + if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { + throw new FormatError("writing to an offset that is not empty"); + } + const value = values[i]; + data[offset0] = 0x1d; + data[offset1] = value >> 24 & 0xff; + data[offset2] = value >> 16 & 0xff; + data[offset3] = value >> 8 & 0xff; + data[offset4] = value & 0xff; + } + } +} +class CFFCompiler { + constructor(cff) { + this.cff = cff; + } + compile() { + const cff = this.cff; + const output = { + data: [], + length: 0, + add(data) { + try { + this.data.push(...data); + } catch { + this.data = this.data.concat(data); + } + this.length = this.data.length; + } + }; + const header = this.compileHeader(cff.header); + output.add(header); + const nameIndex = this.compileNameIndex(cff.names); + output.add(nameIndex); + if (cff.isCIDFont) { + if (cff.topDict.hasName("FontMatrix")) { + const base = cff.topDict.getByName("FontMatrix"); + cff.topDict.removeByName("FontMatrix"); + for (const subDict of cff.fdArray) { + let matrix = base.slice(0); + if (subDict.hasName("FontMatrix")) { + matrix = Util.transform(matrix, subDict.getByName("FontMatrix")); + } + subDict.setByName("FontMatrix", matrix); + } + } + } + const xuid = cff.topDict.getByName("XUID"); + if (xuid?.length > 16) { + cff.topDict.removeByName("XUID"); + } + cff.topDict.setByName("charset", 0); + let compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont); + output.add(compiled.output); + const topDictTracker = compiled.trackers[0]; + const stringIndex = this.compileStringIndex(cff.strings.strings); + output.add(stringIndex); + const globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output.add(globalSubrIndex); + if (cff.encoding && cff.topDict.hasName("Encoding")) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation("Encoding", [cff.encoding.format], output); + } else { + const encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation("Encoding", [output.length], output); + output.add(encoding); + } + } + const charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont); + topDictTracker.setEntryLocation("charset", [output.length], output); + output.add(charset); + const charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation("CharStrings", [output.length], output); + output.add(charStrings); + if (cff.isCIDFont) { + topDictTracker.setEntryLocation("FDSelect", [output.length], output); + const fdSelect = this.compileFDSelect(cff.fdSelect); + output.add(fdSelect); + compiled = this.compileTopDicts(cff.fdArray, output.length, true); + topDictTracker.setEntryLocation("FDArray", [output.length], output); + output.add(compiled.output); + const fontDictTrackers = compiled.trackers; + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); + } + this.compilePrivateDicts([cff.topDict], [topDictTracker], output); + output.add([0]); + return output.data; + } + encodeNumber(value) { + if (Number.isInteger(value)) { + return this.encodeInteger(value); + } + return this.encodeFloat(value); + } + static get EncodeFloatRegExp() { + return shadow(this, "EncodeFloatRegExp", /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/); + } + encodeFloat(num) { + let value = num.toString(); + const m = CFFCompiler.EncodeFloatRegExp.exec(value); + if (m) { + const epsilon = parseFloat("1e" + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + let nibbles = ""; + let i, ii; + for (i = 0, ii = value.length; i < ii; ++i) { + const a = value[i]; + if (a === "e") { + nibbles += value[++i] === "-" ? "c" : "b"; + } else if (a === ".") { + nibbles += "a"; + } else if (a === "-") { + nibbles += "e"; + } else { + nibbles += a; + } + } + nibbles += nibbles.length & 1 ? "f" : "ff"; + const out = [30]; + for (i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substring(i, i + 2), 16)); + } + return out; + } + encodeInteger(value) { + let code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value -= 108; + code = [(value >> 8) + 247, value & 0xff]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [(value >> 8) + 251, value & 0xff]; + } else if (value >= -32768 && value <= 32767) { + code = [0x1c, value >> 8 & 0xff, value & 0xff]; + } else { + code = [0x1d, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff]; + } + return code; + } + compileHeader(header) { + return [header.major, header.minor, 4, header.offSize]; + } + compileNameIndex(names) { + const nameIndex = new CFFIndex(); + for (const name of names) { + const length = Math.min(name.length, 127); + let sanitizedName = new Array(length); + for (let j = 0; j < length; j++) { + let char = name[j]; + if (char < "!" || char > "~" || char === "[" || char === "]" || char === "(" || char === ")" || char === "{" || char === "}" || char === "<" || char === ">" || char === "/" || char === "%") { + char = "_"; + } + sanitizedName[j] = char; + } + sanitizedName = sanitizedName.join(""); + if (sanitizedName === "") { + sanitizedName = "Bad_Font_Name"; + } + nameIndex.add(stringToBytes(sanitizedName)); + } + return this.compileIndex(nameIndex); + } + compileTopDicts(dicts, length, removeCidKeys) { + const fontDictTrackers = []; + let fdArrayIndex = new CFFIndex(); + for (const fontDict of dicts) { + if (removeCidKeys) { + fontDict.removeByName("CIDFontVersion"); + fontDict.removeByName("CIDFontRevision"); + fontDict.removeByName("CIDFontType"); + fontDict.removeByName("CIDCount"); + fontDict.removeByName("UIDBase"); + } + const fontDictTracker = new CFFOffsetTracker(); + const fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + } + compilePrivateDicts(dicts, trackers, output) { + for (let i = 0, ii = dicts.length; i < ii; ++i) { + const fontDict = dicts[i]; + const privateDict = fontDict.privateDict; + if (!privateDict || !fontDict.hasName("Private")) { + throw new FormatError("There must be a private dictionary."); + } + const privateDictTracker = new CFFOffsetTracker(); + const privateDictData = this.compileDict(privateDict, privateDictTracker); + let outputLength = output.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + outputLength = 0; + } + trackers[i].setEntryLocation("Private", [privateDictData.length, outputLength], output); + output.add(privateDictData); + if (privateDict.subrsIndex && privateDict.hasName("Subrs")) { + const subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation("Subrs", [privateDictData.length], output); + output.add(subrs); + } + } + } + compileDict(dict, offsetTracker) { + const out = []; + for (const key of dict.order) { + if (!(key in dict.values)) { + continue; + } + let values = dict.values[key]; + let types = dict.types[key]; + if (!Array.isArray(types)) { + types = [types]; + } + if (!Array.isArray(values)) { + values = [values]; + } + if (values.length === 0) { + continue; + } + for (let j = 0, jj = types.length; j < jj; ++j) { + const type = types[j]; + const value = values[j]; + switch (type) { + case "num": + case "sid": + out.push(...this.encodeNumber(value)); + break; + case "offset": + const name = dict.keyToNameMap[key]; + if (!offsetTracker.isTracking(name)) { + offsetTracker.track(name, out.length); + } + out.push(0x1d, 0, 0, 0, 0); + break; + case "array": + case "delta": + out.push(...this.encodeNumber(value)); + for (let k = 1, kk = values.length; k < kk; ++k) { + out.push(...this.encodeNumber(values[k])); + } + break; + default: + throw new FormatError(`Unknown data type of ${type}`); + } + } + out.push(...dict.opcodes[key]); + } + return out; + } + compileStringIndex(strings) { + const stringIndex = new CFFIndex(); + for (const string of strings) { + stringIndex.add(stringToBytes(string)); + } + return this.compileIndex(stringIndex); + } + compileCharStrings(charStrings) { + const charStringsIndex = new CFFIndex(); + for (let i = 0; i < charStrings.count; i++) { + const glyph = charStrings.get(i); + if (glyph.length === 0) { + charStringsIndex.add(new Uint8Array([0x8b, 0x0e])); + continue; + } + charStringsIndex.add(glyph); + } + return this.compileIndex(charStringsIndex); + } + compileCharset(charset, numGlyphs, strings, isCIDFont) { + let out; + const numGlyphsLessNotDef = numGlyphs - 1; + if (isCIDFont) { + const nLeft = numGlyphsLessNotDef - 1; + out = new Uint8Array([2, 0, 1, nLeft >> 8 & 0xff, nLeft & 0xff]); + } else { + const length = 1 + numGlyphsLessNotDef * 2; + out = new Uint8Array(length); + out[0] = 0; + let charsetIndex = 0; + const numCharsets = charset.charset.length; + let warned = false; + for (let i = 1; i < out.length; i += 2) { + let sid = 0; + if (charsetIndex < numCharsets) { + const name = charset.charset[charsetIndex++]; + sid = strings.getSID(name); + if (sid === -1) { + sid = 0; + if (!warned) { + warned = true; + warn(`Couldn't find ${name} in CFF strings`); + } + } + } + out[i] = sid >> 8 & 0xff; + out[i + 1] = sid & 0xff; + } + } + return this.compileTypedArray(out); + } + compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + } + compileFDSelect(fdSelect) { + const format = fdSelect.format; + let out, i; + switch (format) { + case 0: + out = new Uint8Array(1 + fdSelect.fdSelect.length); + out[0] = format; + for (i = 0; i < fdSelect.fdSelect.length; i++) { + out[i + 1] = fdSelect.fdSelect[i]; + } + break; + case 3: + const start = 0; + let lastFD = fdSelect.fdSelect[0]; + const ranges = [format, 0, 0, start >> 8 & 0xff, start & 0xff, lastFD]; + for (i = 1; i < fdSelect.fdSelect.length; i++) { + const currentFD = fdSelect.fdSelect[i]; + if (currentFD !== lastFD) { + ranges.push(i >> 8 & 0xff, i & 0xff, currentFD); + lastFD = currentFD; + } + } + const numRanges = (ranges.length - 3) / 3; + ranges[1] = numRanges >> 8 & 0xff; + ranges[2] = numRanges & 0xff; + ranges.push(i >> 8 & 0xff, i & 0xff); + out = new Uint8Array(ranges); + break; + } + return this.compileTypedArray(out); + } + compileTypedArray(data) { + return Array.from(data); + } + compileIndex(index, trackers = []) { + const objects = index.objects; + const count = objects.length; + if (count === 0) { + return [0, 0]; + } + const data = [count >> 8 & 0xff, count & 0xff]; + let lastOffset = 1, + i; + for (i = 0; i < count; ++i) { + lastOffset += objects[i].length; + } + let offsetSize; + if (lastOffset < 0x100) { + offsetSize = 1; + } else if (lastOffset < 0x10000) { + offsetSize = 2; + } else if (lastOffset < 0x1000000) { + offsetSize = 3; + } else { + offsetSize = 4; + } + data.push(offsetSize); + let relativeOffset = 1; + for (i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 0xff); + } else if (offsetSize === 2) { + data.push(relativeOffset >> 8 & 0xff, relativeOffset & 0xff); + } else if (offsetSize === 3) { + data.push(relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff); + } else { + data.push(relativeOffset >>> 24 & 0xff, relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff); + } + if (objects[i]) { + relativeOffset += objects[i].length; + } + } + for (i = 0; i < count; i++) { + if (trackers[i]) { + trackers[i].offset(data.length); + } + data.push(...objects[i]); + } + return data; + } +} + +;// ./src/core/standard_fonts.js + + +const getStdFontMap = getLookupTableFactory(function (t) { + t["Times-Roman"] = "Times-Roman"; + t.Helvetica = "Helvetica"; + t.Courier = "Courier"; + t.Symbol = "Symbol"; + t["Times-Bold"] = "Times-Bold"; + t["Helvetica-Bold"] = "Helvetica-Bold"; + t["Courier-Bold"] = "Courier-Bold"; + t.ZapfDingbats = "ZapfDingbats"; + t["Times-Italic"] = "Times-Italic"; + t["Helvetica-Oblique"] = "Helvetica-Oblique"; + t["Courier-Oblique"] = "Courier-Oblique"; + t["Times-BoldItalic"] = "Times-BoldItalic"; + t["Helvetica-BoldOblique"] = "Helvetica-BoldOblique"; + t["Courier-BoldOblique"] = "Courier-BoldOblique"; + t.ArialNarrow = "Helvetica"; + t["ArialNarrow-Bold"] = "Helvetica-Bold"; + t["ArialNarrow-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialNarrow-Italic"] = "Helvetica-Oblique"; + t.ArialBlack = "Helvetica"; + t["ArialBlack-Bold"] = "Helvetica-Bold"; + t["ArialBlack-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialBlack-Italic"] = "Helvetica-Oblique"; + t["Arial-Black"] = "Helvetica"; + t["Arial-Black-Bold"] = "Helvetica-Bold"; + t["Arial-Black-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-Black-Italic"] = "Helvetica-Oblique"; + t.Arial = "Helvetica"; + t["Arial-Bold"] = "Helvetica-Bold"; + t["Arial-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-Italic"] = "Helvetica-Oblique"; + t.ArialMT = "Helvetica"; + t["Arial-BoldItalicMT"] = "Helvetica-BoldOblique"; + t["Arial-BoldMT"] = "Helvetica-Bold"; + t["Arial-ItalicMT"] = "Helvetica-Oblique"; + t["Arial-BoldItalicMT-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-BoldMT-Bold"] = "Helvetica-Bold"; + t["Arial-ItalicMT-Italic"] = "Helvetica-Oblique"; + t.ArialUnicodeMS = "Helvetica"; + t["ArialUnicodeMS-Bold"] = "Helvetica-Bold"; + t["ArialUnicodeMS-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialUnicodeMS-Italic"] = "Helvetica-Oblique"; + t["Courier-BoldItalic"] = "Courier-BoldOblique"; + t["Courier-Italic"] = "Courier-Oblique"; + t.CourierNew = "Courier"; + t["CourierNew-Bold"] = "Courier-Bold"; + t["CourierNew-BoldItalic"] = "Courier-BoldOblique"; + t["CourierNew-Italic"] = "Courier-Oblique"; + t["CourierNewPS-BoldItalicMT"] = "Courier-BoldOblique"; + t["CourierNewPS-BoldMT"] = "Courier-Bold"; + t["CourierNewPS-ItalicMT"] = "Courier-Oblique"; + t.CourierNewPSMT = "Courier"; + t["Helvetica-BoldItalic"] = "Helvetica-BoldOblique"; + t["Helvetica-Italic"] = "Helvetica-Oblique"; + t["HelveticaLTStd-Bold"] = "Helvetica-Bold"; + t["Symbol-Bold"] = "Symbol"; + t["Symbol-BoldItalic"] = "Symbol"; + t["Symbol-Italic"] = "Symbol"; + t.TimesNewRoman = "Times-Roman"; + t["TimesNewRoman-Bold"] = "Times-Bold"; + t["TimesNewRoman-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRoman-Italic"] = "Times-Italic"; + t.TimesNewRomanPS = "Times-Roman"; + t["TimesNewRomanPS-Bold"] = "Times-Bold"; + t["TimesNewRomanPS-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRomanPS-BoldItalicMT"] = "Times-BoldItalic"; + t["TimesNewRomanPS-BoldMT"] = "Times-Bold"; + t["TimesNewRomanPS-Italic"] = "Times-Italic"; + t["TimesNewRomanPS-ItalicMT"] = "Times-Italic"; + t.TimesNewRomanPSMT = "Times-Roman"; + t["TimesNewRomanPSMT-Bold"] = "Times-Bold"; + t["TimesNewRomanPSMT-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRomanPSMT-Italic"] = "Times-Italic"; +}); +const getFontNameToFileMap = getLookupTableFactory(function (t) { + t.Courier = "FoxitFixed.pfb"; + t["Courier-Bold"] = "FoxitFixedBold.pfb"; + t["Courier-BoldOblique"] = "FoxitFixedBoldItalic.pfb"; + t["Courier-Oblique"] = "FoxitFixedItalic.pfb"; + t.Helvetica = "LiberationSans-Regular.ttf"; + t["Helvetica-Bold"] = "LiberationSans-Bold.ttf"; + t["Helvetica-BoldOblique"] = "LiberationSans-BoldItalic.ttf"; + t["Helvetica-Oblique"] = "LiberationSans-Italic.ttf"; + t["Times-Roman"] = "FoxitSerif.pfb"; + t["Times-Bold"] = "FoxitSerifBold.pfb"; + t["Times-BoldItalic"] = "FoxitSerifBoldItalic.pfb"; + t["Times-Italic"] = "FoxitSerifItalic.pfb"; + t.Symbol = "FoxitSymbol.pfb"; + t.ZapfDingbats = "FoxitDingbats.pfb"; + t["LiberationSans-Regular"] = "LiberationSans-Regular.ttf"; + t["LiberationSans-Bold"] = "LiberationSans-Bold.ttf"; + t["LiberationSans-Italic"] = "LiberationSans-Italic.ttf"; + t["LiberationSans-BoldItalic"] = "LiberationSans-BoldItalic.ttf"; +}); +const getNonStdFontMap = getLookupTableFactory(function (t) { + t.Calibri = "Helvetica"; + t["Calibri-Bold"] = "Helvetica-Bold"; + t["Calibri-BoldItalic"] = "Helvetica-BoldOblique"; + t["Calibri-Italic"] = "Helvetica-Oblique"; + t.CenturyGothic = "Helvetica"; + t["CenturyGothic-Bold"] = "Helvetica-Bold"; + t["CenturyGothic-BoldItalic"] = "Helvetica-BoldOblique"; + t["CenturyGothic-Italic"] = "Helvetica-Oblique"; + t.ComicSansMS = "Comic Sans MS"; + t["ComicSansMS-Bold"] = "Comic Sans MS-Bold"; + t["ComicSansMS-BoldItalic"] = "Comic Sans MS-BoldItalic"; + t["ComicSansMS-Italic"] = "Comic Sans MS-Italic"; + t.GillSansMT = "Helvetica"; + t["GillSansMT-Bold"] = "Helvetica-Bold"; + t["GillSansMT-BoldItalic"] = "Helvetica-BoldOblique"; + t["GillSansMT-Italic"] = "Helvetica-Oblique"; + t.Impact = "Helvetica"; + t["ItcSymbol-Bold"] = "Helvetica-Bold"; + t["ItcSymbol-BoldItalic"] = "Helvetica-BoldOblique"; + t["ItcSymbol-Book"] = "Helvetica"; + t["ItcSymbol-BookItalic"] = "Helvetica-Oblique"; + t["ItcSymbol-Medium"] = "Helvetica"; + t["ItcSymbol-MediumItalic"] = "Helvetica-Oblique"; + t.LucidaConsole = "Courier"; + t["LucidaConsole-Bold"] = "Courier-Bold"; + t["LucidaConsole-BoldItalic"] = "Courier-BoldOblique"; + t["LucidaConsole-Italic"] = "Courier-Oblique"; + t["LucidaSans-Demi"] = "Helvetica-Bold"; + t["MS-Gothic"] = "MS Gothic"; + t["MS-Gothic-Bold"] = "MS Gothic-Bold"; + t["MS-Gothic-BoldItalic"] = "MS Gothic-BoldItalic"; + t["MS-Gothic-Italic"] = "MS Gothic-Italic"; + t["MS-Mincho"] = "MS Mincho"; + t["MS-Mincho-Bold"] = "MS Mincho-Bold"; + t["MS-Mincho-BoldItalic"] = "MS Mincho-BoldItalic"; + t["MS-Mincho-Italic"] = "MS Mincho-Italic"; + t["MS-PGothic"] = "MS PGothic"; + t["MS-PGothic-Bold"] = "MS PGothic-Bold"; + t["MS-PGothic-BoldItalic"] = "MS PGothic-BoldItalic"; + t["MS-PGothic-Italic"] = "MS PGothic-Italic"; + t["MS-PMincho"] = "MS PMincho"; + t["MS-PMincho-Bold"] = "MS PMincho-Bold"; + t["MS-PMincho-BoldItalic"] = "MS PMincho-BoldItalic"; + t["MS-PMincho-Italic"] = "MS PMincho-Italic"; + t.NuptialScript = "Times-Italic"; + t.SegoeUISymbol = "Helvetica"; +}); +const getSerifFonts = getLookupTableFactory(function (t) { + t["Adobe Jenson"] = true; + t["Adobe Text"] = true; + t.Albertus = true; + t.Aldus = true; + t.Alexandria = true; + t.Algerian = true; + t["American Typewriter"] = true; + t.Antiqua = true; + t.Apex = true; + t.Arno = true; + t.Aster = true; + t.Aurora = true; + t.Baskerville = true; + t.Bell = true; + t.Bembo = true; + t["Bembo Schoolbook"] = true; + t.Benguiat = true; + t["Berkeley Old Style"] = true; + t["Bernhard Modern"] = true; + t["Berthold City"] = true; + t.Bodoni = true; + t["Bauer Bodoni"] = true; + t["Book Antiqua"] = true; + t.Bookman = true; + t["Bordeaux Roman"] = true; + t["Californian FB"] = true; + t.Calisto = true; + t.Calvert = true; + t.Capitals = true; + t.Cambria = true; + t.Cartier = true; + t.Caslon = true; + t.Catull = true; + t.Centaur = true; + t["Century Old Style"] = true; + t["Century Schoolbook"] = true; + t.Chaparral = true; + t["Charis SIL"] = true; + t.Cheltenham = true; + t["Cholla Slab"] = true; + t.Clarendon = true; + t.Clearface = true; + t.Cochin = true; + t.Colonna = true; + t["Computer Modern"] = true; + t["Concrete Roman"] = true; + t.Constantia = true; + t["Cooper Black"] = true; + t.Corona = true; + t.Ecotype = true; + t.Egyptienne = true; + t.Elephant = true; + t.Excelsior = true; + t.Fairfield = true; + t["FF Scala"] = true; + t.Folkard = true; + t.Footlight = true; + t.FreeSerif = true; + t["Friz Quadrata"] = true; + t.Garamond = true; + t.Gentium = true; + t.Georgia = true; + t.Gloucester = true; + t["Goudy Old Style"] = true; + t["Goudy Schoolbook"] = true; + t["Goudy Pro Font"] = true; + t.Granjon = true; + t["Guardian Egyptian"] = true; + t.Heather = true; + t.Hercules = true; + t["High Tower Text"] = true; + t.Hiroshige = true; + t["Hoefler Text"] = true; + t["Humana Serif"] = true; + t.Imprint = true; + t["Ionic No. 5"] = true; + t.Janson = true; + t.Joanna = true; + t.Korinna = true; + t.Lexicon = true; + t.LiberationSerif = true; + t["Liberation Serif"] = true; + t["Linux Libertine"] = true; + t.Literaturnaya = true; + t.Lucida = true; + t["Lucida Bright"] = true; + t.Melior = true; + t.Memphis = true; + t.Miller = true; + t.Minion = true; + t.Modern = true; + t["Mona Lisa"] = true; + t["Mrs Eaves"] = true; + t["MS Serif"] = true; + t["Museo Slab"] = true; + t["New York"] = true; + t["Nimbus Roman"] = true; + t["NPS Rawlinson Roadway"] = true; + t.NuptialScript = true; + t.Palatino = true; + t.Perpetua = true; + t.Plantin = true; + t["Plantin Schoolbook"] = true; + t.Playbill = true; + t["Poor Richard"] = true; + t["Rawlinson Roadway"] = true; + t.Renault = true; + t.Requiem = true; + t.Rockwell = true; + t.Roman = true; + t["Rotis Serif"] = true; + t.Sabon = true; + t.Scala = true; + t.Seagull = true; + t.Sistina = true; + t.Souvenir = true; + t.STIX = true; + t["Stone Informal"] = true; + t["Stone Serif"] = true; + t.Sylfaen = true; + t.Times = true; + t.Trajan = true; + t["Trinité"] = true; + t["Trump Mediaeval"] = true; + t.Utopia = true; + t["Vale Type"] = true; + t["Bitstream Vera"] = true; + t["Vera Serif"] = true; + t.Versailles = true; + t.Wanted = true; + t.Weiss = true; + t["Wide Latin"] = true; + t.Windsor = true; + t.XITS = true; +}); +const getSymbolsFonts = getLookupTableFactory(function (t) { + t.Dingbats = true; + t.Symbol = true; + t.ZapfDingbats = true; + t.Wingdings = true; + t["Wingdings-Bold"] = true; + t["Wingdings-Regular"] = true; +}); +const getGlyphMapForStandardFonts = getLookupTableFactory(function (t) { + t[2] = 10; + t[3] = 32; + t[4] = 33; + t[5] = 34; + t[6] = 35; + t[7] = 36; + t[8] = 37; + t[9] = 38; + t[10] = 39; + t[11] = 40; + t[12] = 41; + t[13] = 42; + t[14] = 43; + t[15] = 44; + t[16] = 45; + t[17] = 46; + t[18] = 47; + t[19] = 48; + t[20] = 49; + t[21] = 50; + t[22] = 51; + t[23] = 52; + t[24] = 53; + t[25] = 54; + t[26] = 55; + t[27] = 56; + t[28] = 57; + t[29] = 58; + t[30] = 894; + t[31] = 60; + t[32] = 61; + t[33] = 62; + t[34] = 63; + t[35] = 64; + t[36] = 65; + t[37] = 66; + t[38] = 67; + t[39] = 68; + t[40] = 69; + t[41] = 70; + t[42] = 71; + t[43] = 72; + t[44] = 73; + t[45] = 74; + t[46] = 75; + t[47] = 76; + t[48] = 77; + t[49] = 78; + t[50] = 79; + t[51] = 80; + t[52] = 81; + t[53] = 82; + t[54] = 83; + t[55] = 84; + t[56] = 85; + t[57] = 86; + t[58] = 87; + t[59] = 88; + t[60] = 89; + t[61] = 90; + t[62] = 91; + t[63] = 92; + t[64] = 93; + t[65] = 94; + t[66] = 95; + t[67] = 96; + t[68] = 97; + t[69] = 98; + t[70] = 99; + t[71] = 100; + t[72] = 101; + t[73] = 102; + t[74] = 103; + t[75] = 104; + t[76] = 105; + t[77] = 106; + t[78] = 107; + t[79] = 108; + t[80] = 109; + t[81] = 110; + t[82] = 111; + t[83] = 112; + t[84] = 113; + t[85] = 114; + t[86] = 115; + t[87] = 116; + t[88] = 117; + t[89] = 118; + t[90] = 119; + t[91] = 120; + t[92] = 121; + t[93] = 122; + t[94] = 123; + t[95] = 124; + t[96] = 125; + t[97] = 126; + t[98] = 196; + t[99] = 197; + t[100] = 199; + t[101] = 201; + t[102] = 209; + t[103] = 214; + t[104] = 220; + t[105] = 225; + t[106] = 224; + t[107] = 226; + t[108] = 228; + t[109] = 227; + t[110] = 229; + t[111] = 231; + t[112] = 233; + t[113] = 232; + t[114] = 234; + t[115] = 235; + t[116] = 237; + t[117] = 236; + t[118] = 238; + t[119] = 239; + t[120] = 241; + t[121] = 243; + t[122] = 242; + t[123] = 244; + t[124] = 246; + t[125] = 245; + t[126] = 250; + t[127] = 249; + t[128] = 251; + t[129] = 252; + t[130] = 8224; + t[131] = 176; + t[132] = 162; + t[133] = 163; + t[134] = 167; + t[135] = 8226; + t[136] = 182; + t[137] = 223; + t[138] = 174; + t[139] = 169; + t[140] = 8482; + t[141] = 180; + t[142] = 168; + t[143] = 8800; + t[144] = 198; + t[145] = 216; + t[146] = 8734; + t[147] = 177; + t[148] = 8804; + t[149] = 8805; + t[150] = 165; + t[151] = 181; + t[152] = 8706; + t[153] = 8721; + t[154] = 8719; + t[156] = 8747; + t[157] = 170; + t[158] = 186; + t[159] = 8486; + t[160] = 230; + t[161] = 248; + t[162] = 191; + t[163] = 161; + t[164] = 172; + t[165] = 8730; + t[166] = 402; + t[167] = 8776; + t[168] = 8710; + t[169] = 171; + t[170] = 187; + t[171] = 8230; + t[179] = 8220; + t[180] = 8221; + t[181] = 8216; + t[182] = 8217; + t[200] = 193; + t[203] = 205; + t[207] = 211; + t[210] = 218; + t[223] = 711; + t[224] = 321; + t[225] = 322; + t[226] = 352; + t[227] = 353; + t[228] = 381; + t[229] = 382; + t[233] = 221; + t[234] = 253; + t[252] = 263; + t[253] = 268; + t[254] = 269; + t[258] = 258; + t[260] = 260; + t[261] = 261; + t[265] = 280; + t[266] = 281; + t[267] = 282; + t[268] = 283; + t[269] = 313; + t[275] = 323; + t[276] = 324; + t[278] = 328; + t[283] = 344; + t[284] = 345; + t[285] = 346; + t[286] = 347; + t[292] = 367; + t[295] = 377; + t[296] = 378; + t[298] = 380; + t[305] = 963; + t[306] = 964; + t[307] = 966; + t[308] = 8215; + t[309] = 8252; + t[310] = 8319; + t[311] = 8359; + t[312] = 8592; + t[313] = 8593; + t[337] = 9552; + t[493] = 1039; + t[494] = 1040; + t[570] = 1040; + t[571] = 1041; + t[572] = 1042; + t[573] = 1043; + t[574] = 1044; + t[575] = 1045; + t[576] = 1046; + t[577] = 1047; + t[578] = 1048; + t[579] = 1049; + t[580] = 1050; + t[581] = 1051; + t[582] = 1052; + t[583] = 1053; + t[584] = 1054; + t[585] = 1055; + t[586] = 1056; + t[587] = 1057; + t[588] = 1058; + t[589] = 1059; + t[590] = 1060; + t[591] = 1061; + t[592] = 1062; + t[593] = 1063; + t[594] = 1064; + t[595] = 1065; + t[596] = 1066; + t[597] = 1067; + t[598] = 1068; + t[599] = 1069; + t[600] = 1070; + t[672] = 1488; + t[673] = 1489; + t[674] = 1490; + t[675] = 1491; + t[676] = 1492; + t[677] = 1493; + t[678] = 1494; + t[679] = 1495; + t[680] = 1496; + t[681] = 1497; + t[682] = 1498; + t[683] = 1499; + t[684] = 1500; + t[685] = 1501; + t[686] = 1502; + t[687] = 1503; + t[688] = 1504; + t[689] = 1505; + t[690] = 1506; + t[691] = 1507; + t[692] = 1508; + t[693] = 1509; + t[694] = 1510; + t[695] = 1511; + t[696] = 1512; + t[697] = 1513; + t[698] = 1514; + t[705] = 1524; + t[706] = 8362; + t[710] = 64288; + t[711] = 64298; + t[759] = 1617; + t[761] = 1776; + t[763] = 1778; + t[775] = 1652; + t[777] = 1764; + t[778] = 1780; + t[779] = 1781; + t[780] = 1782; + t[782] = 771; + t[783] = 64726; + t[786] = 8363; + t[788] = 8532; + t[790] = 768; + t[791] = 769; + t[792] = 768; + t[795] = 803; + t[797] = 64336; + t[798] = 64337; + t[799] = 64342; + t[800] = 64343; + t[801] = 64344; + t[802] = 64345; + t[803] = 64362; + t[804] = 64363; + t[805] = 64364; + t[2424] = 7821; + t[2425] = 7822; + t[2426] = 7823; + t[2427] = 7824; + t[2428] = 7825; + t[2429] = 7826; + t[2430] = 7827; + t[2433] = 7682; + t[2678] = 8045; + t[2679] = 8046; + t[2830] = 1552; + t[2838] = 686; + t[2840] = 751; + t[2842] = 753; + t[2843] = 754; + t[2844] = 755; + t[2846] = 757; + t[2856] = 767; + t[2857] = 848; + t[2858] = 849; + t[2862] = 853; + t[2863] = 854; + t[2864] = 855; + t[2865] = 861; + t[2866] = 862; + t[2906] = 7460; + t[2908] = 7462; + t[2909] = 7463; + t[2910] = 7464; + t[2912] = 7466; + t[2913] = 7467; + t[2914] = 7468; + t[2916] = 7470; + t[2917] = 7471; + t[2918] = 7472; + t[2920] = 7474; + t[2921] = 7475; + t[2922] = 7476; + t[2924] = 7478; + t[2925] = 7479; + t[2926] = 7480; + t[2928] = 7482; + t[2929] = 7483; + t[2930] = 7484; + t[2932] = 7486; + t[2933] = 7487; + t[2934] = 7488; + t[2936] = 7490; + t[2937] = 7491; + t[2938] = 7492; + t[2940] = 7494; + t[2941] = 7495; + t[2942] = 7496; + t[2944] = 7498; + t[2946] = 7500; + t[2948] = 7502; + t[2950] = 7504; + t[2951] = 7505; + t[2952] = 7506; + t[2954] = 7508; + t[2955] = 7509; + t[2956] = 7510; + t[2958] = 7512; + t[2959] = 7513; + t[2960] = 7514; + t[2962] = 7516; + t[2963] = 7517; + t[2964] = 7518; + t[2966] = 7520; + t[2967] = 7521; + t[2968] = 7522; + t[2970] = 7524; + t[2971] = 7525; + t[2972] = 7526; + t[2974] = 7528; + t[2975] = 7529; + t[2976] = 7530; + t[2978] = 1537; + t[2979] = 1538; + t[2980] = 1539; + t[2982] = 1549; + t[2983] = 1551; + t[2984] = 1552; + t[2986] = 1554; + t[2987] = 1555; + t[2988] = 1556; + t[2990] = 1623; + t[2991] = 1624; + t[2995] = 1775; + t[2999] = 1791; + t[3002] = 64290; + t[3003] = 64291; + t[3004] = 64292; + t[3006] = 64294; + t[3007] = 64295; + t[3008] = 64296; + t[3011] = 1900; + t[3014] = 8223; + t[3015] = 8244; + t[3017] = 7532; + t[3018] = 7533; + t[3019] = 7534; + t[3075] = 7590; + t[3076] = 7591; + t[3079] = 7594; + t[3080] = 7595; + t[3083] = 7598; + t[3084] = 7599; + t[3087] = 7602; + t[3088] = 7603; + t[3091] = 7606; + t[3092] = 7607; + t[3095] = 7610; + t[3096] = 7611; + t[3099] = 7614; + t[3100] = 7615; + t[3103] = 7618; + t[3104] = 7619; + t[3107] = 8337; + t[3108] = 8338; + t[3116] = 1884; + t[3119] = 1885; + t[3120] = 1885; + t[3123] = 1886; + t[3124] = 1886; + t[3127] = 1887; + t[3128] = 1887; + t[3131] = 1888; + t[3132] = 1888; + t[3135] = 1889; + t[3136] = 1889; + t[3139] = 1890; + t[3140] = 1890; + t[3143] = 1891; + t[3144] = 1891; + t[3147] = 1892; + t[3148] = 1892; + t[3153] = 580; + t[3154] = 581; + t[3157] = 584; + t[3158] = 585; + t[3161] = 588; + t[3162] = 589; + t[3165] = 891; + t[3166] = 892; + t[3169] = 1274; + t[3170] = 1275; + t[3173] = 1278; + t[3174] = 1279; + t[3181] = 7622; + t[3182] = 7623; + t[3282] = 11799; + t[3316] = 578; + t[3379] = 42785; + t[3393] = 1159; + t[3416] = 8377; +}); +const getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function (t) { + t[227] = 322; + t[264] = 261; + t[291] = 346; +}); +const getSupplementalGlyphMapForCalibri = getLookupTableFactory(function (t) { + t[1] = 32; + t[4] = 65; + t[5] = 192; + t[6] = 193; + t[9] = 196; + t[17] = 66; + t[18] = 67; + t[21] = 268; + t[24] = 68; + t[28] = 69; + t[29] = 200; + t[30] = 201; + t[32] = 282; + t[38] = 70; + t[39] = 71; + t[44] = 72; + t[47] = 73; + t[48] = 204; + t[49] = 205; + t[58] = 74; + t[60] = 75; + t[62] = 76; + t[68] = 77; + t[69] = 78; + t[75] = 79; + t[76] = 210; + t[80] = 214; + t[87] = 80; + t[89] = 81; + t[90] = 82; + t[92] = 344; + t[94] = 83; + t[97] = 352; + t[100] = 84; + t[104] = 85; + t[109] = 220; + t[115] = 86; + t[116] = 87; + t[121] = 88; + t[122] = 89; + t[124] = 221; + t[127] = 90; + t[129] = 381; + t[258] = 97; + t[259] = 224; + t[260] = 225; + t[263] = 228; + t[268] = 261; + t[271] = 98; + t[272] = 99; + t[273] = 263; + t[275] = 269; + t[282] = 100; + t[286] = 101; + t[287] = 232; + t[288] = 233; + t[290] = 283; + t[295] = 281; + t[296] = 102; + t[336] = 103; + t[346] = 104; + t[349] = 105; + t[350] = 236; + t[351] = 237; + t[361] = 106; + t[364] = 107; + t[367] = 108; + t[371] = 322; + t[373] = 109; + t[374] = 110; + t[381] = 111; + t[382] = 242; + t[383] = 243; + t[386] = 246; + t[393] = 112; + t[395] = 113; + t[396] = 114; + t[398] = 345; + t[400] = 115; + t[401] = 347; + t[403] = 353; + t[410] = 116; + t[437] = 117; + t[442] = 252; + t[448] = 118; + t[449] = 119; + t[454] = 120; + t[455] = 121; + t[457] = 253; + t[460] = 122; + t[462] = 382; + t[463] = 380; + t[853] = 44; + t[855] = 58; + t[856] = 46; + t[876] = 47; + t[878] = 45; + t[882] = 45; + t[894] = 40; + t[895] = 41; + t[896] = 91; + t[897] = 93; + t[923] = 64; + t[940] = 163; + t[1004] = 48; + t[1005] = 49; + t[1006] = 50; + t[1007] = 51; + t[1008] = 52; + t[1009] = 53; + t[1010] = 54; + t[1011] = 55; + t[1012] = 56; + t[1013] = 57; + t[1081] = 37; + t[1085] = 43; + t[1086] = 45; +}); +function getStandardFontName(name) { + const fontName = normalizeFontName(name); + const stdFontMap = getStdFontMap(); + return stdFontMap[fontName]; +} +function isKnownFontName(name) { + const fontName = normalizeFontName(name); + return !!(getStdFontMap()[fontName] || getNonStdFontMap()[fontName] || getSerifFonts()[fontName] || getSymbolsFonts()[fontName]); +} + +;// ./src/core/to_unicode_map.js + +class ToUnicodeMap { + constructor(cmap = []) { + this._map = cmap; + } + get length() { + return this._map.length; + } + forEach(callback) { + for (const charCode in this._map) { + callback(charCode, this._map[charCode].codePointAt(0)); + } + } + has(i) { + return this._map[i] !== undefined; + } + get(i) { + return this._map[i]; + } + charCodeOf(value) { + const map = this._map; + if (map.length <= 0x10000) { + return map.indexOf(value); + } + for (const charCode in map) { + if (map[charCode] === value) { + return charCode | 0; + } + } + return -1; + } + amend(map) { + for (const charCode in map) { + this._map[charCode] = map[charCode]; + } + } +} +class IdentityToUnicodeMap { + constructor(firstChar, lastChar) { + this.firstChar = firstChar; + this.lastChar = lastChar; + } + get length() { + return this.lastChar + 1 - this.firstChar; + } + forEach(callback) { + for (let i = this.firstChar, ii = this.lastChar; i <= ii; i++) { + callback(i, i); + } + } + has(i) { + return this.firstChar <= i && i <= this.lastChar; + } + get(i) { + if (this.firstChar <= i && i <= this.lastChar) { + return String.fromCharCode(i); + } + return undefined; + } + charCodeOf(v) { + return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1; + } + amend(map) { + unreachable("Should not call amend()"); + } +} + +;// ./src/core/cff_font.js + + + +class CFFFont { + constructor(file, properties) { + this.properties = properties; + const parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED); + this.cff = parser.parse(); + this.cff.duplicateFirstGlyph(); + const compiler = new CFFCompiler(this.cff); + this.seacs = this.cff.seacs; + try { + this.data = compiler.compile(); + } catch { + warn("Failed to compile font " + properties.loadedName); + this.data = file; + } + this._createBuiltInEncoding(); + } + get numGlyphs() { + return this.cff.charStrings.count; + } + getCharset() { + return this.cff.charset.charset; + } + getGlyphMapping() { + const cff = this.cff; + const properties = this.properties; + const { + cidToGidMap, + cMap + } = properties; + const charsets = cff.charset.charset; + let charCodeToGlyphId; + let glyphId; + if (properties.composite) { + let invCidToGidMap; + if (cidToGidMap?.length > 0) { + invCidToGidMap = Object.create(null); + for (let i = 0, ii = cidToGidMap.length; i < ii; i++) { + const gid = cidToGidMap[i]; + if (gid !== undefined) { + invCidToGidMap[gid] = i; + } + } + } + charCodeToGlyphId = Object.create(null); + let charCode; + if (cff.isCIDFont) { + for (glyphId = 0; glyphId < charsets.length; glyphId++) { + const cid = charsets[glyphId]; + charCode = cMap.charCodeOf(cid); + if (invCidToGidMap?.[charCode] !== undefined) { + charCode = invCidToGidMap[charCode]; + } + charCodeToGlyphId[charCode] = glyphId; + } + } else { + for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { + charCode = cMap.charCodeOf(glyphId); + charCodeToGlyphId[charCode] = glyphId; + } + } + return charCodeToGlyphId; + } + let encoding = cff.encoding ? cff.encoding.encoding : null; + if (properties.isInternalFont) { + encoding = properties.defaultEncoding; + } + charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); + return charCodeToGlyphId; + } + hasGlyphId(id) { + return this.cff.hasGlyphId(id); + } + _createBuiltInEncoding() { + const { + charset, + encoding + } = this.cff; + if (!charset || !encoding) { + return; + } + const charsets = charset.charset, + encodings = encoding.encoding; + const map = []; + for (const charCode in encodings) { + const glyphId = encodings[charCode]; + if (glyphId >= 0) { + const glyphName = charsets[glyphId]; + if (glyphName) { + map[charCode] = glyphName; + } + } + } + if (map.length > 0) { + this.properties.builtInEncoding = map; + } + } +} + +;// ./src/core/font_renderer.js + + + + + + +function getFloat214(data, offset) { + return readInt16(data, offset) / 16384; +} +function getSubroutineBias(subrs) { + const numSubrs = subrs.length; + let bias = 32768; + if (numSubrs < 1240) { + bias = 107; + } else if (numSubrs < 33900) { + bias = 1131; + } + return bias; +} +function parseCmap(data, start, end) { + const offset = readUint16(data, start + 2) === 1 ? readUint32(data, start + 8) : readUint32(data, start + 16); + const format = readUint16(data, start + offset); + let ranges, p, i; + if (format === 4) { + readUint16(data, start + offset + 2); + const segCount = readUint16(data, start + offset + 6) >> 1; + p = start + offset + 14; + ranges = []; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i] = { + end: readUint16(data, p) + }; + } + p += 2; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].start = readUint16(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = readUint16(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + let idOffset = readUint16(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = readUint16(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + const groups = readUint32(data, start + offset + 12); + p = start + offset + 16; + ranges = []; + for (i = 0; i < groups; i++) { + start = readUint32(data, p); + ranges.push({ + start, + end: readUint32(data, p + 4), + idDelta: readUint32(data, p + 8) - start + }); + p += 12; + } + return ranges; + } + throw new FormatError(`unsupported cmap: ${format}`); +} +function parseCff(data, start, end, seacAnalysisEnabled) { + const properties = {}; + const parser = new CFFParser(new Stream(data, start, end - start), properties, seacAnalysisEnabled); + const cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: cff.topDict.privateDict?.subrsIndex?.objects, + gsubrs: cff.globalSubrIndex?.objects, + isCFFCIDFont: cff.isCIDFont, + fdSelect: cff.fdSelect, + fdArray: cff.fdArray + }; +} +function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + let itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = readUint32; + } else { + itemSize = 2; + itemDecode = (data, offset) => 2 * readUint16(data, offset); + } + const glyphs = []; + let startOffset = itemDecode(loca, 0); + for (let j = itemSize; j < loca.length; j += itemSize) { + const endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; +} +function lookupCmap(ranges, unicode) { + const code = unicode.codePointAt(0); + let gid = 0, + l = 0, + r = ranges.length - 1; + while (l < r) { + const c = l + r + 1 >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l = c; + } + } + if (ranges[l].start <= code && code <= ranges[l].end) { + gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xffff; + } + return { + charCode: code, + glyphId: gid + }; +} +function compileGlyf(code, cmds, font) { + function moveTo(x, y) { + if (firstPoint) { + cmds.add(DrawOPS.lineTo, firstPoint); + } + firstPoint = [x, y]; + cmds.add(DrawOPS.moveTo, [x, y]); + } + function lineTo(x, y) { + cmds.add(DrawOPS.lineTo, [x, y]); + } + function quadraticCurveTo(xa, ya, x, y) { + cmds.add(DrawOPS.quadraticCurveTo, [xa, ya, x, y]); + } + let i = 0; + const numberOfContours = readInt16(code, i); + let flags; + let firstPoint = null; + let x = 0, + y = 0; + i += 10; + if (numberOfContours < 0) { + do { + flags = readUint16(code, i); + const glyphIndex = readUint16(code, i + 2); + i += 4; + let arg1, arg2; + if (flags & 0x01) { + if (flags & 0x02) { + arg1 = readInt16(code, i); + arg2 = readInt16(code, i + 2); + } else { + arg1 = readUint16(code, i); + arg2 = readUint16(code, i + 2); + } + i += 4; + } else if (flags & 0x02) { + arg1 = readInt8(code, i++); + arg2 = readInt8(code, i++); + } else { + arg1 = code[i++]; + arg2 = code[i++]; + } + if (flags & 0x02) { + x = arg1; + y = arg2; + } else { + x = 0; + y = 0; + } + let scaleX = 1, + scaleY = 1, + scale01 = 0, + scale10 = 0; + if (flags & 0x08) { + scaleX = scaleY = getFloat214(code, i); + i += 2; + } else if (flags & 0x40) { + scaleX = getFloat214(code, i); + scaleY = getFloat214(code, i + 2); + i += 4; + } else if (flags & 0x80) { + scaleX = getFloat214(code, i); + scale01 = getFloat214(code, i + 2); + scale10 = getFloat214(code, i + 4); + scaleY = getFloat214(code, i + 6); + i += 8; + } + const subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + cmds.save(); + cmds.transform([scaleX, scale01, scale10, scaleY, x, y]); + if (!(flags & 0x02)) {} + compileGlyf(subglyph, cmds, font); + cmds.restore(); + } + } while (flags & 0x20); + } else { + const endPtsOfContours = []; + let j, jj; + for (j = 0; j < numberOfContours; j++) { + endPtsOfContours.push(readUint16(code, i)); + i += 2; + } + const instructionLength = readUint16(code, i); + i += 2 + instructionLength; + const numberOfPoints = endPtsOfContours.at(-1) + 1; + const points = []; + while (points.length < numberOfPoints) { + flags = code[i++]; + let repeat = 1; + if (flags & 0x08) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({ + flags + }); + } + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x12) { + case 0x00: + x += readInt16(code, i); + i += 2; + break; + case 0x02: + x -= code[i++]; + break; + case 0x12: + x += code[i++]; + break; + } + points[j].x = x; + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x24) { + case 0x00: + y += readInt16(code, i); + i += 2; + break; + case 0x04: + y -= code[i++]; + break; + case 0x24: + y += code[i++]; + break; + } + points[j].y = y; + } + let startPoint = 0; + for (i = 0; i < numberOfContours; i++) { + const endPoint = endPtsOfContours[i]; + const contour = points.slice(startPoint, endPoint + 1); + if (contour[0].flags & 1) { + contour.push(contour[0]); + } else if (contour.at(-1).flags & 1) { + contour.unshift(contour.at(-1)); + } else { + const p = { + flags: 1, + x: (contour[0].x + contour.at(-1).x) / 2, + y: (contour[0].y + contour.at(-1).y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (j = 1, jj = contour.length; j < jj; j++) { + if (contour[j].flags & 1) { + lineTo(contour[j].x, contour[j].y); + } else if (contour[j + 1].flags & 1) { + quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } +} +function compileCharString(charStringCode, cmds, font, glyphId) { + function moveTo(x, y) { + if (firstPoint) { + cmds.add(DrawOPS.lineTo, firstPoint); + } + firstPoint = [x, y]; + cmds.add(DrawOPS.moveTo, [x, y]); + } + function lineTo(x, y) { + cmds.add(DrawOPS.lineTo, [x, y]); + } + function bezierCurveTo(x1, y1, x2, y2, x, y) { + cmds.add(DrawOPS.curveTo, [x1, y1, x2, y2, x, y]); + } + const stack = []; + let x = 0, + y = 0; + let stems = 0; + let firstPoint = null; + function parse(code) { + let i = 0; + while (i < code.length) { + let stackClean = false; + let v = code[i++]; + let xa, xb, ya, yb, y1, y2, y3, n, subrCode; + switch (v) { + case 1: + stems += stack.length >> 1; + stackClean = true; + break; + case 3: + stems += stack.length >> 1; + stackClean = true; + break; + case 4: + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 10: + n = stack.pop(); + subrCode = null; + if (font.isCFFCIDFont) { + const fdIndex = font.fdSelect.getFDIndex(glyphId); + if (fdIndex >= 0 && fdIndex < font.fdArray.length) { + const fontDict = font.fdArray[fdIndex]; + let subrs; + if (fontDict.privateDict?.subrsIndex) { + subrs = fontDict.privateDict.subrsIndex.objects; + } + if (subrs) { + n += getSubroutineBias(subrs); + subrCode = subrs[n]; + } + } else { + warn("Invalid fd index for glyph index."); + } + } else { + subrCode = font.subrs[n + font.subrsBias]; + } + if (subrCode) { + parse(subrCode); + } + break; + case 11: + return; + case 12: + v = code[i++]; + switch (v) { + case 34: + xa = x + stack.shift(); + xb = xa + stack.shift(); + y1 = y + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y, xb, y1, x, y1); + xa = x + stack.shift(); + xb = xa + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y, x, y); + break; + case 35: + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + stack.pop(); + break; + case 36: + xa = x + stack.shift(); + y1 = y + stack.shift(); + xb = xa + stack.shift(); + y2 = y1 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y2, x, y2); + xa = x + stack.shift(); + xb = xa + stack.shift(); + y3 = y2 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y2, xb, y3, x, y); + break; + case 37: + const x0 = x, + y0 = y; + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) { + x += stack.shift(); + } else { + y += stack.shift(); + } + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + throw new FormatError(`unknown operator: 12 ${v}`); + } + break; + case 14: + if (stack.length >= 4) { + const achar = stack.pop(); + const bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + cmds.save(); + cmds.translate(x, y); + let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); + cmds.restore(); + cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); + } + return; + case 18: + stems += stack.length >> 1; + stackClean = true; + break; + case 19: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 20: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 21: + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: + stems += stack.length >> 1; + stackClean = true; + break; + case 24: + while (stack.length > 2) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push(readInt16(code, i)); + i += 2; + break; + case 29: + n = stack.pop() + font.gsubrsBias; + subrCode = font.gsubrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 30: + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) { + throw new FormatError(`unknown operator: ${v}`); + } + if (v < 247) { + stack.push(v - 139); + } else if (v < 251) { + stack.push((v - 247) * 256 + code[i++] + 108); + } else if (v < 255) { + stack.push(-(v - 251) * 256 - code[i++] - 108); + } else { + stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse(charStringCode); +} +const NOOP = ""; +class Commands { + cmds = []; + transformStack = []; + currentTransform = [1, 0, 0, 1, 0, 0]; + add(cmd, args) { + if (args) { + const { + currentTransform + } = this; + for (let i = 0, ii = args.length; i < ii; i += 2) { + Util.applyTransform(args, currentTransform, i); + } + this.cmds.push(cmd, ...args); + } else { + this.cmds.push(cmd); + } + } + transform(transf) { + this.currentTransform = Util.transform(this.currentTransform, transf); + } + translate(x, y) { + this.transform([1, 0, 0, 1, x, y]); + } + save() { + this.transformStack.push(this.currentTransform.slice()); + } + restore() { + this.currentTransform = this.transformStack.pop() || [1, 0, 0, 1, 0, 0]; + } + getPath() { + return new Float16Array(this.cmds); + } +} +class CompiledFont { + constructor(fontMatrix) { + this.fontMatrix = fontMatrix; + this.compiledGlyphs = Object.create(null); + this.compiledCharCodeToGlyphId = Object.create(null); + } + getPathJs(unicode) { + const { + charCode, + glyphId + } = lookupCmap(this.cmap, unicode); + let fn = this.compiledGlyphs[glyphId], + compileEx; + if (fn === undefined) { + try { + fn = this.compileGlyph(this.glyphs[glyphId], glyphId); + } catch (ex) { + fn = NOOP; + compileEx = ex; + } + this.compiledGlyphs[glyphId] = fn; + } + this.compiledCharCodeToGlyphId[charCode] ??= glyphId; + if (compileEx) { + throw compileEx; + } + return fn; + } + compileGlyph(code, glyphId) { + if (!code?.length || code[0] === 14) { + return NOOP; + } + let fontMatrix = this.fontMatrix; + if (this.isCFFCIDFont) { + const fdIndex = this.fdSelect.getFDIndex(glyphId); + if (fdIndex >= 0 && fdIndex < this.fdArray.length) { + const fontDict = this.fdArray[fdIndex]; + fontMatrix = fontDict.getByName("FontMatrix") || FONT_IDENTITY_MATRIX; + } else { + warn("Invalid fd index for glyph index."); + } + } + assert(isNumberArray(fontMatrix, 6), "Expected a valid fontMatrix."); + const cmds = new Commands(); + cmds.transform(fontMatrix.slice()); + this.compileGlyphImpl(code, cmds, glyphId); + cmds.add(DrawOPS.closePath); + return cmds.getPath(); + } + compileGlyphImpl() { + unreachable("Children classes should implement this."); + } + hasBuiltPath(unicode) { + const { + charCode, + glyphId + } = lookupCmap(this.cmap, unicode); + return this.compiledGlyphs[glyphId] !== undefined && this.compiledCharCodeToGlyphId[charCode] !== undefined; + } +} +class TrueTypeCompiled extends CompiledFont { + constructor(glyphs, cmap, fontMatrix) { + super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]); + this.glyphs = glyphs; + this.cmap = cmap; + } + compileGlyphImpl(code, cmds) { + compileGlyf(code, cmds, this); + } +} +class Type2Compiled extends CompiledFont { + constructor(cffInfo, cmap, fontMatrix) { + super(fontMatrix || [0.001, 0, 0, 0.001, 0, 0]); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = getGlyphsUnicode(); + this.gsubrsBias = getSubroutineBias(this.gsubrs); + this.subrsBias = getSubroutineBias(this.subrs); + this.isCFFCIDFont = cffInfo.isCFFCIDFont; + this.fdSelect = cffInfo.fdSelect; + this.fdArray = cffInfo.fdArray; + } + compileGlyphImpl(code, cmds, glyphId) { + compileCharString(code, cmds, this, glyphId); + } +} +class FontRendererFactory { + static create(font, seacAnalysisEnabled) { + const data = new Uint8Array(font.data); + let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + const numTables = readUint16(data, 4); + for (let i = 0, p = 12; i < numTables; i++, p += 16) { + const tag = bytesToString(data.subarray(p, p + 4)); + const offset = readUint32(data, p + 8); + const length = readUint32(data, p + 12); + switch (tag) { + case "cmap": + cmap = parseCmap(data, offset, offset + length); + break; + case "glyf": + glyf = data.subarray(offset, offset + length); + break; + case "loca": + loca = data.subarray(offset, offset + length); + break; + case "head": + unitsPerEm = readUint16(data, offset + 18); + indexToLocFormat = readUint16(data, offset + 50); + break; + case "CFF ": + cff = parseCff(data, offset, offset + length, seacAnalysisEnabled); + break; + } + } + if (glyf) { + const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]; + return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } + return new Type2Compiled(cff, cmap, font.fontMatrix); + } +} + +;// ./src/core/metrics.js + +const getMetrics = getLookupTableFactory(function (t) { + t.Courier = 600; + t["Courier-Bold"] = 600; + t["Courier-BoldOblique"] = 600; + t["Courier-Oblique"] = 600; + t.Helvetica = getLookupTableFactory(function (t) { + t.space = 278; + t.exclam = 278; + t.quotedbl = 355; + t.numbersign = 556; + t.dollar = 556; + t.percent = 889; + t.ampersand = 667; + t.quoteright = 222; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 389; + t.plus = 584; + t.comma = 278; + t.hyphen = 333; + t.period = 278; + t.slash = 278; + t.zero = 556; + t.one = 556; + t.two = 556; + t.three = 556; + t.four = 556; + t.five = 556; + t.six = 556; + t.seven = 556; + t.eight = 556; + t.nine = 556; + t.colon = 278; + t.semicolon = 278; + t.less = 584; + t.equal = 584; + t.greater = 584; + t.question = 556; + t.at = 1015; + t.A = 667; + t.B = 667; + t.C = 722; + t.D = 722; + t.E = 667; + t.F = 611; + t.G = 778; + t.H = 722; + t.I = 278; + t.J = 500; + t.K = 667; + t.L = 556; + t.M = 833; + t.N = 722; + t.O = 778; + t.P = 667; + t.Q = 778; + t.R = 722; + t.S = 667; + t.T = 611; + t.U = 722; + t.V = 667; + t.W = 944; + t.X = 667; + t.Y = 667; + t.Z = 611; + t.bracketleft = 278; + t.backslash = 278; + t.bracketright = 278; + t.asciicircum = 469; + t.underscore = 556; + t.quoteleft = 222; + t.a = 556; + t.b = 556; + t.c = 500; + t.d = 556; + t.e = 556; + t.f = 278; + t.g = 556; + t.h = 556; + t.i = 222; + t.j = 222; + t.k = 500; + t.l = 222; + t.m = 833; + t.n = 556; + t.o = 556; + t.p = 556; + t.q = 556; + t.r = 333; + t.s = 500; + t.t = 278; + t.u = 556; + t.v = 500; + t.w = 722; + t.x = 500; + t.y = 500; + t.z = 500; + t.braceleft = 334; + t.bar = 260; + t.braceright = 334; + t.asciitilde = 584; + t.exclamdown = 333; + t.cent = 556; + t.sterling = 556; + t.fraction = 167; + t.yen = 556; + t.florin = 556; + t.section = 556; + t.currency = 556; + t.quotesingle = 191; + t.quotedblleft = 333; + t.guillemotleft = 556; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 500; + t.fl = 500; + t.endash = 556; + t.dagger = 556; + t.daggerdbl = 556; + t.periodcentered = 278; + t.paragraph = 537; + t.bullet = 350; + t.quotesinglbase = 222; + t.quotedblbase = 333; + t.quotedblright = 333; + t.guillemotright = 556; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 611; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 1000; + t.ordfeminine = 370; + t.Lslash = 556; + t.Oslash = 778; + t.OE = 1000; + t.ordmasculine = 365; + t.ae = 889; + t.dotlessi = 278; + t.lslash = 222; + t.oslash = 611; + t.oe = 944; + t.germandbls = 611; + t.Idieresis = 278; + t.eacute = 556; + t.abreve = 556; + t.uhungarumlaut = 556; + t.ecaron = 556; + t.Ydieresis = 667; + t.divide = 584; + t.Yacute = 667; + t.Acircumflex = 667; + t.aacute = 556; + t.Ucircumflex = 722; + t.yacute = 500; + t.scommaaccent = 500; + t.ecircumflex = 556; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 556; + t.Uacute = 722; + t.uogonek = 556; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 737; + t.Emacron = 667; + t.ccaron = 500; + t.aring = 556; + t.Ncommaaccent = 722; + t.lacute = 222; + t.agrave = 556; + t.Tcommaaccent = 611; + t.Cacute = 722; + t.atilde = 556; + t.Edotaccent = 667; + t.scaron = 500; + t.scedilla = 500; + t.iacute = 278; + t.lozenge = 471; + t.Rcaron = 722; + t.Gcommaaccent = 778; + t.ucircumflex = 556; + t.acircumflex = 556; + t.Amacron = 667; + t.rcaron = 333; + t.ccedilla = 500; + t.Zdotaccent = 611; + t.Thorn = 667; + t.Omacron = 778; + t.Racute = 722; + t.Sacute = 667; + t.dcaron = 643; + t.Umacron = 722; + t.uring = 556; + t.threesuperior = 333; + t.Ograve = 778; + t.Agrave = 667; + t.Abreve = 667; + t.multiply = 584; + t.uacute = 556; + t.Tcaron = 611; + t.partialdiff = 476; + t.ydieresis = 500; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 556; + t.edieresis = 556; + t.cacute = 500; + t.nacute = 556; + t.umacron = 556; + t.Ncaron = 722; + t.Iacute = 278; + t.plusminus = 584; + t.brokenbar = 260; + t.registered = 737; + t.Gbreve = 778; + t.Idotaccent = 278; + t.summation = 600; + t.Egrave = 667; + t.racute = 333; + t.omacron = 556; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 722; + t.lcommaaccent = 222; + t.tcaron = 317; + t.eogonek = 556; + t.Uogonek = 722; + t.Aacute = 667; + t.Adieresis = 667; + t.egrave = 556; + t.zacute = 500; + t.iogonek = 222; + t.Oacute = 778; + t.oacute = 556; + t.amacron = 556; + t.sacute = 500; + t.idieresis = 278; + t.Ocircumflex = 778; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 556; + t.twosuperior = 333; + t.Odieresis = 778; + t.mu = 556; + t.igrave = 278; + t.ohungarumlaut = 556; + t.Eogonek = 667; + t.dcroat = 556; + t.threequarters = 834; + t.Scedilla = 667; + t.lcaron = 299; + t.Kcommaaccent = 667; + t.Lacute = 556; + t.trademark = 1000; + t.edotaccent = 556; + t.Igrave = 278; + t.Imacron = 278; + t.Lcaron = 556; + t.onehalf = 834; + t.lessequal = 549; + t.ocircumflex = 556; + t.ntilde = 556; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 556; + t.gbreve = 556; + t.onequarter = 834; + t.Scaron = 667; + t.Scommaaccent = 667; + t.Ohungarumlaut = 778; + t.degree = 400; + t.ograve = 556; + t.Ccaron = 722; + t.ugrave = 556; + t.radical = 453; + t.Dcaron = 722; + t.rcommaaccent = 333; + t.Ntilde = 722; + t.otilde = 556; + t.Rcommaaccent = 722; + t.Lcommaaccent = 556; + t.Atilde = 667; + t.Aogonek = 667; + t.Aring = 667; + t.Otilde = 778; + t.zdotaccent = 500; + t.Ecaron = 667; + t.Iogonek = 278; + t.kcommaaccent = 500; + t.minus = 584; + t.Icircumflex = 278; + t.ncaron = 556; + t.tcommaaccent = 278; + t.logicalnot = 584; + t.odieresis = 556; + t.udieresis = 556; + t.notequal = 549; + t.gcommaaccent = 556; + t.eth = 556; + t.zcaron = 500; + t.ncommaaccent = 556; + t.onesuperior = 333; + t.imacron = 278; + t.Euro = 556; + }); + t["Helvetica-Bold"] = getLookupTableFactory(function (t) { + t.space = 278; + t.exclam = 333; + t.quotedbl = 474; + t.numbersign = 556; + t.dollar = 556; + t.percent = 889; + t.ampersand = 722; + t.quoteright = 278; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 389; + t.plus = 584; + t.comma = 278; + t.hyphen = 333; + t.period = 278; + t.slash = 278; + t.zero = 556; + t.one = 556; + t.two = 556; + t.three = 556; + t.four = 556; + t.five = 556; + t.six = 556; + t.seven = 556; + t.eight = 556; + t.nine = 556; + t.colon = 333; + t.semicolon = 333; + t.less = 584; + t.equal = 584; + t.greater = 584; + t.question = 611; + t.at = 975; + t.A = 722; + t.B = 722; + t.C = 722; + t.D = 722; + t.E = 667; + t.F = 611; + t.G = 778; + t.H = 722; + t.I = 278; + t.J = 556; + t.K = 722; + t.L = 611; + t.M = 833; + t.N = 722; + t.O = 778; + t.P = 667; + t.Q = 778; + t.R = 722; + t.S = 667; + t.T = 611; + t.U = 722; + t.V = 667; + t.W = 944; + t.X = 667; + t.Y = 667; + t.Z = 611; + t.bracketleft = 333; + t.backslash = 278; + t.bracketright = 333; + t.asciicircum = 584; + t.underscore = 556; + t.quoteleft = 278; + t.a = 556; + t.b = 611; + t.c = 556; + t.d = 611; + t.e = 556; + t.f = 333; + t.g = 611; + t.h = 611; + t.i = 278; + t.j = 278; + t.k = 556; + t.l = 278; + t.m = 889; + t.n = 611; + t.o = 611; + t.p = 611; + t.q = 611; + t.r = 389; + t.s = 556; + t.t = 333; + t.u = 611; + t.v = 556; + t.w = 778; + t.x = 556; + t.y = 556; + t.z = 500; + t.braceleft = 389; + t.bar = 280; + t.braceright = 389; + t.asciitilde = 584; + t.exclamdown = 333; + t.cent = 556; + t.sterling = 556; + t.fraction = 167; + t.yen = 556; + t.florin = 556; + t.section = 556; + t.currency = 556; + t.quotesingle = 238; + t.quotedblleft = 500; + t.guillemotleft = 556; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 611; + t.fl = 611; + t.endash = 556; + t.dagger = 556; + t.daggerdbl = 556; + t.periodcentered = 278; + t.paragraph = 556; + t.bullet = 350; + t.quotesinglbase = 278; + t.quotedblbase = 500; + t.quotedblright = 500; + t.guillemotright = 556; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 611; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 1000; + t.ordfeminine = 370; + t.Lslash = 611; + t.Oslash = 778; + t.OE = 1000; + t.ordmasculine = 365; + t.ae = 889; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 611; + t.oe = 944; + t.germandbls = 611; + t.Idieresis = 278; + t.eacute = 556; + t.abreve = 556; + t.uhungarumlaut = 611; + t.ecaron = 556; + t.Ydieresis = 667; + t.divide = 584; + t.Yacute = 667; + t.Acircumflex = 722; + t.aacute = 556; + t.Ucircumflex = 722; + t.yacute = 556; + t.scommaaccent = 556; + t.ecircumflex = 556; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 556; + t.Uacute = 722; + t.uogonek = 611; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 737; + t.Emacron = 667; + t.ccaron = 556; + t.aring = 556; + t.Ncommaaccent = 722; + t.lacute = 278; + t.agrave = 556; + t.Tcommaaccent = 611; + t.Cacute = 722; + t.atilde = 556; + t.Edotaccent = 667; + t.scaron = 556; + t.scedilla = 556; + t.iacute = 278; + t.lozenge = 494; + t.Rcaron = 722; + t.Gcommaaccent = 778; + t.ucircumflex = 611; + t.acircumflex = 556; + t.Amacron = 722; + t.rcaron = 389; + t.ccedilla = 556; + t.Zdotaccent = 611; + t.Thorn = 667; + t.Omacron = 778; + t.Racute = 722; + t.Sacute = 667; + t.dcaron = 743; + t.Umacron = 722; + t.uring = 611; + t.threesuperior = 333; + t.Ograve = 778; + t.Agrave = 722; + t.Abreve = 722; + t.multiply = 584; + t.uacute = 611; + t.Tcaron = 611; + t.partialdiff = 494; + t.ydieresis = 556; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 556; + t.edieresis = 556; + t.cacute = 556; + t.nacute = 611; + t.umacron = 611; + t.Ncaron = 722; + t.Iacute = 278; + t.plusminus = 584; + t.brokenbar = 280; + t.registered = 737; + t.Gbreve = 778; + t.Idotaccent = 278; + t.summation = 600; + t.Egrave = 667; + t.racute = 389; + t.omacron = 611; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 722; + t.lcommaaccent = 278; + t.tcaron = 389; + t.eogonek = 556; + t.Uogonek = 722; + t.Aacute = 722; + t.Adieresis = 722; + t.egrave = 556; + t.zacute = 500; + t.iogonek = 278; + t.Oacute = 778; + t.oacute = 611; + t.amacron = 556; + t.sacute = 556; + t.idieresis = 278; + t.Ocircumflex = 778; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 611; + t.twosuperior = 333; + t.Odieresis = 778; + t.mu = 611; + t.igrave = 278; + t.ohungarumlaut = 611; + t.Eogonek = 667; + t.dcroat = 611; + t.threequarters = 834; + t.Scedilla = 667; + t.lcaron = 400; + t.Kcommaaccent = 722; + t.Lacute = 611; + t.trademark = 1000; + t.edotaccent = 556; + t.Igrave = 278; + t.Imacron = 278; + t.Lcaron = 611; + t.onehalf = 834; + t.lessequal = 549; + t.ocircumflex = 611; + t.ntilde = 611; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 556; + t.gbreve = 611; + t.onequarter = 834; + t.Scaron = 667; + t.Scommaaccent = 667; + t.Ohungarumlaut = 778; + t.degree = 400; + t.ograve = 611; + t.Ccaron = 722; + t.ugrave = 611; + t.radical = 549; + t.Dcaron = 722; + t.rcommaaccent = 389; + t.Ntilde = 722; + t.otilde = 611; + t.Rcommaaccent = 722; + t.Lcommaaccent = 611; + t.Atilde = 722; + t.Aogonek = 722; + t.Aring = 722; + t.Otilde = 778; + t.zdotaccent = 500; + t.Ecaron = 667; + t.Iogonek = 278; + t.kcommaaccent = 556; + t.minus = 584; + t.Icircumflex = 278; + t.ncaron = 611; + t.tcommaaccent = 333; + t.logicalnot = 584; + t.odieresis = 611; + t.udieresis = 611; + t.notequal = 549; + t.gcommaaccent = 611; + t.eth = 611; + t.zcaron = 500; + t.ncommaaccent = 611; + t.onesuperior = 333; + t.imacron = 278; + t.Euro = 556; + }); + t["Helvetica-BoldOblique"] = getLookupTableFactory(function (t) { + t.space = 278; + t.exclam = 333; + t.quotedbl = 474; + t.numbersign = 556; + t.dollar = 556; + t.percent = 889; + t.ampersand = 722; + t.quoteright = 278; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 389; + t.plus = 584; + t.comma = 278; + t.hyphen = 333; + t.period = 278; + t.slash = 278; + t.zero = 556; + t.one = 556; + t.two = 556; + t.three = 556; + t.four = 556; + t.five = 556; + t.six = 556; + t.seven = 556; + t.eight = 556; + t.nine = 556; + t.colon = 333; + t.semicolon = 333; + t.less = 584; + t.equal = 584; + t.greater = 584; + t.question = 611; + t.at = 975; + t.A = 722; + t.B = 722; + t.C = 722; + t.D = 722; + t.E = 667; + t.F = 611; + t.G = 778; + t.H = 722; + t.I = 278; + t.J = 556; + t.K = 722; + t.L = 611; + t.M = 833; + t.N = 722; + t.O = 778; + t.P = 667; + t.Q = 778; + t.R = 722; + t.S = 667; + t.T = 611; + t.U = 722; + t.V = 667; + t.W = 944; + t.X = 667; + t.Y = 667; + t.Z = 611; + t.bracketleft = 333; + t.backslash = 278; + t.bracketright = 333; + t.asciicircum = 584; + t.underscore = 556; + t.quoteleft = 278; + t.a = 556; + t.b = 611; + t.c = 556; + t.d = 611; + t.e = 556; + t.f = 333; + t.g = 611; + t.h = 611; + t.i = 278; + t.j = 278; + t.k = 556; + t.l = 278; + t.m = 889; + t.n = 611; + t.o = 611; + t.p = 611; + t.q = 611; + t.r = 389; + t.s = 556; + t.t = 333; + t.u = 611; + t.v = 556; + t.w = 778; + t.x = 556; + t.y = 556; + t.z = 500; + t.braceleft = 389; + t.bar = 280; + t.braceright = 389; + t.asciitilde = 584; + t.exclamdown = 333; + t.cent = 556; + t.sterling = 556; + t.fraction = 167; + t.yen = 556; + t.florin = 556; + t.section = 556; + t.currency = 556; + t.quotesingle = 238; + t.quotedblleft = 500; + t.guillemotleft = 556; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 611; + t.fl = 611; + t.endash = 556; + t.dagger = 556; + t.daggerdbl = 556; + t.periodcentered = 278; + t.paragraph = 556; + t.bullet = 350; + t.quotesinglbase = 278; + t.quotedblbase = 500; + t.quotedblright = 500; + t.guillemotright = 556; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 611; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 1000; + t.ordfeminine = 370; + t.Lslash = 611; + t.Oslash = 778; + t.OE = 1000; + t.ordmasculine = 365; + t.ae = 889; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 611; + t.oe = 944; + t.germandbls = 611; + t.Idieresis = 278; + t.eacute = 556; + t.abreve = 556; + t.uhungarumlaut = 611; + t.ecaron = 556; + t.Ydieresis = 667; + t.divide = 584; + t.Yacute = 667; + t.Acircumflex = 722; + t.aacute = 556; + t.Ucircumflex = 722; + t.yacute = 556; + t.scommaaccent = 556; + t.ecircumflex = 556; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 556; + t.Uacute = 722; + t.uogonek = 611; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 737; + t.Emacron = 667; + t.ccaron = 556; + t.aring = 556; + t.Ncommaaccent = 722; + t.lacute = 278; + t.agrave = 556; + t.Tcommaaccent = 611; + t.Cacute = 722; + t.atilde = 556; + t.Edotaccent = 667; + t.scaron = 556; + t.scedilla = 556; + t.iacute = 278; + t.lozenge = 494; + t.Rcaron = 722; + t.Gcommaaccent = 778; + t.ucircumflex = 611; + t.acircumflex = 556; + t.Amacron = 722; + t.rcaron = 389; + t.ccedilla = 556; + t.Zdotaccent = 611; + t.Thorn = 667; + t.Omacron = 778; + t.Racute = 722; + t.Sacute = 667; + t.dcaron = 743; + t.Umacron = 722; + t.uring = 611; + t.threesuperior = 333; + t.Ograve = 778; + t.Agrave = 722; + t.Abreve = 722; + t.multiply = 584; + t.uacute = 611; + t.Tcaron = 611; + t.partialdiff = 494; + t.ydieresis = 556; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 556; + t.edieresis = 556; + t.cacute = 556; + t.nacute = 611; + t.umacron = 611; + t.Ncaron = 722; + t.Iacute = 278; + t.plusminus = 584; + t.brokenbar = 280; + t.registered = 737; + t.Gbreve = 778; + t.Idotaccent = 278; + t.summation = 600; + t.Egrave = 667; + t.racute = 389; + t.omacron = 611; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 722; + t.lcommaaccent = 278; + t.tcaron = 389; + t.eogonek = 556; + t.Uogonek = 722; + t.Aacute = 722; + t.Adieresis = 722; + t.egrave = 556; + t.zacute = 500; + t.iogonek = 278; + t.Oacute = 778; + t.oacute = 611; + t.amacron = 556; + t.sacute = 556; + t.idieresis = 278; + t.Ocircumflex = 778; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 611; + t.twosuperior = 333; + t.Odieresis = 778; + t.mu = 611; + t.igrave = 278; + t.ohungarumlaut = 611; + t.Eogonek = 667; + t.dcroat = 611; + t.threequarters = 834; + t.Scedilla = 667; + t.lcaron = 400; + t.Kcommaaccent = 722; + t.Lacute = 611; + t.trademark = 1000; + t.edotaccent = 556; + t.Igrave = 278; + t.Imacron = 278; + t.Lcaron = 611; + t.onehalf = 834; + t.lessequal = 549; + t.ocircumflex = 611; + t.ntilde = 611; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 556; + t.gbreve = 611; + t.onequarter = 834; + t.Scaron = 667; + t.Scommaaccent = 667; + t.Ohungarumlaut = 778; + t.degree = 400; + t.ograve = 611; + t.Ccaron = 722; + t.ugrave = 611; + t.radical = 549; + t.Dcaron = 722; + t.rcommaaccent = 389; + t.Ntilde = 722; + t.otilde = 611; + t.Rcommaaccent = 722; + t.Lcommaaccent = 611; + t.Atilde = 722; + t.Aogonek = 722; + t.Aring = 722; + t.Otilde = 778; + t.zdotaccent = 500; + t.Ecaron = 667; + t.Iogonek = 278; + t.kcommaaccent = 556; + t.minus = 584; + t.Icircumflex = 278; + t.ncaron = 611; + t.tcommaaccent = 333; + t.logicalnot = 584; + t.odieresis = 611; + t.udieresis = 611; + t.notequal = 549; + t.gcommaaccent = 611; + t.eth = 611; + t.zcaron = 500; + t.ncommaaccent = 611; + t.onesuperior = 333; + t.imacron = 278; + t.Euro = 556; + }); + t["Helvetica-Oblique"] = getLookupTableFactory(function (t) { + t.space = 278; + t.exclam = 278; + t.quotedbl = 355; + t.numbersign = 556; + t.dollar = 556; + t.percent = 889; + t.ampersand = 667; + t.quoteright = 222; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 389; + t.plus = 584; + t.comma = 278; + t.hyphen = 333; + t.period = 278; + t.slash = 278; + t.zero = 556; + t.one = 556; + t.two = 556; + t.three = 556; + t.four = 556; + t.five = 556; + t.six = 556; + t.seven = 556; + t.eight = 556; + t.nine = 556; + t.colon = 278; + t.semicolon = 278; + t.less = 584; + t.equal = 584; + t.greater = 584; + t.question = 556; + t.at = 1015; + t.A = 667; + t.B = 667; + t.C = 722; + t.D = 722; + t.E = 667; + t.F = 611; + t.G = 778; + t.H = 722; + t.I = 278; + t.J = 500; + t.K = 667; + t.L = 556; + t.M = 833; + t.N = 722; + t.O = 778; + t.P = 667; + t.Q = 778; + t.R = 722; + t.S = 667; + t.T = 611; + t.U = 722; + t.V = 667; + t.W = 944; + t.X = 667; + t.Y = 667; + t.Z = 611; + t.bracketleft = 278; + t.backslash = 278; + t.bracketright = 278; + t.asciicircum = 469; + t.underscore = 556; + t.quoteleft = 222; + t.a = 556; + t.b = 556; + t.c = 500; + t.d = 556; + t.e = 556; + t.f = 278; + t.g = 556; + t.h = 556; + t.i = 222; + t.j = 222; + t.k = 500; + t.l = 222; + t.m = 833; + t.n = 556; + t.o = 556; + t.p = 556; + t.q = 556; + t.r = 333; + t.s = 500; + t.t = 278; + t.u = 556; + t.v = 500; + t.w = 722; + t.x = 500; + t.y = 500; + t.z = 500; + t.braceleft = 334; + t.bar = 260; + t.braceright = 334; + t.asciitilde = 584; + t.exclamdown = 333; + t.cent = 556; + t.sterling = 556; + t.fraction = 167; + t.yen = 556; + t.florin = 556; + t.section = 556; + t.currency = 556; + t.quotesingle = 191; + t.quotedblleft = 333; + t.guillemotleft = 556; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 500; + t.fl = 500; + t.endash = 556; + t.dagger = 556; + t.daggerdbl = 556; + t.periodcentered = 278; + t.paragraph = 537; + t.bullet = 350; + t.quotesinglbase = 222; + t.quotedblbase = 333; + t.quotedblright = 333; + t.guillemotright = 556; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 611; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 1000; + t.ordfeminine = 370; + t.Lslash = 556; + t.Oslash = 778; + t.OE = 1000; + t.ordmasculine = 365; + t.ae = 889; + t.dotlessi = 278; + t.lslash = 222; + t.oslash = 611; + t.oe = 944; + t.germandbls = 611; + t.Idieresis = 278; + t.eacute = 556; + t.abreve = 556; + t.uhungarumlaut = 556; + t.ecaron = 556; + t.Ydieresis = 667; + t.divide = 584; + t.Yacute = 667; + t.Acircumflex = 667; + t.aacute = 556; + t.Ucircumflex = 722; + t.yacute = 500; + t.scommaaccent = 500; + t.ecircumflex = 556; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 556; + t.Uacute = 722; + t.uogonek = 556; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 737; + t.Emacron = 667; + t.ccaron = 500; + t.aring = 556; + t.Ncommaaccent = 722; + t.lacute = 222; + t.agrave = 556; + t.Tcommaaccent = 611; + t.Cacute = 722; + t.atilde = 556; + t.Edotaccent = 667; + t.scaron = 500; + t.scedilla = 500; + t.iacute = 278; + t.lozenge = 471; + t.Rcaron = 722; + t.Gcommaaccent = 778; + t.ucircumflex = 556; + t.acircumflex = 556; + t.Amacron = 667; + t.rcaron = 333; + t.ccedilla = 500; + t.Zdotaccent = 611; + t.Thorn = 667; + t.Omacron = 778; + t.Racute = 722; + t.Sacute = 667; + t.dcaron = 643; + t.Umacron = 722; + t.uring = 556; + t.threesuperior = 333; + t.Ograve = 778; + t.Agrave = 667; + t.Abreve = 667; + t.multiply = 584; + t.uacute = 556; + t.Tcaron = 611; + t.partialdiff = 476; + t.ydieresis = 500; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 556; + t.edieresis = 556; + t.cacute = 500; + t.nacute = 556; + t.umacron = 556; + t.Ncaron = 722; + t.Iacute = 278; + t.plusminus = 584; + t.brokenbar = 260; + t.registered = 737; + t.Gbreve = 778; + t.Idotaccent = 278; + t.summation = 600; + t.Egrave = 667; + t.racute = 333; + t.omacron = 556; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 722; + t.lcommaaccent = 222; + t.tcaron = 317; + t.eogonek = 556; + t.Uogonek = 722; + t.Aacute = 667; + t.Adieresis = 667; + t.egrave = 556; + t.zacute = 500; + t.iogonek = 222; + t.Oacute = 778; + t.oacute = 556; + t.amacron = 556; + t.sacute = 500; + t.idieresis = 278; + t.Ocircumflex = 778; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 556; + t.twosuperior = 333; + t.Odieresis = 778; + t.mu = 556; + t.igrave = 278; + t.ohungarumlaut = 556; + t.Eogonek = 667; + t.dcroat = 556; + t.threequarters = 834; + t.Scedilla = 667; + t.lcaron = 299; + t.Kcommaaccent = 667; + t.Lacute = 556; + t.trademark = 1000; + t.edotaccent = 556; + t.Igrave = 278; + t.Imacron = 278; + t.Lcaron = 556; + t.onehalf = 834; + t.lessequal = 549; + t.ocircumflex = 556; + t.ntilde = 556; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 556; + t.gbreve = 556; + t.onequarter = 834; + t.Scaron = 667; + t.Scommaaccent = 667; + t.Ohungarumlaut = 778; + t.degree = 400; + t.ograve = 556; + t.Ccaron = 722; + t.ugrave = 556; + t.radical = 453; + t.Dcaron = 722; + t.rcommaaccent = 333; + t.Ntilde = 722; + t.otilde = 556; + t.Rcommaaccent = 722; + t.Lcommaaccent = 556; + t.Atilde = 667; + t.Aogonek = 667; + t.Aring = 667; + t.Otilde = 778; + t.zdotaccent = 500; + t.Ecaron = 667; + t.Iogonek = 278; + t.kcommaaccent = 500; + t.minus = 584; + t.Icircumflex = 278; + t.ncaron = 556; + t.tcommaaccent = 278; + t.logicalnot = 584; + t.odieresis = 556; + t.udieresis = 556; + t.notequal = 549; + t.gcommaaccent = 556; + t.eth = 556; + t.zcaron = 500; + t.ncommaaccent = 556; + t.onesuperior = 333; + t.imacron = 278; + t.Euro = 556; + }); + t.Symbol = getLookupTableFactory(function (t) { + t.space = 250; + t.exclam = 333; + t.universal = 713; + t.numbersign = 500; + t.existential = 549; + t.percent = 833; + t.ampersand = 778; + t.suchthat = 439; + t.parenleft = 333; + t.parenright = 333; + t.asteriskmath = 500; + t.plus = 549; + t.comma = 250; + t.minus = 549; + t.period = 250; + t.slash = 278; + t.zero = 500; + t.one = 500; + t.two = 500; + t.three = 500; + t.four = 500; + t.five = 500; + t.six = 500; + t.seven = 500; + t.eight = 500; + t.nine = 500; + t.colon = 278; + t.semicolon = 278; + t.less = 549; + t.equal = 549; + t.greater = 549; + t.question = 444; + t.congruent = 549; + t.Alpha = 722; + t.Beta = 667; + t.Chi = 722; + t.Delta = 612; + t.Epsilon = 611; + t.Phi = 763; + t.Gamma = 603; + t.Eta = 722; + t.Iota = 333; + t.theta1 = 631; + t.Kappa = 722; + t.Lambda = 686; + t.Mu = 889; + t.Nu = 722; + t.Omicron = 722; + t.Pi = 768; + t.Theta = 741; + t.Rho = 556; + t.Sigma = 592; + t.Tau = 611; + t.Upsilon = 690; + t.sigma1 = 439; + t.Omega = 768; + t.Xi = 645; + t.Psi = 795; + t.Zeta = 611; + t.bracketleft = 333; + t.therefore = 863; + t.bracketright = 333; + t.perpendicular = 658; + t.underscore = 500; + t.radicalex = 500; + t.alpha = 631; + t.beta = 549; + t.chi = 549; + t.delta = 494; + t.epsilon = 439; + t.phi = 521; + t.gamma = 411; + t.eta = 603; + t.iota = 329; + t.phi1 = 603; + t.kappa = 549; + t.lambda = 549; + t.mu = 576; + t.nu = 521; + t.omicron = 549; + t.pi = 549; + t.theta = 521; + t.rho = 549; + t.sigma = 603; + t.tau = 439; + t.upsilon = 576; + t.omega1 = 713; + t.omega = 686; + t.xi = 493; + t.psi = 686; + t.zeta = 494; + t.braceleft = 480; + t.bar = 200; + t.braceright = 480; + t.similar = 549; + t.Euro = 750; + t.Upsilon1 = 620; + t.minute = 247; + t.lessequal = 549; + t.fraction = 167; + t.infinity = 713; + t.florin = 500; + t.club = 753; + t.diamond = 753; + t.heart = 753; + t.spade = 753; + t.arrowboth = 1042; + t.arrowleft = 987; + t.arrowup = 603; + t.arrowright = 987; + t.arrowdown = 603; + t.degree = 400; + t.plusminus = 549; + t.second = 411; + t.greaterequal = 549; + t.multiply = 549; + t.proportional = 713; + t.partialdiff = 494; + t.bullet = 460; + t.divide = 549; + t.notequal = 549; + t.equivalence = 549; + t.approxequal = 549; + t.ellipsis = 1000; + t.arrowvertex = 603; + t.arrowhorizex = 1000; + t.carriagereturn = 658; + t.aleph = 823; + t.Ifraktur = 686; + t.Rfraktur = 795; + t.weierstrass = 987; + t.circlemultiply = 768; + t.circleplus = 768; + t.emptyset = 823; + t.intersection = 768; + t.union = 768; + t.propersuperset = 713; + t.reflexsuperset = 713; + t.notsubset = 713; + t.propersubset = 713; + t.reflexsubset = 713; + t.element = 713; + t.notelement = 713; + t.angle = 768; + t.gradient = 713; + t.registerserif = 790; + t.copyrightserif = 790; + t.trademarkserif = 890; + t.product = 823; + t.radical = 549; + t.dotmath = 250; + t.logicalnot = 713; + t.logicaland = 603; + t.logicalor = 603; + t.arrowdblboth = 1042; + t.arrowdblleft = 987; + t.arrowdblup = 603; + t.arrowdblright = 987; + t.arrowdbldown = 603; + t.lozenge = 494; + t.angleleft = 329; + t.registersans = 790; + t.copyrightsans = 790; + t.trademarksans = 786; + t.summation = 713; + t.parenlefttp = 384; + t.parenleftex = 384; + t.parenleftbt = 384; + t.bracketlefttp = 384; + t.bracketleftex = 384; + t.bracketleftbt = 384; + t.bracelefttp = 494; + t.braceleftmid = 494; + t.braceleftbt = 494; + t.braceex = 494; + t.angleright = 329; + t.integral = 274; + t.integraltp = 686; + t.integralex = 686; + t.integralbt = 686; + t.parenrighttp = 384; + t.parenrightex = 384; + t.parenrightbt = 384; + t.bracketrighttp = 384; + t.bracketrightex = 384; + t.bracketrightbt = 384; + t.bracerighttp = 494; + t.bracerightmid = 494; + t.bracerightbt = 494; + t.apple = 790; + }); + t["Times-Roman"] = getLookupTableFactory(function (t) { + t.space = 250; + t.exclam = 333; + t.quotedbl = 408; + t.numbersign = 500; + t.dollar = 500; + t.percent = 833; + t.ampersand = 778; + t.quoteright = 333; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 500; + t.plus = 564; + t.comma = 250; + t.hyphen = 333; + t.period = 250; + t.slash = 278; + t.zero = 500; + t.one = 500; + t.two = 500; + t.three = 500; + t.four = 500; + t.five = 500; + t.six = 500; + t.seven = 500; + t.eight = 500; + t.nine = 500; + t.colon = 278; + t.semicolon = 278; + t.less = 564; + t.equal = 564; + t.greater = 564; + t.question = 444; + t.at = 921; + t.A = 722; + t.B = 667; + t.C = 667; + t.D = 722; + t.E = 611; + t.F = 556; + t.G = 722; + t.H = 722; + t.I = 333; + t.J = 389; + t.K = 722; + t.L = 611; + t.M = 889; + t.N = 722; + t.O = 722; + t.P = 556; + t.Q = 722; + t.R = 667; + t.S = 556; + t.T = 611; + t.U = 722; + t.V = 722; + t.W = 944; + t.X = 722; + t.Y = 722; + t.Z = 611; + t.bracketleft = 333; + t.backslash = 278; + t.bracketright = 333; + t.asciicircum = 469; + t.underscore = 500; + t.quoteleft = 333; + t.a = 444; + t.b = 500; + t.c = 444; + t.d = 500; + t.e = 444; + t.f = 333; + t.g = 500; + t.h = 500; + t.i = 278; + t.j = 278; + t.k = 500; + t.l = 278; + t.m = 778; + t.n = 500; + t.o = 500; + t.p = 500; + t.q = 500; + t.r = 333; + t.s = 389; + t.t = 278; + t.u = 500; + t.v = 500; + t.w = 722; + t.x = 500; + t.y = 500; + t.z = 444; + t.braceleft = 480; + t.bar = 200; + t.braceright = 480; + t.asciitilde = 541; + t.exclamdown = 333; + t.cent = 500; + t.sterling = 500; + t.fraction = 167; + t.yen = 500; + t.florin = 500; + t.section = 500; + t.currency = 500; + t.quotesingle = 180; + t.quotedblleft = 444; + t.guillemotleft = 500; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 556; + t.fl = 556; + t.endash = 500; + t.dagger = 500; + t.daggerdbl = 500; + t.periodcentered = 250; + t.paragraph = 453; + t.bullet = 350; + t.quotesinglbase = 333; + t.quotedblbase = 444; + t.quotedblright = 444; + t.guillemotright = 500; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 444; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 889; + t.ordfeminine = 276; + t.Lslash = 611; + t.Oslash = 722; + t.OE = 889; + t.ordmasculine = 310; + t.ae = 667; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 500; + t.oe = 722; + t.germandbls = 500; + t.Idieresis = 333; + t.eacute = 444; + t.abreve = 444; + t.uhungarumlaut = 500; + t.ecaron = 444; + t.Ydieresis = 722; + t.divide = 564; + t.Yacute = 722; + t.Acircumflex = 722; + t.aacute = 444; + t.Ucircumflex = 722; + t.yacute = 500; + t.scommaaccent = 389; + t.ecircumflex = 444; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 444; + t.Uacute = 722; + t.uogonek = 500; + t.Edieresis = 611; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 760; + t.Emacron = 611; + t.ccaron = 444; + t.aring = 444; + t.Ncommaaccent = 722; + t.lacute = 278; + t.agrave = 444; + t.Tcommaaccent = 611; + t.Cacute = 667; + t.atilde = 444; + t.Edotaccent = 611; + t.scaron = 389; + t.scedilla = 389; + t.iacute = 278; + t.lozenge = 471; + t.Rcaron = 667; + t.Gcommaaccent = 722; + t.ucircumflex = 500; + t.acircumflex = 444; + t.Amacron = 722; + t.rcaron = 333; + t.ccedilla = 444; + t.Zdotaccent = 611; + t.Thorn = 556; + t.Omacron = 722; + t.Racute = 667; + t.Sacute = 556; + t.dcaron = 588; + t.Umacron = 722; + t.uring = 500; + t.threesuperior = 300; + t.Ograve = 722; + t.Agrave = 722; + t.Abreve = 722; + t.multiply = 564; + t.uacute = 500; + t.Tcaron = 611; + t.partialdiff = 476; + t.ydieresis = 500; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 611; + t.adieresis = 444; + t.edieresis = 444; + t.cacute = 444; + t.nacute = 500; + t.umacron = 500; + t.Ncaron = 722; + t.Iacute = 333; + t.plusminus = 564; + t.brokenbar = 200; + t.registered = 760; + t.Gbreve = 722; + t.Idotaccent = 333; + t.summation = 600; + t.Egrave = 611; + t.racute = 333; + t.omacron = 500; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 667; + t.lcommaaccent = 278; + t.tcaron = 326; + t.eogonek = 444; + t.Uogonek = 722; + t.Aacute = 722; + t.Adieresis = 722; + t.egrave = 444; + t.zacute = 444; + t.iogonek = 278; + t.Oacute = 722; + t.oacute = 500; + t.amacron = 444; + t.sacute = 389; + t.idieresis = 278; + t.Ocircumflex = 722; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 500; + t.twosuperior = 300; + t.Odieresis = 722; + t.mu = 500; + t.igrave = 278; + t.ohungarumlaut = 500; + t.Eogonek = 611; + t.dcroat = 500; + t.threequarters = 750; + t.Scedilla = 556; + t.lcaron = 344; + t.Kcommaaccent = 722; + t.Lacute = 611; + t.trademark = 980; + t.edotaccent = 444; + t.Igrave = 333; + t.Imacron = 333; + t.Lcaron = 611; + t.onehalf = 750; + t.lessequal = 549; + t.ocircumflex = 500; + t.ntilde = 500; + t.Uhungarumlaut = 722; + t.Eacute = 611; + t.emacron = 444; + t.gbreve = 500; + t.onequarter = 750; + t.Scaron = 556; + t.Scommaaccent = 556; + t.Ohungarumlaut = 722; + t.degree = 400; + t.ograve = 500; + t.Ccaron = 667; + t.ugrave = 500; + t.radical = 453; + t.Dcaron = 722; + t.rcommaaccent = 333; + t.Ntilde = 722; + t.otilde = 500; + t.Rcommaaccent = 667; + t.Lcommaaccent = 611; + t.Atilde = 722; + t.Aogonek = 722; + t.Aring = 722; + t.Otilde = 722; + t.zdotaccent = 444; + t.Ecaron = 611; + t.Iogonek = 333; + t.kcommaaccent = 500; + t.minus = 564; + t.Icircumflex = 333; + t.ncaron = 500; + t.tcommaaccent = 278; + t.logicalnot = 564; + t.odieresis = 500; + t.udieresis = 500; + t.notequal = 549; + t.gcommaaccent = 500; + t.eth = 500; + t.zcaron = 444; + t.ncommaaccent = 500; + t.onesuperior = 300; + t.imacron = 278; + t.Euro = 500; + }); + t["Times-Bold"] = getLookupTableFactory(function (t) { + t.space = 250; + t.exclam = 333; + t.quotedbl = 555; + t.numbersign = 500; + t.dollar = 500; + t.percent = 1000; + t.ampersand = 833; + t.quoteright = 333; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 500; + t.plus = 570; + t.comma = 250; + t.hyphen = 333; + t.period = 250; + t.slash = 278; + t.zero = 500; + t.one = 500; + t.two = 500; + t.three = 500; + t.four = 500; + t.five = 500; + t.six = 500; + t.seven = 500; + t.eight = 500; + t.nine = 500; + t.colon = 333; + t.semicolon = 333; + t.less = 570; + t.equal = 570; + t.greater = 570; + t.question = 500; + t.at = 930; + t.A = 722; + t.B = 667; + t.C = 722; + t.D = 722; + t.E = 667; + t.F = 611; + t.G = 778; + t.H = 778; + t.I = 389; + t.J = 500; + t.K = 778; + t.L = 667; + t.M = 944; + t.N = 722; + t.O = 778; + t.P = 611; + t.Q = 778; + t.R = 722; + t.S = 556; + t.T = 667; + t.U = 722; + t.V = 722; + t.W = 1000; + t.X = 722; + t.Y = 722; + t.Z = 667; + t.bracketleft = 333; + t.backslash = 278; + t.bracketright = 333; + t.asciicircum = 581; + t.underscore = 500; + t.quoteleft = 333; + t.a = 500; + t.b = 556; + t.c = 444; + t.d = 556; + t.e = 444; + t.f = 333; + t.g = 500; + t.h = 556; + t.i = 278; + t.j = 333; + t.k = 556; + t.l = 278; + t.m = 833; + t.n = 556; + t.o = 500; + t.p = 556; + t.q = 556; + t.r = 444; + t.s = 389; + t.t = 333; + t.u = 556; + t.v = 500; + t.w = 722; + t.x = 500; + t.y = 500; + t.z = 444; + t.braceleft = 394; + t.bar = 220; + t.braceright = 394; + t.asciitilde = 520; + t.exclamdown = 333; + t.cent = 500; + t.sterling = 500; + t.fraction = 167; + t.yen = 500; + t.florin = 500; + t.section = 500; + t.currency = 500; + t.quotesingle = 278; + t.quotedblleft = 500; + t.guillemotleft = 500; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 556; + t.fl = 556; + t.endash = 500; + t.dagger = 500; + t.daggerdbl = 500; + t.periodcentered = 250; + t.paragraph = 540; + t.bullet = 350; + t.quotesinglbase = 333; + t.quotedblbase = 500; + t.quotedblright = 500; + t.guillemotright = 500; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 500; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 1000; + t.ordfeminine = 300; + t.Lslash = 667; + t.Oslash = 778; + t.OE = 1000; + t.ordmasculine = 330; + t.ae = 722; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 500; + t.oe = 722; + t.germandbls = 556; + t.Idieresis = 389; + t.eacute = 444; + t.abreve = 500; + t.uhungarumlaut = 556; + t.ecaron = 444; + t.Ydieresis = 722; + t.divide = 570; + t.Yacute = 722; + t.Acircumflex = 722; + t.aacute = 500; + t.Ucircumflex = 722; + t.yacute = 500; + t.scommaaccent = 389; + t.ecircumflex = 444; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 500; + t.Uacute = 722; + t.uogonek = 556; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 747; + t.Emacron = 667; + t.ccaron = 444; + t.aring = 500; + t.Ncommaaccent = 722; + t.lacute = 278; + t.agrave = 500; + t.Tcommaaccent = 667; + t.Cacute = 722; + t.atilde = 500; + t.Edotaccent = 667; + t.scaron = 389; + t.scedilla = 389; + t.iacute = 278; + t.lozenge = 494; + t.Rcaron = 722; + t.Gcommaaccent = 778; + t.ucircumflex = 556; + t.acircumflex = 500; + t.Amacron = 722; + t.rcaron = 444; + t.ccedilla = 444; + t.Zdotaccent = 667; + t.Thorn = 611; + t.Omacron = 778; + t.Racute = 722; + t.Sacute = 556; + t.dcaron = 672; + t.Umacron = 722; + t.uring = 556; + t.threesuperior = 300; + t.Ograve = 778; + t.Agrave = 722; + t.Abreve = 722; + t.multiply = 570; + t.uacute = 556; + t.Tcaron = 667; + t.partialdiff = 494; + t.ydieresis = 500; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 500; + t.edieresis = 444; + t.cacute = 444; + t.nacute = 556; + t.umacron = 556; + t.Ncaron = 722; + t.Iacute = 389; + t.plusminus = 570; + t.brokenbar = 220; + t.registered = 747; + t.Gbreve = 778; + t.Idotaccent = 389; + t.summation = 600; + t.Egrave = 667; + t.racute = 444; + t.omacron = 500; + t.Zacute = 667; + t.Zcaron = 667; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 722; + t.lcommaaccent = 278; + t.tcaron = 416; + t.eogonek = 444; + t.Uogonek = 722; + t.Aacute = 722; + t.Adieresis = 722; + t.egrave = 444; + t.zacute = 444; + t.iogonek = 278; + t.Oacute = 778; + t.oacute = 500; + t.amacron = 500; + t.sacute = 389; + t.idieresis = 278; + t.Ocircumflex = 778; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 556; + t.twosuperior = 300; + t.Odieresis = 778; + t.mu = 556; + t.igrave = 278; + t.ohungarumlaut = 500; + t.Eogonek = 667; + t.dcroat = 556; + t.threequarters = 750; + t.Scedilla = 556; + t.lcaron = 394; + t.Kcommaaccent = 778; + t.Lacute = 667; + t.trademark = 1000; + t.edotaccent = 444; + t.Igrave = 389; + t.Imacron = 389; + t.Lcaron = 667; + t.onehalf = 750; + t.lessequal = 549; + t.ocircumflex = 500; + t.ntilde = 556; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 444; + t.gbreve = 500; + t.onequarter = 750; + t.Scaron = 556; + t.Scommaaccent = 556; + t.Ohungarumlaut = 778; + t.degree = 400; + t.ograve = 500; + t.Ccaron = 722; + t.ugrave = 556; + t.radical = 549; + t.Dcaron = 722; + t.rcommaaccent = 444; + t.Ntilde = 722; + t.otilde = 500; + t.Rcommaaccent = 722; + t.Lcommaaccent = 667; + t.Atilde = 722; + t.Aogonek = 722; + t.Aring = 722; + t.Otilde = 778; + t.zdotaccent = 444; + t.Ecaron = 667; + t.Iogonek = 389; + t.kcommaaccent = 556; + t.minus = 570; + t.Icircumflex = 389; + t.ncaron = 556; + t.tcommaaccent = 333; + t.logicalnot = 570; + t.odieresis = 500; + t.udieresis = 556; + t.notequal = 549; + t.gcommaaccent = 500; + t.eth = 500; + t.zcaron = 444; + t.ncommaaccent = 556; + t.onesuperior = 300; + t.imacron = 278; + t.Euro = 500; + }); + t["Times-BoldItalic"] = getLookupTableFactory(function (t) { + t.space = 250; + t.exclam = 389; + t.quotedbl = 555; + t.numbersign = 500; + t.dollar = 500; + t.percent = 833; + t.ampersand = 778; + t.quoteright = 333; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 500; + t.plus = 570; + t.comma = 250; + t.hyphen = 333; + t.period = 250; + t.slash = 278; + t.zero = 500; + t.one = 500; + t.two = 500; + t.three = 500; + t.four = 500; + t.five = 500; + t.six = 500; + t.seven = 500; + t.eight = 500; + t.nine = 500; + t.colon = 333; + t.semicolon = 333; + t.less = 570; + t.equal = 570; + t.greater = 570; + t.question = 500; + t.at = 832; + t.A = 667; + t.B = 667; + t.C = 667; + t.D = 722; + t.E = 667; + t.F = 667; + t.G = 722; + t.H = 778; + t.I = 389; + t.J = 500; + t.K = 667; + t.L = 611; + t.M = 889; + t.N = 722; + t.O = 722; + t.P = 611; + t.Q = 722; + t.R = 667; + t.S = 556; + t.T = 611; + t.U = 722; + t.V = 667; + t.W = 889; + t.X = 667; + t.Y = 611; + t.Z = 611; + t.bracketleft = 333; + t.backslash = 278; + t.bracketright = 333; + t.asciicircum = 570; + t.underscore = 500; + t.quoteleft = 333; + t.a = 500; + t.b = 500; + t.c = 444; + t.d = 500; + t.e = 444; + t.f = 333; + t.g = 500; + t.h = 556; + t.i = 278; + t.j = 278; + t.k = 500; + t.l = 278; + t.m = 778; + t.n = 556; + t.o = 500; + t.p = 500; + t.q = 500; + t.r = 389; + t.s = 389; + t.t = 278; + t.u = 556; + t.v = 444; + t.w = 667; + t.x = 500; + t.y = 444; + t.z = 389; + t.braceleft = 348; + t.bar = 220; + t.braceright = 348; + t.asciitilde = 570; + t.exclamdown = 389; + t.cent = 500; + t.sterling = 500; + t.fraction = 167; + t.yen = 500; + t.florin = 500; + t.section = 500; + t.currency = 500; + t.quotesingle = 278; + t.quotedblleft = 500; + t.guillemotleft = 500; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 556; + t.fl = 556; + t.endash = 500; + t.dagger = 500; + t.daggerdbl = 500; + t.periodcentered = 250; + t.paragraph = 500; + t.bullet = 350; + t.quotesinglbase = 333; + t.quotedblbase = 500; + t.quotedblright = 500; + t.guillemotright = 500; + t.ellipsis = 1000; + t.perthousand = 1000; + t.questiondown = 500; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 1000; + t.AE = 944; + t.ordfeminine = 266; + t.Lslash = 611; + t.Oslash = 722; + t.OE = 944; + t.ordmasculine = 300; + t.ae = 722; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 500; + t.oe = 722; + t.germandbls = 500; + t.Idieresis = 389; + t.eacute = 444; + t.abreve = 500; + t.uhungarumlaut = 556; + t.ecaron = 444; + t.Ydieresis = 611; + t.divide = 570; + t.Yacute = 611; + t.Acircumflex = 667; + t.aacute = 500; + t.Ucircumflex = 722; + t.yacute = 444; + t.scommaaccent = 389; + t.ecircumflex = 444; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 500; + t.Uacute = 722; + t.uogonek = 556; + t.Edieresis = 667; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 747; + t.Emacron = 667; + t.ccaron = 444; + t.aring = 500; + t.Ncommaaccent = 722; + t.lacute = 278; + t.agrave = 500; + t.Tcommaaccent = 611; + t.Cacute = 667; + t.atilde = 500; + t.Edotaccent = 667; + t.scaron = 389; + t.scedilla = 389; + t.iacute = 278; + t.lozenge = 494; + t.Rcaron = 667; + t.Gcommaaccent = 722; + t.ucircumflex = 556; + t.acircumflex = 500; + t.Amacron = 667; + t.rcaron = 389; + t.ccedilla = 444; + t.Zdotaccent = 611; + t.Thorn = 611; + t.Omacron = 722; + t.Racute = 667; + t.Sacute = 556; + t.dcaron = 608; + t.Umacron = 722; + t.uring = 556; + t.threesuperior = 300; + t.Ograve = 722; + t.Agrave = 667; + t.Abreve = 667; + t.multiply = 570; + t.uacute = 556; + t.Tcaron = 611; + t.partialdiff = 494; + t.ydieresis = 444; + t.Nacute = 722; + t.icircumflex = 278; + t.Ecircumflex = 667; + t.adieresis = 500; + t.edieresis = 444; + t.cacute = 444; + t.nacute = 556; + t.umacron = 556; + t.Ncaron = 722; + t.Iacute = 389; + t.plusminus = 570; + t.brokenbar = 220; + t.registered = 747; + t.Gbreve = 722; + t.Idotaccent = 389; + t.summation = 600; + t.Egrave = 667; + t.racute = 389; + t.omacron = 500; + t.Zacute = 611; + t.Zcaron = 611; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 667; + t.lcommaaccent = 278; + t.tcaron = 366; + t.eogonek = 444; + t.Uogonek = 722; + t.Aacute = 667; + t.Adieresis = 667; + t.egrave = 444; + t.zacute = 389; + t.iogonek = 278; + t.Oacute = 722; + t.oacute = 500; + t.amacron = 500; + t.sacute = 389; + t.idieresis = 278; + t.Ocircumflex = 722; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 500; + t.twosuperior = 300; + t.Odieresis = 722; + t.mu = 576; + t.igrave = 278; + t.ohungarumlaut = 500; + t.Eogonek = 667; + t.dcroat = 500; + t.threequarters = 750; + t.Scedilla = 556; + t.lcaron = 382; + t.Kcommaaccent = 667; + t.Lacute = 611; + t.trademark = 1000; + t.edotaccent = 444; + t.Igrave = 389; + t.Imacron = 389; + t.Lcaron = 611; + t.onehalf = 750; + t.lessequal = 549; + t.ocircumflex = 500; + t.ntilde = 556; + t.Uhungarumlaut = 722; + t.Eacute = 667; + t.emacron = 444; + t.gbreve = 500; + t.onequarter = 750; + t.Scaron = 556; + t.Scommaaccent = 556; + t.Ohungarumlaut = 722; + t.degree = 400; + t.ograve = 500; + t.Ccaron = 667; + t.ugrave = 556; + t.radical = 549; + t.Dcaron = 722; + t.rcommaaccent = 389; + t.Ntilde = 722; + t.otilde = 500; + t.Rcommaaccent = 667; + t.Lcommaaccent = 611; + t.Atilde = 667; + t.Aogonek = 667; + t.Aring = 667; + t.Otilde = 722; + t.zdotaccent = 389; + t.Ecaron = 667; + t.Iogonek = 389; + t.kcommaaccent = 500; + t.minus = 606; + t.Icircumflex = 389; + t.ncaron = 556; + t.tcommaaccent = 278; + t.logicalnot = 606; + t.odieresis = 500; + t.udieresis = 556; + t.notequal = 549; + t.gcommaaccent = 500; + t.eth = 500; + t.zcaron = 389; + t.ncommaaccent = 556; + t.onesuperior = 300; + t.imacron = 278; + t.Euro = 500; + }); + t["Times-Italic"] = getLookupTableFactory(function (t) { + t.space = 250; + t.exclam = 333; + t.quotedbl = 420; + t.numbersign = 500; + t.dollar = 500; + t.percent = 833; + t.ampersand = 778; + t.quoteright = 333; + t.parenleft = 333; + t.parenright = 333; + t.asterisk = 500; + t.plus = 675; + t.comma = 250; + t.hyphen = 333; + t.period = 250; + t.slash = 278; + t.zero = 500; + t.one = 500; + t.two = 500; + t.three = 500; + t.four = 500; + t.five = 500; + t.six = 500; + t.seven = 500; + t.eight = 500; + t.nine = 500; + t.colon = 333; + t.semicolon = 333; + t.less = 675; + t.equal = 675; + t.greater = 675; + t.question = 500; + t.at = 920; + t.A = 611; + t.B = 611; + t.C = 667; + t.D = 722; + t.E = 611; + t.F = 611; + t.G = 722; + t.H = 722; + t.I = 333; + t.J = 444; + t.K = 667; + t.L = 556; + t.M = 833; + t.N = 667; + t.O = 722; + t.P = 611; + t.Q = 722; + t.R = 611; + t.S = 500; + t.T = 556; + t.U = 722; + t.V = 611; + t.W = 833; + t.X = 611; + t.Y = 556; + t.Z = 556; + t.bracketleft = 389; + t.backslash = 278; + t.bracketright = 389; + t.asciicircum = 422; + t.underscore = 500; + t.quoteleft = 333; + t.a = 500; + t.b = 500; + t.c = 444; + t.d = 500; + t.e = 444; + t.f = 278; + t.g = 500; + t.h = 500; + t.i = 278; + t.j = 278; + t.k = 444; + t.l = 278; + t.m = 722; + t.n = 500; + t.o = 500; + t.p = 500; + t.q = 500; + t.r = 389; + t.s = 389; + t.t = 278; + t.u = 500; + t.v = 444; + t.w = 667; + t.x = 444; + t.y = 444; + t.z = 389; + t.braceleft = 400; + t.bar = 275; + t.braceright = 400; + t.asciitilde = 541; + t.exclamdown = 389; + t.cent = 500; + t.sterling = 500; + t.fraction = 167; + t.yen = 500; + t.florin = 500; + t.section = 500; + t.currency = 500; + t.quotesingle = 214; + t.quotedblleft = 556; + t.guillemotleft = 500; + t.guilsinglleft = 333; + t.guilsinglright = 333; + t.fi = 500; + t.fl = 500; + t.endash = 500; + t.dagger = 500; + t.daggerdbl = 500; + t.periodcentered = 250; + t.paragraph = 523; + t.bullet = 350; + t.quotesinglbase = 333; + t.quotedblbase = 556; + t.quotedblright = 556; + t.guillemotright = 500; + t.ellipsis = 889; + t.perthousand = 1000; + t.questiondown = 500; + t.grave = 333; + t.acute = 333; + t.circumflex = 333; + t.tilde = 333; + t.macron = 333; + t.breve = 333; + t.dotaccent = 333; + t.dieresis = 333; + t.ring = 333; + t.cedilla = 333; + t.hungarumlaut = 333; + t.ogonek = 333; + t.caron = 333; + t.emdash = 889; + t.AE = 889; + t.ordfeminine = 276; + t.Lslash = 556; + t.Oslash = 722; + t.OE = 944; + t.ordmasculine = 310; + t.ae = 667; + t.dotlessi = 278; + t.lslash = 278; + t.oslash = 500; + t.oe = 667; + t.germandbls = 500; + t.Idieresis = 333; + t.eacute = 444; + t.abreve = 500; + t.uhungarumlaut = 500; + t.ecaron = 444; + t.Ydieresis = 556; + t.divide = 675; + t.Yacute = 556; + t.Acircumflex = 611; + t.aacute = 500; + t.Ucircumflex = 722; + t.yacute = 444; + t.scommaaccent = 389; + t.ecircumflex = 444; + t.Uring = 722; + t.Udieresis = 722; + t.aogonek = 500; + t.Uacute = 722; + t.uogonek = 500; + t.Edieresis = 611; + t.Dcroat = 722; + t.commaaccent = 250; + t.copyright = 760; + t.Emacron = 611; + t.ccaron = 444; + t.aring = 500; + t.Ncommaaccent = 667; + t.lacute = 278; + t.agrave = 500; + t.Tcommaaccent = 556; + t.Cacute = 667; + t.atilde = 500; + t.Edotaccent = 611; + t.scaron = 389; + t.scedilla = 389; + t.iacute = 278; + t.lozenge = 471; + t.Rcaron = 611; + t.Gcommaaccent = 722; + t.ucircumflex = 500; + t.acircumflex = 500; + t.Amacron = 611; + t.rcaron = 389; + t.ccedilla = 444; + t.Zdotaccent = 556; + t.Thorn = 611; + t.Omacron = 722; + t.Racute = 611; + t.Sacute = 500; + t.dcaron = 544; + t.Umacron = 722; + t.uring = 500; + t.threesuperior = 300; + t.Ograve = 722; + t.Agrave = 611; + t.Abreve = 611; + t.multiply = 675; + t.uacute = 500; + t.Tcaron = 556; + t.partialdiff = 476; + t.ydieresis = 444; + t.Nacute = 667; + t.icircumflex = 278; + t.Ecircumflex = 611; + t.adieresis = 500; + t.edieresis = 444; + t.cacute = 444; + t.nacute = 500; + t.umacron = 500; + t.Ncaron = 667; + t.Iacute = 333; + t.plusminus = 675; + t.brokenbar = 275; + t.registered = 760; + t.Gbreve = 722; + t.Idotaccent = 333; + t.summation = 600; + t.Egrave = 611; + t.racute = 389; + t.omacron = 500; + t.Zacute = 556; + t.Zcaron = 556; + t.greaterequal = 549; + t.Eth = 722; + t.Ccedilla = 667; + t.lcommaaccent = 278; + t.tcaron = 300; + t.eogonek = 444; + t.Uogonek = 722; + t.Aacute = 611; + t.Adieresis = 611; + t.egrave = 444; + t.zacute = 389; + t.iogonek = 278; + t.Oacute = 722; + t.oacute = 500; + t.amacron = 500; + t.sacute = 389; + t.idieresis = 278; + t.Ocircumflex = 722; + t.Ugrave = 722; + t.Delta = 612; + t.thorn = 500; + t.twosuperior = 300; + t.Odieresis = 722; + t.mu = 500; + t.igrave = 278; + t.ohungarumlaut = 500; + t.Eogonek = 611; + t.dcroat = 500; + t.threequarters = 750; + t.Scedilla = 500; + t.lcaron = 300; + t.Kcommaaccent = 667; + t.Lacute = 556; + t.trademark = 980; + t.edotaccent = 444; + t.Igrave = 333; + t.Imacron = 333; + t.Lcaron = 611; + t.onehalf = 750; + t.lessequal = 549; + t.ocircumflex = 500; + t.ntilde = 500; + t.Uhungarumlaut = 722; + t.Eacute = 611; + t.emacron = 444; + t.gbreve = 500; + t.onequarter = 750; + t.Scaron = 500; + t.Scommaaccent = 500; + t.Ohungarumlaut = 722; + t.degree = 400; + t.ograve = 500; + t.Ccaron = 667; + t.ugrave = 500; + t.radical = 453; + t.Dcaron = 722; + t.rcommaaccent = 389; + t.Ntilde = 667; + t.otilde = 500; + t.Rcommaaccent = 611; + t.Lcommaaccent = 556; + t.Atilde = 611; + t.Aogonek = 611; + t.Aring = 611; + t.Otilde = 722; + t.zdotaccent = 389; + t.Ecaron = 611; + t.Iogonek = 333; + t.kcommaaccent = 444; + t.minus = 675; + t.Icircumflex = 333; + t.ncaron = 500; + t.tcommaaccent = 278; + t.logicalnot = 675; + t.odieresis = 500; + t.udieresis = 500; + t.notequal = 549; + t.gcommaaccent = 500; + t.eth = 500; + t.zcaron = 389; + t.ncommaaccent = 500; + t.onesuperior = 300; + t.imacron = 278; + t.Euro = 500; + }); + t.ZapfDingbats = getLookupTableFactory(function (t) { + t.space = 278; + t.a1 = 974; + t.a2 = 961; + t.a202 = 974; + t.a3 = 980; + t.a4 = 719; + t.a5 = 789; + t.a119 = 790; + t.a118 = 791; + t.a117 = 690; + t.a11 = 960; + t.a12 = 939; + t.a13 = 549; + t.a14 = 855; + t.a15 = 911; + t.a16 = 933; + t.a105 = 911; + t.a17 = 945; + t.a18 = 974; + t.a19 = 755; + t.a20 = 846; + t.a21 = 762; + t.a22 = 761; + t.a23 = 571; + t.a24 = 677; + t.a25 = 763; + t.a26 = 760; + t.a27 = 759; + t.a28 = 754; + t.a6 = 494; + t.a7 = 552; + t.a8 = 537; + t.a9 = 577; + t.a10 = 692; + t.a29 = 786; + t.a30 = 788; + t.a31 = 788; + t.a32 = 790; + t.a33 = 793; + t.a34 = 794; + t.a35 = 816; + t.a36 = 823; + t.a37 = 789; + t.a38 = 841; + t.a39 = 823; + t.a40 = 833; + t.a41 = 816; + t.a42 = 831; + t.a43 = 923; + t.a44 = 744; + t.a45 = 723; + t.a46 = 749; + t.a47 = 790; + t.a48 = 792; + t.a49 = 695; + t.a50 = 776; + t.a51 = 768; + t.a52 = 792; + t.a53 = 759; + t.a54 = 707; + t.a55 = 708; + t.a56 = 682; + t.a57 = 701; + t.a58 = 826; + t.a59 = 815; + t.a60 = 789; + t.a61 = 789; + t.a62 = 707; + t.a63 = 687; + t.a64 = 696; + t.a65 = 689; + t.a66 = 786; + t.a67 = 787; + t.a68 = 713; + t.a69 = 791; + t.a70 = 785; + t.a71 = 791; + t.a72 = 873; + t.a73 = 761; + t.a74 = 762; + t.a203 = 762; + t.a75 = 759; + t.a204 = 759; + t.a76 = 892; + t.a77 = 892; + t.a78 = 788; + t.a79 = 784; + t.a81 = 438; + t.a82 = 138; + t.a83 = 277; + t.a84 = 415; + t.a97 = 392; + t.a98 = 392; + t.a99 = 668; + t.a100 = 668; + t.a89 = 390; + t.a90 = 390; + t.a93 = 317; + t.a94 = 317; + t.a91 = 276; + t.a92 = 276; + t.a205 = 509; + t.a85 = 509; + t.a206 = 410; + t.a86 = 410; + t.a87 = 234; + t.a88 = 234; + t.a95 = 334; + t.a96 = 334; + t.a101 = 732; + t.a102 = 544; + t.a103 = 544; + t.a104 = 910; + t.a106 = 667; + t.a107 = 760; + t.a108 = 760; + t.a112 = 776; + t.a111 = 595; + t.a110 = 694; + t.a109 = 626; + t.a120 = 788; + t.a121 = 788; + t.a122 = 788; + t.a123 = 788; + t.a124 = 788; + t.a125 = 788; + t.a126 = 788; + t.a127 = 788; + t.a128 = 788; + t.a129 = 788; + t.a130 = 788; + t.a131 = 788; + t.a132 = 788; + t.a133 = 788; + t.a134 = 788; + t.a135 = 788; + t.a136 = 788; + t.a137 = 788; + t.a138 = 788; + t.a139 = 788; + t.a140 = 788; + t.a141 = 788; + t.a142 = 788; + t.a143 = 788; + t.a144 = 788; + t.a145 = 788; + t.a146 = 788; + t.a147 = 788; + t.a148 = 788; + t.a149 = 788; + t.a150 = 788; + t.a151 = 788; + t.a152 = 788; + t.a153 = 788; + t.a154 = 788; + t.a155 = 788; + t.a156 = 788; + t.a157 = 788; + t.a158 = 788; + t.a159 = 788; + t.a160 = 894; + t.a161 = 838; + t.a163 = 1016; + t.a164 = 458; + t.a196 = 748; + t.a165 = 924; + t.a192 = 748; + t.a166 = 918; + t.a167 = 927; + t.a168 = 928; + t.a169 = 928; + t.a170 = 834; + t.a171 = 873; + t.a172 = 828; + t.a173 = 924; + t.a162 = 924; + t.a174 = 917; + t.a175 = 930; + t.a176 = 931; + t.a177 = 463; + t.a178 = 883; + t.a179 = 836; + t.a193 = 836; + t.a180 = 867; + t.a199 = 867; + t.a181 = 696; + t.a200 = 696; + t.a182 = 874; + t.a201 = 874; + t.a183 = 760; + t.a184 = 946; + t.a197 = 771; + t.a185 = 865; + t.a194 = 771; + t.a198 = 888; + t.a186 = 967; + t.a195 = 888; + t.a187 = 831; + t.a188 = 873; + t.a189 = 927; + t.a190 = 970; + t.a191 = 918; + }); +}); +const getFontBasicMetrics = getLookupTableFactory(function (t) { + t.Courier = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: -426 + }; + t["Courier-Bold"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 439 + }; + t["Courier-Oblique"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 426 + }; + t["Courier-BoldOblique"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 426 + }; + t.Helvetica = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 523 + }; + t["Helvetica-Bold"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 532 + }; + t["Helvetica-Oblique"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 523 + }; + t["Helvetica-BoldOblique"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 532 + }; + t["Times-Roman"] = { + ascent: 683, + descent: -217, + capHeight: 662, + xHeight: 450 + }; + t["Times-Bold"] = { + ascent: 683, + descent: -217, + capHeight: 676, + xHeight: 461 + }; + t["Times-Italic"] = { + ascent: 683, + descent: -217, + capHeight: 653, + xHeight: 441 + }; + t["Times-BoldItalic"] = { + ascent: 683, + descent: -217, + capHeight: 669, + xHeight: 462 + }; + t.Symbol = { + ascent: Math.NaN, + descent: Math.NaN, + capHeight: Math.NaN, + xHeight: Math.NaN + }; + t.ZapfDingbats = { + ascent: Math.NaN, + descent: Math.NaN, + capHeight: Math.NaN, + xHeight: Math.NaN + }; +}); + +;// ./src/core/glyf.js +const ON_CURVE_POINT = 1 << 0; +const X_SHORT_VECTOR = 1 << 1; +const Y_SHORT_VECTOR = 1 << 2; +const REPEAT_FLAG = 1 << 3; +const X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1 << 4; +const Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1 << 5; +const OVERLAP_SIMPLE = 1 << 6; +const ARG_1_AND_2_ARE_WORDS = 1 << 0; +const ARGS_ARE_XY_VALUES = 1 << 1; +const WE_HAVE_A_SCALE = 1 << 3; +const MORE_COMPONENTS = 1 << 5; +const WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; +const WE_HAVE_A_TWO_BY_TWO = 1 << 7; +const WE_HAVE_INSTRUCTIONS = 1 << 8; +class GlyfTable { + constructor({ + glyfTable, + isGlyphLocationsLong, + locaTable, + numGlyphs + }) { + this.glyphs = []; + const loca = new DataView(locaTable.buffer, locaTable.byteOffset, locaTable.byteLength); + const glyf = new DataView(glyfTable.buffer, glyfTable.byteOffset, glyfTable.byteLength); + const offsetSize = isGlyphLocationsLong ? 4 : 2; + let prev = isGlyphLocationsLong ? loca.getUint32(0) : 2 * loca.getUint16(0); + let pos = 0; + for (let i = 0; i < numGlyphs; i++) { + pos += offsetSize; + const next = isGlyphLocationsLong ? loca.getUint32(pos) : 2 * loca.getUint16(pos); + if (next === prev) { + this.glyphs.push(new Glyph({})); + continue; + } + const glyph = Glyph.parse(prev, glyf); + this.glyphs.push(glyph); + prev = next; + } + } + getSize() { + return Math.sumPrecise(this.glyphs.map(g => g.getSize() + 3 & ~3)); + } + write() { + const totalSize = this.getSize(); + const glyfTable = new DataView(new ArrayBuffer(totalSize)); + const isLocationLong = totalSize > 0x1fffe; + const offsetSize = isLocationLong ? 4 : 2; + const locaTable = new DataView(new ArrayBuffer((this.glyphs.length + 1) * offsetSize)); + if (isLocationLong) { + locaTable.setUint32(0, 0); + } else { + locaTable.setUint16(0, 0); + } + let pos = 0; + let locaIndex = 0; + for (const glyph of this.glyphs) { + pos += glyph.write(pos, glyfTable); + pos = pos + 3 & ~3; + locaIndex += offsetSize; + if (isLocationLong) { + locaTable.setUint32(locaIndex, pos); + } else { + locaTable.setUint16(locaIndex, pos >> 1); + } + } + return { + isLocationLong, + loca: new Uint8Array(locaTable.buffer), + glyf: new Uint8Array(glyfTable.buffer) + }; + } + scale(factors) { + for (let i = 0, ii = this.glyphs.length; i < ii; i++) { + this.glyphs[i].scale(factors[i]); + } + } +} +class Glyph { + constructor({ + header = null, + simple = null, + composites = null + }) { + this.header = header; + this.simple = simple; + this.composites = composites; + } + static parse(pos, glyf) { + const [read, header] = GlyphHeader.parse(pos, glyf); + pos += read; + if (header.numberOfContours < 0) { + const composites = []; + while (true) { + const [n, composite] = CompositeGlyph.parse(pos, glyf); + pos += n; + composites.push(composite); + if (!(composite.flags & MORE_COMPONENTS)) { + break; + } + } + return new Glyph({ + header, + composites + }); + } + const simple = SimpleGlyph.parse(pos, glyf, header.numberOfContours); + return new Glyph({ + header, + simple + }); + } + getSize() { + if (!this.header) { + return 0; + } + const size = this.simple ? this.simple.getSize() : Math.sumPrecise(this.composites.map(c => c.getSize())); + return this.header.getSize() + size; + } + write(pos, buf) { + if (!this.header) { + return 0; + } + const spos = pos; + pos += this.header.write(pos, buf); + if (this.simple) { + pos += this.simple.write(pos, buf); + } else { + for (const composite of this.composites) { + pos += composite.write(pos, buf); + } + } + return pos - spos; + } + scale(factor) { + if (!this.header) { + return; + } + const xMiddle = (this.header.xMin + this.header.xMax) / 2; + this.header.scale(xMiddle, factor); + if (this.simple) { + this.simple.scale(xMiddle, factor); + } else { + for (const composite of this.composites) { + composite.scale(xMiddle, factor); + } + } + } +} +class GlyphHeader { + constructor({ + numberOfContours, + xMin, + yMin, + xMax, + yMax + }) { + this.numberOfContours = numberOfContours; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + } + static parse(pos, glyf) { + return [10, new GlyphHeader({ + numberOfContours: glyf.getInt16(pos), + xMin: glyf.getInt16(pos + 2), + yMin: glyf.getInt16(pos + 4), + xMax: glyf.getInt16(pos + 6), + yMax: glyf.getInt16(pos + 8) + })]; + } + getSize() { + return 10; + } + write(pos, buf) { + buf.setInt16(pos, this.numberOfContours); + buf.setInt16(pos + 2, this.xMin); + buf.setInt16(pos + 4, this.yMin); + buf.setInt16(pos + 6, this.xMax); + buf.setInt16(pos + 8, this.yMax); + return 10; + } + scale(x, factor) { + this.xMin = Math.round(x + (this.xMin - x) * factor); + this.xMax = Math.round(x + (this.xMax - x) * factor); + } +} +class Contour { + constructor({ + flags, + xCoordinates, + yCoordinates + }) { + this.xCoordinates = xCoordinates; + this.yCoordinates = yCoordinates; + this.flags = flags; + } +} +class SimpleGlyph { + constructor({ + contours, + instructions + }) { + this.contours = contours; + this.instructions = instructions; + } + static parse(pos, glyf, numberOfContours) { + const endPtsOfContours = []; + for (let i = 0; i < numberOfContours; i++) { + const endPt = glyf.getUint16(pos); + pos += 2; + endPtsOfContours.push(endPt); + } + const numberOfPt = endPtsOfContours[numberOfContours - 1] + 1; + const instructionLength = glyf.getUint16(pos); + pos += 2; + const instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); + pos += instructionLength; + const flags = []; + for (let i = 0; i < numberOfPt; pos++, i++) { + let flag = glyf.getUint8(pos); + flags.push(flag); + if (flag & REPEAT_FLAG) { + const count = glyf.getUint8(++pos); + flag ^= REPEAT_FLAG; + for (let m = 0; m < count; m++) { + flags.push(flag); + } + i += count; + } + } + const allXCoordinates = []; + let xCoordinates = []; + let yCoordinates = []; + let pointFlags = []; + const contours = []; + let endPtsOfContoursIndex = 0; + let lastCoordinate = 0; + for (let i = 0; i < numberOfPt; i++) { + const flag = flags[i]; + if (flag & X_SHORT_VECTOR) { + const x = glyf.getUint8(pos++); + lastCoordinate += flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR ? x : -x; + xCoordinates.push(lastCoordinate); + } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) { + xCoordinates.push(lastCoordinate); + } else { + lastCoordinate += glyf.getInt16(pos); + pos += 2; + xCoordinates.push(lastCoordinate); + } + if (endPtsOfContours[endPtsOfContoursIndex] === i) { + endPtsOfContoursIndex++; + allXCoordinates.push(xCoordinates); + xCoordinates = []; + } + } + lastCoordinate = 0; + endPtsOfContoursIndex = 0; + for (let i = 0; i < numberOfPt; i++) { + const flag = flags[i]; + if (flag & Y_SHORT_VECTOR) { + const y = glyf.getUint8(pos++); + lastCoordinate += flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR ? y : -y; + yCoordinates.push(lastCoordinate); + } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) { + yCoordinates.push(lastCoordinate); + } else { + lastCoordinate += glyf.getInt16(pos); + pos += 2; + yCoordinates.push(lastCoordinate); + } + pointFlags.push(flag & ON_CURVE_POINT | flag & OVERLAP_SIMPLE); + if (endPtsOfContours[endPtsOfContoursIndex] === i) { + xCoordinates = allXCoordinates[endPtsOfContoursIndex]; + endPtsOfContoursIndex++; + contours.push(new Contour({ + flags: pointFlags, + xCoordinates, + yCoordinates + })); + yCoordinates = []; + pointFlags = []; + } + } + return new SimpleGlyph({ + contours, + instructions + }); + } + getSize() { + let size = this.contours.length * 2 + 2 + this.instructions.length; + let lastX = 0; + let lastY = 0; + for (const contour of this.contours) { + size += contour.flags.length; + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + const x = contour.xCoordinates[i]; + const y = contour.yCoordinates[i]; + let abs = Math.abs(x - lastX); + if (abs > 255) { + size += 2; + } else if (abs > 0) { + size += 1; + } + lastX = x; + abs = Math.abs(y - lastY); + if (abs > 255) { + size += 2; + } else if (abs > 0) { + size += 1; + } + lastY = y; + } + } + return size; + } + write(pos, buf) { + const spos = pos; + const xCoordinates = []; + const yCoordinates = []; + const flags = []; + let lastX = 0; + let lastY = 0; + for (const contour of this.contours) { + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + let flag = contour.flags[i]; + const x = contour.xCoordinates[i]; + let delta = x - lastX; + if (delta === 0) { + flag |= X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR; + xCoordinates.push(0); + } else { + const abs = Math.abs(delta); + if (abs <= 255) { + flag |= delta >= 0 ? X_SHORT_VECTOR | X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR : X_SHORT_VECTOR; + xCoordinates.push(abs); + } else { + xCoordinates.push(delta); + } + } + lastX = x; + const y = contour.yCoordinates[i]; + delta = y - lastY; + if (delta === 0) { + flag |= Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR; + yCoordinates.push(0); + } else { + const abs = Math.abs(delta); + if (abs <= 255) { + flag |= delta >= 0 ? Y_SHORT_VECTOR | Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR : Y_SHORT_VECTOR; + yCoordinates.push(abs); + } else { + yCoordinates.push(delta); + } + } + lastY = y; + flags.push(flag); + } + buf.setUint16(pos, xCoordinates.length - 1); + pos += 2; + } + buf.setUint16(pos, this.instructions.length); + pos += 2; + if (this.instructions.length) { + new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); + pos += this.instructions.length; + } + for (const flag of flags) { + buf.setUint8(pos++, flag); + } + for (let i = 0, ii = xCoordinates.length; i < ii; i++) { + const x = xCoordinates[i]; + const flag = flags[i]; + if (flag & X_SHORT_VECTOR) { + buf.setUint8(pos++, x); + } else if (!(flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR)) { + buf.setInt16(pos, x); + pos += 2; + } + } + for (let i = 0, ii = yCoordinates.length; i < ii; i++) { + const y = yCoordinates[i]; + const flag = flags[i]; + if (flag & Y_SHORT_VECTOR) { + buf.setUint8(pos++, y); + } else if (!(flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR)) { + buf.setInt16(pos, y); + pos += 2; + } + } + return pos - spos; + } + scale(x, factor) { + for (const contour of this.contours) { + if (contour.xCoordinates.length === 0) { + continue; + } + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + contour.xCoordinates[i] = Math.round(x + (contour.xCoordinates[i] - x) * factor); + } + } + } +} +class CompositeGlyph { + constructor({ + flags, + glyphIndex, + argument1, + argument2, + transf, + instructions + }) { + this.flags = flags; + this.glyphIndex = glyphIndex; + this.argument1 = argument1; + this.argument2 = argument2; + this.transf = transf; + this.instructions = instructions; + } + static parse(pos, glyf) { + const spos = pos; + const transf = []; + let flags = glyf.getUint16(pos); + const glyphIndex = glyf.getUint16(pos + 2); + pos += 4; + let argument1, argument2; + if (flags & ARG_1_AND_2_ARE_WORDS) { + if (flags & ARGS_ARE_XY_VALUES) { + argument1 = glyf.getInt16(pos); + argument2 = glyf.getInt16(pos + 2); + } else { + argument1 = glyf.getUint16(pos); + argument2 = glyf.getUint16(pos + 2); + } + pos += 4; + flags ^= ARG_1_AND_2_ARE_WORDS; + } else { + if (flags & ARGS_ARE_XY_VALUES) { + argument1 = glyf.getInt8(pos); + argument2 = glyf.getInt8(pos + 1); + } else { + argument1 = glyf.getUint8(pos); + argument2 = glyf.getUint8(pos + 1); + } + pos += 2; + } + if (flags & WE_HAVE_A_SCALE) { + transf.push(glyf.getUint16(pos)); + pos += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2)); + pos += 4; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { + transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2), glyf.getUint16(pos + 4), glyf.getUint16(pos + 6)); + pos += 8; + } + let instructions = null; + if (flags & WE_HAVE_INSTRUCTIONS) { + const instructionLength = glyf.getUint16(pos); + pos += 2; + instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); + pos += instructionLength; + } + return [pos - spos, new CompositeGlyph({ + flags, + glyphIndex, + argument1, + argument2, + transf, + instructions + })]; + } + getSize() { + let size = 2 + 2 + this.transf.length * 2; + if (this.flags & WE_HAVE_INSTRUCTIONS) { + size += 2 + this.instructions.length; + } + size += 2; + if (this.flags & 2) { + if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { + size += 2; + } + } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { + size += 2; + } + return size; + } + write(pos, buf) { + const spos = pos; + if (this.flags & ARGS_ARE_XY_VALUES) { + if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { + this.flags |= ARG_1_AND_2_ARE_WORDS; + } + } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { + this.flags |= ARG_1_AND_2_ARE_WORDS; + } + buf.setUint16(pos, this.flags); + buf.setUint16(pos + 2, this.glyphIndex); + pos += 4; + if (this.flags & ARG_1_AND_2_ARE_WORDS) { + if (this.flags & ARGS_ARE_XY_VALUES) { + buf.setInt16(pos, this.argument1); + buf.setInt16(pos + 2, this.argument2); + } else { + buf.setUint16(pos, this.argument1); + buf.setUint16(pos + 2, this.argument2); + } + pos += 4; + } else { + buf.setUint8(pos, this.argument1); + buf.setUint8(pos + 1, this.argument2); + pos += 2; + } + if (this.flags & WE_HAVE_INSTRUCTIONS) { + buf.setUint16(pos, this.instructions.length); + pos += 2; + if (this.instructions.length) { + new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); + pos += this.instructions.length; + } + } + return pos - spos; + } + scale(x, factor) {} +} + +;// ./src/core/opentype_file_builder.js + + +function writeInt16(dest, offset, num) { + dest[offset] = num >> 8 & 0xff; + dest[offset + 1] = num & 0xff; +} +function writeInt32(dest, offset, num) { + dest[offset] = num >> 24 & 0xff; + dest[offset + 1] = num >> 16 & 0xff; + dest[offset + 2] = num >> 8 & 0xff; + dest[offset + 3] = num & 0xff; +} +function writeData(dest, offset, data) { + if (data instanceof Uint8Array) { + dest.set(data, offset); + } else if (typeof data === "string") { + for (let i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data.charCodeAt(i) & 0xff; + } + } else { + for (const num of data) { + dest[offset++] = num & 0xff; + } + } +} +const OTF_HEADER_SIZE = 12; +const OTF_TABLE_ENTRY_SIZE = 16; +class OpenTypeFileBuilder { + constructor(sfnt) { + this.sfnt = sfnt; + this.tables = Object.create(null); + } + static getSearchParams(entriesCount, entrySize) { + let maxPower2 = 1, + log2 = 0; + while ((maxPower2 ^ entriesCount) > maxPower2) { + maxPower2 <<= 1; + log2++; + } + const searchRange = maxPower2 * entrySize; + return { + range: searchRange, + entry: log2, + rangeShift: entrySize * entriesCount - searchRange + }; + } + toArray() { + let sfnt = this.sfnt; + const tables = this.tables; + const tablesNames = Object.keys(tables); + tablesNames.sort(); + const numTables = tablesNames.length; + let i, j, jj, table, tableName; + let offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; + const tableOffsets = [offset]; + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + const paddedLength = (table.length + 3 & ~3) >>> 0; + offset += paddedLength; + tableOffsets.push(offset); + } + const file = new Uint8Array(offset); + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + writeData(file, tableOffsets[i], table); + } + if (sfnt === "true") { + sfnt = string32(0x00010000); + } + file[0] = sfnt.charCodeAt(0) & 0xff; + file[1] = sfnt.charCodeAt(1) & 0xff; + file[2] = sfnt.charCodeAt(2) & 0xff; + file[3] = sfnt.charCodeAt(3) & 0xff; + writeInt16(file, 4, numTables); + const searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); + writeInt16(file, 6, searchParams.range); + writeInt16(file, 8, searchParams.entry); + writeInt16(file, 10, searchParams.rangeShift); + offset = OTF_HEADER_SIZE; + for (i = 0; i < numTables; i++) { + tableName = tablesNames[i]; + file[offset] = tableName.charCodeAt(0) & 0xff; + file[offset + 1] = tableName.charCodeAt(1) & 0xff; + file[offset + 2] = tableName.charCodeAt(2) & 0xff; + file[offset + 3] = tableName.charCodeAt(3) & 0xff; + let checksum = 0; + for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { + const quad = readUint32(file, j); + checksum = checksum + quad >>> 0; + } + writeInt32(file, offset + 4, checksum); + writeInt32(file, offset + 8, tableOffsets[i]); + writeInt32(file, offset + 12, tables[tableName].length); + offset += OTF_TABLE_ENTRY_SIZE; + } + return file; + } + addTable(tag, data) { + if (tag in this.tables) { + throw new Error("Table " + tag + " already exists"); + } + this.tables[tag] = data; + } +} + +;// ./src/core/type1_parser.js + + + + +const HINTING_ENABLED = false; +const COMMAND_MAP = { + hstem: [1], + vstem: [3], + vmoveto: [4], + rlineto: [5], + hlineto: [6], + vlineto: [7], + rrcurveto: [8], + callsubr: [10], + flex: [12, 35], + drop: [12, 18], + endchar: [14], + rmoveto: [21], + hmoveto: [22], + vhcurveto: [30], + hvcurveto: [31] +}; +class Type1CharString { + constructor() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + convert(encoded, subrs, seacAnalysisEnabled) { + const count = encoded.length; + let error = false; + let wx, sbx, subrNumber; + for (let i = 0; i < count; i++) { + let value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: + if (this.flexing) { + if (this.stack.length < 1) { + error = true; + break; + } + const dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: + error = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: + error = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: + error = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: + error = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: + this.stack = []; + break; + case 10: + if (this.stack.length < 1) { + error = true; + break; + } + subrNumber = this.stack.pop(); + if (!subrs[subrNumber]) { + error = true; + break; + } + error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled); + break; + case 11: + return error; + case 13: + if (this.stack.length < 2) { + error = true; + break; + } + wx = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx); + error = this.executeCommand(2, COMMAND_MAP.hmoveto); + break; + case 14: + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: + if (this.flexing) { + break; + } + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: + if (this.flexing) { + this.stack.push(0); + break; + } + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: + error = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: + error = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: + this.stack = []; + break; + case (12 << 8) + 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: + if (seacAnalysisEnabled) { + const asb = this.stack.at(-5); + this.seac = this.stack.splice(-4, 4); + this.seac[0] += this.lsb - asb; + error = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: + if (this.stack.length < 4) { + error = true; + break; + } + this.stack.pop(); + wx = this.stack.pop(); + const sby = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx, sby); + error = this.executeCommand(3, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: + if (this.stack.length < 2) { + error = true; + break; + } + const num2 = this.stack.pop(); + const num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: + if (this.stack.length < 2) { + error = true; + break; + } + subrNumber = this.stack.pop(); + const numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + const flexArgs = this.stack.splice(-17, 17); + this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]); + error = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: + break; + case (12 << 8) + 33: + this.stack = []; + break; + default: + warn('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error) { + break; + } + continue; + } else if (value <= 246) { + value -= 139; + } else if (value <= 250) { + value = (value - 247) * 256 + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; + } + this.stack.push(value); + } + return error; + } + executeCommand(howManyArgs, command, keepStack) { + const stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + const start = stackLength - howManyArgs; + for (let i = start; i < stackLength; i++) { + let value = this.stack[i]; + if (Number.isInteger(value)) { + this.output.push(28, value >> 8 & 0xff, value & 0xff); + } else { + value = 65536 * value | 0; + this.output.push(255, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); + } + } + this.output.push(...command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack.length = 0; + } + return false; + } +} +const EEXEC_ENCRYPT_KEY = 55665; +const CHAR_STRS_ENCRYPT_KEY = 4330; +function isHexDigit(code) { + return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102; +} +function decrypt(data, key, discardNumber) { + if (discardNumber >= data.length) { + return new Uint8Array(0); + } + const c1 = 52845, + c2 = 22719; + let r = key | 0, + i, + j; + for (i = 0; i < discardNumber; i++) { + r = (data[i] + r) * c1 + c2 & (1 << 16) - 1; + } + const count = data.length - discardNumber; + const decrypted = new Uint8Array(count); + for (i = discardNumber, j = 0; j < count; i++, j++) { + const value = data[i]; + decrypted[j] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + return decrypted; +} +function decryptAscii(data, key, discardNumber) { + const c1 = 52845, + c2 = 22719; + let r = key | 0; + const count = data.length, + maybeLength = count >>> 1; + const decrypted = new Uint8Array(maybeLength); + let i, j; + for (i = 0, j = 0; i < count; i++) { + const digit1 = data[i]; + if (!isHexDigit(digit1)) { + continue; + } + i++; + let digit2; + while (i < count && !isHexDigit(digit2 = data[i])) { + i++; + } + if (i < count) { + const value = parseInt(String.fromCharCode(digit1, digit2), 16); + decrypted[j++] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + } + return decrypted.slice(discardNumber, j); +} +function isSpecial(c) { + return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29; +} +class Type1Parser { + constructor(stream, encrypted, seacAnalysisEnabled) { + if (encrypted) { + const data = stream.getBytes(); + const isBinary = !((isHexDigit(data[0]) || isWhiteSpace(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7])); + stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); + } + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + this.stream = stream; + this.nextChar(); + } + readNumberArray() { + this.getToken(); + const array = []; + while (true) { + const token = this.getToken(); + if (token === null || token === "]" || token === "}") { + break; + } + array.push(parseFloat(token || 0)); + } + return array; + } + readNumber() { + const token = this.getToken(); + return parseFloat(token || 0); + } + readInt() { + const token = this.getToken(); + return parseInt(token || 0, 10) | 0; + } + readBoolean() { + const token = this.getToken(); + return token === "true" ? 1 : 0; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + prevChar() { + this.stream.skip(-2); + return this.currentChar = this.stream.getByte(); + } + getToken() { + let comment = false; + let ch = this.currentChar; + while (true) { + if (ch === -1) { + return null; + } + if (comment) { + if (ch === 0x0a || ch === 0x0d) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (!isWhiteSpace(ch)) { + break; + } + ch = this.nextChar(); + } + if (isSpecial(ch)) { + this.nextChar(); + return String.fromCharCode(ch); + } + let token = ""; + do { + token += String.fromCharCode(ch); + ch = this.nextChar(); + } while (ch >= 0 && !isWhiteSpace(ch) && !isSpecial(ch)); + return token; + } + readCharStrings(bytes, lenIV) { + if (lenIV === -1) { + return bytes; + } + return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV); + } + extractFontProgram(properties) { + const stream = this.stream; + const subrs = [], + charstrings = []; + const privateData = Object.create(null); + privateData.lenIV = 4; + const program = { + subrs: [], + charstrings: [], + properties: { + privateData + } + }; + let token, length, data, lenIV; + while ((token = this.getToken()) !== null) { + if (token !== "/") { + continue; + } + token = this.getToken(); + switch (token) { + case "CharStrings": + this.getToken(); + this.getToken(); + this.getToken(); + this.getToken(); + while (true) { + token = this.getToken(); + if (token === null || token === "end") { + break; + } + if (token !== "/") { + continue; + } + const glyph = this.getToken(); + length = this.readInt(); + this.getToken(); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); + lenIV = program.properties.privateData.lenIV; + const encoded = this.readCharStrings(data, lenIV); + this.nextChar(); + token = this.getToken(); + if (token === "noaccess") { + this.getToken(); + } else if (token === "/") { + this.prevChar(); + } + charstrings.push({ + glyph, + encoded + }); + } + break; + case "Subrs": + this.readInt(); + this.getToken(); + while (this.getToken() === "dup") { + const index = this.readInt(); + length = this.readInt(); + this.getToken(); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); + lenIV = program.properties.privateData.lenIV; + const encoded = this.readCharStrings(data, lenIV); + this.nextChar(); + token = this.getToken(); + if (token === "noaccess") { + this.getToken(); + } + subrs[index] = encoded; + } + break; + case "BlueValues": + case "OtherBlues": + case "FamilyBlues": + case "FamilyOtherBlues": + const blueArray = this.readNumberArray(); + if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case "StemSnapH": + case "StemSnapV": + program.properties.privateData[token] = this.readNumberArray(); + break; + case "StdHW": + case "StdVW": + program.properties.privateData[token] = this.readNumberArray()[0]; + break; + case "BlueShift": + case "lenIV": + case "BlueFuzz": + case "BlueScale": + case "LanguageGroup": + program.properties.privateData[token] = this.readNumber(); + break; + case "ExpansionFactor": + program.properties.privateData[token] = this.readNumber() || 0.06; + break; + case "ForceBold": + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + for (const { + encoded, + glyph + } of charstrings) { + const charString = new Type1CharString(); + const error = charString.convert(encoded, subrs, this.seacAnalysisEnabled); + let output = charString.output; + if (error) { + output = [14]; + } + const charStringObject = { + glyphName: glyph, + charstring: output, + width: charString.width, + lsb: charString.lsb, + seac: charString.seac + }; + if (glyph === ".notdef") { + program.charstrings.unshift(charStringObject); + } else { + program.charstrings.push(charStringObject); + } + if (properties.builtInEncoding) { + const index = properties.builtInEncoding.indexOf(glyph); + if (index > -1 && properties.widths[index] === undefined && index >= properties.firstChar && index <= properties.lastChar) { + properties.widths[index] = charString.width; + } + } + } + return program; + } + extractFontHeader(properties) { + let token; + while ((token = this.getToken()) !== null) { + if (token !== "/") { + continue; + } + token = this.getToken(); + switch (token) { + case "FontMatrix": + const matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case "Encoding": + const encodingArg = this.getToken(); + let encoding; + if (!/^\d+$/.test(encodingArg)) { + encoding = getEncoding(encodingArg); + } else { + encoding = []; + const size = parseInt(encodingArg, 10) | 0; + this.getToken(); + for (let j = 0; j < size; j++) { + token = this.getToken(); + while (token !== "dup" && token !== "def") { + token = this.getToken(); + if (token === null) { + return; + } + } + if (token === "def") { + break; + } + const index = this.readInt(); + this.getToken(); + const glyph = this.getToken(); + encoding[index] = glyph; + this.getToken(); + } + } + properties.builtInEncoding = encoding; + break; + case "FontBBox": + const fontBBox = this.readNumberArray(); + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + break; + } + } + } +} + +;// ./src/core/type1_font.js + + + + + + +function findBlock(streamBytes, signature, startIndex) { + const streamBytesLength = streamBytes.length; + const signatureLength = signature.length; + const scanLength = streamBytesLength - signatureLength; + let i = startIndex, + found = false; + while (i < scanLength) { + let j = 0; + while (j < signatureLength && streamBytes[i + j] === signature[j]) { + j++; + } + if (j >= signatureLength) { + i += j; + while (i < streamBytesLength && isWhiteSpace(streamBytes[i])) { + i++; + } + found = true; + break; + } + i++; + } + return { + found, + length: i + }; +} +function getHeaderBlock(stream, suggestedLength) { + const EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63]; + const streamStartPos = stream.pos; + let headerBytes, headerBytesLength, block; + try { + headerBytes = stream.getBytes(suggestedLength); + headerBytesLength = headerBytes.length; + } catch {} + if (headerBytesLength === suggestedLength) { + block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length); + if (block.found && block.length === suggestedLength) { + return { + stream: new Stream(headerBytes), + length: suggestedLength + }; + } + } + warn('Invalid "Length1" property in Type1 font -- trying to recover.'); + stream.pos = streamStartPos; + const SCAN_BLOCK_LENGTH = 2048; + let actualLength; + while (true) { + const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); + block = findBlock(scanBytes, EEXEC_SIGNATURE, 0); + if (block.length === 0) { + break; + } + stream.pos += block.length; + if (block.found) { + actualLength = stream.pos - streamStartPos; + break; + } + } + stream.pos = streamStartPos; + if (actualLength) { + return { + stream: new Stream(stream.getBytes(actualLength)), + length: actualLength + }; + } + warn('Unable to recover "Length1" property in Type1 font -- using as is.'); + return { + stream: new Stream(stream.getBytes(suggestedLength)), + length: suggestedLength + }; +} +function getEexecBlock(stream, suggestedLength) { + const eexecBytes = stream.getBytes(); + if (eexecBytes.length === 0) { + throw new FormatError("getEexecBlock - no font program found."); + } + return { + stream: new Stream(eexecBytes), + length: eexecBytes.length + }; +} +class Type1Font { + constructor(name, file, properties) { + const PFB_HEADER_SIZE = 6; + let headerBlockLength = properties.length1; + let eexecBlockLength = properties.length2; + let pfbHeader = file.peekBytes(PFB_HEADER_SIZE); + const pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; + if (pfbHeaderPresent) { + file.skip(PFB_HEADER_SIZE); + headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + const headerBlock = getHeaderBlock(file, headerBlockLength); + const headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED); + headerBlockParser.extractFontHeader(properties); + if (pfbHeaderPresent) { + pfbHeader = file.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + const eexecBlock = getEexecBlock(file, eexecBlockLength); + const eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED); + const data = eexecBlockParser.extractFontProgram(properties); + for (const key in data.properties) { + properties[key] = data.properties[key]; + } + const charstrings = data.charstrings; + const type2Charstrings = this.getType2Charstrings(charstrings); + const subrs = this.getType2Subrs(data.subrs); + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties); + this.seacs = this.getSeacs(data.charstrings); + } + get numGlyphs() { + return this.charstrings.length + 1; + } + getCharset() { + const charset = [".notdef"]; + for (const { + glyphName + } of this.charstrings) { + charset.push(glyphName); + } + return charset; + } + getGlyphMapping(properties) { + const charstrings = this.charstrings; + if (properties.composite) { + const charCodeToGlyphId = Object.create(null); + for (let glyphId = 0, charstringsLen = charstrings.length; glyphId < charstringsLen; glyphId++) { + const charCode = properties.cMap.charCodeOf(glyphId); + charCodeToGlyphId[charCode] = glyphId + 1; + } + return charCodeToGlyphId; + } + const glyphNames = [".notdef"]; + let builtInEncoding, glyphId; + for (glyphId = 0; glyphId < charstrings.length; glyphId++) { + glyphNames.push(charstrings[glyphId].glyphName); + } + const encoding = properties.builtInEncoding; + if (encoding) { + builtInEncoding = Object.create(null); + for (const charCode in encoding) { + glyphId = glyphNames.indexOf(encoding[charCode]); + if (glyphId >= 0) { + builtInEncoding[charCode] = glyphId; + } + } + } + return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); + } + hasGlyphId(id) { + if (id < 0 || id >= this.numGlyphs) { + return false; + } + if (id === 0) { + return true; + } + const glyph = this.charstrings[id - 1]; + return glyph.charstring.length > 0; + } + getSeacs(charstrings) { + const seacMap = []; + for (let i = 0, ii = charstrings.length; i < ii; i++) { + const charstring = charstrings[i]; + if (charstring.seac) { + seacMap[i + 1] = charstring.seac; + } + } + return seacMap; + } + getType2Charstrings(type1Charstrings) { + const type2Charstrings = []; + for (const type1Charstring of type1Charstrings) { + type2Charstrings.push(type1Charstring.charstring); + } + return type2Charstrings; + } + getType2Subrs(type1Subrs) { + let bias = 0; + const count = type1Subrs.length; + if (count < 1133) { + bias = 107; + } else if (count < 33769) { + bias = 1131; + } else { + bias = 32768; + } + const type2Subrs = []; + let i; + for (i = 0; i < bias; i++) { + type2Subrs.push([0x0b]); + } + for (i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + return type2Subrs; + } + wrap(name, glyphs, charstrings, subrs, properties) { + const cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + cff.names = [name]; + const topDict = new CFFTopDict(); + topDict.setByName("version", 391); + topDict.setByName("Notice", 392); + topDict.setByName("FullName", 393); + topDict.setByName("FamilyName", 394); + topDict.setByName("Weight", 395); + topDict.setByName("Encoding", null); + topDict.setByName("FontMatrix", properties.fontMatrix); + topDict.setByName("FontBBox", properties.bbox); + topDict.setByName("charset", null); + topDict.setByName("CharStrings", null); + topDict.setByName("Private", null); + cff.topDict = topDict; + const strings = new CFFStrings(); + strings.add("Version 0.11"); + strings.add("See original notice"); + strings.add(name); + strings.add(name); + strings.add("Medium"); + cff.strings = strings; + cff.globalSubrIndex = new CFFIndex(); + const count = glyphs.length; + const charsetArray = [".notdef"]; + let i, ii; + for (i = 0; i < count; i++) { + const glyphName = charstrings[i].glyphName; + const index = CFFStandardStrings.indexOf(glyphName); + if (index === -1) { + strings.add(glyphName); + } + charsetArray.push(glyphName); + } + cff.charset = new CFFCharset(false, 0, charsetArray); + const charStringsIndex = new CFFIndex(); + charStringsIndex.add([0x8b, 0x0e]); + for (i = 0; i < count; i++) { + charStringsIndex.add(glyphs[i]); + } + cff.charStrings = charStringsIndex; + const privateDict = new CFFPrivateDict(); + privateDict.setByName("Subrs", null); + const fields = ["BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StemSnapH", "StemSnapV", "BlueShift", "BlueFuzz", "BlueScale", "LanguageGroup", "ExpansionFactor", "ForceBold", "StdHW", "StdVW"]; + for (i = 0, ii = fields.length; i < ii; i++) { + const field = fields[i]; + if (!(field in properties.privateData)) { + continue; + } + const value = properties.privateData[field]; + if (Array.isArray(value)) { + for (let j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + const subrIndex = new CFFIndex(); + for (i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + const compiler = new CFFCompiler(cff); + return compiler.compile(); + } +} + +;// ./src/core/fonts.js + + + + + + + + + + + + + + + + + +const PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]]; +const PDF_GLYPH_SPACE_UNITS = 1000; +const EXPORT_DATA_PROPERTIES = ["ascent", "bbox", "black", "bold", "charProcOperatorList", "cssFontInfo", "data", "defaultVMetrics", "defaultWidth", "descent", "disableFontFace", "fallbackName", "fontExtraProperties", "fontMatrix", "isInvalidPDFjsFont", "isType3Font", "italic", "loadedName", "mimetype", "missingFile", "name", "remeasure", "systemFontInfo", "vertical"]; +const EXPORT_DATA_EXTRA_PROPERTIES = ["cMap", "composite", "defaultEncoding", "differences", "isMonospace", "isSerifFont", "isSymbolicFont", "seacMap", "subtype", "toFontChar", "toUnicode", "type", "vmetrics", "widths"]; +function adjustWidths(properties) { + if (!properties.fontMatrix) { + return; + } + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { + return; + } + const scale = 0.001 / properties.fontMatrix[0]; + const glyphsWidths = properties.widths; + for (const glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} +function adjustTrueTypeToUnicode(properties, isSymbolicFont, nameRecords) { + if (properties.isInternalFont) { + return; + } + if (properties.hasIncludedToUnicodeMap) { + return; + } + if (properties.hasEncoding) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + if (!isSymbolicFont) { + return; + } + if (nameRecords.length === 0) { + return; + } + if (properties.defaultEncoding === WinAnsiEncoding) { + return; + } + for (const r of nameRecords) { + if (!isWinNameRecord(r)) { + return; + } + } + const encoding = WinAnsiEncoding; + const toUnicode = [], + glyphsUnicodeMap = getGlyphsUnicode(); + for (const charCode in encoding) { + const glyphName = encoding[charCode]; + if (glyphName === "") { + continue; + } + const unicode = glyphsUnicodeMap[glyphName]; + if (unicode === undefined) { + continue; + } + toUnicode[charCode] = String.fromCharCode(unicode); + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +function adjustType1ToUnicode(properties, builtInEncoding) { + if (properties.isInternalFont) { + return; + } + if (properties.hasIncludedToUnicodeMap) { + return; + } + if (builtInEncoding === properties.defaultEncoding) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + const toUnicode = [], + glyphsUnicodeMap = getGlyphsUnicode(); + for (const charCode in builtInEncoding) { + if (properties.hasEncoding) { + if (properties.baseEncodingName || properties.differences[charCode] !== undefined) { + continue; + } + } + const glyphName = builtInEncoding[charCode]; + const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + toUnicode[charCode] = String.fromCharCode(unicode); + } + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +function amendFallbackToUnicode(properties) { + if (!properties.fallbackToUnicode) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + const toUnicode = []; + for (const charCode in properties.fallbackToUnicode) { + if (properties.toUnicode.has(charCode)) { + continue; + } + toUnicode[charCode] = properties.fallbackToUnicode[charCode]; + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +class fonts_Glyph { + constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { + this.originalCharCode = originalCharCode; + this.fontChar = fontChar; + this.unicode = unicode; + this.accent = accent; + this.width = width; + this.vmetric = vmetric; + this.operatorListId = operatorListId; + this.isSpace = isSpace; + this.isInFont = isInFont; + } + get category() { + return shadow(this, "category", getCharUnicodeCategory(this.unicode), true); + } +} +function int16(b0, b1) { + return (b0 << 8) + b1; +} +function writeSignedInt16(bytes, index, value) { + bytes[index + 1] = value; + bytes[index] = value >>> 8; +} +function signedInt16(b0, b1) { + const value = (b0 << 8) + b1; + return value & 1 << 15 ? value - 0x10000 : value; +} +function writeUint32(bytes, index, value) { + bytes[index + 3] = value & 0xff; + bytes[index + 2] = value >>> 8; + bytes[index + 1] = value >>> 16; + bytes[index] = value >>> 24; +} +function int32(b0, b1, b2, b3) { + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; +} +function string16(value) { + return String.fromCharCode(value >> 8 & 0xff, value & 0xff); +} +function safeString16(value) { + if (value > 0x7fff) { + value = 0x7fff; + } else if (value < -0x8000) { + value = -0x8000; + } + return String.fromCharCode(value >> 8 & 0xff, value & 0xff); +} +function isTrueTypeFile(file) { + const header = file.peekBytes(4); + return readUint32(header, 0) === 0x00010000 || bytesToString(header) === "true"; +} +function isTrueTypeCollectionFile(file) { + const header = file.peekBytes(4); + return bytesToString(header) === "ttcf"; +} +function isOpenTypeFile(file) { + const header = file.peekBytes(4); + return bytesToString(header) === "OTTO"; +} +function isType1File(file) { + const header = file.peekBytes(2); + if (header[0] === 0x25 && header[1] === 0x21) { + return true; + } + if (header[0] === 0x80 && header[1] === 0x01) { + return true; + } + return false; +} +function isCFFFile(file) { + const header = file.peekBytes(4); + if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) { + return true; + } + return false; +} +function getFontFileType(file, { + type, + subtype, + composite +}) { + let fileType, fileSubtype; + if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) { + fileType = composite ? "CIDFontType2" : "TrueType"; + } else if (isOpenTypeFile(file)) { + fileType = composite ? "CIDFontType2" : "OpenType"; + } else if (isType1File(file)) { + if (composite) { + fileType = "CIDFontType0"; + } else { + fileType = type === "MMType1" ? "MMType1" : "Type1"; + } + } else if (isCFFFile(file)) { + if (composite) { + fileType = "CIDFontType0"; + fileSubtype = "CIDFontType0C"; + } else { + fileType = type === "MMType1" ? "MMType1" : "Type1"; + fileSubtype = "Type1C"; + } + } else { + warn("getFontFileType: Unable to detect correct font file Type/Subtype."); + fileType = type; + fileSubtype = subtype; + } + return [fileType, fileSubtype]; +} +function applyStandardFontGlyphMap(map, glyphMap) { + for (const charCode in glyphMap) { + map[+charCode] = glyphMap[charCode]; + } +} +function buildToFontChar(encoding, glyphsUnicodeMap, differences) { + const toFontChar = []; + let unicode; + for (let i = 0, ii = encoding.length; i < ii; i++) { + unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[i] = unicode; + } + } + for (const charCode in differences) { + unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[+charCode] = unicode; + } + } + return toFontChar; +} +function isMacNameRecord(r) { + return r.platform === 1 && r.encoding === 0 && r.language === 0; +} +function isWinNameRecord(r) { + return r.platform === 3 && r.encoding === 1 && r.language === 0x409; +} +function convertCidString(charCode, cid, shouldThrow = false) { + switch (cid.length) { + case 1: + return cid.charCodeAt(0); + case 2: + return cid.charCodeAt(0) << 8 | cid.charCodeAt(1); + } + const msg = `Unsupported CID string (charCode ${charCode}): "${cid}".`; + if (shouldThrow) { + throw new FormatError(msg); + } + warn(msg); + return cid; +} +function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId, toUnicode) { + const newMap = Object.create(null); + const toUnicodeExtraMap = new Map(); + const toFontChar = []; + const usedGlyphIds = new Set(); + let privateUseAreaIndex = 0; + const privateUseOffetStart = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; + let nextAvailableFontCharCode = privateUseOffetStart; + let privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; + const isInPrivateArea = code => PRIVATE_USE_AREAS[0][0] <= code && code <= PRIVATE_USE_AREAS[0][1] || PRIVATE_USE_AREAS[1][0] <= code && code <= PRIVATE_USE_AREAS[1][1]; + let LIGATURE_TO_UNICODE = null; + for (const originalCharCode in charCodeToGlyphId) { + let glyphId = charCodeToGlyphId[originalCharCode]; + if (!hasGlyph(glyphId)) { + continue; + } + if (nextAvailableFontCharCode > privateUseOffetEnd) { + privateUseAreaIndex++; + if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) { + warn("Ran out of space in font private use area."); + break; + } + nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; + privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; + } + const fontCharCode = nextAvailableFontCharCode++; + if (glyphId === 0) { + glyphId = newGlyphZeroId; + } + let unicode = toUnicode.get(originalCharCode); + if (typeof unicode === "string") { + if (unicode.length === 1) { + unicode = unicode.codePointAt(0); + } else { + if (!LIGATURE_TO_UNICODE) { + LIGATURE_TO_UNICODE = new Map(); + for (let i = 0xfb00; i <= 0xfb4f; i++) { + const normalized = String.fromCharCode(i).normalize("NFKD"); + if (normalized.length > 1) { + LIGATURE_TO_UNICODE.set(normalized, i); + } + } + } + unicode = LIGATURE_TO_UNICODE.get(unicode) || unicode.codePointAt(0); + } + } + if (unicode && !isInPrivateArea(unicode) && !usedGlyphIds.has(glyphId)) { + toUnicodeExtraMap.set(unicode, glyphId); + usedGlyphIds.add(glyphId); + } + newMap[fontCharCode] = glyphId; + toFontChar[originalCharCode] = fontCharCode; + } + return { + toFontChar, + charCodeToGlyphId: newMap, + toUnicodeExtraMap, + nextAvailableFontCharCode + }; +} +function getRanges(glyphs, toUnicodeExtraMap, numGlyphs) { + const codes = []; + for (const charCode in glyphs) { + if (glyphs[charCode] >= numGlyphs) { + continue; + } + codes.push({ + fontCharCode: charCode | 0, + glyphId: glyphs[charCode] + }); + } + if (toUnicodeExtraMap) { + for (const [unicode, glyphId] of toUnicodeExtraMap) { + if (glyphId >= numGlyphs) { + continue; + } + codes.push({ + fontCharCode: unicode, + glyphId + }); + } + } + if (codes.length === 0) { + codes.push({ + fontCharCode: 0, + glyphId: 0 + }); + } + codes.sort((a, b) => a.fontCharCode - b.fontCharCode); + const ranges = []; + const length = codes.length; + for (let n = 0; n < length;) { + const start = codes[n].fontCharCode; + const codeIndices = [codes[n].glyphId]; + ++n; + let end = start; + while (n < length && end + 1 === codes[n].fontCharCode) { + codeIndices.push(codes[n].glyphId); + ++end; + ++n; + if (end === 0xffff) { + break; + } + } + ranges.push([start, end, codeIndices]); + } + return ranges; +} +function createCmapTable(glyphs, toUnicodeExtraMap, numGlyphs) { + const ranges = getRanges(glyphs, toUnicodeExtraMap, numGlyphs); + const numTables = ranges.at(-1)[1] > 0xffff ? 2 : 1; + let cmap = "\x00\x00" + string16(numTables) + "\x00\x03" + "\x00\x01" + string32(4 + numTables * 8); + let i, ii, j, jj; + for (i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 0xffff) { + break; + } + } + const bmpLength = i + 1; + if (ranges[i][0] < 0xffff && ranges[i][1] === 0xffff) { + ranges[i][1] = 0xfffe; + } + const trailingRangesCount = ranges[i][1] < 0xffff ? 1 : 0; + const segCount = bmpLength + trailingRangesCount; + const searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); + let startCount = ""; + let endCount = ""; + let idDeltas = ""; + let idRangeOffsets = ""; + let glyphsIds = ""; + let bias = 0; + let range, start, end, codes; + for (i = 0, ii = bmpLength; i < ii; i++) { + range = ranges[i]; + start = range[0]; + end = range[1]; + startCount += string16(start); + endCount += string16(end); + codes = range[2]; + let contiguous = true; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + const offset = (segCount - i) * 2 + bias * 2; + bias += end - start + 1; + idDeltas += string16(0); + idRangeOffsets += string16(offset); + for (j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + const startCode = codes[0]; + idDeltas += string16(startCode - start & 0xffff); + idRangeOffsets += string16(0); + } + } + if (trailingRangesCount > 0) { + endCount += "\xFF\xFF"; + startCount += "\xFF\xFF"; + idDeltas += "\x00\x01"; + idRangeOffsets += "\x00\x00"; + } + const format314 = "\x00\x00" + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + "\x00\x00" + startCount + idDeltas + idRangeOffsets + glyphsIds; + let format31012 = ""; + let header31012 = ""; + if (numTables > 1) { + cmap += "\x00\x03" + "\x00\x0A" + string32(4 + numTables * 8 + 4 + format314.length); + format31012 = ""; + for (i = 0, ii = ranges.length; i < ii; i++) { + range = ranges[i]; + start = range[0]; + codes = range[2]; + let code = codes[0]; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + end = range[0] + j - 1; + format31012 += string32(start) + string32(end) + string32(code); + start = end + 1; + code = codes[j]; + } + } + format31012 += string32(start) + string32(range[1]) + string32(code); + } + header31012 = "\x00\x0C" + "\x00\x00" + string32(format31012.length + 16) + "\x00\x00\x00\x00" + string32(format31012.length / 12); + } + return cmap + "\x00\x04" + string16(format314.length + 4) + format314 + header31012 + format31012; +} +function validateOS2Table(os2, file) { + file.pos = (file.start || 0) + os2.offset; + const version = file.getUint16(); + file.skip(60); + const selection = file.getUint16(); + if (version < 4 && selection & 0x0300) { + return false; + } + const firstChar = file.getUint16(); + const lastChar = file.getUint16(); + if (firstChar > lastChar) { + return false; + } + file.skip(6); + const usWinAscent = file.getUint16(); + if (usWinAscent === 0) { + return false; + } + os2.data[8] = os2.data[9] = 0; + return true; +} +function createOS2Table(properties, charstrings, override) { + override ||= { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + let ulUnicodeRange1 = 0; + let ulUnicodeRange2 = 0; + let ulUnicodeRange3 = 0; + let ulUnicodeRange4 = 0; + let firstCharIndex = null; + let lastCharIndex = 0; + let position = -1; + if (charstrings) { + for (let code in charstrings) { + code |= 0; + if (firstCharIndex > code || !firstCharIndex) { + firstCharIndex = code; + } + if (lastCharIndex < code) { + lastCharIndex = code; + } + position = getUnicodeRangeFor(code, position); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + throw new FormatError("Unicode ranges Bits > 123 are reserved for internal usage"); + } + } + if (lastCharIndex > 0xffff) { + lastCharIndex = 0xffff; + } + } else { + firstCharIndex = 0; + lastCharIndex = 255; + } + const bbox = properties.bbox || [0, 0, 0, 0]; + const unitsPerEm = override.unitsPerEm || (properties.fontMatrix ? 1 / Math.max(...properties.fontMatrix.slice(0, 4).map(Math.abs)) : 1000); + const scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS; + const typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3])); + let typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1])); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; + } + const winAscent = override.yMax || typoAscent; + const winDescent = -override.yMin || -typoDescent; + return "\x00\x03" + "\x02\x24" + "\x01\xF4" + "\x00\x05" + "\x00\x00" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x00\x8C" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x01\xDF" + "\x00\x31" + "\x01\x02" + "\x00\x00" + "\x00\x00\x06" + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + "\x00\x00\x00\x00\x00\x00" + string32(ulUnicodeRange1) + string32(ulUnicodeRange2) + string32(ulUnicodeRange3) + string32(ulUnicodeRange4) + "\x2A\x32\x31\x2A" + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + "\x00\x64" + string16(winAscent) + string16(winDescent) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + "\x00\x03"; +} +function createPostTable(properties) { + const angle = Math.floor(properties.italicAngle * 2 ** 16); + return "\x00\x03\x00\x00" + string32(angle) + "\x00\x00" + "\x00\x00" + string32(properties.fixedPitch ? 1 : 0) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00"; +} +function createPostscriptName(name) { + return name.replaceAll(/[^\x21-\x7E]|[[\](){}<>/%]/g, "").slice(0, 63); +} +function createNameTable(name, proto) { + if (!proto) { + proto = [[], []]; + } + const strings = [proto[0][0] || "Original licence", proto[0][1] || name, proto[0][2] || "Unknown", proto[0][3] || "uniqueID", proto[0][4] || name, proto[0][5] || "Version 0.11", proto[0][6] || createPostscriptName(name), proto[0][7] || "Unknown", proto[0][8] || "Unknown", proto[0][9] || "Unknown"]; + const stringsUnicode = []; + let i, ii, j, jj, str; + for (i = 0, ii = strings.length; i < ii; i++) { + str = proto[1][i] || strings[i]; + const strBufUnicode = []; + for (j = 0, jj = str.length; j < jj; j++) { + strBufUnicode.push(string16(str.charCodeAt(j))); + } + stringsUnicode.push(strBufUnicode.join("")); + } + const names = [strings, stringsUnicode]; + const platforms = ["\x00\x01", "\x00\x03"]; + const encodings = ["\x00\x00", "\x00\x01"]; + const languages = ["\x00\x00", "\x04\x09"]; + const namesRecordCount = strings.length * platforms.length; + let nameTable = "\x00\x00" + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6); + let strOffset = 0; + for (i = 0, ii = platforms.length; i < ii; i++) { + const strs = names[i]; + for (j = 0, jj = strs.length; j < jj; j++) { + str = strs[j]; + const nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + nameTable += strings.join("") + stringsUnicode.join(""); + return nameTable; +} +class Font { + constructor(name, file, properties, evaluatorOptions) { + this.name = name; + this.psName = null; + this.mimetype = null; + this.disableFontFace = evaluatorOptions.disableFontFace; + this.fontExtraProperties = evaluatorOptions.fontExtraProperties; + this.loadedName = properties.loadedName; + this.isType3Font = properties.isType3Font; + this.missingFile = false; + this.cssFontInfo = properties.cssFontInfo; + this._charsCache = Object.create(null); + this._glyphCache = Object.create(null); + let isSerifFont = !!(properties.flags & FontFlags.Serif); + if (!isSerifFont && !properties.isSimulatedFlags) { + const stdFontMap = getStdFontMap(), + nonStdFontMap = getNonStdFontMap(), + serifFonts = getSerifFonts(); + for (const namePart of name.split("+")) { + let fontName = namePart.replaceAll(/[,_]/g, "-"); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + fontName = fontName.split("-", 1)[0]; + if (serifFonts[fontName]) { + isSerifFont = true; + break; + } + } + } + this.isSerifFont = isSerifFont; + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + let { + type, + subtype + } = properties; + this.type = type; + this.subtype = subtype; + this.systemFontInfo = properties.systemFontInfo; + const matches = name.match(/^InvalidPDFjsFont_(.*)_\d+$/); + this.isInvalidPDFjsFont = !!matches; + if (this.isInvalidPDFjsFont) { + this.fallbackName = matches[1]; + } else if (this.isMonospace) { + this.fallbackName = "monospace"; + } else if (this.isSerifFont) { + this.fallbackName = "serif"; + } else { + this.fallbackName = "sans-serif"; + } + if (this.systemFontInfo?.guessFallback) { + this.systemFontInfo.guessFallback = false; + this.systemFontInfo.css += `,${this.fallbackName}`; + } + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.cMap = properties.cMap; + this.capHeight = properties.capHeight / PDF_GLYPH_SPACE_UNITS; + this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; + this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; + this.lineHeight = this.ascent - this.descent; + this.fontMatrix = properties.fontMatrix; + this.bbox = properties.bbox; + this.defaultEncoding = properties.defaultEncoding; + this.toUnicode = properties.toUnicode; + this.toFontChar = []; + if (properties.type === "Type3") { + for (let charCode = 0; charCode < 256; charCode++) { + this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode]; + } + return; + } + this.cidEncoding = properties.cidEncoding || ""; + this.vertical = !!properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + if (!file || file.isEmpty) { + if (file) { + warn('Font file is empty in "' + name + '" (' + this.loadedName + ")"); + } + this.fallbackToSystemFont(properties); + return; + } + [type, subtype] = getFontFileType(file, properties); + if (type !== this.type || subtype !== this.subtype) { + info("Inconsistent font file Type/SubType, expected: " + `${this.type}/${this.subtype} but found: ${type}/${subtype}.`); + } + let data; + try { + switch (type) { + case "MMType1": + info("MMType1 font (" + name + "), falling back to Type1."); + case "Type1": + case "CIDFontType0": + this.mimetype = "font/opentype"; + const cff = subtype === "Type1C" || subtype === "CIDFontType0C" ? new CFFFont(file, properties) : new Type1Font(name, file, properties); + adjustWidths(properties); + data = this.convert(name, cff, properties); + break; + case "OpenType": + case "TrueType": + case "CIDFontType2": + this.mimetype = "font/opentype"; + data = this.checkAndRepair(name, file, properties); + adjustWidths(properties); + if (this.isOpenType) { + type = "OpenType"; + } + break; + default: + throw new FormatError(`Font ${type} is not supported`); + } + } catch (e) { + warn(e); + this.fallbackToSystemFont(properties); + return; + } + amendFallbackToUnicode(properties); + this.data = data; + this.type = type; + this.subtype = subtype; + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.toUnicode = properties.toUnicode; + this.seacMap = properties.seacMap; + } + get renderer() { + const renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED); + return shadow(this, "renderer", renderer); + } + exportData() { + const data = Object.create(null); + for (const prop of EXPORT_DATA_PROPERTIES) { + const value = this[prop]; + if (value !== undefined) { + data[prop] = value; + } + } + if (!this.fontExtraProperties) { + return { + data + }; + } + const extra = Object.create(null); + for (const prop of EXPORT_DATA_EXTRA_PROPERTIES) { + const value = this[prop]; + if (value !== undefined) { + extra[prop] = value; + } + } + return { + data, + extra + }; + } + fallbackToSystemFont(properties) { + this.missingFile = true; + const { + name, + type + } = this; + let fontName = normalizeFontName(name); + const stdFontMap = getStdFontMap(), + nonStdFontMap = getNonStdFontMap(); + const isStandardFont = !!stdFontMap[fontName]; + const isMappedToStandardFont = !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + const fontBasicMetricsMap = getFontBasicMetrics(); + const metrics = fontBasicMetricsMap[fontName]; + if (metrics) { + if (isNaN(this.ascent)) { + this.ascent = metrics.ascent / PDF_GLYPH_SPACE_UNITS; + } + if (isNaN(this.descent)) { + this.descent = metrics.descent / PDF_GLYPH_SPACE_UNITS; + } + if (isNaN(this.capHeight)) { + this.capHeight = metrics.capHeight / PDF_GLYPH_SPACE_UNITS; + } + } + this.bold = /bold/gi.test(fontName); + this.italic = /oblique|italic/gi.test(fontName); + this.black = /Black/g.test(name); + const isNarrow = /Narrow/g.test(name); + this.remeasure = (!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0; + if ((isStandardFont || isMappedToStandardFont) && type === "CIDFontType2" && this.cidEncoding.startsWith("Identity-")) { + const cidToGidMap = properties.cidToGidMap; + const map = []; + applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts()); + if (/Arial-?Black/i.test(name)) { + applyStandardFontGlyphMap(map, getSupplementalGlyphMapForArialBlack()); + } else if (/Calibri/i.test(name)) { + applyStandardFontGlyphMap(map, getSupplementalGlyphMapForCalibri()); + } + if (cidToGidMap) { + for (const charCode in map) { + const cid = map[charCode]; + if (cidToGidMap[cid] !== undefined) { + map[+charCode] = cidToGidMap[cid]; + } + } + if (cidToGidMap.length !== this.toUnicode.length && properties.hasIncludedToUnicodeMap && this.toUnicode instanceof IdentityToUnicodeMap) { + this.toUnicode.forEach(function (charCode, unicodeCharCode) { + const cid = map[charCode]; + if (cidToGidMap[cid] === undefined) { + map[+charCode] = unicodeCharCode; + } + }); + } + } + if (!(this.toUnicode instanceof IdentityToUnicodeMap)) { + this.toUnicode.forEach(function (charCode, unicodeCharCode) { + map[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map; + this.toUnicode = new ToUnicodeMap(map); + } else if (/Symbol/i.test(fontName)) { + this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), this.differences); + } else if (/Dingbats/i.test(fontName)) { + this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), this.differences); + } else if (isStandardFont || isMappedToStandardFont) { + const map = buildToFontChar(this.defaultEncoding, getGlyphsUnicode(), this.differences); + if (type === "CIDFontType2" && !this.cidEncoding.startsWith("Identity-") && !(this.toUnicode instanceof IdentityToUnicodeMap)) { + this.toUnicode.forEach(function (charCode, unicodeCharCode) { + map[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map; + } else { + const glyphsUnicodeMap = getGlyphsUnicode(); + const map = []; + this.toUnicode.forEach((charCode, unicodeCharCode) => { + if (!this.composite) { + const glyphName = this.differences[charCode] || this.defaultEncoding[charCode]; + const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + unicodeCharCode = unicode; + } + } + map[+charCode] = unicodeCharCode; + }); + if (this.composite && this.toUnicode instanceof IdentityToUnicodeMap) { + if (/Tahoma|Verdana/i.test(name)) { + applyStandardFontGlyphMap(map, getGlyphMapForStandardFonts()); + } + } + this.toFontChar = map; + } + amendFallbackToUnicode(properties); + this.loadedName = fontName.split("-", 1)[0]; + } + checkAndRepair(name, font, properties) { + const VALID_TABLES = ["OS/2", "cmap", "head", "hhea", "hmtx", "maxp", "name", "post", "loca", "glyf", "fpgm", "prep", "cvt ", "CFF "]; + function readTables(file, numTables) { + const tables = Object.create(null); + tables["OS/2"] = null; + tables.cmap = null; + tables.head = null; + tables.hhea = null; + tables.hmtx = null; + tables.maxp = null; + tables.name = null; + tables.post = null; + for (let i = 0; i < numTables; i++) { + const table = readTableEntry(file); + if (!VALID_TABLES.includes(table.tag)) { + continue; + } + if (table.length === 0) { + continue; + } + tables[table.tag] = table; + } + return tables; + } + function readTableEntry(file) { + const tag = file.getString(4); + const checksum = file.getInt32() >>> 0; + const offset = file.getInt32() >>> 0; + const length = file.getInt32() >>> 0; + const previousPosition = file.pos; + file.pos = file.start || 0; + file.skip(offset); + const data = file.getBytes(length); + file.pos = previousPosition; + if (tag === "head") { + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 0x20; + } + return { + tag, + checksum, + length, + offset, + data + }; + } + function readOpenTypeHeader(ttf) { + return { + version: ttf.getString(4), + numTables: ttf.getUint16(), + searchRange: ttf.getUint16(), + entrySelector: ttf.getUint16(), + rangeShift: ttf.getUint16() + }; + } + function readTrueTypeCollectionHeader(ttc) { + const ttcTag = ttc.getString(4); + assert(ttcTag === "ttcf", "Must be a TrueType Collection font."); + const majorVersion = ttc.getUint16(); + const minorVersion = ttc.getUint16(); + const numFonts = ttc.getInt32() >>> 0; + const offsetTable = []; + for (let i = 0; i < numFonts; i++) { + offsetTable.push(ttc.getInt32() >>> 0); + } + const header = { + ttcTag, + majorVersion, + minorVersion, + numFonts, + offsetTable + }; + switch (majorVersion) { + case 1: + return header; + case 2: + header.dsigTag = ttc.getInt32() >>> 0; + header.dsigLength = ttc.getInt32() >>> 0; + header.dsigOffset = ttc.getInt32() >>> 0; + return header; + } + throw new FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`); + } + function readTrueTypeCollectionData(ttc, fontName) { + const { + numFonts, + offsetTable + } = readTrueTypeCollectionHeader(ttc); + const fontNameParts = fontName.split("+"); + let fallbackData; + for (let i = 0; i < numFonts; i++) { + ttc.pos = (ttc.start || 0) + offsetTable[i]; + const potentialHeader = readOpenTypeHeader(ttc); + const potentialTables = readTables(ttc, potentialHeader.numTables); + if (!potentialTables.name) { + throw new FormatError('TrueType Collection font must contain a "name" table.'); + } + const [nameTable] = readNameTable(potentialTables.name); + for (let j = 0, jj = nameTable.length; j < jj; j++) { + for (let k = 0, kk = nameTable[j].length; k < kk; k++) { + const nameEntry = nameTable[j][k]?.replaceAll(/\s/g, ""); + if (!nameEntry) { + continue; + } + if (nameEntry === fontName) { + return { + header: potentialHeader, + tables: potentialTables + }; + } + if (fontNameParts.length < 2) { + continue; + } + for (const part of fontNameParts) { + if (nameEntry === part) { + fallbackData = { + name: part, + header: potentialHeader, + tables: potentialTables + }; + } + } + } + } + } + if (fallbackData) { + warn(`TrueType Collection does not contain "${fontName}" font, ` + `falling back to "${fallbackData.name}" font instead.`); + return { + header: fallbackData.header, + tables: fallbackData.tables + }; + } + throw new FormatError(`TrueType Collection does not contain "${fontName}" font.`); + } + function readCmapTable(cmap, file, isSymbolicFont, hasEncoding) { + if (!cmap) { + warn("No cmap table available."); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + let segment; + let start = (file.start || 0) + cmap.offset; + file.pos = start; + file.skip(2); + const numTables = file.getUint16(); + let potentialTable; + let canBreak = false; + for (let i = 0; i < numTables; i++) { + const platformId = file.getUint16(); + const encodingId = file.getUint16(); + const offset = file.getInt32() >>> 0; + let useTable = false; + if (potentialTable?.platformId === platformId && potentialTable?.encodingId === encodingId) { + continue; + } + if (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 3)) { + useTable = true; + } else if (platformId === 1 && encodingId === 0) { + useTable = true; + } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) { + useTable = true; + if (!isSymbolicFont) { + canBreak = true; + } + } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { + useTable = true; + let correctlySorted = true; + if (i < numTables - 1) { + const nextBytes = file.peekBytes(2), + nextPlatformId = int16(nextBytes[0], nextBytes[1]); + if (nextPlatformId < platformId) { + correctlySorted = false; + } + } + if (correctlySorted) { + canBreak = true; + } + } + if (useTable) { + potentialTable = { + platformId, + encodingId, + offset + }; + } + if (canBreak) { + break; + } + } + if (potentialTable) { + file.pos = start + potentialTable.offset; + } + if (!potentialTable || file.peekByte() === -1) { + warn("Could not find a preferred cmap table."); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + const format = file.getUint16(); + let hasShortCmap = false; + const mappings = []; + let j, glyphId; + if (format === 0) { + file.skip(2 + 2); + for (j = 0; j < 256; j++) { + const index = file.getByte(); + if (!index) { + continue; + } + mappings.push({ + charCode: j, + glyphId: index + }); + } + hasShortCmap = true; + } else if (format === 2) { + file.skip(2 + 2); + const subHeaderKeys = []; + let maxSubHeaderKey = 0; + for (let i = 0; i < 256; i++) { + const subHeaderKey = file.getUint16() >> 3; + subHeaderKeys.push(subHeaderKey); + maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey); + } + const subHeaders = []; + for (let i = 0; i <= maxSubHeaderKey; i++) { + subHeaders.push({ + firstCode: file.getUint16(), + entryCount: file.getUint16(), + idDelta: signedInt16(file.getByte(), file.getByte()), + idRangePos: file.pos + file.getUint16() + }); + } + for (let i = 0; i < 256; i++) { + if (subHeaderKeys[i] === 0) { + file.pos = subHeaders[0].idRangePos + 2 * i; + glyphId = file.getUint16(); + mappings.push({ + charCode: i, + glyphId + }); + } else { + const s = subHeaders[subHeaderKeys[i]]; + for (j = 0; j < s.entryCount; j++) { + const charCode = (i << 8) + j + s.firstCode; + file.pos = s.idRangePos + 2 * j; + glyphId = file.getUint16(); + if (glyphId !== 0) { + glyphId = (glyphId + s.idDelta) % 65536; + } + mappings.push({ + charCode, + glyphId + }); + } + } + } + } else if (format === 4) { + file.skip(2 + 2); + const segCount = file.getUint16() >> 1; + file.skip(6); + const segments = []; + let segIndex; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ + end: file.getUint16() + }); + } + file.skip(2); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = file.getUint16(); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = file.getUint16(); + } + let offsetsCount = 0, + offsetIndex; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + const rangeOffset = file.getUint16(); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1); + } + const offsets = []; + for (j = 0; j < offsetsCount; j++) { + offsets.push(file.getUint16()); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + start = segment.start; + const end = segment.end; + const delta = segment.delta; + offsetIndex = segment.offsetIndex; + for (j = start; j <= end; j++) { + if (j === 0xffff) { + continue; + } + glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start]; + glyphId = glyphId + delta & 0xffff; + mappings.push({ + charCode: j, + glyphId + }); + } + } + } else if (format === 6) { + file.skip(2 + 2); + const firstCode = file.getUint16(); + const entryCount = file.getUint16(); + for (j = 0; j < entryCount; j++) { + glyphId = file.getUint16(); + const charCode = firstCode + j; + mappings.push({ + charCode, + glyphId + }); + } + } else if (format === 12) { + file.skip(2 + 4 + 4); + const nGroups = file.getInt32() >>> 0; + for (j = 0; j < nGroups; j++) { + const startCharCode = file.getInt32() >>> 0; + const endCharCode = file.getInt32() >>> 0; + let glyphCode = file.getInt32() >>> 0; + for (let charCode = startCharCode; charCode <= endCharCode; charCode++) { + mappings.push({ + charCode, + glyphId: glyphCode++ + }); + } + } + } else { + warn("cmap table has unsupported format: " + format); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + mappings.sort((a, b) => a.charCode - b.charCode); + const finalMappings = [], + seenCharCodes = new Set(); + for (const map of mappings) { + const { + charCode + } = map; + if (seenCharCodes.has(charCode)) { + continue; + } + seenCharCodes.add(charCode); + finalMappings.push(map); + } + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + mappings: finalMappings, + hasShortCmap + }; + } + function sanitizeMetrics(file, header, metrics, headTable, numGlyphs, dupFirstEntry) { + if (!header) { + if (metrics) { + metrics.data = null; + } + return; + } + file.pos = (file.start || 0) + header.offset; + file.pos += 4; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + file.pos += 2; + const caretOffset = file.getUint16(); + file.pos += 8; + file.pos += 2; + let numOfMetrics = file.getUint16(); + if (caretOffset !== 0) { + const macStyle = int16(headTable.data[44], headTable.data[45]); + if (!(macStyle & 2)) { + header.data[22] = 0; + header.data[23] = 0; + } + } + if (numOfMetrics > numGlyphs) { + info(`The numOfMetrics (${numOfMetrics}) should not be ` + `greater than the numGlyphs (${numGlyphs}).`); + numOfMetrics = numGlyphs; + header.data[34] = (numOfMetrics & 0xff00) >> 8; + header.data[35] = numOfMetrics & 0x00ff; + } + const numOfSidebearings = numGlyphs - numOfMetrics; + const numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1); + if (numMissing > 0) { + const entries = new Uint8Array(metrics.length + numMissing * 2); + entries.set(metrics.data); + if (dupFirstEntry) { + entries[metrics.length] = metrics.data[2]; + entries[metrics.length + 1] = metrics.data[3]; + } + metrics.data = entries; + } + } + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) { + const glyphProfile = { + length: 0, + sizeOfInstructions: 0 + }; + if (sourceStart < 0 || sourceStart >= source.length || sourceEnd > source.length || sourceEnd - sourceStart <= 12) { + return glyphProfile; + } + const glyf = source.subarray(sourceStart, sourceEnd); + const xMin = signedInt16(glyf[2], glyf[3]); + const yMin = signedInt16(glyf[4], glyf[5]); + const xMax = signedInt16(glyf[6], glyf[7]); + const yMax = signedInt16(glyf[8], glyf[9]); + if (xMin > xMax) { + writeSignedInt16(glyf, 2, xMax); + writeSignedInt16(glyf, 6, xMin); + } + if (yMin > yMax) { + writeSignedInt16(glyf, 4, yMax); + writeSignedInt16(glyf, 8, yMin); + } + const contoursCount = signedInt16(glyf[0], glyf[1]); + if (contoursCount < 0) { + if (contoursCount < -1) { + return glyphProfile; + } + dest.set(glyf, destStart); + glyphProfile.length = glyf.length; + return glyphProfile; + } + let i, + j = 10, + flagsCount = 0; + for (i = 0; i < contoursCount; i++) { + const endPoint = glyf[j] << 8 | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + const instructionsStart = j; + const instructionsLength = glyf[j] << 8 | glyf[j + 1]; + glyphProfile.sizeOfInstructions = instructionsLength; + j += 2 + instructionsLength; + const instructionsEnd = j; + let coordinatesLength = 0; + for (i = 0; i < flagsCount; i++) { + const flag = glyf[j++]; + if (flag & 0xc0) { + glyf[j - 1] = flag & 0x3f; + } + let xLength = 2; + if (flag & 2) { + xLength = 1; + } else if (flag & 16) { + xLength = 0; + } + let yLength = 2; + if (flag & 4) { + yLength = 1; + } else if (flag & 32) { + yLength = 0; + } + const xyLength = xLength + yLength; + coordinatesLength += xyLength; + if (flag & 8) { + const repeat = glyf[j++]; + if (repeat === 0) { + glyf[j - 1] ^= 8; + } + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + if (coordinatesLength === 0) { + return glyphProfile; + } + let glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + return glyphProfile; + } + if (!hintsValid && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([0, 0], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + } + glyphProfile.length = glyphDataLength; + return glyphProfile; + } + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + glyphProfile.length = glyphDataLength; + return glyphProfile; + } + dest.set(glyf, destStart); + glyphProfile.length = glyf.length; + return glyphProfile; + } + function sanitizeHead(head, numGlyphs, locaLength) { + const data = head.data; + const version = int32(data[0], data[1], data[2], data[3]); + if (version >> 16 !== 1) { + info("Attempting to fix invalid version in head table: " + version); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + const indexToLocFormat = int16(data[50], data[51]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info("Attempting to fix invalid indexToLocFormat in head table: " + indexToLocFormat); + const numGlyphsPlusOne = numGlyphs + 1; + if (locaLength === numGlyphsPlusOne << 1) { + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + data[50] = 0; + data[51] = 1; + } else { + throw new FormatError("Could not fix indexToLocFormat: " + indexToLocFormat); + } + } + } + function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) { + let itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = value >>> 24 & 0xff; + data[offset + 1] = value >> 16 & 0xff; + data[offset + 2] = value >> 8 & 0xff; + data[offset + 3] = value & 0xff; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return data[offset] << 9 | data[offset + 1] << 1; + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = value >> 9 & 0xff; + data[offset + 1] = value >> 1 & 0xff; + }; + } + const numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs; + const locaDataSize = itemSize * (1 + numGlyphsOut); + const locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + const oldGlyfData = glyf.data; + const oldGlyfDataLength = oldGlyfData.length; + const newGlyfData = new Uint8Array(oldGlyfDataLength); + let i, j; + const locaEntries = []; + for (i = 0, j = 0; i < numGlyphs + 1; i++, j += itemSize) { + let offset = itemDecode(locaData, j); + if (offset > oldGlyfDataLength) { + offset = oldGlyfDataLength; + } + locaEntries.push({ + index: i, + offset, + endOffset: 0 + }); + } + locaEntries.sort((a, b) => a.offset - b.offset); + for (i = 0; i < numGlyphs; i++) { + locaEntries[i].endOffset = locaEntries[i + 1].offset; + } + locaEntries.sort((a, b) => a.index - b.index); + for (i = 0; i < numGlyphs; i++) { + const { + offset, + endOffset + } = locaEntries[i]; + if (offset !== 0 || endOffset !== 0) { + break; + } + const nextOffset = locaEntries[i + 1].offset; + if (nextOffset === 0) { + continue; + } + locaEntries[i].endOffset = nextOffset; + break; + } + const last = locaEntries.at(-2); + if (last.offset !== 0 && last.endOffset === 0) { + last.endOffset = oldGlyfDataLength; + } + const missingGlyphs = Object.create(null); + let writeOffset = 0; + itemEncode(locaData, 0, writeOffset); + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + const glyphProfile = sanitizeGlyph(oldGlyfData, locaEntries[i].offset, locaEntries[i].endOffset, newGlyfData, writeOffset, hintsValid); + const newLength = glyphProfile.length; + if (newLength === 0) { + missingGlyphs[i] = true; + } + if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) { + maxSizeOfInstructions = glyphProfile.sizeOfInstructions; + } + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + } + if (writeOffset === 0) { + const simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); + for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) { + itemEncode(locaData, j, simpleGlyph.length); + } + glyf.data = simpleGlyph; + } else if (dupFirstEntry) { + const firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + return { + missingGlyphs, + maxSizeOfInstructions + }; + } + function readPostScriptTable(post, propertiesObj, maxpNumGlyphs) { + const start = (font.start || 0) + post.offset; + font.pos = start; + const length = post.length, + end = start + length; + const version = font.getInt32(); + font.skip(28); + let glyphNames; + let valid = true; + let i; + switch (version) { + case 0x00010000: + glyphNames = MacStandardGlyphOrdering; + break; + case 0x00020000: + const numGlyphs = font.getUint16(); + if (numGlyphs !== maxpNumGlyphs) { + valid = false; + break; + } + const glyphNameIndexes = []; + for (i = 0; i < numGlyphs; ++i) { + const index = font.getUint16(); + if (index >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index); + } + if (!valid) { + break; + } + const customNames = [], + strBuf = []; + while (font.pos < end) { + const stringLength = font.getByte(); + strBuf.length = stringLength; + for (i = 0; i < stringLength; ++i) { + strBuf[i] = String.fromCharCode(font.getByte()); + } + customNames.push(strBuf.join("")); + } + glyphNames = []; + for (i = 0; i < numGlyphs; ++i) { + const j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 0x00030000: + break; + default: + warn("Unknown/unsupported post table version " + version); + valid = false; + if (propertiesObj.defaultEncoding) { + glyphNames = propertiesObj.defaultEncoding; + } + break; + } + propertiesObj.glyphNames = glyphNames; + return valid; + } + function readNameTable(nameTable) { + const start = (font.start || 0) + nameTable.offset; + font.pos = start; + const names = [[], []], + records = []; + const length = nameTable.length, + end = start + length; + const format = font.getUint16(); + const FORMAT_0_HEADER_LENGTH = 6; + if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { + return [names, records]; + } + const numRecords = font.getUint16(); + const stringsStart = font.getUint16(); + const NAME_RECORD_LENGTH = 12; + let i, ii; + for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) { + const r = { + platform: font.getUint16(), + encoding: font.getUint16(), + language: font.getUint16(), + name: font.getUint16(), + length: font.getUint16(), + offset: font.getUint16() + }; + if (isMacNameRecord(r) || isWinNameRecord(r)) { + records.push(r); + } + } + for (i = 0, ii = records.length; i < ii; i++) { + const record = records[i]; + if (record.length <= 0) { + continue; + } + const pos = start + stringsStart + record.offset; + if (pos + record.length > end) { + continue; + } + font.pos = pos; + const nameIndex = record.name; + if (record.encoding) { + let str = ""; + for (let j = 0, jj = record.length; j < jj; j += 2) { + str += String.fromCharCode(font.getUint16()); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = font.getString(record.length); + } + } + return [names, records]; + } + const TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; + function sanitizeTTProgram(table, ttContext) { + let data = table.data; + let i = 0, + j, + n, + b, + funcId, + pc, + lastEndf = 0, + lastDeff = 0; + const stack = []; + const callstack = []; + const functionsCalled = []; + let tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions; + let inFDEF = false, + ifLevel = 0, + inELSE = 0; + for (let ii = data.length; i < ii;) { + const op = data[i++]; + if (op === 0x40) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 0x41) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push(b << 8 | data[i++]); + } + } + } else if ((op & 0xf8) === 0xb0) { + n = op - 0xb0 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 0xf8) === 0xb8) { + n = op - 0xb8 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push(signedInt16(b, data[i++])); + } + } + } else if (op === 0x2b && !tooComplexToFollowFunctions) { + if (!inFDEF && !inELSE) { + funcId = stack.at(-1); + if (isNaN(funcId)) { + info("TT: CALL empty stack (or invalid entry)."); + } else { + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + const newStackLength = stack.length + ttContext.functionsStackDeltas[funcId]; + if (newStackLength < 0) { + warn("TT: CALL invalid functions stack delta."); + ttContext.hintsValid = false; + return; + } + stack.length = newStackLength; + } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) { + callstack.push({ + data, + i, + stackTop: stack.length - 1 + }); + functionsCalled.push(funcId); + pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn("TT: CALL non-existent function"); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } + } else if (op === 0x2c && !tooComplexToFollowFunctions) { + if (inFDEF || inELSE) { + warn("TT: nested FDEFs not allowed"); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + funcId = stack.pop(); + ttContext.functionsDefined[funcId] = { + data, + i + }; + } else if (op === 0x2d) { + if (inFDEF) { + inFDEF = false; + lastEndf = i; + } else { + pc = callstack.pop(); + if (!pc) { + warn("TT: ENDF bad stack"); + ttContext.hintsValid = false; + return; + } + funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop; + } + } else if (op === 0x89) { + if (inFDEF || inELSE) { + warn("TT: nested IDEFs not allowed"); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + } else if (op === 0x58) { + ++ifLevel; + } else if (op === 0x1b) { + inELSE = ifLevel; + } else if (op === 0x59) { + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 0x1c) { + if (!inFDEF && !inELSE) { + const offset = stack.at(-1); + if (offset > 0) { + i += offset - 1; + } + } + } + if (!inFDEF && !inELSE) { + let stackDelta = 0; + if (op <= 0x8e) { + stackDelta = TTOpsStackDeltas[op]; + } else if (op >= 0xc0 && op <= 0xdf) { + stackDelta = -1; + } else if (op >= 0xe0) { + stackDelta = -2; + } + if (op >= 0x71 && op <= 0x75) { + n = stack.pop(); + if (!isNaN(n)) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + const content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn("TT: complementing a missing function tail"); + content.push(new Uint8Array([0x22, 0x2d])); + } + foldTTTable(table, content); + } + function checkInvalidFunctions(ttContext, maxFunctionDefs) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + if (ttContext.functionsDefined.length > maxFunctionDefs) { + warn("TT: more functions defined than expected"); + ttContext.hintsValid = false; + return; + } + for (let j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs) { + warn("TT: invalid function id: " + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn("TT: undefined function: " + j); + ttContext.hintsValid = false; + return; + } + } + } + function foldTTTable(table, content) { + if (content.length > 1) { + let newLength = 0; + let j, jj; + for (j = 0, jj = content.length; j < jj; j++) { + newLength += content[j].length; + } + newLength = newLength + 3 & ~3; + const result = new Uint8Array(newLength); + let pos = 0; + for (j = 0, jj = content.length; j < jj; j++) { + result.set(content[j], pos); + pos += content[j].length; + } + table.data = result; + table.length = newLength; + } + } + function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) { + const ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + if (cvt && cvt.length & 1) { + const cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + font = new Stream(new Uint8Array(font.getBytes())); + let header, tables; + if (isTrueTypeCollectionFile(font)) { + const ttcData = readTrueTypeCollectionData(font, this.name); + header = ttcData.header; + tables = ttcData.tables; + } else { + header = readOpenTypeHeader(font); + tables = readTables(font, header.numTables); + } + let cff, cffFile; + const isTrueType = !tables["CFF "]; + if (!isTrueType) { + const isComposite = properties.composite && (properties.cidToGidMap?.length > 0 || !(properties.cMap instanceof IdentityCMap)); + if (header.version === "OTTO" && !isComposite || !tables.head || !tables.hhea || !tables.maxp || !tables.post) { + cffFile = new Stream(tables["CFF "].data); + cff = new CFFFont(cffFile, properties); + return this.convert(name, cff, properties); + } + delete tables.glyf; + delete tables.loca; + delete tables.fpgm; + delete tables.prep; + delete tables["cvt "]; + this.isOpenType = true; + } else { + if (!tables.loca) { + throw new FormatError('Required "loca" table is not found'); + } + if (!tables.glyf) { + warn('Required "glyf" table is not found -- trying to recover.'); + tables.glyf = { + tag: "glyf", + data: new Uint8Array(0) + }; + } + this.isOpenType = false; + } + if (!tables.maxp) { + throw new FormatError('Required "maxp" table is not found'); + } + font.pos = (font.start || 0) + tables.maxp.offset; + let version = font.getInt32(); + const numGlyphs = font.getUint16(); + if (version !== 0x00010000 && version !== 0x00005000) { + if (tables.maxp.length === 6) { + version = 0x0005000; + } else if (tables.maxp.length >= 32) { + version = 0x00010000; + } else { + throw new FormatError(`"maxp" table has a wrong version number`); + } + writeUint32(tables.maxp.data, 0, version); + } + if (properties.scaleFactors?.length === numGlyphs && isTrueType) { + const { + scaleFactors + } = properties; + const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); + const glyphs = new GlyfTable({ + glyfTable: tables.glyf.data, + isGlyphLocationsLong, + locaTable: tables.loca.data, + numGlyphs + }); + glyphs.scale(scaleFactors); + const { + glyf, + loca, + isLocationLong + } = glyphs.write(); + tables.glyf.data = glyf; + tables.loca.data = loca; + if (isLocationLong !== !!isGlyphLocationsLong) { + tables.head.data[50] = 0; + tables.head.data[51] = isLocationLong ? 1 : 0; + } + const metrics = tables.hmtx.data; + for (let i = 0; i < numGlyphs; i++) { + const j = 4 * i; + const advanceWidth = Math.round(scaleFactors[i] * int16(metrics[j], metrics[j + 1])); + metrics[j] = advanceWidth >> 8 & 0xff; + metrics[j + 1] = advanceWidth & 0xff; + const lsb = Math.round(scaleFactors[i] * signedInt16(metrics[j + 2], metrics[j + 3])); + writeSignedInt16(metrics, j + 2, lsb); + } + } + let numGlyphsOut = numGlyphs + 1; + let dupFirstEntry = true; + if (numGlyphsOut > 0xffff) { + dupFirstEntry = false; + numGlyphsOut = numGlyphs; + warn("Not enough space in glyfs to duplicate first glyph."); + } + let maxFunctionDefs = 0; + let maxSizeOfInstructions = 0; + if (version >= 0x00010000 && tables.maxp.length >= 32) { + font.pos += 8; + const maxZones = font.getUint16(); + if (maxZones > 2) { + tables.maxp.data[14] = 0; + tables.maxp.data[15] = 2; + } + font.pos += 4; + maxFunctionDefs = font.getUint16(); + font.pos += 4; + maxSizeOfInstructions = font.getUint16(); + } + tables.maxp.data[4] = numGlyphsOut >> 8; + tables.maxp.data[5] = numGlyphsOut & 255; + const hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, tables["cvt "], maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + delete tables["cvt "]; + } + sanitizeMetrics(font, tables.hhea, tables.hmtx, tables.head, numGlyphsOut, dupFirstEntry); + if (!tables.head) { + throw new FormatError('Required "head" table is not found'); + } + sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); + let missingGlyphs = Object.create(null); + if (isTrueType) { + const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); + const glyphsInfo = sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions); + missingGlyphs = glyphsInfo.missingGlyphs; + if (version >= 0x00010000 && tables.maxp.length >= 32) { + tables.maxp.data[26] = glyphsInfo.maxSizeOfInstructions >> 8; + tables.maxp.data[27] = glyphsInfo.maxSizeOfInstructions & 255; + } + } + if (!tables.hhea) { + throw new FormatError('Required "hhea" table is not found'); + } + if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { + tables.hhea.data[10] = 0xff; + tables.hhea.data[11] = 0xff; + } + const metricsOverride = { + unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), + yMax: signedInt16(tables.head.data[42], tables.head.data[43]), + yMin: signedInt16(tables.head.data[38], tables.head.data[39]), + ascent: signedInt16(tables.hhea.data[4], tables.hhea.data[5]), + descent: signedInt16(tables.hhea.data[6], tables.hhea.data[7]), + lineGap: signedInt16(tables.hhea.data[8], tables.hhea.data[9]) + }; + this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm; + this.descent = metricsOverride.descent / metricsOverride.unitsPerEm; + this.lineGap = metricsOverride.lineGap / metricsOverride.unitsPerEm; + if (this.cssFontInfo?.lineHeight) { + this.lineHeight = this.cssFontInfo.metrics.lineHeight; + this.lineGap = this.cssFontInfo.metrics.lineGap; + } else { + this.lineHeight = this.ascent - this.descent + this.lineGap; + } + if (tables.post) { + readPostScriptTable(tables.post, properties, numGlyphs); + } + tables.post = { + tag: "post", + data: createPostTable(properties) + }; + const charCodeToGlyphId = Object.create(null); + function hasGlyph(glyphId) { + return !missingGlyphs[glyphId]; + } + if (properties.composite) { + const cidToGidMap = properties.cidToGidMap || []; + const isCidToGidMapEmpty = cidToGidMap.length === 0; + properties.cMap.forEach(function (charCode, cid) { + if (typeof cid === "string") { + cid = convertCidString(charCode, cid, true); + } + if (cid > 0xffff) { + throw new FormatError("Max size of CID is 65,535"); + } + let glyphId = -1; + if (isCidToGidMapEmpty) { + glyphId = cid; + } else if (cidToGidMap[cid] !== undefined) { + glyphId = cidToGidMap[cid]; + } + if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) { + charCodeToGlyphId[charCode] = glyphId; + } + }); + } else { + const cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont, properties.hasEncoding); + const cmapPlatformId = cmapTable.platformId; + const cmapEncodingId = cmapTable.encodingId; + const cmapMappings = cmapTable.mappings; + let baseEncoding = [], + forcePostTable = false; + if (properties.hasEncoding && (properties.baseEncodingName === "MacRomanEncoding" || properties.baseEncodingName === "WinAnsiEncoding")) { + baseEncoding = getEncoding(properties.baseEncodingName); + } + if (properties.hasEncoding && !this.isSymbolicFont && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0)) { + const glyphsUnicodeMap = getGlyphsUnicode(); + for (let charCode = 0; charCode < 256; charCode++) { + let glyphName; + if (this.differences[charCode] !== undefined) { + glyphName = this.differences[charCode]; + } else if (baseEncoding.length && baseEncoding[charCode] !== "") { + glyphName = baseEncoding[charCode]; + } else { + glyphName = StandardEncoding[charCode]; + } + if (!glyphName) { + continue; + } + const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + let unicodeOrCharCode; + if (cmapPlatformId === 3 && cmapEncodingId === 1) { + unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; + } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { + unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName); + } + if (unicodeOrCharCode === undefined) { + if (!properties.glyphNames && properties.hasIncludedToUnicodeMap && !(this.toUnicode instanceof IdentityToUnicodeMap)) { + const unicode = this.toUnicode.get(charCode); + if (unicode) { + unicodeOrCharCode = unicode.codePointAt(0); + } + } + if (unicodeOrCharCode === undefined) { + continue; + } + } + for (const mapping of cmapMappings) { + if (mapping.charCode !== unicodeOrCharCode) { + continue; + } + charCodeToGlyphId[charCode] = mapping.glyphId; + break; + } + } + } else if (cmapPlatformId === 0) { + for (const mapping of cmapMappings) { + charCodeToGlyphId[mapping.charCode] = mapping.glyphId; + } + forcePostTable = true; + } else if (cmapPlatformId === 3 && cmapEncodingId === 0) { + for (const mapping of cmapMappings) { + let charCode = mapping.charCode; + if (charCode >= 0xf000 && charCode <= 0xf0ff) { + charCode &= 0xff; + } + charCodeToGlyphId[charCode] = mapping.glyphId; + } + } else { + for (const mapping of cmapMappings) { + charCodeToGlyphId[mapping.charCode] = mapping.glyphId; + } + } + if (properties.glyphNames && (baseEncoding.length || this.differences.length)) { + for (let i = 0; i < 256; ++i) { + if (!forcePostTable && charCodeToGlyphId[i] !== undefined) { + continue; + } + const glyphName = this.differences[i] || baseEncoding[i]; + if (!glyphName) { + continue; + } + const glyphId = properties.glyphNames.indexOf(glyphName); + if (glyphId > 0 && hasGlyph(glyphId)) { + charCodeToGlyphId[i] = glyphId; + } + } + } + } + if (charCodeToGlyphId.length === 0) { + charCodeToGlyphId[0] = 0; + } + let glyphZeroId = numGlyphsOut - 1; + if (!dupFirstEntry) { + glyphZeroId = 0; + } + if (!properties.cssFontInfo) { + const newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId, this.toUnicode); + this.toFontChar = newMapping.toFontChar; + tables.cmap = { + tag: "cmap", + data: createCmapTable(newMapping.charCodeToGlyphId, newMapping.toUnicodeExtraMap, numGlyphsOut) + }; + if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) { + tables["OS/2"] = { + tag: "OS/2", + data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride) + }; + } + } + if (!isTrueType) { + try { + cffFile = new Stream(tables["CFF "].data); + const parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED); + cff = parser.parse(); + cff.duplicateFirstGlyph(); + const compiler = new CFFCompiler(cff); + tables["CFF "].data = compiler.compile(); + } catch { + warn("Failed to compile font " + properties.loadedName); + } + } + if (!tables.name) { + tables.name = { + tag: "name", + data: createNameTable(this.name) + }; + } else { + const [namePrototype, nameRecords] = readNameTable(tables.name); + tables.name.data = createNameTable(name, namePrototype); + this.psName = namePrototype[0][6] || null; + if (!properties.composite) { + adjustTrueTypeToUnicode(properties, this.isSymbolicFont, nameRecords); + } + } + const builder = new OpenTypeFileBuilder(header.version); + for (const tableTag in tables) { + builder.addTable(tableTag, tables[tableTag].data); + } + return builder.toArray(); + } + convert(fontName, font, properties) { + properties.fixedPitch = false; + if (properties.builtInEncoding) { + adjustType1ToUnicode(properties, properties.builtInEncoding); + } + let glyphZeroId = 1; + if (font instanceof CFFFont) { + glyphZeroId = font.numGlyphs - 1; + } + const mapping = font.getGlyphMapping(properties); + let newMapping = null; + let newCharCodeToGlyphId = mapping; + let toUnicodeExtraMap = null; + if (!properties.cssFontInfo) { + newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId, this.toUnicode); + this.toFontChar = newMapping.toFontChar; + newCharCodeToGlyphId = newMapping.charCodeToGlyphId; + toUnicodeExtraMap = newMapping.toUnicodeExtraMap; + } + const numGlyphs = font.numGlyphs; + function getCharCodes(charCodeToGlyphId, glyphId) { + let charCodes = null; + for (const charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + (charCodes ||= []).push(charCode | 0); + } + } + return charCodes; + } + function createCharCode(charCodeToGlyphId, glyphId) { + for (const charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + return charCode | 0; + } + } + newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId; + return newMapping.nextAvailableFontCharCode++; + } + const seacs = font.seacs; + if (newMapping && SEAC_ANALYSIS_ENABLED && seacs?.length) { + const matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX; + const charset = font.getCharset(); + const seacMap = Object.create(null); + for (let glyphId in seacs) { + glyphId |= 0; + const seac = seacs[glyphId]; + const baseGlyphName = StandardEncoding[seac[2]]; + const accentGlyphName = StandardEncoding[seac[3]]; + const baseGlyphId = charset.indexOf(baseGlyphName); + const accentGlyphId = charset.indexOf(accentGlyphName); + if (baseGlyphId < 0 || accentGlyphId < 0) { + continue; + } + const accentOffset = { + x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], + y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] + }; + const charCodes = getCharCodes(mapping, glyphId); + if (!charCodes) { + continue; + } + for (const charCode of charCodes) { + const charCodeToGlyphId = newMapping.charCodeToGlyphId; + const baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId); + const accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId); + seacMap[charCode] = { + baseFontCharCode, + accentFontCharCode, + accentOffset + }; + } + } + properties.seacMap = seacMap; + } + const unitsPerEm = properties.fontMatrix ? 1 / Math.max(...properties.fontMatrix.slice(0, 4).map(Math.abs)) : 1000; + const builder = new OpenTypeFileBuilder("\x4F\x54\x54\x4F"); + builder.addTable("CFF ", font.data); + builder.addTable("OS/2", createOS2Table(properties, newCharCodeToGlyphId)); + builder.addTable("cmap", createCmapTable(newCharCodeToGlyphId, toUnicodeExtraMap, numGlyphs)); + builder.addTable("head", "\x00\x01\x00\x00" + "\x00\x00\x10\x00" + "\x00\x00\x00\x00" + "\x5F\x0F\x3C\xF5" + "\x00\x00" + safeString16(unitsPerEm) + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00" + safeString16(properties.descent) + "\x0F\xFF" + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + "\x00\x11" + "\x00\x00" + "\x00\x00" + "\x00\x00"); + builder.addTable("hhea", "\x00\x01\x00\x00" + safeString16(properties.ascent) + safeString16(properties.descent) + "\x00\x00" + "\xFF\xFF" + "\x00\x00" + "\x00\x00" + "\x00\x00" + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + string16(numGlyphs)); + builder.addTable("hmtx", function fontFieldsHmtx() { + const charstrings = font.charstrings; + const cffWidths = font.cff ? font.cff.widths : null; + let hmtx = "\x00\x00\x00\x00"; + for (let i = 1, ii = numGlyphs; i < ii; i++) { + let width = 0; + if (charstrings) { + const charstring = charstrings[i - 1]; + width = "width" in charstring ? charstring.width : 0; + } else if (cffWidths) { + width = Math.ceil(cffWidths[i] || 0); + } + hmtx += string16(width) + string16(0); + } + return hmtx; + }()); + builder.addTable("maxp", "\x00\x00\x50\x00" + string16(numGlyphs)); + builder.addTable("name", createNameTable(fontName)); + builder.addTable("post", createPostTable(properties)); + return builder.toArray(); + } + get _spaceWidth() { + const possibleSpaceReplacements = ["space", "minus", "one", "i", "I"]; + let width; + for (const glyphName of possibleSpaceReplacements) { + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + const glyphsUnicodeMap = getGlyphsUnicode(); + const glyphUnicode = glyphsUnicodeMap[glyphName]; + let charcode = 0; + if (this.composite && this.cMap.contains(glyphUnicode)) { + charcode = this.cMap.lookup(glyphUnicode); + if (typeof charcode === "string") { + charcode = convertCidString(glyphUnicode, charcode); + } + } + if (!charcode && this.toUnicode) { + charcode = this.toUnicode.charCodeOf(glyphUnicode); + } + if (charcode <= 0) { + charcode = glyphUnicode; + } + width = this.widths[charcode]; + if (width) { + break; + } + } + return shadow(this, "_spaceWidth", width || this.defaultWidth); + } + _charToGlyph(charcode, isSpace = false) { + let glyph = this._glyphCache[charcode]; + if (glyph?.isSpace === isSpace) { + return glyph; + } + let fontCharCode, width, operatorListId; + let widthCode = charcode; + if (this.cMap?.contains(charcode)) { + widthCode = this.cMap.lookup(charcode); + if (typeof widthCode === "string") { + widthCode = convertCidString(charcode, widthCode); + } + } + width = this.widths[widthCode]; + if (typeof width !== "number") { + width = this.defaultWidth; + } + const vmetric = this.vmetrics?.[widthCode]; + let unicode = this.toUnicode.get(charcode) || charcode; + if (typeof unicode === "number") { + unicode = String.fromCharCode(unicode); + } + let isInFont = this.toFontChar[charcode] !== undefined; + fontCharCode = this.toFontChar[charcode] || charcode; + if (this.missingFile) { + const glyphName = this.differences[charcode] || this.defaultEncoding[charcode]; + if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") { + fontCharCode = 0x20; + if (glyphName === "") { + width ||= this._spaceWidth; + unicode = String.fromCharCode(fontCharCode); + } + } + fontCharCode = mapSpecialUnicodeValues(fontCharCode); + } + if (this.isType3Font) { + operatorListId = fontCharCode; + } + let accent = null; + if (this.seacMap?.[charcode]) { + isInFont = true; + const seac = this.seacMap[charcode]; + fontCharCode = seac.baseFontCharCode; + accent = { + fontChar: String.fromCodePoint(seac.accentFontCharCode), + offset: seac.accentOffset + }; + } + let fontChar = ""; + if (typeof fontCharCode === "number") { + if (fontCharCode <= 0x10ffff) { + fontChar = String.fromCodePoint(fontCharCode); + } else { + warn(`charToGlyph - invalid fontCharCode: ${fontCharCode}`); + } + } + if (this.missingFile && this.vertical && fontChar.length === 1) { + const vertical = getVerticalPresentationForm()[fontChar.charCodeAt(0)]; + if (vertical) { + fontChar = unicode = String.fromCharCode(vertical); + } + } + glyph = new fonts_Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont); + return this._glyphCache[charcode] = glyph; + } + charsToGlyphs(chars) { + let glyphs = this._charsCache[chars]; + if (glyphs) { + return glyphs; + } + glyphs = []; + if (this.cMap) { + const c = Object.create(null), + ii = chars.length; + let i = 0; + while (i < ii) { + this.cMap.readCharCode(chars, i, c); + const { + charcode, + length + } = c; + i += length; + const glyph = this._charToGlyph(charcode, length === 1 && chars.charCodeAt(i - 1) === 0x20); + glyphs.push(glyph); + } + } else { + for (let i = 0, ii = chars.length; i < ii; ++i) { + const charcode = chars.charCodeAt(i); + const glyph = this._charToGlyph(charcode, charcode === 0x20); + glyphs.push(glyph); + } + } + return this._charsCache[chars] = glyphs; + } + getCharPositions(chars) { + const positions = []; + if (this.cMap) { + const c = Object.create(null); + let i = 0; + while (i < chars.length) { + this.cMap.readCharCode(chars, i, c); + const length = c.length; + positions.push([i, i + length]); + i += length; + } + } else { + for (let i = 0, ii = chars.length; i < ii; ++i) { + positions.push([i, i + 1]); + } + } + return positions; + } + get glyphCacheValues() { + return Object.values(this._glyphCache); + } + encodeString(str) { + const buffers = []; + const currentBuf = []; + const hasCurrentBufErrors = () => buffers.length % 2 === 1; + const getCharCode = this.toUnicode instanceof IdentityToUnicodeMap ? unicode => this.toUnicode.charCodeOf(unicode) : unicode => this.toUnicode.charCodeOf(String.fromCodePoint(unicode)); + for (let i = 0, ii = str.length; i < ii; i++) { + const unicode = str.codePointAt(i); + if (unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)) { + i++; + } + if (this.toUnicode) { + const charCode = getCharCode(unicode); + if (charCode !== -1) { + if (hasCurrentBufErrors()) { + buffers.push(currentBuf.join("")); + currentBuf.length = 0; + } + const charCodeLength = this.cMap ? this.cMap.getCharCodeLength(charCode) : 1; + for (let j = charCodeLength - 1; j >= 0; j--) { + currentBuf.push(String.fromCharCode(charCode >> 8 * j & 0xff)); + } + continue; + } + } + if (!hasCurrentBufErrors()) { + buffers.push(currentBuf.join("")); + currentBuf.length = 0; + } + currentBuf.push(String.fromCodePoint(unicode)); + } + buffers.push(currentBuf.join("")); + return buffers; + } +} +class ErrorFont { + constructor(error) { + this.error = error; + this.loadedName = "g_font_error"; + this.missingFile = true; + } + charsToGlyphs() { + return []; + } + encodeString(chars) { + return [chars]; + } + exportData() { + return { + error: this.error + }; + } +} + +;// ./src/shared/obj-bin-transform.js + +class CssFontInfo { + #buffer; + #view; + #decoder; + static strings = ["fontFamily", "fontWeight", "italicAngle"]; + static write(info) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encoder.encode(info[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + const buffer = new ArrayBuffer(stringsLength); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + assert(offset === buffer.byteLength, "CssFontInfo.write: Buffer overflow"); + return buffer; + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + #readString(index) { + assert(index < CssFontInfo.strings.length, "Invalid string index"); + let offset = 0; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get fontFamily() { + return this.#readString(0); + } + get fontWeight() { + return this.#readString(1); + } + get italicAngle() { + return this.#readString(2); + } +} +class SystemFontInfo { + #buffer; + #view; + #decoder; + static strings = ["css", "loadedName", "baseFontName", "src"]; + static write(info) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encoder.encode(info[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + stringsLength += 4; + let encodedStyleStyle, + encodedStyleWeight, + lengthEstimate = 1 + stringsLength; + if (info.style) { + encodedStyleStyle = encoder.encode(info.style.style); + encodedStyleWeight = encoder.encode(info.style.weight); + lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length; + } + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + view.setUint8(offset++, info.guessFallback ? 1 : 0); + view.setUint32(offset, 0); + offset += 4; + stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + stringsLength += 4 + length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(offset - stringsLength - 4, stringsLength); + if (info.style) { + view.setUint32(offset, encodedStyleStyle.length); + data.set(encodedStyleStyle, offset + 4); + offset += 4 + encodedStyleStyle.length; + view.setUint32(offset, encodedStyleWeight.length); + data.set(encodedStyleWeight, offset + 4); + offset += 4 + encodedStyleWeight.length; + } + assert(offset <= buffer.byteLength, "SubstitionInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + get guessFallback() { + return this.#view.getUint8(0) !== 0; + } + #readString(index) { + assert(index < SystemFontInfo.strings.length, "Invalid string index"); + let offset = 5; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get css() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get baseFontName() { + return this.#readString(2); + } + get src() { + return this.#readString(3); + } + get style() { + let offset = 1; + offset += 4 + this.#view.getUint32(offset); + const styleLength = this.#view.getUint32(offset); + const style = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, styleLength)); + offset += 4 + styleLength; + const weightLength = this.#view.getUint32(offset); + const weight = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, weightLength)); + return { + style, + weight + }; + } +} +class FontInfo { + static bools = ["black", "bold", "disableFontFace", "fontExtraProperties", "isInvalidPDFjsFont", "isType3Font", "italic", "missingFile", "remeasure", "vertical"]; + static numbers = ["ascent", "defaultWidth", "descent"]; + static strings = ["fallbackName", "loadedName", "mimetype", "name"]; + static #OFFSET_NUMBERS = Math.ceil(this.bools.length * 2 / 8); + static #OFFSET_BBOX = this.#OFFSET_NUMBERS + this.numbers.length * 8; + static #OFFSET_FONT_MATRIX = this.#OFFSET_BBOX + 1 + 2 * 4; + static #OFFSET_DEFAULT_VMETRICS = this.#OFFSET_FONT_MATRIX + 1 + 8 * 6; + static #OFFSET_STRINGS = this.#OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3; + #buffer; + #decoder; + #view; + constructor({ + data, + extra + }) { + this.#buffer = data; + this.#decoder = new TextDecoder(); + this.#view = new DataView(this.#buffer); + if (extra) { + Object.assign(this, extra); + } + } + #readBoolean(index) { + assert(index < FontInfo.bools.length, "Invalid boolean index"); + const byteOffset = Math.floor(index / 4); + const bitOffset = index * 2 % 8; + const value = this.#view.getUint8(byteOffset) >> bitOffset & 0x03; + return value === 0x00 ? undefined : value === 0x02; + } + get black() { + return this.#readBoolean(0); + } + get bold() { + return this.#readBoolean(1); + } + get disableFontFace() { + return this.#readBoolean(2); + } + get fontExtraProperties() { + return this.#readBoolean(3); + } + get isInvalidPDFjsFont() { + return this.#readBoolean(4); + } + get isType3Font() { + return this.#readBoolean(5); + } + get italic() { + return this.#readBoolean(6); + } + get missingFile() { + return this.#readBoolean(7); + } + get remeasure() { + return this.#readBoolean(8); + } + get vertical() { + return this.#readBoolean(9); + } + #readNumber(index) { + assert(index < FontInfo.numbers.length, "Invalid number index"); + return this.#view.getFloat64(FontInfo.#OFFSET_NUMBERS + index * 8); + } + get ascent() { + return this.#readNumber(0); + } + get defaultWidth() { + return this.#readNumber(1); + } + get descent() { + return this.#readNumber(2); + } + get bbox() { + let offset = FontInfo.#OFFSET_BBOX; + const numCoords = this.#view.getUint8(offset); + if (numCoords === 0) { + return undefined; + } + offset += 1; + const bbox = []; + for (let i = 0; i < 4; i++) { + bbox.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return bbox; + } + get fontMatrix() { + let offset = FontInfo.#OFFSET_FONT_MATRIX; + const numPoints = this.#view.getUint8(offset); + if (numPoints === 0) { + return undefined; + } + offset += 1; + const fontMatrix = []; + for (let i = 0; i < 6; i++) { + fontMatrix.push(this.#view.getFloat64(offset, true)); + offset += 8; + } + return fontMatrix; + } + get defaultVMetrics() { + let offset = FontInfo.#OFFSET_DEFAULT_VMETRICS; + const numMetrics = this.#view.getUint8(offset); + if (numMetrics === 0) { + return undefined; + } + offset += 1; + const defaultVMetrics = []; + for (let i = 0; i < 3; i++) { + defaultVMetrics.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return defaultVMetrics; + } + #readString(index) { + assert(index < FontInfo.strings.length, "Invalid string index"); + let offset = FontInfo.#OFFSET_STRINGS + 4; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + const stringData = new Uint8Array(length); + stringData.set(new Uint8Array(this.#buffer, offset + 4, length)); + return this.#decoder.decode(stringData); + } + get fallbackName() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get mimetype() { + return this.#readString(2); + } + get name() { + return this.#readString(3); + } + get data() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + if (length === 0) { + return undefined; + } + return new Uint8Array(this.#buffer, offset + 4, length); + } + clearData() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + const data = new Uint8Array(this.#buffer, offset + 4, length); + data.fill(0); + this.#view.setUint32(offset, 0); + } + get cssFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + if (cssFontInfoLength === 0) { + return null; + } + const cssFontInfoData = new Uint8Array(cssFontInfoLength); + cssFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength)); + return new CssFontInfo(cssFontInfoData.buffer); + } + get systemFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + if (systemFontInfoLength === 0) { + return null; + } + const systemFontInfoData = new Uint8Array(systemFontInfoLength); + systemFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength)); + return new SystemFontInfo(systemFontInfoData.buffer); + } + static write(font) { + const systemFontInfoBuffer = font.systemFontInfo ? SystemFontInfo.write(font.systemFontInfo) : null; + const cssFontInfoBuffer = font.cssFontInfo ? CssFontInfo.write(font.cssFontInfo) : null; + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of FontInfo.strings) { + encodedStrings[prop] = encoder.encode(font[prop]); + stringsLength += 4 + encodedStrings[prop].length; + } + const lengthEstimate = FontInfo.#OFFSET_STRINGS + 4 + stringsLength + 4 + (systemFontInfoBuffer ? systemFontInfoBuffer.byteLength : 0) + 4 + (cssFontInfoBuffer ? cssFontInfoBuffer.byteLength : 0) + 4 + (font.data ? font.data.length : 0); + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + const numBools = FontInfo.bools.length; + let boolByte = 0, + boolBit = 0; + for (let i = 0; i < numBools; i++) { + const value = font[FontInfo.bools[i]]; + const bits = value === undefined ? 0x00 : value ? 0x02 : 0x01; + boolByte |= bits << boolBit; + boolBit += 2; + if (boolBit === 8 || i === numBools - 1) { + view.setUint8(offset++, boolByte); + boolByte = 0; + boolBit = 0; + } + } + assert(offset === FontInfo.#OFFSET_NUMBERS, "FontInfo.write: Boolean properties offset mismatch"); + for (const prop of FontInfo.numbers) { + view.setFloat64(offset, font[prop]); + offset += 8; + } + assert(offset === FontInfo.#OFFSET_BBOX, "FontInfo.write: Number properties offset mismatch"); + if (font.bbox) { + view.setUint8(offset++, 4); + for (const coord of font.bbox) { + view.setInt16(offset, coord, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 2 * 4; + } + assert(offset === FontInfo.#OFFSET_FONT_MATRIX, "FontInfo.write: BBox properties offset mismatch"); + if (font.fontMatrix) { + view.setUint8(offset++, 6); + for (const point of font.fontMatrix) { + view.setFloat64(offset, point, true); + offset += 8; + } + } else { + view.setUint8(offset++, 0); + offset += 8 * 6; + } + assert(offset === FontInfo.#OFFSET_DEFAULT_VMETRICS, "FontInfo.write: FontMatrix properties offset mismatch"); + if (font.defaultVMetrics) { + view.setUint8(offset++, 1); + for (const metric of font.defaultVMetrics) { + view.setInt16(offset, metric, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 3 * 2; + } + assert(offset === FontInfo.#OFFSET_STRINGS, "FontInfo.write: DefaultVMetrics properties offset mismatch"); + view.setUint32(FontInfo.#OFFSET_STRINGS, 0); + offset += 4; + for (const prop of FontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(FontInfo.#OFFSET_STRINGS, offset - FontInfo.#OFFSET_STRINGS - 4); + if (!systemFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = systemFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at systemFontInfo"); + data.set(new Uint8Array(systemFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (!cssFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = cssFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at cssFontInfo"); + data.set(new Uint8Array(cssFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (font.data === undefined) { + view.setUint32(offset, 0); + offset += 4; + } else { + view.setUint32(offset, font.data.length); + data.set(font.data, offset + 4); + offset += 4 + font.data.length; + } + assert(offset <= buffer.byteLength, "FontInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } +} +class PatternInfo { + static #KIND = 0; + static #HAS_BBOX = 1; + static #HAS_BACKGROUND = 2; + static #SHADING_TYPE = 3; + static #N_COORD = 4; + static #N_COLOR = 8; + static #N_STOP = 12; + static #N_FIGURES = 16; + constructor(buffer) { + this.buffer = buffer; + this.view = new DataView(buffer); + this.data = new Uint8Array(buffer); + } + static write(ir) { + let kind, + bbox = null, + coords = [], + colors = [], + colorStops = [], + figures = [], + shadingType = null, + background = null; + switch (ir[0]) { + case "RadialAxial": + kind = ir[1] === "axial" ? 1 : 2; + bbox = ir[2]; + colorStops = ir[3]; + if (kind === 1) { + coords.push(...ir[4], ...ir[5]); + } else { + coords.push(ir[4][0], ir[4][1], ir[6], ir[5][0], ir[5][1], ir[7]); + } + break; + case "Mesh": + kind = 3; + shadingType = ir[1]; + coords = ir[2]; + colors = ir[3]; + figures = ir[4] || []; + bbox = ir[6]; + background = ir[7]; + break; + default: + throw new Error(`Unsupported pattern type: ${ir[0]}`); + } + const nCoord = Math.floor(coords.length / 2); + const nColor = Math.floor(colors.length / 3); + const nStop = colorStops.length; + const nFigures = figures.length; + let figuresSize = 0; + for (const figure of figures) { + figuresSize += 1; + figuresSize = Math.ceil(figuresSize / 4) * 4; + figuresSize += 4 + figure.coords.length * 4; + figuresSize += 4 + figure.colors.length * 4; + if (figure.verticesPerRow !== undefined) { + figuresSize += 4; + } + } + const byteLen = 20 + nCoord * 8 + nColor * 3 + nStop * 8 + (bbox ? 16 : 0) + (background ? 3 : 0) + figuresSize; + const buffer = new ArrayBuffer(byteLen); + const dataView = new DataView(buffer); + const u8data = new Uint8Array(buffer); + dataView.setUint8(PatternInfo.#KIND, kind); + dataView.setUint8(PatternInfo.#HAS_BBOX, bbox ? 1 : 0); + dataView.setUint8(PatternInfo.#HAS_BACKGROUND, background ? 1 : 0); + dataView.setUint8(PatternInfo.#SHADING_TYPE, shadingType); + dataView.setUint32(PatternInfo.#N_COORD, nCoord, true); + dataView.setUint32(PatternInfo.#N_COLOR, nColor, true); + dataView.setUint32(PatternInfo.#N_STOP, nStop, true); + dataView.setUint32(PatternInfo.#N_FIGURES, nFigures, true); + let offset = 20; + const coordsView = new Float32Array(buffer, offset, nCoord * 2); + coordsView.set(coords); + offset += nCoord * 8; + u8data.set(colors, offset); + offset += nColor * 3; + for (const [pos, hex] of colorStops) { + dataView.setFloat32(offset, pos, true); + offset += 4; + dataView.setUint32(offset, parseInt(hex.slice(1), 16), true); + offset += 4; + } + if (bbox) { + for (const v of bbox) { + dataView.setFloat32(offset, v, true); + offset += 4; + } + } + if (background) { + u8data.set(background, offset); + offset += 3; + } + for (let i = 0; i < figures.length; i++) { + const figure = figures[i]; + dataView.setUint8(offset, figure.type); + offset += 1; + offset = Math.ceil(offset / 4) * 4; + dataView.setUint32(offset, figure.coords.length, true); + offset += 4; + const figureCoordsView = new Int32Array(buffer, offset, figure.coords.length); + figureCoordsView.set(figure.coords); + offset += figure.coords.length * 4; + dataView.setUint32(offset, figure.colors.length, true); + offset += 4; + const colorsView = new Int32Array(buffer, offset, figure.colors.length); + colorsView.set(figure.colors); + offset += figure.colors.length * 4; + if (figure.verticesPerRow !== undefined) { + dataView.setUint32(offset, figure.verticesPerRow, true); + offset += 4; + } + } + return buffer; + } + getIR() { + const dataView = this.view; + const kind = this.data[PatternInfo.#KIND]; + const hasBBox = !!this.data[PatternInfo.#HAS_BBOX]; + const hasBackground = !!this.data[PatternInfo.#HAS_BACKGROUND]; + const nCoord = dataView.getUint32(PatternInfo.#N_COORD, true); + const nColor = dataView.getUint32(PatternInfo.#N_COLOR, true); + const nStop = dataView.getUint32(PatternInfo.#N_STOP, true); + const nFigures = dataView.getUint32(PatternInfo.#N_FIGURES, true); + let offset = 20; + const coords = new Float32Array(this.buffer, offset, nCoord * 2); + offset += nCoord * 8; + const colors = new Uint8Array(this.buffer, offset, nColor * 3); + offset += nColor * 3; + const stops = []; + for (let i = 0; i < nStop; ++i) { + const p = dataView.getFloat32(offset, true); + offset += 4; + const rgb = dataView.getUint32(offset, true); + offset += 4; + stops.push([p, `#${rgb.toString(16).padStart(6, "0")}`]); + } + let bbox = null; + if (hasBBox) { + bbox = []; + for (let i = 0; i < 4; ++i) { + bbox.push(dataView.getFloat32(offset, true)); + offset += 4; + } + } + let background = null; + if (hasBackground) { + background = new Uint8Array(this.buffer, offset, 3); + offset += 3; + } + const figures = []; + for (let i = 0; i < nFigures; ++i) { + const type = dataView.getUint8(offset); + offset += 1; + offset = Math.ceil(offset / 4) * 4; + const coordsLength = dataView.getUint32(offset, true); + offset += 4; + const figureCoords = new Int32Array(this.buffer, offset, coordsLength); + offset += coordsLength * 4; + const colorsLength = dataView.getUint32(offset, true); + offset += 4; + const figureColors = new Int32Array(this.buffer, offset, colorsLength); + offset += colorsLength * 4; + const figure = { + type, + coords: figureCoords, + colors: figureColors + }; + if (type === MeshFigureType.LATTICE) { + figure.verticesPerRow = dataView.getUint32(offset, true); + offset += 4; + } + figures.push(figure); + } + if (kind === 1) { + return ["RadialAxial", "axial", bbox, stops, Array.from(coords.slice(0, 2)), Array.from(coords.slice(2, 4)), null, null]; + } + if (kind === 2) { + return ["RadialAxial", "radial", bbox, stops, [coords[0], coords[1]], [coords[3], coords[4]], coords[2], coords[5]]; + } + if (kind === 3) { + const shadingType = this.data[PatternInfo.#SHADING_TYPE]; + let bounds = null; + if (coords.length > 0) { + let minX = coords[0], + maxX = coords[0]; + let minY = coords[1], + maxY = coords[1]; + for (let i = 0; i < coords.length; i += 2) { + const x = coords[i], + y = coords[i + 1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + bounds = [minX, minY, maxX, maxY]; + } + return ["Mesh", shadingType, coords, colors, figures, bounds, bbox, background]; + } + throw new Error(`Unsupported pattern kind: ${kind}`); + } +} + +;// ./src/core/pattern.js + + + + +const ShadingType = { + FUNCTION_BASED: 1, + AXIAL: 2, + RADIAL: 3, + FREE_FORM_MESH: 4, + LATTICE_FORM_MESH: 5, + COONS_PATCH_MESH: 6, + TENSOR_PATCH_MESH: 7 +}; +class Pattern { + constructor() { + unreachable("Cannot initialize Pattern."); + } + static parseShading(shading, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + const dict = shading instanceof BaseStream ? shading.dict : shading; + const type = dict.get("ShadingType"); + try { + switch (type) { + case ShadingType.AXIAL: + case ShadingType.RADIAL: + return new RadialAxialShading(dict, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache); + case ShadingType.FREE_FORM_MESH: + case ShadingType.LATTICE_FORM_MESH: + case ShadingType.COONS_PATCH_MESH: + case ShadingType.TENSOR_PATCH_MESH: + return new MeshShading(shading, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache); + default: + throw new FormatError("Unsupported ShadingType: " + type); + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(ex); + return new DummyShading(); + } + } +} +class BaseShading { + static SMALL_NUMBER = 1e-6; + getIR() { + unreachable("Abstract method `getIR` called."); + } +} +class RadialAxialShading extends BaseShading { + constructor(dict, xref, resources, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + super(); + this.shadingType = dict.get("ShadingType"); + let coordsLen = 0; + if (this.shadingType === ShadingType.AXIAL) { + coordsLen = 4; + } else if (this.shadingType === ShadingType.RADIAL) { + coordsLen = 6; + } + this.coordsArr = dict.getArray("Coords"); + if (!isNumberArray(this.coordsArr, coordsLen)) { + throw new FormatError("RadialAxialShading: Invalid /Coords array."); + } + const cs = ColorSpaceUtils.parse({ + cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.bbox = lookupNormalRect(dict.getArray("BBox"), null); + let t0 = 0.0, + t1 = 1.0; + const domainArr = dict.getArray("Domain"); + if (isNumberArray(domainArr, 2)) { + [t0, t1] = domainArr; + } + let extendStart = false, + extendEnd = false; + const extendArr = dict.getArray("Extend"); + if (isBooleanArray(extendArr, 2)) { + [extendStart, extendEnd] = extendArr; + } + if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) { + const [x1, y1, r1, x2, y2, r2] = this.coordsArr; + const distance = Math.hypot(x1 - x2, y1 - y2); + if (r1 <= r2 + distance && r2 <= r1 + distance) { + warn("Unsupported radial gradient."); + } + } + this.extendStart = extendStart; + this.extendEnd = extendEnd; + const fnObj = dict.getRaw("Function"); + const fn = pdfFunctionFactory.create(fnObj, true); + const NUMBER_OF_SAMPLES = 840; + const step = (t1 - t0) / NUMBER_OF_SAMPLES; + const colorStops = this.colorStops = []; + if (t0 >= t1 || step <= 0) { + info("Bad shading domain."); + return; + } + const color = new Float32Array(cs.numComps), + ratio = new Float32Array(1); + let iBase = 0; + ratio[0] = t0; + fn(ratio, 0, color, 0); + const rgbBuffer = new Uint8ClampedArray(3); + cs.getRgb(color, 0, rgbBuffer); + let [rBase, gBase, bBase] = rgbBuffer; + colorStops.push([0, Util.makeHexColor(rBase, gBase, bBase)]); + let iPrev = 1; + ratio[0] = t0 + step; + fn(ratio, 0, color, 0); + cs.getRgb(color, 0, rgbBuffer); + let [rPrev, gPrev, bPrev] = rgbBuffer; + let maxSlopeR = rPrev - rBase + 1; + let maxSlopeG = gPrev - gBase + 1; + let maxSlopeB = bPrev - bBase + 1; + let minSlopeR = rPrev - rBase - 1; + let minSlopeG = gPrev - gBase - 1; + let minSlopeB = bPrev - bBase - 1; + for (let i = 2; i < NUMBER_OF_SAMPLES; i++) { + ratio[0] = t0 + i * step; + fn(ratio, 0, color, 0); + cs.getRgb(color, 0, rgbBuffer); + const [r, g, b] = rgbBuffer; + const run = i - iBase; + maxSlopeR = Math.min(maxSlopeR, (r - rBase + 1) / run); + maxSlopeG = Math.min(maxSlopeG, (g - gBase + 1) / run); + maxSlopeB = Math.min(maxSlopeB, (b - bBase + 1) / run); + minSlopeR = Math.max(minSlopeR, (r - rBase - 1) / run); + minSlopeG = Math.max(minSlopeG, (g - gBase - 1) / run); + minSlopeB = Math.max(minSlopeB, (b - bBase - 1) / run); + const slopesExist = minSlopeR <= maxSlopeR && minSlopeG <= maxSlopeG && minSlopeB <= maxSlopeB; + if (!slopesExist) { + const cssColor = Util.makeHexColor(rPrev, gPrev, bPrev); + colorStops.push([iPrev / NUMBER_OF_SAMPLES, cssColor]); + maxSlopeR = r - rPrev + 1; + maxSlopeG = g - gPrev + 1; + maxSlopeB = b - bPrev + 1; + minSlopeR = r - rPrev - 1; + minSlopeG = g - gPrev - 1; + minSlopeB = b - bPrev - 1; + iBase = iPrev; + rBase = rPrev; + gBase = gPrev; + bBase = bPrev; + } + iPrev = i; + rPrev = r; + gPrev = g; + bPrev = b; + } + colorStops.push([1, Util.makeHexColor(rPrev, gPrev, bPrev)]); + let background = "transparent"; + if (dict.has("Background")) { + background = cs.getRgbHex(dict.get("Background"), 0); + } + if (!extendStart) { + colorStops.unshift([0, background]); + colorStops[1][0] += BaseShading.SMALL_NUMBER; + } + if (!extendEnd) { + colorStops.at(-1)[0] -= BaseShading.SMALL_NUMBER; + colorStops.push([1, background]); + } + this.colorStops = colorStops; + } + getIR() { + const { + coordsArr, + shadingType + } = this; + let type, p0, p1, r0, r1; + if (shadingType === ShadingType.AXIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[2], coordsArr[3]]; + r0 = null; + r1 = null; + type = "axial"; + } else if (shadingType === ShadingType.RADIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[3], coordsArr[4]]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = "radial"; + } else { + unreachable(`getPattern type unknown: ${shadingType}`); + } + return ["RadialAxial", type, this.bbox, this.colorStops, p0, p1, r0, r1]; + } +} +class MeshStreamReader { + constructor(stream, context) { + this.stream = stream; + this.context = context; + this.buffer = 0; + this.bufferLength = 0; + const numComps = context.numComps; + this.tmpCompsBuf = new Float32Array(numComps); + const csNumComps = context.colorSpace.numComps; + this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf; + } + get hasData() { + if (this.stream.end) { + return this.stream.pos < this.stream.end; + } + if (this.bufferLength > 0) { + return true; + } + const nextByte = this.stream.getByte(); + if (nextByte < 0) { + return false; + } + this.buffer = nextByte; + this.bufferLength = 8; + return true; + } + readBits(n) { + const { + stream + } = this; + let { + buffer, + bufferLength + } = this; + if (n === 32) { + if (bufferLength === 0) { + return stream.getInt32() >>> 0; + } + buffer = buffer << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte(); + const nextByte = stream.getByte(); + this.buffer = nextByte & (1 << bufferLength) - 1; + return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0; + } + if (n === 8 && bufferLength === 0) { + return stream.getByte(); + } + while (bufferLength < n) { + buffer = buffer << 8 | stream.getByte(); + bufferLength += 8; + } + bufferLength -= n; + this.bufferLength = bufferLength; + this.buffer = buffer & (1 << bufferLength) - 1; + return buffer >> bufferLength; + } + align() { + this.buffer = 0; + this.bufferLength = 0; + } + readFlag() { + return this.readBits(this.context.bitsPerFlag); + } + readCoordinate() { + const { + bitsPerCoordinate, + decode + } = this.context; + const xi = this.readBits(bitsPerCoordinate); + const yi = this.readBits(bitsPerCoordinate); + const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10; + return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]]; + } + readComponents() { + const { + bitsPerComponent, + colorFn, + colorSpace, + decode, + numComps + } = this.context; + const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10; + const components = this.tmpCompsBuf; + for (let i = 0, j = 4; i < numComps; i++, j += 2) { + const ci = this.readBits(bitsPerComponent); + components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; + } + const color = this.tmpCsCompsBuf; + colorFn?.(components, 0, color, 0); + return colorSpace.getRgb(color, 0); + } +} +let bCache = Object.create(null); +function buildB(count) { + const lut = []; + for (let i = 0; i <= count; i++) { + const t = i / count, + t_ = 1 - t; + lut.push(new Float32Array([t_ ** 3, 3 * t * t_ ** 2, 3 * t ** 2 * t_, t ** 3])); + } + return lut; +} +function getB(count) { + return bCache[count] ||= buildB(count); +} +function clearPatternCaches() { + bCache = Object.create(null); +} +class MeshShading extends BaseShading { + static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; + static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; + static TRIANGLE_DENSITY = 20; + constructor(stream, xref, resources, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + super(); + if (!(stream instanceof BaseStream)) { + throw new FormatError("Mesh data is not a stream"); + } + const dict = stream.dict; + this.shadingType = dict.get("ShadingType"); + this.bbox = lookupNormalRect(dict.getArray("BBox"), null); + const cs = ColorSpaceUtils.parse({ + cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null; + const fnObj = dict.getRaw("Function"); + const fn = fnObj ? pdfFunctionFactory.create(fnObj, true) : null; + this.coords = []; + this.colors = []; + this.figures = []; + const decodeContext = { + bitsPerCoordinate: dict.get("BitsPerCoordinate"), + bitsPerComponent: dict.get("BitsPerComponent"), + bitsPerFlag: dict.get("BitsPerFlag"), + decode: dict.getArray("Decode"), + colorFn: fn, + colorSpace: cs, + numComps: fn ? 1 : cs.numComps + }; + const reader = new MeshStreamReader(stream, decodeContext); + let patchMesh = false; + switch (this.shadingType) { + case ShadingType.FREE_FORM_MESH: + this._decodeType4Shading(reader); + break; + case ShadingType.LATTICE_FORM_MESH: + const verticesPerRow = dict.get("VerticesPerRow") | 0; + if (verticesPerRow < 2) { + throw new FormatError("Invalid VerticesPerRow"); + } + this._decodeType5Shading(reader, verticesPerRow); + break; + case ShadingType.COONS_PATCH_MESH: + this._decodeType6Shading(reader); + patchMesh = true; + break; + case ShadingType.TENSOR_PATCH_MESH: + this._decodeType7Shading(reader); + patchMesh = true; + break; + default: + unreachable("Unsupported mesh type."); + break; + } + if (patchMesh) { + this._updateBounds(); + for (let i = 0, ii = this.figures.length; i < ii; i++) { + this._buildFigureFromPatch(i); + } + } + this._updateBounds(); + this._packData(); + } + _decodeType4Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const operators = []; + const ps = []; + let verticesLeft = 0; + while (reader.hasData) { + const f = reader.readFlag(); + const coord = reader.readCoordinate(); + const color = reader.readComponents(); + if (verticesLeft === 0) { + if (!(0 <= f && f <= 2)) { + throw new FormatError("Unknown type4 flag"); + } + switch (f) { + case 0: + verticesLeft = 3; + break; + case 1: + ps.push(ps.at(-2), ps.at(-1)); + verticesLeft = 1; + break; + case 2: + ps.push(ps.at(-3), ps.at(-1)); + verticesLeft = 1; + break; + } + operators.push(f); + } + ps.push(coords.length); + coords.push(coord); + colors.push(color); + verticesLeft--; + reader.align(); + } + this.figures.push({ + type: MeshFigureType.TRIANGLES, + coords: new Int32Array(ps), + colors: new Int32Array(ps) + }); + } + _decodeType5Shading(reader, verticesPerRow) { + const coords = this.coords; + const colors = this.colors; + const ps = []; + while (reader.hasData) { + const coord = reader.readCoordinate(); + const color = reader.readComponents(); + ps.push(coords.length); + coords.push(coord); + colors.push(color); + } + this.figures.push({ + type: MeshFigureType.LATTICE, + coords: new Int32Array(ps), + colors: new Int32Array(ps), + verticesPerRow + }); + } + _decodeType6Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const ps = new Int32Array(16); + const cs = new Int32Array(4); + while (reader.hasData) { + const f = reader.readFlag(); + if (!(0 <= f && f <= 3)) { + throw new FormatError("Unknown type6 flag"); + } + const pi = coords.length; + for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + const ci = colors.length; + for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + let tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + ps[5] = coords.length; + coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]); + ps[6] = coords.length; + coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]); + ps[9] = coords.length; + coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]); + ps[10] = coords.length; + coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]); + this.figures.push({ + type: MeshFigureType.PATCH, + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + _decodeType7Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const ps = new Int32Array(16); + const cs = new Int32Array(4); + while (reader.hasData) { + const f = reader.readFlag(); + if (!(0 <= f && f <= 3)) { + throw new FormatError("Unknown type7 flag"); + } + const pi = coords.length; + for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + const ci = colors.length; + for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + let tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[9] = pi + 13; + ps[10] = pi + 14; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[5] = pi + 12; + ps[6] = pi + 15; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + this.figures.push({ + type: MeshFigureType.PATCH, + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + _buildFigureFromPatch(index) { + const figure = this.figures[index]; + assert(figure.type === MeshFigureType.PATCH, "Unexpected patch mesh figure"); + const coords = this.coords, + colors = this.colors; + const pi = figure.coords; + const ci = figure.colors; + const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + let splitXBy = Math.ceil((figureMaxX - figureMinX) * MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])); + splitXBy = MathClamp(splitXBy, MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT); + let splitYBy = Math.ceil((figureMaxY - figureMinY) * MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])); + splitYBy = MathClamp(splitYBy, MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT); + const verticesPerRow = splitXBy + 1; + const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); + const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); + let k = 0; + const cl = new Uint8Array(3), + cr = new Uint8Array(3); + const c0 = colors[ci[0]], + c1 = colors[ci[1]], + c2 = colors[ci[2]], + c3 = colors[ci[3]]; + const bRow = getB(splitYBy), + bCol = getB(splitXBy); + for (let row = 0; row <= splitYBy; row++) { + cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0; + cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0; + cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0; + cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0; + cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0; + cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0; + for (let col = 0; col <= splitXBy; col++, k++) { + if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) { + continue; + } + let x = 0, + y = 0; + let q = 0; + for (let i = 0; i <= 3; i++) { + for (let j = 0; j <= 3; j++, q++) { + const m = bRow[row][i] * bCol[col][j]; + x += coords[pi[q]][0] * m; + y += coords[pi[q]][1] * m; + } + } + figureCoords[k] = coords.length; + coords.push([x, y]); + figureColors[k] = colors.length; + const newColor = new Uint8Array(3); + newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0; + newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0; + newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0; + colors.push(newColor); + } + } + figureCoords[0] = pi[0]; + figureColors[0] = ci[0]; + figureCoords[splitXBy] = pi[3]; + figureColors[splitXBy] = ci[1]; + figureCoords[verticesPerRow * splitYBy] = pi[12]; + figureColors[verticesPerRow * splitYBy] = ci[2]; + figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; + figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; + this.figures[index] = { + type: MeshFigureType.LATTICE, + coords: figureCoords, + colors: figureColors, + verticesPerRow + }; + } + _updateBounds() { + let minX = this.coords[0][0], + minY = this.coords[0][1], + maxX = minX, + maxY = minY; + for (let i = 1, ii = this.coords.length; i < ii; i++) { + const x = this.coords[i][0], + y = this.coords[i][1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + this.bounds = [minX, minY, maxX, maxY]; + } + _packData() { + let i, ii, j, jj; + const coords = this.coords; + const coordsPacked = new Float32Array(coords.length * 2); + for (i = 0, j = 0, ii = coords.length; i < ii; i++) { + const xy = coords[i]; + coordsPacked[j++] = xy[0]; + coordsPacked[j++] = xy[1]; + } + this.coords = coordsPacked; + const colors = this.colors; + const colorsPacked = new Uint8Array(colors.length * 3); + for (i = 0, j = 0, ii = colors.length; i < ii; i++) { + const c = colors[i]; + colorsPacked[j++] = c[0]; + colorsPacked[j++] = c[1]; + colorsPacked[j++] = c[2]; + } + this.colors = colorsPacked; + const figures = this.figures; + for (i = 0, ii = figures.length; i < ii; i++) { + const figure = figures[i], + ps = figure.coords, + cs = figure.colors; + for (j = 0, jj = ps.length; j < jj; j++) { + ps[j] *= 2; + cs[j] *= 3; + } + } + } + getIR() { + const { + bounds + } = this; + if (bounds[2] - bounds[0] === 0 || bounds[3] - bounds[1] === 0) { + throw new FormatError(`Invalid MeshShading bounds: [${bounds}].`); + } + return ["Mesh", this.shadingType, this.coords, this.colors, this.figures, bounds, this.bbox, this.background]; + } +} +class DummyShading extends BaseShading { + getIR() { + return ["Dummy"]; + } +} +function getTilingPatternIR(operatorList, dict, color) { + const matrix = lookupMatrix(dict.getArray("Matrix"), IDENTITY_MATRIX); + const bbox = lookupNormalRect(dict.getArray("BBox"), null); + if (!bbox || bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) { + throw new FormatError(`Invalid getTilingPatternIR /BBox array.`); + } + const xstep = dict.get("XStep"); + if (typeof xstep !== "number") { + throw new FormatError(`Invalid getTilingPatternIR /XStep value.`); + } + const ystep = dict.get("YStep"); + if (typeof ystep !== "number") { + throw new FormatError(`Invalid getTilingPatternIR /YStep value.`); + } + const paintType = dict.get("PaintType"); + if (!Number.isInteger(paintType)) { + throw new FormatError(`Invalid getTilingPatternIR /PaintType value.`); + } + const tilingType = dict.get("TilingType"); + if (!Number.isInteger(tilingType)) { + throw new FormatError(`Invalid getTilingPatternIR /TilingType value.`); + } + return ["TilingPattern", color, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType]; +} + +;// ./src/core/calibri_factors.js +const CalibriBoldFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.54657, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.73293, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.9121, 0.86943, 0.79795, 0.88198, 0.77958, 0.70864, 0.81055, 0.90399, 0.88653, 0.96017, 0.82577, 0.77892, 0.78257, 0.97507, 1.54657, 0.97507, 0.85284, 0.89552, 0.90176, 0.88762, 0.8785, 0.75241, 0.8785, 0.90518, 0.95015, 0.77618, 0.8785, 0.88401, 0.91916, 0.86304, 0.88401, 0.91488, 0.8785, 0.8801, 0.8785, 0.8785, 0.91343, 0.7173, 1.04106, 0.8785, 0.85075, 0.95794, 0.82616, 0.85162, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.12401, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.73293, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.9121, 0.86943, 0.86943, 0.86943, 0.86943, 0.86943, 0.85284, 0.87508, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.8715, 0.75241, 0.90518, 0.90518, 0.90518, 0.90518, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.8785, 0.8801, 0.8801, 0.8801, 0.8801, 0.8801, 0.90747, 0.89049, 0.8785, 0.8785, 0.8785, 0.8785, 0.85162, 0.8785, 0.85162, 0.83908, 0.88762, 0.83908, 0.88762, 0.83908, 0.88762, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.87289, 0.83016, 0.88506, 0.93125, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.81921, 0.77618, 0.81921, 0.77618, 0.81921, 0.77618, 1, 1, 0.87356, 0.8785, 0.91075, 0.89608, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76229, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.79468, 0.91926, 0.88175, 0.70823, 0.94903, 0.9121, 0.8785, 1, 1, 0.9121, 0.8785, 0.87802, 0.88656, 0.8785, 0.86943, 0.8801, 0.86943, 0.8801, 0.86943, 0.8801, 0.87402, 0.89291, 0.77958, 0.91343, 1, 1, 0.77958, 0.91343, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.96017, 0.95794, 0.77892, 0.85162, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.88762, 0.77539, 0.8715, 0.87508, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70674, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.06303, 0.83908, 0.80352, 0.57184, 0.6965, 0.56289, 0.82001, 0.56029, 0.81235, 1.02988, 0.83908, 0.7762, 0.68156, 0.80367, 0.73133, 0.78257, 0.87356, 0.86943, 0.95958, 0.75727, 0.89019, 1.04924, 0.9121, 0.7648, 0.86943, 0.87356, 0.79795, 0.78275, 0.81055, 0.77892, 0.9762, 0.82577, 0.99819, 0.84896, 0.95958, 0.77892, 0.96108, 1.01407, 0.89049, 1.02988, 0.94211, 0.96108, 0.8936, 0.84021, 0.87842, 0.96399, 0.79109, 0.89049, 1.00813, 1.02988, 0.86077, 0.87445, 0.92099, 0.84723, 0.86513, 0.8801, 0.75638, 0.85714, 0.78216, 0.79586, 0.87965, 0.94211, 0.97747, 0.78287, 0.97926, 0.84971, 1.02988, 0.94211, 0.8801, 0.94211, 0.84971, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90264, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90518, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90548, 1, 1, 1, 1, 1, 1, 0.96017, 0.95794, 0.96017, 0.95794, 0.96017, 0.95794, 0.77892, 0.85162, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.92794, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71143, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.93835, 0.83406, 0.91133, 0.84107, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90527, 1.81055, 0.90527, 1.81055, 1.31006, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const CalibriBoldMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 +}; +const CalibriBoldItalicFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.56239, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.71805, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.90872, 0.85938, 0.79795, 0.87068, 0.77958, 0.69766, 0.81055, 0.90399, 0.88653, 0.96068, 0.82577, 0.77892, 0.78257, 0.97507, 1.529, 0.97507, 0.85284, 0.89552, 0.90176, 0.94908, 0.86411, 0.74012, 0.86411, 0.88323, 0.95015, 0.86411, 0.86331, 0.88401, 0.91916, 0.86304, 0.88401, 0.9039, 0.86331, 0.86331, 0.86411, 0.86411, 0.90464, 0.70852, 1.04106, 0.86331, 0.84372, 0.95794, 0.82616, 0.84548, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.19129, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.71805, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.90872, 0.85938, 0.85938, 0.85938, 0.85938, 0.85938, 0.85284, 0.87068, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.85887, 0.74012, 0.88323, 0.88323, 0.88323, 0.88323, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.90747, 0.89049, 0.86331, 0.86331, 0.86331, 0.86331, 0.84548, 0.86411, 0.84548, 0.83908, 0.94908, 0.83908, 0.94908, 0.83908, 0.94908, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.87289, 0.79538, 0.88506, 0.92726, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.81921, 0.86411, 0.81921, 0.86411, 0.81921, 0.86411, 1, 1, 0.87356, 0.86331, 0.91075, 0.8777, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76467, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.77312, 0.91926, 0.88175, 0.70823, 0.94903, 0.90872, 0.86331, 1, 1, 0.90872, 0.86331, 0.86906, 0.88116, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.87402, 0.86549, 0.77958, 0.90464, 1, 1, 0.77958, 0.90464, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.96068, 0.95794, 0.77892, 0.84548, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.94908, 0.77539, 0.85887, 0.87068, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70088, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.48387, 0.83908, 0.80352, 0.57118, 0.6965, 0.56347, 0.79179, 0.55853, 0.80346, 1.02988, 0.83908, 0.7762, 0.67174, 0.86036, 0.73133, 0.78257, 0.87356, 0.86441, 0.95958, 0.75727, 0.89019, 1.04924, 0.90872, 0.74889, 0.85938, 0.87891, 0.79795, 0.7957, 0.81055, 0.77892, 0.97447, 0.82577, 0.97466, 0.87179, 0.95958, 0.77892, 0.94252, 0.95612, 0.8753, 1.02988, 0.92733, 0.94252, 0.87411, 0.84021, 0.8728, 0.95612, 0.74081, 0.8753, 1.02189, 1.02988, 0.84814, 0.87445, 0.91822, 0.84723, 0.85668, 0.86331, 0.81344, 0.87581, 0.76422, 0.82046, 0.96057, 0.92733, 0.99375, 0.78022, 0.95452, 0.86015, 1.02988, 0.92733, 0.86331, 0.92733, 0.86015, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88323, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85174, 1, 1, 1, 1, 1, 1, 0.96068, 0.95794, 0.96068, 0.95794, 0.96068, 0.95794, 0.77892, 0.84548, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.89807, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71094, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.92972, 0.83406, 0.91133, 0.83326, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90616, 1.81055, 0.90527, 1.81055, 1.3107, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const CalibriBoldItalicMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 +}; +const CalibriItalicFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39543, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.72346, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89249, 0.84118, 0.77452, 0.85374, 0.75186, 0.67789, 0.79776, 0.88844, 0.85066, 0.94309, 0.77818, 0.7306, 0.76659, 1.10369, 1.38313, 1.10369, 1.06139, 0.89552, 0.8739, 0.9245, 0.9245, 0.83203, 0.9245, 0.85865, 1.09842, 0.9245, 0.9245, 1.03297, 1.07692, 0.90918, 1.03297, 0.94959, 0.9245, 0.92274, 0.9245, 0.9245, 1.02933, 0.77832, 1.20562, 0.9245, 0.8916, 0.98986, 0.86621, 0.89453, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.16359, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.72346, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89249, 0.84118, 0.84118, 0.84118, 0.84118, 0.84118, 0.85284, 0.84557, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.84843, 0.83203, 0.85865, 0.85865, 0.85865, 0.85865, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.9245, 0.92274, 0.92274, 0.92274, 0.92274, 0.92274, 0.90747, 0.86651, 0.9245, 0.9245, 0.9245, 0.9245, 0.89453, 0.9245, 0.89453, 0.8675, 0.9245, 0.8675, 0.9245, 0.8675, 0.9245, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.85193, 0.8875, 0.86477, 0.99034, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.81105, 0.9245, 0.81105, 0.9245, 0.81105, 0.9245, 1, 1, 0.86275, 0.9245, 0.90872, 0.93591, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77896, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.9375, 0.98156, 0.93407, 0.77261, 1.11429, 0.89249, 0.9245, 1, 1, 0.89249, 0.9245, 0.92534, 0.86698, 0.9245, 0.84118, 0.92274, 0.84118, 0.92274, 0.84118, 0.92274, 0.8667, 0.86291, 0.75186, 1.02933, 1, 1, 0.75186, 1.02933, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 1, 1, 0.79776, 0.97655, 0.79776, 1.23023, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.94309, 0.98986, 0.7306, 0.89453, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.9245, 0.76318, 0.84843, 0.84557, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67009, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.8675, 0.90861, 0.6192, 0.7363, 0.64824, 0.82411, 0.56321, 0.85696, 1.23516, 0.8675, 0.81552, 0.7286, 0.84134, 0.73206, 0.76659, 0.86275, 0.84369, 0.90685, 0.77892, 0.85871, 1.02638, 0.89249, 0.75828, 0.84118, 0.85984, 0.77452, 0.76466, 0.79776, 0.7306, 0.90782, 0.77818, 0.903, 0.87291, 0.90685, 0.7306, 0.99058, 1.03667, 0.94635, 1.23516, 0.9849, 0.99058, 0.92393, 0.8916, 0.942, 1.03667, 0.75026, 0.94635, 1.0297, 1.23516, 0.90918, 0.94048, 0.98217, 0.89746, 0.84153, 0.92274, 0.82507, 0.88832, 0.84438, 0.88178, 1.03525, 0.9849, 1.00225, 0.78086, 0.97248, 0.89404, 1.23516, 0.9849, 0.92274, 0.9849, 0.89404, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89693, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85865, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90933, 1, 1, 1, 1, 1, 1, 0.94309, 0.98986, 0.94309, 0.98986, 0.94309, 0.98986, 0.7306, 0.89453, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.68994, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.97858, 0.82616, 0.91133, 0.83437, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90572, 1.81055, 0.90749, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85284, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const CalibriItalicMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 +}; +const CalibriRegularFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39016, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.73834, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89385, 0.85122, 0.77452, 0.86503, 0.75186, 0.68887, 0.79776, 0.88844, 0.85066, 0.94258, 0.77818, 0.7306, 0.76659, 1.10369, 1.39016, 1.10369, 1.06139, 0.89552, 0.8739, 0.86128, 0.94469, 0.8457, 0.94469, 0.89464, 1.09842, 0.84636, 0.94469, 1.03297, 1.07692, 0.90918, 1.03297, 0.95897, 0.94469, 0.9482, 0.94469, 0.94469, 1.04692, 0.78223, 1.20562, 0.94469, 0.90332, 0.98986, 0.86621, 0.90527, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.08707, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.73834, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89385, 0.85122, 0.85122, 0.85122, 0.85122, 0.85122, 0.85284, 0.85311, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.8693, 0.8457, 0.89464, 0.89464, 0.89464, 0.89464, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.94469, 0.9482, 0.9482, 0.9482, 0.9482, 0.9482, 0.90747, 0.86651, 0.94469, 0.94469, 0.94469, 0.94469, 0.90527, 0.94469, 0.90527, 0.8675, 0.86128, 0.8675, 0.86128, 0.8675, 0.86128, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.85193, 0.92454, 0.86477, 0.9921, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.81105, 0.84636, 0.81105, 0.84636, 0.81105, 0.84636, 1, 1, 0.86275, 0.94469, 0.90872, 0.95786, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77741, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.90452, 0.98156, 1.11842, 0.77261, 1.11429, 0.89385, 0.94469, 1, 1, 0.89385, 0.94469, 0.95877, 0.86901, 0.94469, 0.85122, 0.9482, 0.85122, 0.9482, 0.85122, 0.9482, 0.8667, 0.90016, 0.75186, 1.04692, 1, 1, 0.75186, 1.04692, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 1, 1, 0.79776, 0.92188, 0.79776, 1.23023, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.94258, 0.98986, 0.7306, 0.90527, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.86128, 0.76318, 0.8693, 0.85311, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67742, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.86686, 0.90861, 0.62267, 0.74359, 0.65649, 0.85498, 0.56963, 0.88254, 1.23516, 0.8675, 0.81552, 0.75443, 0.84503, 0.73206, 0.76659, 0.86275, 0.85122, 0.90685, 0.77892, 0.85746, 1.02638, 0.89385, 0.75657, 0.85122, 0.86275, 0.77452, 0.74171, 0.79776, 0.7306, 0.95165, 0.77818, 0.89772, 0.88831, 0.90685, 0.7306, 0.98142, 1.02191, 0.96576, 1.23516, 0.99018, 0.98142, 0.9236, 0.89258, 0.94035, 1.02191, 0.78848, 0.96576, 0.9561, 1.23516, 0.90918, 0.92578, 0.95424, 0.89746, 0.83969, 0.9482, 0.80113, 0.89442, 0.85208, 0.86155, 0.98022, 0.99018, 1.00452, 0.81209, 0.99247, 0.89181, 1.23516, 0.99018, 0.9482, 0.99018, 0.89181, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88844, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89464, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96766, 1, 1, 1, 1, 1, 1, 0.94258, 0.98986, 0.94258, 0.98986, 0.94258, 0.98986, 0.7306, 0.90527, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.69043, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.99331, 0.82616, 0.91133, 0.84286, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90527, 1.81055, 0.90527, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1.07185, 0.99413, 0.96334, 1.08065, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const CalibriRegularMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 +}; + +;// ./src/core/helvetica_factors.js +const HelveticaBoldFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.03374, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.00042, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.03828, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00034, 0.99977, 1, 0.99997, 1.00026, 1.00078, 1.00036, 0.99973, 1.00013, 1.0006, 0.99977, 0.99977, 0.99988, 0.85148, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 1.00069, 1.00022, 0.99977, 1.00001, 0.99984, 1.00026, 1.00001, 1.00024, 1.00001, 0.9999, 1, 1.0006, 1.00001, 1.00041, 0.99962, 1.00026, 1.0006, 0.99995, 1.00041, 0.99942, 0.99973, 0.99927, 1.00082, 0.99902, 1.00026, 1.00087, 1.0006, 1.00069, 0.99973, 0.99867, 0.99973, 0.9993, 1.00026, 1.00049, 1.00056, 1, 0.99988, 0.99935, 0.99995, 0.99954, 1.00055, 0.99945, 1.00032, 1.0006, 0.99995, 1.00026, 0.99995, 1.00032, 1.00001, 1.00008, 0.99971, 1.00019, 0.9994, 1.00001, 1.0006, 1.00044, 0.99973, 1.00023, 1.00047, 1, 0.99942, 0.99561, 0.99989, 1.00035, 0.99977, 1.00035, 0.99977, 1.00019, 0.99944, 1.00001, 1.00021, 0.99926, 1.00035, 1.00035, 0.99942, 1.00048, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.99989, 1.00057, 1.00001, 0.99936, 1.00052, 1.00012, 0.99996, 1.00043, 1, 1.00035, 0.9994, 0.99976, 1.00035, 0.99973, 1.00052, 1.00041, 1.00119, 1.00037, 0.99973, 1.00002, 0.99986, 1.00041, 1.00041, 0.99902, 0.9996, 1.00034, 0.99999, 1.00026, 0.99999, 1.00026, 0.99973, 1.00052, 0.99973, 1, 0.99973, 1.00041, 1.00075, 0.9994, 1.0003, 0.99999, 1, 1.00041, 0.99955, 1, 0.99915, 0.99973, 0.99973, 1.00026, 1.00119, 0.99955, 0.99973, 1.0006, 0.99911, 1.0006, 1.00026, 0.99972, 1.00026, 0.99902, 1.00041, 0.99973, 0.99999, 1, 1, 1.00038, 1.0005, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 1.00047, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const HelveticaBoldMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; +const HelveticaBoldItalicFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.0044, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99971, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.01011, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99977, 1, 1, 1.00026, 0.99969, 0.99972, 0.99981, 0.9998, 1.0006, 0.99977, 0.99977, 1.00022, 0.91155, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 0.99966, 1.00022, 1.00032, 1.00001, 0.99944, 1.00026, 1.00001, 0.99968, 1.00001, 1.00047, 1, 1.0006, 1.00001, 0.99981, 1.00101, 1.00026, 1.0006, 0.99948, 0.99981, 1.00064, 0.99973, 0.99942, 1.00101, 1.00061, 1.00026, 1.00069, 1.0006, 1.00014, 0.99973, 1.01322, 0.99973, 1.00065, 1.00026, 1.00012, 0.99923, 1, 1.00064, 1.00076, 0.99948, 1.00055, 1.00063, 1.00007, 0.99943, 1.0006, 0.99948, 1.00026, 0.99948, 0.99943, 1.00001, 1.00001, 1.00029, 1.00038, 1.00035, 1.00001, 1.0006, 1.0006, 0.99973, 0.99978, 1.00001, 1.00057, 0.99989, 0.99967, 0.99964, 0.99967, 0.99977, 0.99999, 0.99977, 1.00038, 0.99977, 1.00001, 0.99973, 1.00066, 0.99967, 0.99967, 1.00041, 0.99998, 0.99999, 0.99977, 1.00022, 0.99967, 1.00001, 0.99977, 1.00026, 0.99964, 1.00031, 1.00001, 0.99999, 0.99999, 1, 1.00023, 1, 1, 0.99999, 1.00035, 1.00001, 0.99999, 0.99973, 0.99977, 0.99999, 1.00058, 0.99973, 0.99973, 0.99955, 0.9995, 1.00026, 1.00026, 1.00032, 0.99989, 1.00034, 0.99999, 1.00026, 1.00026, 1.00026, 0.99973, 0.45998, 0.99973, 1.00026, 0.99973, 1.00001, 0.99999, 0.99982, 0.99994, 0.99996, 1, 1.00042, 1.00044, 1.00029, 1.00023, 0.99973, 0.99973, 1.00026, 0.99949, 1.00002, 0.99973, 1.0006, 1.0006, 1.0006, 0.99975, 1.00026, 1.00026, 1.00032, 0.98685, 0.99973, 1.00026, 1, 1, 0.99966, 1.00044, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1, 0.99973, 0.99971, 0.99978, 1, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00098, 1, 1, 1, 1.00049, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const HelveticaBoldItalicMetrics = { + lineHeight: 1.35, + lineGap: 0.2 +}; +const HelveticaItalicFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.0288, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 0.99946, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.06311, 0.99973, 1.00024, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00041, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.89547, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00001, 1, 1.00054, 0.99977, 1.00084, 1.00007, 0.99973, 1.00013, 0.99924, 1.00001, 1.00001, 0.99945, 0.91221, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00001, 0.99999, 0.99977, 0.99933, 1.00022, 1.00054, 1.00001, 1.00065, 1.00026, 1.00001, 1.0001, 1.00001, 1.00052, 1, 1.0006, 1.00001, 0.99945, 0.99897, 0.99968, 0.99924, 1.00036, 0.99945, 0.99949, 1, 1.0006, 0.99897, 0.99918, 0.99968, 0.99911, 0.99924, 1, 0.99962, 1.01487, 1, 1.0005, 0.99973, 1.00012, 1.00043, 1, 0.99995, 0.99994, 1.00036, 0.99947, 1.00019, 1.00063, 1.00025, 0.99924, 1.00036, 0.99973, 1.00036, 1.00025, 1.00001, 1.00001, 1.00027, 1.0001, 1.00068, 1.00001, 1.0006, 1.0006, 1, 1.00008, 0.99957, 0.99972, 0.9994, 0.99954, 0.99975, 1.00051, 1.00001, 1.00019, 1.00001, 1.0001, 0.99986, 1.00001, 1.00001, 1.00038, 0.99954, 0.99954, 0.9994, 1.00066, 0.99999, 0.99977, 1.00022, 1.00054, 1.00001, 0.99977, 1.00026, 0.99975, 1.0001, 1.00001, 0.99993, 0.9995, 0.99955, 1.00016, 0.99978, 0.99974, 1.00019, 1.00022, 0.99955, 1.00053, 0.99973, 1.00089, 1.00005, 0.99967, 1.00048, 0.99973, 1.00002, 1.00034, 0.99973, 0.99973, 0.99964, 1.00006, 1.00066, 0.99947, 0.99973, 0.98894, 0.99973, 1, 0.44898, 1, 0.99946, 1, 1.00039, 1.00082, 0.99991, 0.99991, 0.99985, 1.00022, 1.00023, 1.00061, 1.00006, 0.99966, 0.99973, 0.99973, 0.99973, 1.00019, 1.0008, 1, 0.99924, 0.99924, 0.99924, 0.99983, 1.00044, 0.99973, 0.99964, 0.98332, 1, 0.99973, 1, 1, 0.99962, 0.99895, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 1.00423, 0.99925, 0.99999, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00049, 1, 1.00245, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 1.00003, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const HelveticaItalicMetrics = { + lineHeight: 1.35, + lineGap: 0.2 +}; +const HelveticaRegularFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.04596, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 1.00019, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.02572, 0.99973, 1.00005, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99999, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.84533, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99928, 1, 0.99977, 1.00013, 1.00055, 0.99947, 0.99945, 0.99941, 0.99924, 1.00001, 1.00001, 1.0004, 0.91621, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00005, 0.99999, 0.99977, 1.00015, 1.00022, 0.99977, 1.00001, 0.99973, 1.00026, 1.00001, 1.00019, 1.00001, 0.99946, 1, 1.0006, 1.00001, 0.99978, 1.00045, 0.99973, 0.99924, 1.00023, 0.99978, 0.99966, 1, 1.00065, 1.00045, 1.00019, 0.99973, 0.99973, 0.99924, 1, 1, 0.96499, 1, 1.00055, 0.99973, 1.00008, 1.00027, 1, 0.9997, 0.99995, 1.00023, 0.99933, 1.00019, 1.00015, 1.00031, 0.99924, 1.00023, 0.99973, 1.00023, 1.00031, 1.00001, 0.99928, 1.00029, 1.00092, 1.00035, 1.00001, 1.0006, 1.0006, 1, 0.99988, 0.99975, 1, 1.00082, 0.99561, 0.9996, 1.00035, 1.00001, 0.99962, 1.00001, 1.00092, 0.99964, 1.00001, 0.99963, 0.99999, 1.00035, 1.00035, 1.00082, 0.99962, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.9996, 0.99967, 1.00001, 1.00034, 1.00074, 1.00054, 1.00053, 1.00063, 0.99971, 0.99962, 1.00035, 0.99975, 0.99977, 0.99973, 1.00043, 0.99953, 1.0007, 0.99915, 0.99973, 1.00008, 0.99892, 1.00073, 1.00073, 1.00114, 0.99915, 1.00073, 0.99955, 0.99973, 1.00092, 0.99973, 1, 0.99998, 1, 1.0003, 1, 1.00043, 1.00001, 0.99969, 1.0003, 1, 1.00035, 1.00001, 0.9995, 1, 1.00092, 0.99973, 0.99973, 0.99973, 1.0007, 0.9995, 1, 0.99924, 1.0006, 0.99924, 0.99972, 1.00062, 0.99973, 1.00114, 1.00073, 1, 0.99955, 1, 1, 1.00047, 0.99968, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 0.99925, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const HelveticaRegularMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; + +;// ./src/core/liberationsans_widths.js +const LiberationSansBoldWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 719, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 785, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 385, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 465, 722, 333, 853, 906, 474, 825, 927, 838, 278, 722, 722, 601, 719, 667, 611, 722, 778, 278, 722, 667, 833, 722, 644, 778, 722, 667, 600, 611, 667, 821, 667, 809, 802, 278, 667, 615, 451, 611, 278, 582, 615, 610, 556, 606, 475, 460, 611, 541, 278, 558, 556, 612, 556, 445, 611, 766, 619, 520, 684, 446, 582, 715, 576, 753, 845, 278, 582, 611, 582, 845, 667, 669, 885, 567, 711, 667, 278, 276, 556, 1094, 1062, 875, 610, 722, 622, 719, 722, 719, 722, 567, 712, 667, 904, 626, 719, 719, 610, 702, 833, 722, 778, 719, 667, 722, 611, 622, 854, 667, 730, 703, 1005, 1019, 870, 979, 719, 711, 1031, 719, 556, 618, 615, 417, 635, 556, 709, 497, 615, 615, 500, 635, 740, 604, 611, 604, 611, 556, 490, 556, 875, 556, 615, 581, 833, 844, 729, 854, 615, 552, 854, 583, 556, 556, 611, 417, 552, 556, 278, 281, 278, 969, 906, 611, 500, 615, 556, 604, 778, 611, 487, 447, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1094, 556, 885, 489, 1115, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; +const LiberationSansBoldMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; +const LiberationSansBoldItalicWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 740, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 782, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 396, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 722, 333, 854, 906, 473, 844, 930, 847, 278, 722, 722, 610, 671, 667, 611, 722, 778, 278, 722, 667, 833, 722, 657, 778, 718, 667, 590, 611, 667, 822, 667, 829, 781, 278, 667, 620, 479, 611, 278, 591, 620, 621, 556, 610, 479, 492, 611, 558, 278, 566, 556, 603, 556, 450, 611, 712, 605, 532, 664, 409, 591, 704, 578, 773, 834, 278, 591, 611, 591, 834, 667, 667, 886, 614, 719, 667, 278, 278, 556, 1094, 1042, 854, 622, 719, 677, 719, 722, 708, 722, 614, 722, 667, 927, 643, 719, 719, 615, 687, 833, 722, 778, 719, 667, 722, 611, 677, 781, 667, 729, 708, 979, 989, 854, 1000, 708, 719, 1042, 729, 556, 619, 604, 534, 618, 556, 736, 510, 611, 611, 507, 622, 740, 604, 611, 611, 611, 556, 889, 556, 885, 556, 646, 583, 889, 935, 707, 854, 594, 552, 865, 589, 556, 556, 611, 469, 563, 556, 278, 278, 278, 969, 906, 611, 507, 619, 556, 611, 778, 611, 575, 467, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1104, 556, 885, 516, 1146, 1000, 768, 600, 834, 834, 834, 834, 999, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; +const LiberationSansBoldItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; +const LiberationSansItalicWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 625, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 733, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 281, 556, 400, 556, 222, 722, 556, 722, 556, 722, 556, 615, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 354, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 789, 846, 389, 794, 865, 775, 222, 667, 667, 570, 671, 667, 611, 722, 778, 278, 667, 667, 833, 722, 648, 778, 725, 667, 600, 611, 667, 837, 667, 831, 761, 278, 667, 570, 439, 555, 222, 550, 570, 571, 500, 556, 439, 463, 555, 542, 222, 500, 492, 548, 500, 447, 556, 670, 573, 486, 603, 374, 550, 652, 546, 728, 779, 222, 550, 556, 550, 779, 667, 667, 843, 544, 708, 667, 278, 278, 500, 1066, 982, 844, 589, 715, 639, 724, 667, 651, 667, 544, 704, 667, 917, 614, 715, 715, 589, 686, 833, 722, 778, 725, 667, 722, 611, 639, 795, 667, 727, 673, 920, 923, 805, 886, 651, 694, 1022, 682, 556, 562, 522, 493, 553, 556, 688, 465, 556, 556, 472, 564, 686, 550, 556, 556, 556, 500, 833, 500, 835, 500, 572, 518, 830, 851, 621, 736, 526, 492, 752, 534, 556, 556, 556, 378, 496, 500, 222, 222, 222, 910, 828, 556, 472, 565, 500, 556, 778, 556, 492, 339, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1083, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 998, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 584, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; +const LiberationSansItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; +const LiberationSansRegularWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 615, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 735, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 292, 556, 334, 556, 222, 722, 556, 722, 556, 722, 556, 604, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 375, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 784, 838, 384, 774, 855, 752, 222, 667, 667, 551, 668, 667, 611, 722, 778, 278, 667, 668, 833, 722, 650, 778, 722, 667, 618, 611, 667, 798, 667, 835, 748, 278, 667, 578, 446, 556, 222, 547, 578, 575, 500, 557, 446, 441, 556, 556, 222, 500, 500, 576, 500, 448, 556, 690, 569, 482, 617, 395, 547, 648, 525, 713, 781, 222, 547, 556, 547, 781, 667, 667, 865, 542, 719, 667, 278, 278, 500, 1057, 1010, 854, 583, 722, 635, 719, 667, 656, 667, 542, 677, 667, 923, 604, 719, 719, 583, 656, 833, 722, 778, 719, 667, 722, 611, 635, 760, 667, 740, 667, 917, 938, 792, 885, 656, 719, 1010, 722, 556, 573, 531, 365, 583, 556, 669, 458, 559, 559, 438, 583, 688, 552, 556, 542, 556, 500, 458, 500, 823, 500, 573, 521, 802, 823, 625, 719, 521, 510, 750, 542, 556, 556, 556, 365, 510, 500, 222, 278, 222, 906, 812, 556, 438, 559, 500, 552, 778, 556, 489, 411, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1073, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; +const LiberationSansRegularMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; + +;// ./src/core/myriadpro_factors.js +const MyriadProBoldFactors = [1.36898, 1, 1, 0.72706, 0.80479, 0.83734, 0.98894, 0.99793, 0.9897, 0.93884, 0.86209, 0.94292, 0.94292, 1.16661, 1.02058, 0.93582, 0.96694, 0.93582, 1.19137, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.72851, 0.78966, 0.90838, 0.83637, 0.82391, 0.96376, 0.80061, 0.86275, 0.8768, 0.95407, 1.0258, 0.73901, 0.85022, 0.83655, 1.0156, 0.95546, 0.92179, 0.87107, 0.92179, 0.82114, 0.8096, 0.89713, 0.94438, 0.95353, 0.94083, 0.91905, 0.90406, 0.9446, 0.94292, 1.18777, 0.94292, 1.02058, 0.89903, 0.90088, 0.94938, 0.97898, 0.81093, 0.97571, 0.94938, 1.024, 0.9577, 0.95933, 0.98621, 1.0474, 0.97455, 0.98981, 0.9672, 0.95933, 0.9446, 0.97898, 0.97407, 0.97646, 0.78036, 1.10208, 0.95442, 0.95298, 0.97579, 0.9332, 0.94039, 0.938, 0.80687, 1.01149, 0.80687, 1.02058, 0.80479, 0.99793, 0.99793, 0.99793, 0.99793, 1.01149, 1.00872, 0.90088, 0.91882, 1.0213, 0.8361, 1.02058, 0.62295, 0.54324, 0.89022, 1.08595, 1, 1, 0.90088, 1, 0.97455, 0.93582, 0.90088, 1, 1.05686, 0.8361, 0.99642, 0.99642, 0.99642, 0.72851, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.868, 0.82391, 0.80061, 0.80061, 0.80061, 0.80061, 1.0258, 1.0258, 1.0258, 1.0258, 0.97484, 0.95546, 0.92179, 0.92179, 0.92179, 0.92179, 0.92179, 1.02058, 0.92179, 0.94438, 0.94438, 0.94438, 0.94438, 0.90406, 0.86958, 0.98225, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.9031, 0.81093, 0.94938, 0.94938, 0.94938, 0.94938, 0.98621, 0.98621, 0.98621, 0.98621, 0.93969, 0.95933, 0.9446, 0.9446, 0.9446, 0.9446, 0.9446, 1.08595, 0.9446, 0.95442, 0.95442, 0.95442, 0.95442, 0.94039, 0.97898, 0.94039, 0.90838, 0.94938, 0.90838, 0.94938, 0.90838, 0.94938, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.96376, 0.84313, 0.97484, 0.97571, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.8768, 0.9577, 0.8768, 0.9577, 0.8768, 0.9577, 1, 1, 0.95407, 0.95933, 0.97069, 0.95933, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 0.887, 1.01591, 0.73901, 1.0474, 1, 1, 0.97455, 0.83655, 0.98981, 1, 1, 0.83655, 0.73977, 0.83655, 0.73903, 0.84638, 1.033, 0.95546, 0.95933, 1, 1, 0.95546, 0.95933, 0.8271, 0.95417, 0.95933, 0.92179, 0.9446, 0.92179, 0.9446, 0.92179, 0.9446, 0.936, 0.91964, 0.82114, 0.97646, 1, 1, 0.82114, 0.97646, 0.8096, 0.78036, 0.8096, 0.78036, 1, 1, 0.8096, 0.78036, 1, 1, 0.89713, 0.77452, 0.89713, 1.10208, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94083, 0.97579, 0.90406, 0.94039, 0.90406, 0.9446, 0.938, 0.9446, 0.938, 0.9446, 0.938, 1, 0.99793, 0.90838, 0.94938, 0.868, 0.9031, 0.92179, 0.9446, 1, 1, 0.89713, 1.10208, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90989, 0.9358, 0.91945, 0.83181, 0.75261, 0.87992, 0.82976, 0.96034, 0.83689, 0.97268, 1.0078, 0.90838, 0.83637, 0.8019, 0.90157, 0.80061, 0.9446, 0.95407, 0.92436, 1.0258, 0.85022, 0.97153, 1.0156, 0.95546, 0.89192, 0.92179, 0.92361, 0.87107, 0.96318, 0.89713, 0.93704, 0.95638, 0.91905, 0.91709, 0.92796, 1.0258, 0.93704, 0.94836, 1.0373, 0.95933, 1.0078, 0.95871, 0.94836, 0.96174, 0.92601, 0.9498, 0.98607, 0.95776, 0.95933, 1.05453, 1.0078, 0.98275, 0.9314, 0.95617, 0.91701, 1.05993, 0.9446, 0.78367, 0.9553, 1, 0.86832, 1.0128, 0.95871, 0.99394, 0.87548, 0.96361, 0.86774, 1.0078, 0.95871, 0.9446, 0.95871, 0.86774, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.94083, 0.97579, 0.94083, 0.97579, 0.94083, 0.97579, 0.90406, 0.94039, 0.96694, 1, 0.89903, 1, 1, 1, 0.93582, 0.93582, 0.93582, 1, 0.908, 0.908, 0.918, 0.94219, 0.94219, 0.96544, 1, 1.285, 1, 1, 0.81079, 0.81079, 1, 1, 0.74854, 1, 1, 1, 1, 0.99793, 1, 1, 1, 0.65, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.17173, 1, 0.80535, 0.76169, 1.02058, 1.0732, 1.05486, 1, 1, 1.30692, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.16161, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const MyriadProBoldMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; +const MyriadProBoldItalicFactors = [1.36898, 1, 1, 0.66227, 0.80779, 0.81625, 0.97276, 0.97276, 0.97733, 0.92222, 0.83266, 0.94292, 0.94292, 1.16148, 1.02058, 0.93582, 0.96694, 0.93582, 1.17337, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.71541, 0.76813, 0.85576, 0.80591, 0.80729, 0.94299, 0.77512, 0.83655, 0.86523, 0.92222, 0.98621, 0.71743, 0.81698, 0.79726, 0.98558, 0.92222, 0.90637, 0.83809, 0.90637, 0.80729, 0.76463, 0.86275, 0.90699, 0.91605, 0.9154, 0.85308, 0.85458, 0.90531, 0.94292, 1.21296, 0.94292, 1.02058, 0.89903, 1.18616, 0.99613, 0.91677, 0.78216, 0.91677, 0.90083, 0.98796, 0.9135, 0.92168, 0.95381, 0.98981, 0.95298, 0.95381, 0.93459, 0.92168, 0.91513, 0.92004, 0.91677, 0.95077, 0.748, 1.04502, 0.91677, 0.92061, 0.94236, 0.89544, 0.89364, 0.9, 0.80687, 0.8578, 0.80687, 1.02058, 0.80779, 0.97276, 0.97276, 0.97276, 0.97276, 0.8578, 0.99973, 1.18616, 0.91339, 1.08074, 0.82891, 1.02058, 0.55509, 0.71526, 0.89022, 1.08595, 1, 1, 1.18616, 1, 0.96736, 0.93582, 1.18616, 1, 1.04864, 0.82711, 0.99043, 0.99043, 0.99043, 0.71541, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.845, 0.80729, 0.77512, 0.77512, 0.77512, 0.77512, 0.98621, 0.98621, 0.98621, 0.98621, 0.95961, 0.92222, 0.90637, 0.90637, 0.90637, 0.90637, 0.90637, 1.02058, 0.90251, 0.90699, 0.90699, 0.90699, 0.90699, 0.85458, 0.83659, 0.94951, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.85811, 0.78216, 0.90083, 0.90083, 0.90083, 0.90083, 0.95381, 0.95381, 0.95381, 0.95381, 0.9135, 0.92168, 0.91513, 0.91513, 0.91513, 0.91513, 0.91513, 1.08595, 0.91677, 0.91677, 0.91677, 0.91677, 0.91677, 0.89364, 0.92332, 0.89364, 0.85576, 0.99613, 0.85576, 0.99613, 0.85576, 0.99613, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.94299, 0.76783, 0.95961, 0.91677, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.86523, 0.9135, 0.86523, 0.9135, 0.86523, 0.9135, 1, 1, 0.92222, 0.92168, 0.92222, 0.92168, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.86036, 0.97096, 0.71743, 0.98981, 1, 1, 0.95298, 0.79726, 0.95381, 1, 1, 0.79726, 0.6894, 0.79726, 0.74321, 0.81691, 1.0006, 0.92222, 0.92168, 1, 1, 0.92222, 0.92168, 0.79464, 0.92098, 0.92168, 0.90637, 0.91513, 0.90637, 0.91513, 0.90637, 0.91513, 0.909, 0.87514, 0.80729, 0.95077, 1, 1, 0.80729, 0.95077, 0.76463, 0.748, 0.76463, 0.748, 1, 1, 0.76463, 0.748, 1, 1, 0.86275, 0.72651, 0.86275, 1.04502, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.9154, 0.94236, 0.85458, 0.89364, 0.85458, 0.90531, 0.9, 0.90531, 0.9, 0.90531, 0.9, 1, 0.97276, 0.85576, 0.99613, 0.845, 0.85811, 0.90251, 0.91677, 1, 1, 0.86275, 1.04502, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.00899, 1.30628, 0.85576, 0.80178, 0.66862, 0.7927, 0.69323, 0.88127, 0.72459, 0.89711, 0.95381, 0.85576, 0.80591, 0.7805, 0.94729, 0.77512, 0.90531, 0.92222, 0.90637, 0.98621, 0.81698, 0.92655, 0.98558, 0.92222, 0.85359, 0.90637, 0.90976, 0.83809, 0.94523, 0.86275, 0.83509, 0.93157, 0.85308, 0.83392, 0.92346, 0.98621, 0.83509, 0.92886, 0.91324, 0.92168, 0.95381, 0.90646, 0.92886, 0.90557, 0.86847, 0.90276, 0.91324, 0.86842, 0.92168, 0.99531, 0.95381, 0.9224, 0.85408, 0.92699, 0.86847, 1.0051, 0.91513, 0.80487, 0.93481, 1, 0.88159, 1.05214, 0.90646, 0.97355, 0.81539, 0.89398, 0.85923, 0.95381, 0.90646, 0.91513, 0.90646, 0.85923, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9154, 0.94236, 0.9154, 0.94236, 0.9154, 0.94236, 0.85458, 0.89364, 0.96694, 1, 0.89903, 1, 1, 1, 0.91782, 0.91782, 0.91782, 1, 0.896, 0.896, 0.896, 0.9332, 0.9332, 0.95973, 1, 1.26, 1, 1, 0.80479, 0.80178, 1, 1, 0.85633, 1, 1, 1, 1, 0.97276, 1, 1, 1, 0.698, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.14542, 1, 0.79199, 0.78694, 1.02058, 1.03493, 1.05486, 1, 1, 1.23026, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.20006, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const MyriadProBoldItalicMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; +const MyriadProItalicFactors = [1.36898, 1, 1, 0.65507, 0.84943, 0.85639, 0.88465, 0.88465, 0.86936, 0.88307, 0.86948, 0.85283, 0.85283, 1.06383, 1.02058, 0.75945, 0.9219, 0.75945, 1.17337, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.75945, 0.75945, 1.02058, 1.02058, 1.02058, 0.69046, 0.70926, 0.85158, 0.77812, 0.76852, 0.89591, 0.70466, 0.76125, 0.80094, 0.86822, 0.83864, 0.728, 0.77212, 0.79475, 0.93637, 0.87514, 0.8588, 0.76013, 0.8588, 0.72421, 0.69866, 0.77598, 0.85991, 0.80811, 0.87832, 0.78112, 0.77512, 0.8562, 1.0222, 1.18417, 1.0222, 1.27014, 0.89903, 1.15012, 0.93859, 0.94399, 0.846, 0.94399, 0.81453, 1.0186, 0.94219, 0.96017, 1.03075, 1.02175, 0.912, 1.03075, 0.96998, 0.96017, 0.93859, 0.94399, 0.94399, 0.95493, 0.746, 1.12658, 0.94578, 0.91, 0.979, 0.882, 0.882, 0.83, 0.85034, 0.83537, 0.85034, 1.02058, 0.70869, 0.88465, 0.88465, 0.88465, 0.88465, 0.83537, 0.90083, 1.15012, 0.9161, 0.94565, 0.73541, 1.02058, 0.53609, 0.69353, 0.79519, 1.08595, 1, 1, 1.15012, 1, 0.91974, 0.75945, 1.15012, 1, 0.9446, 0.73361, 0.9005, 0.9005, 0.9005, 0.62864, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.773, 0.76852, 0.70466, 0.70466, 0.70466, 0.70466, 0.83864, 0.83864, 0.83864, 0.83864, 0.90561, 0.87514, 0.8588, 0.8588, 0.8588, 0.8588, 0.8588, 1.02058, 0.85751, 0.85991, 0.85991, 0.85991, 0.85991, 0.77512, 0.76013, 0.88075, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.8075, 0.846, 0.81453, 0.81453, 0.81453, 0.81453, 0.82424, 0.82424, 0.82424, 0.82424, 0.9278, 0.96017, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 1.08595, 0.8562, 0.94578, 0.94578, 0.94578, 0.94578, 0.882, 0.94578, 0.882, 0.85158, 0.93859, 0.85158, 0.93859, 0.85158, 0.93859, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.89591, 0.8544, 0.90561, 0.94399, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.80094, 0.94219, 0.80094, 0.94219, 0.80094, 0.94219, 1, 1, 0.86822, 0.96017, 0.86822, 0.96017, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 1.03075, 0.83864, 0.82424, 0.81402, 1.02738, 0.728, 1.02175, 1, 1, 0.912, 0.79475, 1.03075, 1, 1, 0.79475, 0.83911, 0.79475, 0.66266, 0.80553, 1.06676, 0.87514, 0.96017, 1, 1, 0.87514, 0.96017, 0.86865, 0.87396, 0.96017, 0.8588, 0.93859, 0.8588, 0.93859, 0.8588, 0.93859, 0.867, 0.84759, 0.72421, 0.95493, 1, 1, 0.72421, 0.95493, 0.69866, 0.746, 0.69866, 0.746, 1, 1, 0.69866, 0.746, 1, 1, 0.77598, 0.88417, 0.77598, 1.12658, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.87832, 0.979, 0.77512, 0.882, 0.77512, 0.8562, 0.83, 0.8562, 0.83, 0.8562, 0.83, 1, 0.88465, 0.85158, 0.93859, 0.773, 0.8075, 0.85751, 0.8562, 1, 1, 0.77598, 1.12658, 1.15012, 1.15012, 1.15012, 1.15012, 1.15012, 1.15313, 1.15012, 1.15012, 1.15012, 1.08106, 1.03901, 0.85158, 0.77025, 0.62264, 0.7646, 0.65351, 0.86026, 0.69461, 0.89947, 1.03075, 0.85158, 0.77812, 0.76449, 0.88836, 0.70466, 0.8562, 0.86822, 0.8588, 0.83864, 0.77212, 0.85308, 0.93637, 0.87514, 0.82352, 0.8588, 0.85701, 0.76013, 0.89058, 0.77598, 0.8156, 0.82565, 0.78112, 0.77899, 0.89386, 0.83864, 0.8156, 0.9486, 0.92388, 0.96186, 1.03075, 0.91123, 0.9486, 0.93298, 0.878, 0.93942, 0.92388, 0.84596, 0.96186, 0.95119, 1.03075, 0.922, 0.88787, 0.95829, 0.88, 0.93559, 0.93859, 0.78815, 0.93758, 1, 0.89217, 1.03737, 0.91123, 0.93969, 0.77487, 0.85769, 0.86799, 1.03075, 0.91123, 0.93859, 0.91123, 0.86799, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87832, 0.979, 0.87832, 0.979, 0.87832, 0.979, 0.77512, 0.882, 0.9219, 1, 0.89903, 1, 1, 1, 0.87321, 0.87321, 0.87321, 1, 1.027, 1.027, 1.027, 0.86847, 0.86847, 0.79121, 1, 1.124, 1, 1, 0.73572, 0.73572, 1, 1, 0.85034, 1, 1, 1, 1, 0.88465, 1, 1, 1, 0.669, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04828, 1, 0.74948, 0.75187, 1.02058, 0.98391, 1.02119, 1, 1, 1.06233, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05233, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const MyriadProItalicMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; +const MyriadProRegularFactors = [1.36898, 1, 1, 0.76305, 0.82784, 0.94935, 0.89364, 0.92241, 0.89073, 0.90706, 0.98472, 0.85283, 0.85283, 1.0664, 1.02058, 0.74505, 0.9219, 0.74505, 1.23456, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.74505, 0.74505, 1.02058, 1.02058, 1.02058, 0.73002, 0.72601, 0.91755, 0.8126, 0.80314, 0.92222, 0.73764, 0.79726, 0.83051, 0.90284, 0.86023, 0.74, 0.8126, 0.84869, 0.96518, 0.91115, 0.8858, 0.79761, 0.8858, 0.74498, 0.73914, 0.81363, 0.89591, 0.83659, 0.89633, 0.85608, 0.8111, 0.90531, 1.0222, 1.22736, 1.0222, 1.27014, 0.89903, 0.90088, 0.86667, 1.0231, 0.896, 1.01411, 0.90083, 1.05099, 1.00512, 0.99793, 1.05326, 1.09377, 0.938, 1.06226, 1.00119, 0.99793, 0.98714, 1.0231, 1.01231, 0.98196, 0.792, 1.19137, 0.99074, 0.962, 1.01915, 0.926, 0.942, 0.856, 0.85034, 0.92006, 0.85034, 1.02058, 0.69067, 0.92241, 0.92241, 0.92241, 0.92241, 0.92006, 0.9332, 0.90088, 0.91882, 0.93484, 0.75339, 1.02058, 0.56866, 0.54324, 0.79519, 1.08595, 1, 1, 0.90088, 1, 0.95325, 0.74505, 0.90088, 1, 0.97198, 0.75339, 0.91009, 0.91009, 0.91009, 0.66466, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.788, 0.80314, 0.73764, 0.73764, 0.73764, 0.73764, 0.86023, 0.86023, 0.86023, 0.86023, 0.92915, 0.91115, 0.8858, 0.8858, 0.8858, 0.8858, 0.8858, 1.02058, 0.8858, 0.89591, 0.89591, 0.89591, 0.89591, 0.8111, 0.79611, 0.89713, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86936, 0.896, 0.90083, 0.90083, 0.90083, 0.90083, 0.84224, 0.84224, 0.84224, 0.84224, 0.97276, 0.99793, 0.98714, 0.98714, 0.98714, 0.98714, 0.98714, 1.08595, 0.89876, 0.99074, 0.99074, 0.99074, 0.99074, 0.942, 1.0231, 0.942, 0.91755, 0.86667, 0.91755, 0.86667, 0.91755, 0.86667, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.92222, 0.93372, 0.92915, 1.01411, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.83051, 1.00512, 0.83051, 1.00512, 0.83051, 1.00512, 1, 1, 0.90284, 0.99793, 0.90976, 0.99793, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 1.05326, 0.86023, 0.84224, 0.82873, 1.07469, 0.74, 1.09377, 1, 1, 0.938, 0.84869, 1.06226, 1, 1, 0.84869, 0.83704, 0.84869, 0.81441, 0.85588, 1.08927, 0.91115, 0.99793, 1, 1, 0.91115, 0.99793, 0.91887, 0.90991, 0.99793, 0.8858, 0.98714, 0.8858, 0.98714, 0.8858, 0.98714, 0.894, 0.91434, 0.74498, 0.98196, 1, 1, 0.74498, 0.98196, 0.73914, 0.792, 0.73914, 0.792, 1, 1, 0.73914, 0.792, 1, 1, 0.81363, 0.904, 0.81363, 1.19137, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89633, 1.01915, 0.8111, 0.942, 0.8111, 0.90531, 0.856, 0.90531, 0.856, 0.90531, 0.856, 1, 0.92241, 0.91755, 0.86667, 0.788, 0.86936, 0.8858, 0.89876, 1, 1, 0.81363, 1.19137, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90388, 1.03901, 0.92138, 0.78105, 0.7154, 0.86169, 0.80513, 0.94007, 0.82528, 0.98612, 1.06226, 0.91755, 0.8126, 0.81884, 0.92819, 0.73764, 0.90531, 0.90284, 0.8858, 0.86023, 0.8126, 0.91172, 0.96518, 0.91115, 0.83089, 0.8858, 0.87791, 0.79761, 0.89297, 0.81363, 0.88157, 0.89992, 0.85608, 0.81992, 0.94307, 0.86023, 0.88157, 0.95308, 0.98699, 0.99793, 1.06226, 0.95817, 0.95308, 0.97358, 0.928, 0.98088, 0.98699, 0.92761, 0.99793, 0.96017, 1.06226, 0.986, 0.944, 0.95978, 0.938, 0.96705, 0.98714, 0.80442, 0.98972, 1, 0.89762, 1.04552, 0.95817, 0.99007, 0.87064, 0.91879, 0.88888, 1.06226, 0.95817, 0.98714, 0.95817, 0.88888, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89633, 1.01915, 0.89633, 1.01915, 0.89633, 1.01915, 0.8111, 0.942, 0.9219, 1, 0.89903, 1, 1, 1, 0.93173, 0.93173, 0.93173, 1, 1.06304, 1.06304, 1.06904, 0.89903, 0.89903, 0.80549, 1, 1.156, 1, 1, 0.76575, 0.76575, 1, 1, 0.72458, 1, 1, 1, 1, 0.92241, 1, 1, 1, 0.619, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.07257, 1, 0.74705, 0.71119, 1.02058, 1.024, 1.02119, 1, 1, 1.1536, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05638, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const MyriadProRegularMetrics = { + lineHeight: 1.2, + lineGap: 0.2 +}; + +;// ./src/core/segoeui_factors.js +const SegoeuiBoldFactors = [1.76738, 1, 1, 0.99297, 0.9824, 1.04016, 1.06497, 1.03424, 0.97529, 1.17647, 1.23203, 1.1085, 1.1085, 1.16939, 1.2107, 0.9754, 1.21408, 0.9754, 1.59578, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 0.81378, 0.81378, 1.2107, 1.2107, 1.2107, 0.71703, 0.97847, 0.97363, 0.88776, 0.8641, 1.02096, 0.79795, 0.85132, 0.914, 1.06085, 1.1406, 0.8007, 0.89858, 0.83693, 1.14889, 1.09398, 0.97489, 0.92094, 0.97489, 0.90399, 0.84041, 0.95923, 1.00135, 1, 1.06467, 0.98243, 0.90996, 0.99361, 1.1085, 1.56942, 1.1085, 1.2107, 0.74627, 0.94282, 0.96752, 1.01519, 0.86304, 1.01359, 0.97278, 1.15103, 1.01359, 0.98561, 1.02285, 1.02285, 1.00527, 1.02285, 1.0302, 0.99041, 1.0008, 1.01519, 1.01359, 1.02258, 0.79104, 1.16862, 0.99041, 0.97454, 1.02511, 0.99298, 0.96752, 0.95801, 0.94856, 1.16579, 0.94856, 1.2107, 0.9824, 1.03424, 1.03424, 1, 1.03424, 1.16579, 0.8727, 1.3871, 1.18622, 1.10818, 1.04478, 1.2107, 1.18622, 0.75155, 0.94994, 1.28826, 1.21408, 1.21408, 0.91056, 1, 0.91572, 0.9754, 0.64663, 1.18328, 1.24866, 1.04478, 1.14169, 1.15749, 1.17389, 0.71703, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.93506, 0.8641, 0.79795, 0.79795, 0.79795, 0.79795, 1.1406, 1.1406, 1.1406, 1.1406, 1.02096, 1.09398, 0.97426, 0.97426, 0.97426, 0.97426, 0.97426, 1.2107, 0.97489, 1.00135, 1.00135, 1.00135, 1.00135, 0.90996, 0.92094, 1.02798, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.93136, 0.86304, 0.97278, 0.97278, 0.97278, 0.97278, 1.02285, 1.02285, 1.02285, 1.02285, 0.97122, 0.99041, 1, 1, 1, 1, 1, 1.28826, 1.0008, 0.99041, 0.99041, 0.99041, 0.99041, 0.96752, 1.01519, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 1.02096, 1.03057, 1.02096, 1.03517, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.914, 1.01359, 0.914, 1.01359, 0.914, 1.01359, 1, 1, 1.06085, 0.98561, 1.06085, 1.00879, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 0.97138, 1.08692, 0.8007, 1.02285, 1, 1, 1.00527, 0.83693, 1.02285, 1, 1, 0.83693, 0.9455, 0.83693, 0.90418, 0.83693, 1.13005, 1.09398, 0.99041, 1, 1, 1.09398, 0.99041, 0.96692, 1.09251, 0.99041, 0.97489, 1.0008, 0.97489, 1.0008, 0.97489, 1.0008, 0.93994, 0.97931, 0.90399, 1.02258, 1, 1, 0.90399, 1.02258, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 1, 1, 0.95923, 1.07034, 0.95923, 1.16862, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.06467, 1.02511, 0.90996, 0.96752, 0.90996, 0.99361, 0.95801, 0.99361, 0.95801, 0.99361, 0.95801, 1.07733, 1.03424, 0.97363, 0.96752, 0.93506, 0.93136, 0.97489, 1.0008, 1, 1, 0.95923, 1.16862, 1.15103, 1.15103, 1.01173, 1.03959, 0.75953, 0.81378, 0.79912, 1.15103, 1.21994, 0.95161, 0.87815, 1.01149, 0.81525, 0.7676, 0.98167, 1.01134, 1.02546, 0.84097, 1.03089, 1.18102, 0.97363, 0.88776, 0.85134, 0.97826, 0.79795, 0.99361, 1.06085, 0.97489, 1.1406, 0.89858, 1.0388, 1.14889, 1.09398, 0.86039, 0.97489, 1.0595, 0.92094, 0.94793, 0.95923, 0.90996, 0.99346, 0.98243, 1.02112, 0.95493, 1.1406, 0.90996, 1.03574, 1.02597, 1.0008, 1.18102, 1.06628, 1.03574, 1.0192, 1.01932, 1.00886, 0.97531, 1.0106, 1.0008, 1.13189, 1.18102, 1.02277, 0.98683, 1.0016, 0.99561, 1.07237, 1.0008, 0.90434, 0.99921, 0.93803, 0.8965, 1.23085, 1.06628, 1.04983, 0.96268, 1.0499, 0.98439, 1.18102, 1.06628, 1.0008, 1.06628, 0.98439, 0.79795, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09466, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.97278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.02065, 1, 1, 1, 1, 1, 1, 1.06467, 1.02511, 1.06467, 1.02511, 1.06467, 1.02511, 0.90996, 0.96752, 1, 1.21408, 0.89903, 1, 1, 0.75155, 1.04394, 1.04394, 1.04394, 1.04394, 0.98633, 0.98633, 0.98633, 0.73047, 0.73047, 1.20642, 0.91211, 1.25635, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.12454, 0.93503, 1.03424, 1.19687, 1.03424, 1, 1, 1, 0.771, 1, 1, 1.15749, 1.15749, 1.15749, 1.10948, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.16897, 1, 0.96085, 0.90137, 1.2107, 1.18416, 1.13973, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21172, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18874, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.09193, 1.09193, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const SegoeuiBoldMetrics = { + lineHeight: 1.33008, + lineGap: 0 +}; +const SegoeuiBoldItalicFactors = [1.76738, 1, 1, 0.98946, 1.03959, 1.04016, 1.02809, 1.036, 0.97639, 1.10953, 1.23203, 1.11144, 1.11144, 1.16939, 1.21237, 0.9754, 1.21261, 0.9754, 1.59754, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 0.81378, 0.81378, 1.21237, 1.21237, 1.21237, 0.73541, 0.97847, 0.97363, 0.89723, 0.87897, 1.0426, 0.79429, 0.85292, 0.91149, 1.05815, 1.1406, 0.79631, 0.90128, 0.83853, 1.04396, 1.10615, 0.97552, 0.94436, 0.97552, 0.88641, 0.80527, 0.96083, 1.00135, 1, 1.06777, 0.9817, 0.91142, 0.99361, 1.11144, 1.57293, 1.11144, 1.21237, 0.74627, 1.31818, 1.06585, 0.97042, 0.83055, 0.97042, 0.93503, 1.1261, 0.97042, 0.97922, 1.14236, 0.94552, 1.01054, 1.14236, 1.02471, 0.97922, 0.94165, 0.97042, 0.97042, 1.0276, 0.78929, 1.1261, 0.97922, 0.95874, 1.02197, 0.98507, 0.96752, 0.97168, 0.95107, 1.16579, 0.95107, 1.21237, 1.03959, 1.036, 1.036, 1, 1.036, 1.16579, 0.87357, 1.31818, 1.18754, 1.26781, 1.05356, 1.21237, 1.18622, 0.79487, 0.94994, 1.29004, 1.24047, 1.24047, 1.31818, 1, 0.91484, 0.9754, 1.31818, 1.1349, 1.24866, 1.05356, 1.13934, 1.15574, 1.17389, 0.73541, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.94385, 0.87897, 0.79429, 0.79429, 0.79429, 0.79429, 1.1406, 1.1406, 1.1406, 1.1406, 1.0426, 1.10615, 0.97552, 0.97552, 0.97552, 0.97552, 0.97552, 1.21237, 0.97552, 1.00135, 1.00135, 1.00135, 1.00135, 0.91142, 0.94436, 0.98721, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 0.96705, 0.83055, 0.93503, 0.93503, 0.93503, 0.93503, 1.14236, 1.14236, 1.14236, 1.14236, 0.93125, 0.97922, 0.94165, 0.94165, 0.94165, 0.94165, 0.94165, 1.29004, 0.94165, 0.97922, 0.97922, 0.97922, 0.97922, 0.96752, 0.97042, 0.96752, 0.97363, 1.06585, 0.97363, 1.06585, 0.97363, 1.06585, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 1.0426, 1.0033, 1.0426, 0.97042, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.91149, 0.97042, 0.91149, 0.97042, 0.91149, 0.97042, 1, 1, 1.05815, 0.97922, 1.05815, 0.97922, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 0.97441, 1.04302, 0.79631, 1.01582, 1, 1, 1.01054, 0.83853, 1.14236, 1, 1, 0.83853, 1.09125, 0.83853, 0.90418, 0.83853, 1.19508, 1.10615, 0.97922, 1, 1, 1.10615, 0.97922, 1.01034, 1.10466, 0.97922, 0.97552, 0.94165, 0.97552, 0.94165, 0.97552, 0.94165, 0.91602, 0.91981, 0.88641, 1.0276, 1, 1, 0.88641, 1.0276, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 1, 1, 0.96083, 1.05403, 0.95923, 1.16862, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.06777, 1.02197, 0.91142, 0.96752, 0.91142, 0.99361, 0.97168, 0.99361, 0.97168, 0.99361, 0.97168, 1.23199, 1.036, 0.97363, 1.06585, 0.94385, 0.96705, 0.97552, 0.94165, 1, 1, 0.96083, 1.1261, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 0.95161, 1.27126, 1.00811, 0.83284, 0.77702, 0.99137, 0.95253, 1.0347, 0.86142, 1.07205, 1.14236, 0.97363, 0.89723, 0.86869, 1.09818, 0.79429, 0.99361, 1.05815, 0.97552, 1.1406, 0.90128, 1.06662, 1.04396, 1.10615, 0.84918, 0.97552, 1.04694, 0.94436, 0.98015, 0.96083, 0.91142, 1.00356, 0.9817, 1.01945, 0.98999, 1.1406, 0.91142, 1.04961, 0.9898, 1.00639, 1.14236, 1.07514, 1.04961, 0.99607, 1.02897, 1.008, 0.9898, 0.95134, 1.00639, 1.11121, 1.14236, 1.00518, 0.97981, 1.02186, 1, 1.08578, 0.94165, 0.99314, 0.98387, 0.93028, 0.93377, 1.35125, 1.07514, 1.10687, 0.93491, 1.04232, 1.00351, 1.14236, 1.07514, 0.94165, 1.07514, 1.00351, 0.79429, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09097, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.93503, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96609, 1, 1, 1, 1, 1, 1, 1.06777, 1.02197, 1.06777, 1.02197, 1.06777, 1.02197, 0.91142, 0.96752, 1, 1.21261, 0.89903, 1, 1, 0.75155, 1.04745, 1.04745, 1.04745, 1.04394, 0.98633, 0.98633, 0.98633, 0.72959, 0.72959, 1.20502, 0.91406, 1.26514, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.09125, 0.93327, 1.03336, 1.16541, 1.036, 1, 1, 1, 0.771, 1, 1, 1.15574, 1.15574, 1.15574, 1.15574, 0.86364, 0.94434, 0.86279, 0.94434, 0.86224, 1, 1, 1.16798, 1, 0.96085, 0.90068, 1.21237, 1.18416, 1.13904, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21339, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18775, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.13269, 1.13269, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const SegoeuiBoldItalicMetrics = { + lineHeight: 1.33008, + lineGap: 0 +}; +const SegoeuiItalicFactors = [1.76738, 1, 1, 0.98946, 1.14763, 1.05365, 1.06234, 0.96927, 0.92586, 1.15373, 1.18414, 0.91349, 0.91349, 1.07403, 1.17308, 0.78383, 1.20088, 0.78383, 1.42531, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78383, 0.78383, 1.17308, 1.17308, 1.17308, 0.77349, 0.94565, 0.94729, 0.85944, 0.88506, 0.9858, 0.74817, 0.80016, 0.88449, 0.98039, 0.95782, 0.69238, 0.89898, 0.83231, 0.98183, 1.03989, 0.96924, 0.86237, 0.96924, 0.80595, 0.74524, 0.86091, 0.95402, 0.94143, 0.98448, 0.8858, 0.83089, 0.93285, 1.0949, 1.39016, 1.0949, 1.45994, 0.74627, 1.04839, 0.97454, 0.97454, 0.87207, 0.97454, 0.87533, 1.06151, 0.97454, 1.00176, 1.16484, 1.08132, 0.98047, 1.16484, 1.02989, 1.01054, 0.96225, 0.97454, 0.97454, 1.06598, 0.79004, 1.16344, 1.00351, 0.94629, 0.9973, 0.91016, 0.96777, 0.9043, 0.91082, 0.92481, 0.91082, 1.17308, 0.95748, 0.96927, 0.96927, 1, 0.96927, 0.92481, 0.80597, 1.04839, 1.23393, 1.1781, 0.9245, 1.17308, 1.20808, 0.63218, 0.94261, 1.24822, 1.09971, 1.09971, 1.04839, 1, 0.85273, 0.78032, 1.04839, 1.09971, 1.22326, 0.9245, 1.09836, 1.13525, 1.15222, 0.70424, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.85498, 0.88506, 0.74817, 0.74817, 0.74817, 0.74817, 0.95782, 0.95782, 0.95782, 0.95782, 0.9858, 1.03989, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.17308, 0.96924, 0.95402, 0.95402, 0.95402, 0.95402, 0.83089, 0.86237, 0.88409, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.92916, 0.87207, 0.87533, 0.87533, 0.87533, 0.87533, 0.93146, 0.93146, 0.93146, 0.93146, 0.93854, 1.01054, 0.96225, 0.96225, 0.96225, 0.96225, 0.96225, 1.24822, 0.8761, 1.00351, 1.00351, 1.00351, 1.00351, 0.96777, 0.97454, 0.96777, 0.94729, 0.97454, 0.94729, 0.97454, 0.94729, 0.97454, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.9858, 0.95391, 0.9858, 0.97454, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.88449, 0.97454, 0.88449, 0.97454, 0.88449, 0.97454, 1, 1, 0.98039, 1.00176, 0.98039, 1.00176, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 1.16484, 0.95782, 0.93146, 0.84421, 1.12761, 0.69238, 1.08132, 1, 1, 0.98047, 0.83231, 1.16484, 1, 1, 0.84723, 1.04861, 0.84723, 0.78755, 0.83231, 1.23736, 1.03989, 1.01054, 1, 1, 1.03989, 1.01054, 0.9857, 1.03849, 1.01054, 0.96924, 0.96225, 0.96924, 0.96225, 0.96924, 0.96225, 0.92383, 0.90171, 0.80595, 1.06598, 1, 1, 0.80595, 1.06598, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 1, 1, 0.86091, 1.02759, 0.85771, 1.16344, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.98448, 0.9973, 0.83089, 0.96777, 0.83089, 0.93285, 0.9043, 0.93285, 0.9043, 0.93285, 0.9043, 1.31868, 0.96927, 0.94729, 0.97454, 0.85498, 0.92916, 0.96924, 0.8761, 1, 1, 0.86091, 1.16344, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 0.81965, 0.81965, 0.94729, 0.78032, 0.71022, 0.90883, 0.84171, 0.99877, 0.77596, 1.05734, 1.2, 0.94729, 0.85944, 0.82791, 0.9607, 0.74817, 0.93285, 0.98039, 0.96924, 0.95782, 0.89898, 0.98316, 0.98183, 1.03989, 0.78614, 0.96924, 0.97642, 0.86237, 0.86075, 0.86091, 0.83089, 0.90082, 0.8858, 0.97296, 1.01284, 0.95782, 0.83089, 1.0976, 1.04, 1.03342, 1.2, 1.0675, 1.0976, 0.98205, 1.03809, 1.05097, 1.04, 0.95364, 1.03342, 1.05401, 1.2, 1.02148, 1.0119, 1.04724, 1.0127, 1.02732, 0.96225, 0.8965, 0.97783, 0.93574, 0.94818, 1.30679, 1.0675, 1.11826, 0.99821, 1.0557, 1.0326, 1.2, 1.0675, 0.96225, 1.0675, 1.0326, 0.74817, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03754, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87533, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.98705, 1, 1, 1, 1, 1, 1, 0.98448, 0.9973, 0.98448, 0.9973, 0.98448, 0.9973, 0.83089, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 0.94945, 0.94945, 0.94945, 0.94945, 1.12317, 1.12317, 1.12317, 0.67603, 0.67603, 1.15621, 0.73584, 1.21191, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87709, 0.96927, 1.01473, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.09836, 1.09836, 1.09836, 1.01522, 0.86321, 0.94434, 0.8649, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86438, 1.17308, 1.18416, 1.14589, 0.69825, 0.97622, 1.96791, 1.24822, 1.24822, 1.17308, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.17984, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10742, 1.10742, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const SegoeuiItalicMetrics = { + lineHeight: 1.33008, + lineGap: 0 +}; +const SegoeuiRegularFactors = [1.76738, 1, 1, 0.98594, 1.02285, 1.10454, 1.06234, 0.96927, 0.92037, 1.19985, 1.2046, 0.90616, 0.90616, 1.07152, 1.1714, 0.78032, 1.20088, 0.78032, 1.40246, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78032, 0.78032, 1.1714, 1.1714, 1.1714, 0.80597, 0.94084, 0.96706, 0.85944, 0.85734, 0.97093, 0.75842, 0.79936, 0.88198, 0.9831, 0.95782, 0.71387, 0.86969, 0.84636, 1.07796, 1.03584, 0.96924, 0.83968, 0.96924, 0.82826, 0.79649, 0.85771, 0.95132, 0.93119, 0.98965, 0.88433, 0.8287, 0.93365, 1.08612, 1.3638, 1.08612, 1.45786, 0.74627, 0.80499, 0.91484, 1.05707, 0.92383, 1.05882, 0.9403, 1.12654, 1.05882, 1.01756, 1.09011, 1.09011, 0.99414, 1.09011, 1.034, 1.01756, 1.05356, 1.05707, 1.05882, 1.04399, 0.84863, 1.21968, 1.01756, 0.95801, 1.00068, 0.91797, 0.96777, 0.9043, 0.90351, 0.92105, 0.90351, 1.1714, 0.85337, 0.96927, 0.96927, 0.99912, 0.96927, 0.92105, 0.80597, 1.2434, 1.20808, 1.05937, 0.90957, 1.1714, 1.20808, 0.75155, 0.94261, 1.24644, 1.09971, 1.09971, 0.84751, 1, 0.85273, 0.78032, 0.61584, 1.05425, 1.17914, 0.90957, 1.08665, 1.11593, 1.14169, 0.73381, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.86035, 0.85734, 0.75842, 0.75842, 0.75842, 0.75842, 0.95782, 0.95782, 0.95782, 0.95782, 0.97093, 1.03584, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.1714, 0.96924, 0.95132, 0.95132, 0.95132, 0.95132, 0.8287, 0.83968, 0.89049, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.93575, 0.92383, 0.9403, 0.9403, 0.9403, 0.9403, 0.8717, 0.8717, 0.8717, 0.8717, 1.00527, 1.01756, 1.05356, 1.05356, 1.05356, 1.05356, 1.05356, 1.24644, 0.95923, 1.01756, 1.01756, 1.01756, 1.01756, 0.96777, 1.05707, 0.96777, 0.96706, 0.91484, 0.96706, 0.91484, 0.96706, 0.91484, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.97093, 1.0969, 0.97093, 1.05882, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.88198, 1.05882, 0.88198, 1.05882, 0.88198, 1.05882, 1, 1, 0.9831, 1.01756, 0.9831, 1.01756, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 1.09011, 0.95782, 0.8717, 0.84784, 1.11551, 0.71387, 1.09011, 1, 1, 0.99414, 0.84636, 1.09011, 1, 1, 0.84636, 1.0536, 0.84636, 0.94298, 0.84636, 1.23297, 1.03584, 1.01756, 1, 1, 1.03584, 1.01756, 1.00323, 1.03444, 1.01756, 0.96924, 1.05356, 0.96924, 1.05356, 0.96924, 1.05356, 0.93066, 0.98293, 0.82826, 1.04399, 1, 1, 0.82826, 1.04399, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 1, 1, 0.85771, 1.17318, 0.85771, 1.21968, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.98965, 1.00068, 0.8287, 0.96777, 0.8287, 0.93365, 0.9043, 0.93365, 0.9043, 0.93365, 0.9043, 1.08571, 0.96927, 0.96706, 0.91484, 0.86035, 0.93575, 0.96924, 0.95923, 1, 1, 0.85771, 1.21968, 1.11437, 1.11437, 0.93109, 0.91202, 0.60411, 0.84164, 0.55572, 1.01173, 0.97361, 0.81818, 0.81818, 0.96635, 0.78032, 0.72727, 0.92366, 0.98601, 1.03405, 0.77968, 1.09799, 1.2, 0.96706, 0.85944, 0.85638, 0.96491, 0.75842, 0.93365, 0.9831, 0.96924, 0.95782, 0.86969, 0.94152, 1.07796, 1.03584, 0.78437, 0.96924, 0.98715, 0.83968, 0.83491, 0.85771, 0.8287, 0.94492, 0.88433, 0.9287, 1.0098, 0.95782, 0.8287, 1.0625, 0.98248, 1.03424, 1.2, 1.01071, 1.0625, 0.95246, 1.03809, 1.04912, 0.98248, 1.00221, 1.03424, 1.05443, 1.2, 1.04785, 0.99609, 1.00169, 1.05176, 0.99346, 1.05356, 0.9087, 1.03004, 0.95542, 0.93117, 1.23362, 1.01071, 1.07831, 1.02512, 1.05205, 1.03502, 1.2, 1.01071, 1.05356, 1.01071, 1.03502, 0.75842, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03719, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9403, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04021, 1, 1, 1, 1, 1, 1, 0.98965, 1.00068, 0.98965, 1.00068, 0.98965, 1.00068, 0.8287, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 1.03077, 1.03077, 1.03077, 1.03077, 1.13196, 1.13196, 1.13196, 0.67428, 0.67428, 1.16039, 0.73291, 1.20996, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87796, 0.96927, 1.01518, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.10539, 1.10539, 1.11358, 1.06967, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86507, 1.1714, 1.18416, 1.14589, 0.69825, 0.97622, 1.9697, 1.24822, 1.24822, 1.17238, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18083, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10938, 1.10938, 1, 1, 1, 1.05425, 1.09971, 1.09971, 1.09971, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; +const SegoeuiRegularMetrics = { + lineHeight: 1.33008, + lineGap: 0 +}; + +;// ./src/core/xfa_fonts.js + + + + + + + + +const getXFAFontMap = getLookupTableFactory(function (t) { + t["MyriadPro-Regular"] = t["PdfJS-Fallback-Regular"] = { + name: "LiberationSans-Regular", + factors: MyriadProRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: MyriadProRegularMetrics + }; + t["MyriadPro-Bold"] = t["PdfJS-Fallback-Bold"] = { + name: "LiberationSans-Bold", + factors: MyriadProBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: MyriadProBoldMetrics + }; + t["MyriadPro-It"] = t["MyriadPro-Italic"] = t["PdfJS-Fallback-Italic"] = { + name: "LiberationSans-Italic", + factors: MyriadProItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: MyriadProItalicMetrics + }; + t["MyriadPro-BoldIt"] = t["MyriadPro-BoldItalic"] = t["PdfJS-Fallback-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: MyriadProBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: MyriadProBoldItalicMetrics + }; + t.ArialMT = t.Arial = t["Arial-Regular"] = { + name: "LiberationSans-Regular", + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping + }; + t["Arial-BoldMT"] = t["Arial-Bold"] = { + name: "LiberationSans-Bold", + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping + }; + t["Arial-ItalicMT"] = t["Arial-Italic"] = { + name: "LiberationSans-Italic", + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping + }; + t["Arial-BoldItalicMT"] = t["Arial-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping + }; + t["Calibri-Regular"] = { + name: "LiberationSans-Regular", + factors: CalibriRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: CalibriRegularMetrics + }; + t["Calibri-Bold"] = { + name: "LiberationSans-Bold", + factors: CalibriBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: CalibriBoldMetrics + }; + t["Calibri-Italic"] = { + name: "LiberationSans-Italic", + factors: CalibriItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: CalibriItalicMetrics + }; + t["Calibri-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: CalibriBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: CalibriBoldItalicMetrics + }; + t["Segoeui-Regular"] = { + name: "LiberationSans-Regular", + factors: SegoeuiRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: SegoeuiRegularMetrics + }; + t["Segoeui-Bold"] = { + name: "LiberationSans-Bold", + factors: SegoeuiBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: SegoeuiBoldMetrics + }; + t["Segoeui-Italic"] = { + name: "LiberationSans-Italic", + factors: SegoeuiItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: SegoeuiItalicMetrics + }; + t["Segoeui-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: SegoeuiBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: SegoeuiBoldItalicMetrics + }; + t["Helvetica-Regular"] = t.Helvetica = { + name: "LiberationSans-Regular", + factors: HelveticaRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: HelveticaRegularMetrics + }; + t["Helvetica-Bold"] = { + name: "LiberationSans-Bold", + factors: HelveticaBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: HelveticaBoldMetrics + }; + t["Helvetica-Italic"] = { + name: "LiberationSans-Italic", + factors: HelveticaItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: HelveticaItalicMetrics + }; + t["Helvetica-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: HelveticaBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: HelveticaBoldItalicMetrics + }; +}); +function getXfaFontName(name) { + const fontName = normalizeFontName(name); + const fontMap = getXFAFontMap(); + return fontMap[fontName]; +} +function getXfaFontWidths(name) { + const info = getXfaFontName(name); + if (!info) { + return null; + } + const { + baseWidths, + baseMapping, + factors + } = info; + const rescaledBaseWidths = !factors ? baseWidths : baseWidths.map((w, i) => w * factors[i]); + let currentCode = -2; + let currentArray; + const newWidths = []; + for (const [unicode, glyphIndex] of baseMapping.map((charUnicode, index) => [charUnicode, index]).sort(([unicode1], [unicode2]) => unicode1 - unicode2)) { + if (unicode === -1) { + continue; + } + if (unicode === currentCode + 1) { + currentArray.push(rescaledBaseWidths[glyphIndex]); + currentCode += 1; + } else { + currentCode = unicode; + currentArray = [rescaledBaseWidths[glyphIndex]]; + newWidths.push(unicode, currentArray); + } + } + return newWidths; +} +function getXfaFontDict(name) { + const widths = getXfaFontWidths(name); + const dict = new Dict(null); + dict.set("BaseFont", Name.get(name)); + dict.set("Type", Name.get("Font")); + dict.set("Subtype", Name.get("CIDFontType2")); + dict.set("Encoding", Name.get("Identity-H")); + dict.set("CIDToGIDMap", Name.get("Identity")); + dict.set("W", widths); + dict.set("FirstChar", widths[0]); + dict.set("LastChar", widths.at(-2) + widths.at(-1).length - 1); + const descriptor = new Dict(null); + dict.set("FontDescriptor", descriptor); + const systemInfo = new Dict(null); + systemInfo.set("Ordering", "Identity"); + systemInfo.set("Registry", "Adobe"); + systemInfo.set("Supplement", 0); + dict.set("CIDSystemInfo", systemInfo); + return dict; +} + +;// ./src/core/ps_parser.js + + + +class PostScriptParser { + constructor(lexer) { + this.lexer = lexer; + this.operators = []; + this.token = null; + this.prev = null; + } + nextToken() { + this.prev = this.token; + this.token = this.lexer.getToken(); + } + accept(type) { + if (this.token.type === type) { + this.nextToken(); + return true; + } + return false; + } + expect(type) { + if (this.accept(type)) { + return true; + } + throw new FormatError(`Unexpected symbol: found ${this.token.type} expected ${type}.`); + } + parse() { + this.nextToken(); + this.expect(PostScriptTokenTypes.LBRACE); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + return this.operators; + } + parseBlock() { + while (true) { + if (this.accept(PostScriptTokenTypes.NUMBER)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.OPERATOR)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + this.parseCondition(); + } else { + return; + } + } + } + parseCondition() { + const conditionLocation = this.operators.length; + this.operators.push(null, null); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + if (this.accept(PostScriptTokenTypes.IF)) { + this.operators[conditionLocation] = this.operators.length; + this.operators[conditionLocation + 1] = "jz"; + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + const jumpLocation = this.operators.length; + this.operators.push(null, null); + const endOfTrue = this.operators.length; + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + this.expect(PostScriptTokenTypes.IFELSE); + this.operators[jumpLocation] = this.operators.length; + this.operators[jumpLocation + 1] = "j"; + this.operators[conditionLocation] = endOfTrue; + this.operators[conditionLocation + 1] = "jz"; + } else { + throw new FormatError("PS Function: error parsing conditional."); + } + } +} +const PostScriptTokenTypes = { + LBRACE: 0, + RBRACE: 1, + NUMBER: 2, + OPERATOR: 3, + IF: 4, + IFELSE: 5 +}; +class PostScriptToken { + static get opCache() { + return shadow(this, "opCache", Object.create(null)); + } + constructor(type, value) { + this.type = type; + this.value = value; + } + static getOperator(op) { + return PostScriptToken.opCache[op] ||= new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); + } + static get LBRACE() { + return shadow(this, "LBRACE", new PostScriptToken(PostScriptTokenTypes.LBRACE, "{")); + } + static get RBRACE() { + return shadow(this, "RBRACE", new PostScriptToken(PostScriptTokenTypes.RBRACE, "}")); + } + static get IF() { + return shadow(this, "IF", new PostScriptToken(PostScriptTokenTypes.IF, "IF")); + } + static get IFELSE() { + return shadow(this, "IFELSE", new PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE")); + } +} +class PostScriptLexer { + constructor(stream) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + getToken() { + let comment = false; + let ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0a || ch === 0x0d) { + comment = false; + } + } else if (ch === 0x25) { + comment = true; + } else if (!isWhiteSpace(ch)) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x2b: + case 0x2d: + case 0x2e: + return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber()); + case 0x7b: + this.nextChar(); + return PostScriptToken.LBRACE; + case 0x7d: + this.nextChar(); + return PostScriptToken.RBRACE; + } + const strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a)) { + strBuf.push(String.fromCharCode(ch)); + } + const str = strBuf.join(""); + switch (str.toLowerCase()) { + case "if": + return PostScriptToken.IF; + case "ifelse": + return PostScriptToken.IFELSE; + default: + return PostScriptToken.getOperator(str); + } + } + getNumber() { + let ch = this.currentChar; + const strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + while ((ch = this.nextChar()) >= 0) { + if (ch >= 0x30 && ch <= 0x39 || ch === 0x2d || ch === 0x2e) { + strBuf.push(String.fromCharCode(ch)); + } else { + break; + } + } + const value = parseFloat(strBuf.join("")); + if (isNaN(value)) { + throw new FormatError(`Invalid floating point number: ${value}`); + } + return value; + } +} + +;// ./src/core/image_utils.js + + +class BaseLocalCache { + constructor(options) { + this._onlyRefs = options?.onlyRefs === true; + if (!this._onlyRefs) { + this._nameRefMap = new Map(); + this._imageMap = new Map(); + } + this._imageCache = new RefSetCache(); + } + getByName(name) { + if (this._onlyRefs) { + unreachable("Should not call `getByName` method."); + } + const ref = this._nameRefMap.get(name); + if (ref) { + return this.getByRef(ref); + } + return this._imageMap.get(name) || null; + } + getByRef(ref) { + return this._imageCache.get(ref) || null; + } + set(name, ref, data) { + unreachable("Abstract method `set` called."); + } +} +class LocalImageCache extends BaseLocalCache { + set(name, ref = null, data) { + if (typeof name !== "string") { + throw new Error('LocalImageCache.set - expected "name" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + this._nameRefMap.set(name, ref); + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } +} +class LocalColorSpaceCache extends BaseLocalCache { + set(name = null, ref = null, data) { + if (typeof name !== "string" && !ref) { + throw new Error('LocalColorSpaceCache.set - expected "name" and/or "ref" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + if (name !== null) { + this._nameRefMap.set(name, ref); + } + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } +} +class LocalFunctionCache extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('LocalFunctionCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } +} +class LocalGStateCache extends BaseLocalCache { + set(name, ref = null, data) { + if (typeof name !== "string") { + throw new Error('LocalGStateCache.set - expected "name" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + this._nameRefMap.set(name, ref); + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } +} +class LocalTilingPatternCache extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('LocalTilingPatternCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } +} +class RegionalImageCache extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('RegionalImageCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } +} +class GlobalColorSpaceCache extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('GlobalColorSpaceCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } + clear() { + this._imageCache.clear(); + } +} +class GlobalImageCache { + static NUM_PAGES_THRESHOLD = 2; + static MIN_IMAGES_TO_CACHE = 10; + static MAX_BYTE_SIZE = 5e7; + #decodeFailedSet = new RefSet(); + constructor() { + this._refCache = new RefSetCache(); + this._imageCache = new RefSetCache(); + } + get #byteSize() { + let byteSize = 0; + for (const imageData of this._imageCache) { + byteSize += imageData.byteSize; + } + return byteSize; + } + get #cacheLimitReached() { + if (this._imageCache.size < GlobalImageCache.MIN_IMAGES_TO_CACHE) { + return false; + } + if (this.#byteSize < GlobalImageCache.MAX_BYTE_SIZE) { + return false; + } + return true; + } + shouldCache(ref, pageIndex) { + let pageIndexSet = this._refCache.get(ref); + if (!pageIndexSet) { + pageIndexSet = new Set(); + this._refCache.put(ref, pageIndexSet); + } + pageIndexSet.add(pageIndex); + if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) { + return false; + } + if (!this._imageCache.has(ref) && this.#cacheLimitReached) { + return false; + } + return true; + } + addDecodeFailed(ref) { + this.#decodeFailedSet.put(ref); + } + hasDecodeFailed(ref) { + return this.#decodeFailedSet.has(ref); + } + addByteSize(ref, byteSize) { + const imageData = this._imageCache.get(ref); + if (!imageData) { + return; + } + if (imageData.byteSize) { + return; + } + imageData.byteSize = byteSize; + } + getData(ref, pageIndex) { + const pageIndexSet = this._refCache.get(ref); + if (!pageIndexSet) { + return null; + } + if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) { + return null; + } + const imageData = this._imageCache.get(ref); + if (!imageData) { + return null; + } + pageIndexSet.add(pageIndex); + return imageData; + } + setData(ref, data) { + if (!this._refCache.has(ref)) { + throw new Error('GlobalImageCache.setData - expected "shouldCache" to have been called.'); + } + if (this._imageCache.has(ref)) { + return; + } + if (this.#cacheLimitReached) { + warn("GlobalImageCache.setData - cache limit reached."); + return; + } + this._imageCache.put(ref, data); + } + clear(onlyData = false) { + if (!onlyData) { + this.#decodeFailedSet.clear(); + this._refCache.clear(); + } + this._imageCache.clear(); + } +} + +;// ./src/core/function.js + + + + + + +class PDFFunctionFactory { + constructor({ + xref, + isEvalSupported = true + }) { + this.xref = xref; + this.isEvalSupported = isEvalSupported !== false; + } + create(fn, parseArray = false) { + let fnRef, parsedFn; + if (fn instanceof Ref) { + fnRef = fn; + } else if (fn instanceof Dict) { + fnRef = fn.objId; + } else if (fn instanceof BaseStream) { + fnRef = fn.dict?.objId; + } + if (fnRef) { + const cachedFn = this._localFunctionCache.getByRef(fnRef); + if (cachedFn) { + return cachedFn; + } + } + const fnObj = this.xref.fetchIfRef(fn); + if (Array.isArray(fnObj)) { + if (!parseArray) { + throw new Error('PDFFunctionFactory.create - expected "parseArray" argument.'); + } + parsedFn = PDFFunction.parseArray(this, fnObj); + } else { + parsedFn = PDFFunction.parse(this, fnObj); + } + if (fnRef) { + this._localFunctionCache.set(null, fnRef, parsedFn); + } + return parsedFn; + } + get _localFunctionCache() { + return shadow(this, "_localFunctionCache", new LocalFunctionCache()); + } +} +function toNumberArray(arr) { + if (!Array.isArray(arr)) { + return null; + } + if (!isNumberArray(arr, null)) { + return arr.map(x => +x); + } + return arr; +} +class PDFFunction { + static getSampleArray(size, outputSize, bps, stream) { + let i, ii; + let length = 1; + for (i = 0, ii = size.length; i < ii; i++) { + length *= size[i]; + } + length *= outputSize; + const array = new Array(length); + let codeSize = 0; + let codeBuf = 0; + const sampleMul = 1.0 / (2.0 ** bps - 1); + const strBytes = stream.getBytes((length * bps + 7) / 8); + let strIdx = 0; + for (i = 0; i < length; i++) { + while (codeSize < bps) { + codeBuf <<= 8; + codeBuf |= strBytes[strIdx++]; + codeSize += 8; + } + codeSize -= bps; + array[i] = (codeBuf >> codeSize) * sampleMul; + codeBuf &= (1 << codeSize) - 1; + } + return array; + } + static parse(factory, fn) { + const dict = fn.dict || fn; + const typeNum = dict.get("FunctionType"); + switch (typeNum) { + case 0: + return this.constructSampled(factory, fn, dict); + case 1: + break; + case 2: + return this.constructInterpolated(factory, dict); + case 3: + return this.constructStiched(factory, dict); + case 4: + return this.constructPostScript(factory, fn, dict); + } + throw new FormatError("Unknown type of function"); + } + static parseArray(factory, fnObj) { + const { + xref + } = factory; + const fnArray = []; + for (const fn of fnObj) { + fnArray.push(this.parse(factory, xref.fetchIfRef(fn))); + } + return function (src, srcOffset, dest, destOffset) { + for (let i = 0, ii = fnArray.length; i < ii; i++) { + fnArray[i](src, srcOffset, dest, destOffset + i); + } + }; + } + static constructSampled(factory, fn, dict) { + function toMultiArray(arr) { + const inputLength = arr.length; + const out = []; + let index = 0; + for (let i = 0; i < inputLength; i += 2) { + out[index++] = [arr[i], arr[i + 1]]; + } + return out; + } + function interpolate(x, xmin, xmax, ymin, ymax) { + return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin)); + } + let domain = toNumberArray(dict.getArray("Domain")); + let range = toNumberArray(dict.getArray("Range")); + if (!domain || !range) { + throw new FormatError("No domain or range"); + } + const inputSize = domain.length / 2; + const outputSize = range.length / 2; + domain = toMultiArray(domain); + range = toMultiArray(range); + const size = toNumberArray(dict.getArray("Size")); + const bps = dict.get("BitsPerSample"); + const order = dict.get("Order") || 1; + if (order !== 1) { + info("No support for cubic spline interpolation: " + order); + } + let encode = toNumberArray(dict.getArray("Encode")); + if (!encode) { + encode = []; + for (let i = 0; i < inputSize; ++i) { + encode.push([0, size[i] - 1]); + } + } else { + encode = toMultiArray(encode); + } + let decode = toNumberArray(dict.getArray("Decode")); + decode = !decode ? range : toMultiArray(decode); + const samples = this.getSampleArray(size, outputSize, bps, fn); + return function constructSampledFn(src, srcOffset, dest, destOffset) { + const cubeVertices = 1 << inputSize; + const cubeN = new Float64Array(cubeVertices).fill(1); + const cubeVertex = new Uint32Array(cubeVertices); + let i, j; + let k = outputSize, + pos = 1; + for (i = 0; i < inputSize; ++i) { + const domain_2i = domain[i][0]; + const domain_2i_1 = domain[i][1]; + const xi = MathClamp(src[srcOffset + i], domain_2i, domain_2i_1); + let e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]); + const size_i = size[i]; + e = MathClamp(e, 0, size_i - 1); + const e0 = e < size_i - 1 ? Math.floor(e) : e - 1; + const n0 = e0 + 1 - e; + const n1 = e - e0; + const offset0 = e0 * k; + const offset1 = offset0 + k; + for (j = 0; j < cubeVertices; j++) { + if (j & pos) { + cubeN[j] *= n1; + cubeVertex[j] += offset1; + } else { + cubeN[j] *= n0; + cubeVertex[j] += offset0; + } + } + k *= size_i; + pos <<= 1; + } + for (j = 0; j < outputSize; ++j) { + let rj = 0; + for (i = 0; i < cubeVertices; i++) { + rj += samples[cubeVertex[i] + j] * cubeN[i]; + } + rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); + dest[destOffset + j] = MathClamp(rj, range[j][0], range[j][1]); + } + }; + } + static constructInterpolated(factory, dict) { + const c0 = toNumberArray(dict.getArray("C0")) || [0]; + const c1 = toNumberArray(dict.getArray("C1")) || [1]; + const n = dict.get("N"); + const diff = []; + for (let i = 0, ii = c0.length; i < ii; ++i) { + diff.push(c1[i] - c0[i]); + } + const length = diff.length; + return function constructInterpolatedFn(src, srcOffset, dest, destOffset) { + const x = n === 1 ? src[srcOffset] : src[srcOffset] ** n; + for (let j = 0; j < length; ++j) { + dest[destOffset + j] = c0[j] + x * diff[j]; + } + }; + } + static constructStiched(factory, dict) { + const domain = toNumberArray(dict.getArray("Domain")); + if (!domain) { + throw new FormatError("No domain"); + } + const inputSize = domain.length / 2; + if (inputSize !== 1) { + throw new FormatError("Bad domain for stiched function"); + } + const { + xref + } = factory; + const fns = []; + for (const fn of dict.get("Functions")) { + fns.push(this.parse(factory, xref.fetchIfRef(fn))); + } + const bounds = toNumberArray(dict.getArray("Bounds")); + const encode = toNumberArray(dict.getArray("Encode")); + const tmpBuf = new Float32Array(1); + return function constructStichedFn(src, srcOffset, dest, destOffset) { + const v = MathClamp(src[srcOffset], domain[0], domain[1]); + const length = bounds.length; + let i; + for (i = 0; i < length; ++i) { + if (v < bounds[i]) { + break; + } + } + let dmin = domain[0]; + if (i > 0) { + dmin = bounds[i - 1]; + } + let dmax = domain[1]; + if (i < bounds.length) { + dmax = bounds[i]; + } + const rmin = encode[2 * i]; + const rmax = encode[2 * i + 1]; + tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + fns[i](tmpBuf, 0, dest, destOffset); + }; + } + static constructPostScript(factory, fn, dict) { + const domain = toNumberArray(dict.getArray("Domain")); + const range = toNumberArray(dict.getArray("Range")); + if (!domain) { + throw new FormatError("No domain."); + } + if (!range) { + throw new FormatError("No range."); + } + const lexer = new PostScriptLexer(fn); + const parser = new PostScriptParser(lexer); + const code = parser.parse(); + if (factory.isEvalSupported && FeatureTest.isEvalSupported) { + const compiled = new PostScriptCompiler().compile(code, domain, range); + if (compiled) { + return new Function("src", "srcOffset", "dest", "destOffset", compiled); + } + } + info("Unable to compile PS function"); + const numOutputs = range.length >> 1; + const numInputs = domain.length >> 1; + const evaluator = new PostScriptEvaluator(code); + const cache = Object.create(null); + const MAX_CACHE_SIZE = 2048 * 4; + let cache_available = MAX_CACHE_SIZE; + const tmpBuf = new Float32Array(numInputs); + return function constructPostScriptFn(src, srcOffset, dest, destOffset) { + let i, value; + let key = ""; + const input = tmpBuf; + for (i = 0; i < numInputs; i++) { + value = src[srcOffset + i]; + input[i] = value; + key += value + "_"; + } + const cachedValue = cache[key]; + if (cachedValue !== undefined) { + dest.set(cachedValue, destOffset); + return; + } + const output = new Float32Array(numOutputs); + const stack = evaluator.execute(input); + const stackIndex = stack.length - numOutputs; + for (i = 0; i < numOutputs; i++) { + value = stack[stackIndex + i]; + let bound = range[i * 2]; + if (value < bound) { + value = bound; + } else { + bound = range[i * 2 + 1]; + if (value > bound) { + value = bound; + } + } + output[i] = value; + } + if (cache_available > 0) { + cache_available--; + cache[key] = output; + } + dest.set(output, destOffset); + }; + } +} +function isPDFFunction(v) { + let fnDict; + if (v instanceof Dict) { + fnDict = v; + } else if (v instanceof BaseStream) { + fnDict = v.dict; + } else { + return false; + } + return fnDict.has("FunctionType"); +} +class PostScriptStack { + static MAX_STACK_SIZE = 100; + constructor(initialStack) { + this.stack = initialStack ? Array.from(initialStack) : []; + } + push(value) { + if (this.stack.length >= PostScriptStack.MAX_STACK_SIZE) { + throw new Error("PostScript function stack overflow."); + } + this.stack.push(value); + } + pop() { + if (this.stack.length <= 0) { + throw new Error("PostScript function stack underflow."); + } + return this.stack.pop(); + } + copy(n) { + if (this.stack.length + n >= PostScriptStack.MAX_STACK_SIZE) { + throw new Error("PostScript function stack overflow."); + } + const stack = this.stack; + for (let i = stack.length - n, j = n - 1; j >= 0; j--, i++) { + stack.push(stack[i]); + } + } + index(n) { + this.push(this.stack[this.stack.length - n - 1]); + } + roll(n, p) { + const stack = this.stack; + const l = stack.length - n; + const r = stack.length - 1; + const c = l + (p - Math.floor(p / n) * n); + for (let i = l, j = r; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (let i = l, j = c - 1; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (let i = c, j = r; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + } +} +class PostScriptEvaluator { + constructor(operators) { + this.operators = operators; + } + execute(initialStack) { + const stack = new PostScriptStack(initialStack); + let counter = 0; + const operators = this.operators; + const length = operators.length; + let operator, a, b; + while (counter < length) { + operator = operators[counter++]; + if (typeof operator === "number") { + stack.push(operator); + continue; + } + switch (operator) { + case "jz": + b = stack.pop(); + a = stack.pop(); + if (!a) { + counter = b; + } + break; + case "j": + a = stack.pop(); + counter = a; + break; + case "abs": + a = stack.pop(); + stack.push(Math.abs(a)); + break; + case "add": + b = stack.pop(); + a = stack.pop(); + stack.push(a + b); + break; + case "and": + b = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b === "boolean") { + stack.push(a && b); + } else { + stack.push(a & b); + } + break; + case "atan": + b = stack.pop(); + a = stack.pop(); + a = Math.atan2(a, b) / Math.PI * 180; + if (a < 0) { + a += 360; + } + stack.push(a); + break; + case "bitshift": + b = stack.pop(); + a = stack.pop(); + if (a > 0) { + stack.push(a << b); + } else { + stack.push(a >> b); + } + break; + case "ceiling": + a = stack.pop(); + stack.push(Math.ceil(a)); + break; + case "copy": + a = stack.pop(); + stack.copy(a); + break; + case "cos": + a = stack.pop(); + stack.push(Math.cos(a % 360 / 180 * Math.PI)); + break; + case "cvi": + a = stack.pop() | 0; + stack.push(a); + break; + case "cvr": + break; + case "div": + b = stack.pop(); + a = stack.pop(); + stack.push(a / b); + break; + case "dup": + stack.copy(1); + break; + case "eq": + b = stack.pop(); + a = stack.pop(); + stack.push(a === b); + break; + case "exch": + stack.roll(2, 1); + break; + case "exp": + b = stack.pop(); + a = stack.pop(); + stack.push(a ** b); + break; + case "false": + stack.push(false); + break; + case "floor": + a = stack.pop(); + stack.push(Math.floor(a)); + break; + case "ge": + b = stack.pop(); + a = stack.pop(); + stack.push(a >= b); + break; + case "gt": + b = stack.pop(); + a = stack.pop(); + stack.push(a > b); + break; + case "idiv": + b = stack.pop(); + a = stack.pop(); + stack.push(a / b | 0); + break; + case "index": + a = stack.pop(); + stack.index(a); + break; + case "le": + b = stack.pop(); + a = stack.pop(); + stack.push(a <= b); + break; + case "ln": + a = stack.pop(); + stack.push(Math.log(a)); + break; + case "log": + a = stack.pop(); + stack.push(Math.log10(a)); + break; + case "lt": + b = stack.pop(); + a = stack.pop(); + stack.push(a < b); + break; + case "mod": + b = stack.pop(); + a = stack.pop(); + stack.push(a % b); + break; + case "mul": + b = stack.pop(); + a = stack.pop(); + stack.push(a * b); + break; + case "ne": + b = stack.pop(); + a = stack.pop(); + stack.push(a !== b); + break; + case "neg": + a = stack.pop(); + stack.push(-a); + break; + case "not": + a = stack.pop(); + if (typeof a === "boolean") { + stack.push(!a); + } else { + stack.push(~a); + } + break; + case "or": + b = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b === "boolean") { + stack.push(a || b); + } else { + stack.push(a | b); + } + break; + case "pop": + stack.pop(); + break; + case "roll": + b = stack.pop(); + a = stack.pop(); + stack.roll(a, b); + break; + case "round": + a = stack.pop(); + stack.push(Math.round(a)); + break; + case "sin": + a = stack.pop(); + stack.push(Math.sin(a % 360 / 180 * Math.PI)); + break; + case "sqrt": + a = stack.pop(); + stack.push(Math.sqrt(a)); + break; + case "sub": + b = stack.pop(); + a = stack.pop(); + stack.push(a - b); + break; + case "true": + stack.push(true); + break; + case "truncate": + a = stack.pop(); + a = a < 0 ? Math.ceil(a) : Math.floor(a); + stack.push(a); + break; + case "xor": + b = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b === "boolean") { + stack.push(a !== b); + } else { + stack.push(a ^ b); + } + break; + default: + throw new FormatError(`Unknown operator ${operator}`); + } + } + return stack.stack; + } +} +class AstNode { + constructor(type) { + this.type = type; + } + visit(visitor) { + unreachable("abstract method"); + } +} +class AstArgument extends AstNode { + constructor(index, min, max) { + super("args"); + this.index = index; + this.min = min; + this.max = max; + } + visit(visitor) { + visitor.visitArgument(this); + } +} +class AstLiteral extends AstNode { + constructor(number) { + super("literal"); + this.number = number; + this.min = number; + this.max = number; + } + visit(visitor) { + visitor.visitLiteral(this); + } +} +class AstBinaryOperation extends AstNode { + constructor(op, arg1, arg2, min, max) { + super("binary"); + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + this.min = min; + this.max = max; + } + visit(visitor) { + visitor.visitBinaryOperation(this); + } +} +class AstMin extends AstNode { + constructor(arg, max) { + super("max"); + this.arg = arg; + this.min = arg.min; + this.max = max; + } + visit(visitor) { + visitor.visitMin(this); + } +} +class AstVariable extends AstNode { + constructor(index, min, max) { + super("var"); + this.index = index; + this.min = min; + this.max = max; + } + visit(visitor) { + visitor.visitVariable(this); + } +} +class AstVariableDefinition extends AstNode { + constructor(variable, arg) { + super("definition"); + this.variable = variable; + this.arg = arg; + } + visit(visitor) { + visitor.visitVariableDefinition(this); + } +} +class ExpressionBuilderVisitor { + constructor() { + this.parts = []; + } + visitArgument(arg) { + this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))"); + } + visitVariable(variable) { + this.parts.push("v", variable.index); + } + visitLiteral(literal) { + this.parts.push(literal.number); + } + visitBinaryOperation(operation) { + this.parts.push("("); + operation.arg1.visit(this); + this.parts.push(" ", operation.op, " "); + operation.arg2.visit(this); + this.parts.push(")"); + } + visitVariableDefinition(definition) { + this.parts.push("var "); + definition.variable.visit(this); + this.parts.push(" = "); + definition.arg.visit(this); + this.parts.push(";"); + } + visitMin(max) { + this.parts.push("Math.min("); + max.arg.visit(this); + this.parts.push(", ", max.max, ")"); + } + toString() { + return this.parts.join(""); + } +} +function buildAddOperation(num1, num2) { + if (num2.type === "literal" && num2.number === 0) { + return num1; + } + if (num1.type === "literal" && num1.number === 0) { + return num2; + } + if (num2.type === "literal" && num1.type === "literal") { + return new AstLiteral(num1.number + num2.number); + } + return new AstBinaryOperation("+", num1, num2, num1.min + num2.min, num1.max + num2.max); +} +function buildMulOperation(num1, num2) { + if (num2.type === "literal") { + if (num2.number === 0) { + return new AstLiteral(0); + } else if (num2.number === 1) { + return num1; + } else if (num1.type === "literal") { + return new AstLiteral(num1.number * num2.number); + } + } + if (num1.type === "literal") { + if (num1.number === 0) { + return new AstLiteral(0); + } else if (num1.number === 1) { + return num2; + } + } + const min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + const max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + return new AstBinaryOperation("*", num1, num2, min, max); +} +function buildSubOperation(num1, num2) { + if (num2.type === "literal") { + if (num2.number === 0) { + return num1; + } else if (num1.type === "literal") { + return new AstLiteral(num1.number - num2.number); + } + } + if (num2.type === "binary" && num2.op === "-" && num1.type === "literal" && num1.number === 1 && num2.arg1.type === "literal" && num2.arg1.number === 1) { + return num2.arg2; + } + return new AstBinaryOperation("-", num1, num2, num1.min - num2.max, num1.max - num2.min); +} +function buildMinOperation(num1, max) { + if (num1.min >= max) { + return new AstLiteral(max); + } else if (num1.max <= max) { + return num1; + } + return new AstMin(num1, max); +} +class PostScriptCompiler { + compile(code, domain, range) { + const stack = []; + const instructions = []; + const inputSize = domain.length >> 1, + outputSize = range.length >> 1; + let lastRegister = 0; + let n, j; + let num1, num2, ast1, ast2, tmpVar, item; + for (let i = 0; i < inputSize; i++) { + stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); + } + for (let i = 0, ii = code.length; i < ii; i++) { + item = code[i]; + if (typeof item === "number") { + stack.push(new AstLiteral(item)); + continue; + } + switch (item) { + case "add": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildAddOperation(num1, num2)); + break; + case "cvr": + if (stack.length < 1) { + return null; + } + break; + case "mul": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildMulOperation(num1, num2)); + break; + case "sub": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildSubOperation(num1, num2)); + break; + case "exch": + if (stack.length < 2) { + return null; + } + ast1 = stack.pop(); + ast2 = stack.pop(); + stack.push(ast1, ast2); + break; + case "pop": + if (stack.length < 1) { + return null; + } + stack.pop(); + break; + case "index": + if (stack.length < 1) { + return null; + } + num1 = stack.pop(); + if (num1.type !== "literal") { + return null; + } + n = num1.number; + if (n < 0 || !Number.isInteger(n) || stack.length < n) { + return null; + } + ast1 = stack[stack.length - n - 1]; + if (ast1.type === "literal" || ast1.type === "var") { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - n - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case "dup": + if (stack.length < 1) { + return null; + } + if (typeof code[i + 1] === "number" && code[i + 2] === "gt" && code[i + 3] === i + 7 && code[i + 4] === "jz" && code[i + 5] === "pop" && code[i + 6] === code[i + 1]) { + num1 = stack.pop(); + stack.push(buildMinOperation(num1, code[i + 1])); + i += 6; + break; + } + ast1 = stack.at(-1); + if (ast1.type === "literal" || ast1.type === "var") { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case "roll": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + if (num2.type !== "literal" || num1.type !== "literal") { + return null; + } + j = num2.number; + n = num1.number; + if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) { + return null; + } + j = (j % n + n) % n; + if (j === 0) { + break; + } + stack.push(...stack.splice(stack.length - n, n - j)); + break; + default: + return null; + } + } + if (stack.length !== outputSize) { + return null; + } + const result = []; + for (const instruction of instructions) { + const statementBuilder = new ExpressionBuilderVisitor(); + instruction.visit(statementBuilder); + result.push(statementBuilder.toString()); + } + for (let i = 0, ii = stack.length; i < ii; i++) { + const expr = stack[i], + statementBuilder = new ExpressionBuilderVisitor(); + expr.visit(statementBuilder); + const min = range[i * 2], + max = range[i * 2 + 1]; + const out = [statementBuilder.toString()]; + if (min > expr.min) { + out.unshift("Math.max(", min, ", "); + out.push(")"); + } + if (max < expr.max) { + out.unshift("Math.min(", max, ", "); + out.push(")"); + } + out.unshift("dest[destOffset + ", i, "] = "); + out.push(";"); + result.push(out.join("")); + } + return result.join("\n"); + } +} + +;// ./src/core/bidi.js + +const baseTypes = ["BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S", "WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "ON", "ON", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "ON", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "BN", "BN", "BN", "BN", "BN", "BN", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "ON", "ET", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "L", "ON", "ON", "BN", "ON", "ON", "ET", "ET", "EN", "EN", "ON", "L", "ON", "ON", "ON", "EN", "L", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L"]; +const arabicTypes = ["AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL", "CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "ET", "AN", "AN", "AL", "AL", "AL", "NSM", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM", "ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL"]; +function isOdd(i) { + return (i & 1) !== 0; +} +function isEven(i) { + return (i & 1) === 0; +} +function findUnequal(arr, start, value) { + let j, jj; + for (j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] !== value) { + return j; + } + } + return j; +} +function reverseValues(arr, start, end) { + for (let i = start, j = end - 1; i < j; ++i, --j) { + const temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } +} +function createBidiText(str, isLTR, vertical = false) { + let dir = "ltr"; + if (vertical) { + dir = "ttb"; + } else if (!isLTR) { + dir = "rtl"; + } + return { + str, + dir + }; +} +const chars = []; +const types = []; +function bidi(str, startLevel = -1, vertical = false) { + let isLTR = true; + const strLength = str.length; + if (strLength === 0 || vertical) { + return createBidiText(str, isLTR, vertical); + } + chars.length = strLength; + types.length = strLength; + let numBidi = 0; + let i, ii; + for (i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + const charCode = str.charCodeAt(i); + let charType = "L"; + if (charCode <= 0x00ff) { + charType = baseTypes[charCode]; + } else if (0x0590 <= charCode && charCode <= 0x05f4) { + charType = "R"; + } else if (0x0600 <= charCode && charCode <= 0x06ff) { + charType = arabicTypes[charCode & 0xff]; + if (!charType) { + warn("Bidi: invalid Unicode character " + charCode.toString(16)); + } + } else if (0x0700 <= charCode && charCode <= 0x08ac || 0xfb50 <= charCode && charCode <= 0xfdff || 0xfe70 <= charCode && charCode <= 0xfeff) { + charType = "AL"; + } + if (charType === "R" || charType === "AL" || charType === "AN") { + numBidi++; + } + types[i] = charType; + } + if (numBidi === 0) { + isLTR = true; + return createBidiText(str, isLTR); + } + if (startLevel === -1) { + if (numBidi / strLength < 0.3 && strLength > 4) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + const levels = []; + for (i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + const e = isOdd(startLevel) ? "R" : "L"; + const sor = e; + const eor = sor; + let lastType = sor; + for (i = 0; i < strLength; ++i) { + if (types[i] === "NSM") { + types[i] = lastType; + } else { + lastType = types[i]; + } + } + lastType = sor; + let t; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === "EN") { + types[i] = lastType === "AL" ? "AN" : "EN"; + } else if (t === "R" || t === "L" || t === "AL") { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === "AL") { + types[i] = "R"; + } + } + for (i = 1; i < strLength - 1; ++i) { + if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") { + types[i] = "EN"; + } + if (types[i] === "CS" && (types[i - 1] === "EN" || types[i - 1] === "AN") && types[i + 1] === types[i - 1]) { + types[i] = types[i - 1]; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === "EN") { + for (let j = i - 1; j >= 0; --j) { + if (types[j] !== "ET") { + break; + } + types[j] = "EN"; + } + for (let j = i + 1; j < strLength; ++j) { + if (types[j] !== "ET") { + break; + } + types[j] = "EN"; + } + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === "WS" || t === "ES" || t === "ET" || t === "CS") { + types[i] = "ON"; + } + } + lastType = sor; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === "EN") { + types[i] = lastType === "L" ? "L" : "EN"; + } else if (t === "R" || t === "L") { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === "ON") { + const end = findUnequal(types, i + 1, "ON"); + let before = sor; + if (i > 0) { + before = types[i - 1]; + } + let after = eor; + if (end + 1 < strLength) { + after = types[end + 1]; + } + if (before !== "L") { + before = "R"; + } + if (after !== "L") { + after = "R"; + } + if (before === after) { + types.fill(before, i, end); + } + i = end - 1; + } + } + for (i = 0; i < strLength; ++i) { + if (types[i] === "ON") { + types[i] = e; + } + } + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (isEven(levels[i])) { + if (t === "R") { + levels[i] += 1; + } else if (t === "AN" || t === "EN") { + levels[i] += 2; + } + } else if (t === "L" || t === "AN" || t === "EN") { + levels[i] += 1; + } + } + let highestLevel = -1; + let lowestOddLevel = 99; + let level; + for (i = 0, ii = levels.length; i < ii; ++i) { + level = levels[i]; + if (highestLevel < level) { + highestLevel = level; + } + if (lowestOddLevel > level && isOdd(level)) { + lowestOddLevel = level; + } + } + for (level = highestLevel; level >= lowestOddLevel; --level) { + let start = -1; + for (i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + for (i = 0, ii = chars.length; i < ii; ++i) { + const ch = chars[i]; + if (ch === "<" || ch === ">") { + chars[i] = ""; + } + } + return createBidiText(chars.join(""), isLTR); +} + +;// ./src/core/font_substitutions.js + + + +const NORMAL = { + style: "normal", + weight: "normal" +}; +const BOLD = { + style: "normal", + weight: "bold" +}; +const ITALIC = { + style: "italic", + weight: "normal" +}; +const BOLDITALIC = { + style: "italic", + weight: "bold" +}; +const substitutionMap = new Map([["Times-Roman", { + local: ["Times New Roman", "Times-Roman", "Times", "Liberation Serif", "Nimbus Roman", "Nimbus Roman L", "Tinos", "Thorndale", "TeX Gyre Termes", "FreeSerif", "Linux Libertine O", "Libertinus Serif", "PT Astra Serif", "DejaVu Serif", "Bitstream Vera Serif", "Ubuntu"], + style: NORMAL, + ultimate: "serif" +}], ["Times-Bold", { + alias: "Times-Roman", + style: BOLD, + ultimate: "serif" +}], ["Times-Italic", { + alias: "Times-Roman", + style: ITALIC, + ultimate: "serif" +}], ["Times-BoldItalic", { + alias: "Times-Roman", + style: BOLDITALIC, + ultimate: "serif" +}], ["Helvetica", { + local: ["Helvetica", "Helvetica Neue", "Arial", "Arial Nova", "Liberation Sans", "Arimo", "Nimbus Sans", "Nimbus Sans L", "A030", "TeX Gyre Heros", "FreeSans", "DejaVu Sans", "Albany", "Bitstream Vera Sans", "Arial Unicode MS", "Microsoft Sans Serif", "Apple Symbols", "Cantarell"], + path: "LiberationSans-Regular.ttf", + style: NORMAL, + ultimate: "sans-serif" +}], ["Helvetica-Bold", { + alias: "Helvetica", + path: "LiberationSans-Bold.ttf", + style: BOLD, + ultimate: "sans-serif" +}], ["Helvetica-Oblique", { + alias: "Helvetica", + path: "LiberationSans-Italic.ttf", + style: ITALIC, + ultimate: "sans-serif" +}], ["Helvetica-BoldOblique", { + alias: "Helvetica", + path: "LiberationSans-BoldItalic.ttf", + style: BOLDITALIC, + ultimate: "sans-serif" +}], ["Courier", { + local: ["Courier", "Courier New", "Liberation Mono", "Nimbus Mono", "Nimbus Mono L", "Cousine", "Cumberland", "TeX Gyre Cursor", "FreeMono", "Linux Libertine Mono O", "Libertinus Mono"], + style: NORMAL, + ultimate: "monospace" +}], ["Courier-Bold", { + alias: "Courier", + style: BOLD, + ultimate: "monospace" +}], ["Courier-Oblique", { + alias: "Courier", + style: ITALIC, + ultimate: "monospace" +}], ["Courier-BoldOblique", { + alias: "Courier", + style: BOLDITALIC, + ultimate: "monospace" +}], ["ArialBlack", { + local: ["Arial Black"], + style: { + style: "normal", + weight: "900" + }, + fallback: "Helvetica-Bold" +}], ["ArialBlack-Bold", { + alias: "ArialBlack" +}], ["ArialBlack-Italic", { + alias: "ArialBlack", + style: { + style: "italic", + weight: "900" + }, + fallback: "Helvetica-BoldOblique" +}], ["ArialBlack-BoldItalic", { + alias: "ArialBlack-Italic" +}], ["ArialNarrow", { + local: ["Arial Narrow", "Liberation Sans Narrow", "Helvetica Condensed", "Nimbus Sans Narrow", "TeX Gyre Heros Cn"], + style: NORMAL, + fallback: "Helvetica" +}], ["ArialNarrow-Bold", { + alias: "ArialNarrow", + style: BOLD, + fallback: "Helvetica-Bold" +}], ["ArialNarrow-Italic", { + alias: "ArialNarrow", + style: ITALIC, + fallback: "Helvetica-Oblique" +}], ["ArialNarrow-BoldItalic", { + alias: "ArialNarrow", + style: BOLDITALIC, + fallback: "Helvetica-BoldOblique" +}], ["Calibri", { + local: ["Calibri", "Carlito"], + style: NORMAL, + fallback: "Helvetica" +}], ["Calibri-Bold", { + alias: "Calibri", + style: BOLD, + fallback: "Helvetica-Bold" +}], ["Calibri-Italic", { + alias: "Calibri", + style: ITALIC, + fallback: "Helvetica-Oblique" +}], ["Calibri-BoldItalic", { + alias: "Calibri", + style: BOLDITALIC, + fallback: "Helvetica-BoldOblique" +}], ["Wingdings", { + local: ["Wingdings", "URW Dingbats"], + style: NORMAL +}], ["Wingdings-Regular", { + alias: "Wingdings" +}], ["Wingdings-Bold", { + alias: "Wingdings" +}]]); +const fontAliases = new Map([["Arial-Black", "ArialBlack"]]); +function getStyleToAppend(style) { + switch (style) { + case BOLD: + return "Bold"; + case ITALIC: + return "Italic"; + case BOLDITALIC: + return "Bold Italic"; + default: + if (style?.weight === "bold") { + return "Bold"; + } + if (style?.style === "italic") { + return "Italic"; + } + } + return ""; +} +function getFamilyName(str) { + const keywords = new Set(["thin", "extralight", "ultralight", "demilight", "semilight", "light", "book", "regular", "normal", "medium", "demibold", "semibold", "bold", "extrabold", "ultrabold", "black", "heavy", "extrablack", "ultrablack", "roman", "italic", "oblique", "ultracondensed", "extracondensed", "condensed", "semicondensed", "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded", "bolditalic"]); + return str.split(/[- ,+]+/g).filter(tok => !keywords.has(tok.toLowerCase())).join(" "); +} +function generateFont({ + alias, + local, + path, + fallback, + style, + ultimate +}, src, localFontPath, useFallback = true, usePath = true, append = "") { + const result = { + style: null, + ultimate: null + }; + if (local) { + const extra = append ? ` ${append}` : ""; + for (const name of local) { + src.push(`local(${name}${extra})`); + } + } + if (alias) { + const substitution = substitutionMap.get(alias); + const aliasAppend = append || getStyleToAppend(style); + Object.assign(result, generateFont(substitution, src, localFontPath, useFallback && !fallback, usePath && !path, aliasAppend)); + } + if (style) { + result.style = style; + } + if (ultimate) { + result.ultimate = ultimate; + } + if (useFallback && fallback) { + const fallbackInfo = substitutionMap.get(fallback); + const { + ultimate: fallbackUltimate + } = generateFont(fallbackInfo, src, localFontPath, useFallback, usePath && !path, append); + result.ultimate ||= fallbackUltimate; + } + if (usePath && path && localFontPath) { + src.push(`url(${localFontPath}${path})`); + } + return result; +} +function getFontSubstitution(systemFontCache, idFactory, localFontPath, baseFontName, standardFontName, type) { + if (baseFontName.startsWith("InvalidPDFjsFont_")) { + return null; + } + if ((type === "TrueType" || type === "Type1") && /^[A-Z]{6}\+/.test(baseFontName)) { + baseFontName = baseFontName.slice(7); + } + baseFontName = normalizeFontName(baseFontName); + const key = baseFontName; + let substitutionInfo = systemFontCache.get(key); + if (substitutionInfo) { + return substitutionInfo; + } + let substitution = substitutionMap.get(baseFontName); + if (!substitution) { + for (const [alias, subst] of fontAliases) { + if (baseFontName.startsWith(alias)) { + baseFontName = `${subst}${baseFontName.substring(alias.length)}`; + substitution = substitutionMap.get(baseFontName); + break; + } + } + } + let mustAddBaseFont = false; + if (!substitution) { + substitution = substitutionMap.get(standardFontName); + mustAddBaseFont = true; + } + const loadedName = `${idFactory.getDocId()}_s${idFactory.createFontId()}`; + if (!substitution) { + if (!validateFontName(baseFontName)) { + warn(`Cannot substitute the font because of its name: ${baseFontName}`); + systemFontCache.set(key, null); + return null; + } + const bold = /bold/gi.test(baseFontName); + const italic = /oblique|italic/gi.test(baseFontName); + const style = bold && italic && BOLDITALIC || bold && BOLD || italic && ITALIC || NORMAL; + substitutionInfo = { + css: `"${getFamilyName(baseFontName)}",${loadedName}`, + guessFallback: true, + loadedName, + baseFontName, + src: `local(${baseFontName})`, + style + }; + systemFontCache.set(key, substitutionInfo); + return substitutionInfo; + } + const src = []; + if (mustAddBaseFont && validateFontName(baseFontName)) { + src.push(`local(${baseFontName})`); + } + const { + style, + ultimate + } = generateFont(substitution, src, localFontPath); + const guessFallback = ultimate === null; + const fallback = guessFallback ? "" : `,${ultimate}`; + substitutionInfo = { + css: `"${getFamilyName(baseFontName)}",${loadedName}${fallback}`, + guessFallback, + loadedName, + baseFontName, + src: src.join(","), + style + }; + systemFontCache.set(key, substitutionInfo); + return substitutionInfo; +} + +;// ./src/shared/murmurhash3.js +const SEED = 0xc3d2e1f0; +const MASK_HIGH = 0xffff0000; +const MASK_LOW = 0xffff; +class MurmurHash3_64 { + constructor(seed) { + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + update(input) { + let data, length; + if (typeof input === "string") { + data = new Uint8Array(input.length * 2); + length = 0; + for (let i = 0, ii = input.length; i < ii; i++) { + const code = input.charCodeAt(i); + if (code <= 0xff) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if (ArrayBuffer.isView(input)) { + data = input.slice(); + length = data.byteLength; + } else { + throw new Error("Invalid data format, must be a string or TypedArray."); + } + const blockCounts = length >> 2; + const tailLength = length - blockCounts * 4; + const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); + let k1 = 0, + k2 = 0; + let h1 = this.h1, + h2 = this.h2; + const C1 = 0xcc9e2d51, + C2 = 0x1b873593; + const C1_LOW = C1 & MASK_LOW, + C2_LOW = C2 & MASK_LOW; + for (let i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + k1 = 0; + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + this.h1 = h1; + this.h2 = h2; + } + hexdigest() { + let h1 = this.h1, + h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; + h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; + h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0"); + } +} + +;// ./src/core/image.js + + + + + + + + + + +function resizeImageMask(src, bpc, w1, h1, w2, h2) { + const length = w2 * h2; + let dest; + if (bpc <= 8) { + dest = new Uint8Array(length); + } else if (bpc <= 16) { + dest = new Uint16Array(length); + } else { + dest = new Uint32Array(length); + } + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let i, + j, + py, + newIndex = 0, + oldIndex; + const xScaled = new Uint16Array(w2); + const w1Scanline = w1; + for (i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio); + } + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex]; + } + } + return dest; +} +class PDFImage { + constructor({ + xref, + res, + image, + isInline = false, + smask = null, + mask = null, + isMask = false, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }) { + this.image = image; + const dict = image.dict; + const filter = dict.get("F", "Filter"); + let filterName; + if (filter instanceof Name) { + filterName = filter.name; + } else if (Array.isArray(filter)) { + const filterZero = xref.fetchIfRef(filter[0]); + if (filterZero instanceof Name) { + filterName = filterZero.name; + } + } + switch (filterName) { + case "JPXDecode": + ({ + width: image.width, + height: image.height, + componentsCount: image.numComps, + bitsPerComponent: image.bitsPerComponent + } = JpxImage.parseImageProperties(image.stream)); + image.stream.reset(); + const reducePower = ImageResizer.getReducePowerForJPX(image.width, image.height, image.numComps); + this.jpxDecoderOptions = { + numComponents: 0, + isIndexedColormap: false, + smaskInData: dict.has("SMaskInData"), + reducePower + }; + if (reducePower) { + const factor = 2 ** reducePower; + image.width = Math.ceil(image.width / factor); + image.height = Math.ceil(image.height / factor); + } + break; + case "JBIG2Decode": + image.bitsPerComponent = 1; + image.numComps = 1; + break; + } + let width = dict.get("W", "Width"); + let height = dict.get("H", "Height"); + if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) { + warn("PDFImage - using the Width/Height of the image data, " + "rather than the image dictionary."); + width = image.width; + height = image.height; + } else { + const validWidth = typeof width === "number" && width > 0, + validHeight = typeof height === "number" && height > 0; + if (!validWidth || !validHeight) { + if (!image.fallbackDims) { + throw new FormatError(`Invalid image width: ${width} or height: ${height}`); + } + warn("PDFImage - using the Width/Height of the parent image, for SMask/Mask data."); + if (!validWidth) { + width = image.fallbackDims.width; + } + if (!validHeight) { + height = image.fallbackDims.height; + } + } + } + this.width = width; + this.height = height; + this.interpolate = dict.get("I", "Interpolate"); + this.imageMask = dict.get("IM", "ImageMask") || false; + this.matte = dict.get("Matte") || false; + let bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get("BPC", "BitsPerComponent"); + if (!bitsPerComponent) { + if (this.imageMask) { + bitsPerComponent = 1; + } else { + throw new FormatError(`Bits per component missing in image: ${this.imageMask}`); + } + } + } + this.bpc = bitsPerComponent; + if (!this.imageMask) { + let colorSpace = dict.getRaw("CS") || dict.getRaw("ColorSpace"); + const hasColorSpace = !!colorSpace; + if (!hasColorSpace) { + if (this.jpxDecoderOptions) { + colorSpace = Name.get("DeviceRGBA"); + } else { + switch (image.numComps) { + case 1: + colorSpace = Name.get("DeviceGray"); + break; + case 3: + colorSpace = Name.get("DeviceRGB"); + break; + case 4: + colorSpace = Name.get("DeviceCMYK"); + break; + default: + throw new Error(`Images with ${image.numComps} color components not supported.`); + } + } + } else if (this.jpxDecoderOptions?.smaskInData) { + colorSpace = Name.get("DeviceRGBA"); + } + this.colorSpace = ColorSpaceUtils.parse({ + cs: colorSpace, + xref, + resources: isInline ? res : null, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.numComps = this.colorSpace.numComps; + if (this.jpxDecoderOptions) { + this.jpxDecoderOptions.numComponents = hasColorSpace ? this.numComps : 0; + this.jpxDecoderOptions.isIndexedColormap = this.colorSpace.name === "Indexed"; + } + } + this.decode = dict.getArray("D", "Decode"); + this.needsDecode = false; + if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) { + this.needsDecode = true; + const max = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + const isIndexed = this.colorSpace?.name === "Indexed"; + for (let i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + const dmin = this.decode[i]; + const dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max : dmax - dmin; + this.decodeAddends[j] = isIndexed ? dmin : max * dmin; + } + } + if (smask) { + smask.fallbackDims ??= { + width, + height + }; + this.smask = new PDFImage({ + xref, + res, + image: smask, + isInline, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } else if (mask) { + if (mask instanceof BaseStream) { + const maskDict = mask.dict, + imageMask = maskDict.get("IM", "ImageMask"); + if (!imageMask) { + warn("Ignoring /Mask in image without /ImageMask."); + } else { + mask.fallbackDims ??= { + width, + height + }; + this.mask = new PDFImage({ + xref, + res, + image: mask, + isInline, + isMask: true, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } + } else { + this.mask = mask; + } + } + } + static async buildImage({ + xref, + res, + image, + isInline = false, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }) { + const imageData = image; + let smaskData = null; + let maskData = null; + const smask = image.dict.get("SMask"); + const mask = image.dict.get("Mask"); + if (smask) { + if (smask instanceof BaseStream) { + smaskData = smask; + } else { + warn("Unsupported /SMask format."); + } + } else if (mask) { + if (mask instanceof BaseStream || Array.isArray(mask)) { + maskData = mask; + } else { + warn("Unsupported /Mask format."); + } + } + return new PDFImage({ + xref, + res, + image: imageData, + isInline, + smask: smaskData, + mask: maskData, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } + static async createMask({ + image, + isOffscreenCanvasSupported = false + }) { + const { + dict + } = image; + const width = dict.get("W", "Width"); + const height = dict.get("H", "Height"); + const interpolate = dict.get("I", "Interpolate"); + const decode = dict.getArray("D", "Decode"); + const inverseDecode = decode?.[0] > 0; + const computedLength = (width + 7 >> 3) * height; + const imgArray = image.getBytes(computedLength); + const isSingleOpaquePixel = width === 1 && height === 1 && inverseDecode === (imgArray.length === 0 || !!(imgArray[0] & 128)); + if (isSingleOpaquePixel) { + return { + isSingleOpaquePixel + }; + } + if (isOffscreenCanvasSupported) { + if (ImageResizer.needsToBeResized(width, height)) { + const data = new Uint8ClampedArray(width * height * 4); + convertBlackAndWhiteToRGBA({ + src: imgArray, + dest: data, + width, + height, + nonBlackColor: 0, + inverseDecode + }); + return ImageResizer.createImage({ + kind: ImageKind.RGBA_32BPP, + data, + width, + height, + interpolate + }); + } + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + const imgData = ctx.createImageData(width, height); + convertBlackAndWhiteToRGBA({ + src: imgArray, + dest: imgData.data, + width, + height, + nonBlackColor: 0, + inverseDecode + }); + ctx.putImageData(imgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width, + height, + interpolate, + bitmap + }; + } + const actualLength = imgArray.byteLength; + const haveFullData = computedLength === actualLength; + let data; + if (image instanceof DecodeStream && (!inverseDecode || haveFullData)) { + data = imgArray; + } else if (!inverseDecode) { + data = new Uint8Array(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + data.fill(0xff, actualLength); + } + if (inverseDecode) { + for (let i = 0; i < actualLength; i++) { + data[i] ^= 0xff; + } + } + return { + data, + width, + height, + interpolate + }; + } + get drawWidth() { + return Math.max(this.width, this.smask?.width || 0, this.mask?.width || 0); + } + get drawHeight() { + return Math.max(this.height, this.smask?.height || 0, this.mask?.height || 0); + } + decodeBuffer(buffer) { + const bpc = this.bpc; + const numComps = this.numComps; + const decodeAddends = this.decodeAddends; + const decodeCoefficients = this.decodeCoefficients; + const max = (1 << bpc) - 1; + let i, ii; + if (bpc === 1) { + for (i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = +!buffer[i]; + } + return; + } + let index = 0; + for (i = 0, ii = this.width * this.height; i < ii; i++) { + for (let j = 0; j < numComps; j++) { + buffer[index] = MathClamp(decodeAddends[j] + buffer[index] * decodeCoefficients[j], 0, max); + index++; + } + } + } + getComponents(buffer) { + const bpc = this.bpc; + if (bpc === 8) { + return buffer; + } + const width = this.width; + const height = this.height; + const numComps = this.numComps; + const length = width * height * numComps; + let bufferPos = 0; + let output; + if (bpc <= 8) { + output = new Uint8Array(length); + } else if (bpc <= 16) { + output = new Uint16Array(length); + } else { + output = new Uint32Array(length); + } + const rowComps = width * numComps; + const max = (1 << bpc) - 1; + let i = 0, + ii, + buf; + if (bpc === 1) { + let mask, loop1End, loop2End; + for (let j = 0; j < height; j++) { + loop1End = i + (rowComps & ~7); + loop2End = i + rowComps; + while (i < loop1End) { + buf = buffer[bufferPos++]; + output[i] = buf >> 7 & 1; + output[i + 1] = buf >> 6 & 1; + output[i + 2] = buf >> 5 & 1; + output[i + 3] = buf >> 4 & 1; + output[i + 4] = buf >> 3 & 1; + output[i + 5] = buf >> 2 & 1; + output[i + 6] = buf >> 1 & 1; + output[i + 7] = buf & 1; + i += 8; + } + if (i < loop2End) { + buf = buffer[bufferPos++]; + mask = 128; + while (i < loop2End) { + output[i++] = +!!(buf & mask); + mask >>= 1; + } + } + } + } else { + let bits = 0; + buf = 0; + for (i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + while (bits < bpc) { + buf = buf << 8 | buffer[bufferPos++]; + bits += 8; + } + const remainingBits = bits - bpc; + let value = buf >> remainingBits; + if (value < 0) { + value = 0; + } else if (value > max) { + value = max; + } + output[i] = value; + buf &= (1 << remainingBits) - 1; + bits = remainingBits; + } + } + return output; + } + async fillOpacity(rgbaBuf, width, height, actualHeight, image) { + const smask = this.smask; + const mask = this.mask; + let alphaBuf, sw, sh, i, ii, j; + if (smask) { + sw = smask.width; + sh = smask.height; + alphaBuf = new Uint8ClampedArray(sw * sh); + await smask.fillGrayBuffer(alphaBuf); + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height); + } + } else if (mask) { + if (mask instanceof PDFImage) { + sw = mask.width; + sh = mask.height; + alphaBuf = new Uint8ClampedArray(sw * sh); + mask.numComps = 1; + await mask.fillGrayBuffer(alphaBuf); + for (i = 0, ii = sw * sh; i < ii; ++i) { + alphaBuf[i] = 255 - alphaBuf[i]; + } + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height); + } + } else if (Array.isArray(mask)) { + alphaBuf = new Uint8ClampedArray(width * height); + const numComps = this.numComps; + for (i = 0, ii = width * height; i < ii; ++i) { + let opacity = 0; + const imageOffset = i * numComps; + for (j = 0; j < numComps; ++j) { + const color = image[imageOffset + j]; + const maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + throw new FormatError("Unknown mask format."); + } + } + if (alphaBuf) { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = alphaBuf[i]; + } + } else { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = 255; + } + } + } + undoPreblend(buffer, width, height) { + const matte = this.smask?.matte; + if (!matte) { + return; + } + const matteRgb = this.colorSpace.getRgb(matte, 0); + const matteR = matteRgb[0]; + const matteG = matteRgb[1]; + const matteB = matteRgb[2]; + const length = width * height * 4; + for (let i = 0; i < length; i += 4) { + const alpha = buffer[i + 3]; + if (alpha === 0) { + buffer[i] = 255; + buffer[i + 1] = 255; + buffer[i + 2] = 255; + continue; + } + const k = 255 / alpha; + buffer[i] = (buffer[i] - matteR) * k + matteR; + buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG; + buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB; + } + } + async createImageData(forceRGBA = false, isOffscreenCanvasSupported = false) { + const drawWidth = this.drawWidth; + const drawHeight = this.drawHeight; + const imgData = { + width: drawWidth, + height: drawHeight, + interpolate: this.interpolate, + kind: 0, + data: null + }; + const numComps = this.numComps; + const originalWidth = this.width; + const originalHeight = this.height; + const bpc = this.bpc; + const rowBytes = originalWidth * numComps * bpc + 7 >> 3; + const mustBeResized = isOffscreenCanvasSupported && ImageResizer.needsToBeResized(drawWidth, drawHeight); + if (!this.smask && !this.mask && this.colorSpace.name === "DeviceRGBA") { + imgData.kind = ImageKind.RGBA_32BPP; + const imgArray = imgData.data = await this.getImageBytes(originalHeight * originalWidth * 4, {}); + if (isOffscreenCanvasSupported) { + if (!mustBeResized) { + return this.createBitmap(ImageKind.RGBA_32BPP, drawWidth, drawHeight, imgArray); + } + return ImageResizer.createImage(imgData, false); + } + return imgData; + } + if (!forceRGBA) { + let kind; + if (this.colorSpace.name === "DeviceGray" && bpc === 1) { + kind = ImageKind.GRAYSCALE_1BPP; + } else if (this.colorSpace.name === "DeviceRGB" && bpc === 8 && !this.needsDecode) { + kind = ImageKind.RGB_24BPP; + } + if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) { + const image = await this.#getImage(originalWidth, originalHeight); + if (image) { + return image; + } + const data = await this.getImageBytes(originalHeight * rowBytes, {}); + if (isOffscreenCanvasSupported) { + if (mustBeResized) { + return ImageResizer.createImage({ + data, + kind, + width: drawWidth, + height: drawHeight, + interpolate: this.interpolate + }, this.needsDecode); + } + return this.createBitmap(kind, originalWidth, originalHeight, data); + } + imgData.kind = kind; + imgData.data = data; + if (this.needsDecode) { + assert(kind === ImageKind.GRAYSCALE_1BPP, "PDFImage.createImageData: The image must be grayscale."); + const buffer = imgData.data; + for (let i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] ^= 0xff; + } + } + return imgData; + } + if (this.image instanceof JpegStream && !this.smask && !this.mask && !this.needsDecode) { + let imageLength = originalHeight * rowBytes; + if (isOffscreenCanvasSupported && !mustBeResized) { + let isHandled = false; + switch (this.colorSpace.name) { + case "DeviceGray": + imageLength *= 4; + isHandled = true; + break; + case "DeviceRGB": + imageLength = imageLength / 3 * 4; + isHandled = true; + break; + case "DeviceCMYK": + isHandled = true; + break; + } + if (isHandled) { + const image = await this.#getImage(drawWidth, drawHeight); + if (image) { + return image; + } + const rgba = await this.getImageBytes(imageLength, { + drawWidth, + drawHeight, + forceRGBA: true + }); + return this.createBitmap(ImageKind.RGBA_32BPP, drawWidth, drawHeight, rgba); + } + } else { + switch (this.colorSpace.name) { + case "DeviceGray": + imageLength *= 3; + case "DeviceRGB": + case "DeviceCMYK": + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = await this.getImageBytes(imageLength, { + drawWidth, + drawHeight, + forceRGB: true + }); + if (mustBeResized) { + return ImageResizer.createImage(imgData); + } + return imgData; + } + } + } + } + const imgArray = await this.getImageBytes(originalHeight * rowBytes, { + internal: true + }); + const actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight; + const comps = this.getComponents(imgArray); + let alpha01, maybeUndoPreblend; + let canvas, ctx, canvasImgData, data; + if (isOffscreenCanvasSupported && !mustBeResized) { + canvas = new OffscreenCanvas(drawWidth, drawHeight); + ctx = canvas.getContext("2d"); + canvasImgData = ctx.createImageData(drawWidth, drawHeight); + data = canvasImgData.data; + } + imgData.kind = ImageKind.RGBA_32BPP; + if (!forceRGBA && !this.smask && !this.mask) { + if (!isOffscreenCanvasSupported || mustBeResized) { + imgData.kind = ImageKind.RGB_24BPP; + data = new Uint8ClampedArray(drawWidth * drawHeight * 3); + alpha01 = 0; + } else { + const arr = new Uint32Array(data.buffer); + arr.fill(FeatureTest.isLittleEndian ? 0xff000000 : 0x000000ff); + alpha01 = 1; + } + maybeUndoPreblend = false; + } else { + if (!isOffscreenCanvasSupported || mustBeResized) { + data = new Uint8ClampedArray(drawWidth * drawHeight * 4); + } + alpha01 = 1; + maybeUndoPreblend = true; + await this.fillOpacity(data, drawWidth, drawHeight, actualHeight, comps); + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + this.colorSpace.fillRgb(data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01); + if (maybeUndoPreblend) { + this.undoPreblend(data, drawWidth, actualHeight); + } + if (isOffscreenCanvasSupported && !mustBeResized) { + ctx.putImageData(canvasImgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width: drawWidth, + height: drawHeight, + bitmap, + interpolate: this.interpolate + }; + } + imgData.data = data; + if (mustBeResized) { + return ImageResizer.createImage(imgData); + } + return imgData; + } + async fillGrayBuffer(buffer) { + const numComps = this.numComps; + if (numComps !== 1) { + throw new FormatError(`Reading gray scale from a color image: ${numComps}`); + } + const width = this.width; + const height = this.height; + const bpc = this.bpc; + const rowBytes = width * numComps * bpc + 7 >> 3; + const imgArray = await this.getImageBytes(height * rowBytes, { + internal: true + }); + const comps = this.getComponents(imgArray); + let i, length; + if (bpc === 1) { + length = width * height; + if (this.needsDecode) { + for (i = 0; i < length; ++i) { + buffer[i] = comps[i] - 1 & 255; + } + } else { + for (i = 0; i < length; ++i) { + buffer[i] = -comps[i] & 255; + } + } + return; + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + length = width * height; + const scale = 255 / ((1 << bpc) - 1); + for (i = 0; i < length; ++i) { + buffer[i] = scale * comps[i]; + } + } + createBitmap(kind, width, height, src) { + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + let imgData; + if (kind === ImageKind.RGBA_32BPP) { + imgData = new ImageData(src, width, height); + } else { + imgData = ctx.createImageData(width, height); + convertToRGBA({ + kind, + src, + dest: new Uint32Array(imgData.data.buffer), + width, + height, + inverseDecode: this.needsDecode + }); + } + ctx.putImageData(imgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width, + height, + bitmap, + interpolate: this.interpolate + }; + } + async #getImage(width, height) { + const bitmap = await this.image.getTransferableImage(); + if (!bitmap) { + return null; + } + return { + data: null, + width, + height, + bitmap, + interpolate: this.interpolate + }; + } + async getImageBytes(length, { + drawWidth, + drawHeight, + forceRGBA = false, + forceRGB = false, + internal = false + }) { + this.image.reset(); + this.image.drawWidth = drawWidth || this.width; + this.image.drawHeight = drawHeight || this.height; + this.image.forceRGBA = !!forceRGBA; + this.image.forceRGB = !!forceRGB; + const imageBytes = await this.image.getImageData(length, this.jpxDecoderOptions); + if (internal || this.image instanceof DecodeStream) { + return imageBytes; + } + assert(imageBytes instanceof Uint8Array, 'PDFImage.getImageBytes: Unsupported "imageBytes" type.'); + return new Uint8Array(imageBytes); + } +} + +;// ./src/core/evaluator.js + + + + + + + + + + + + + + + + + + + + + + + + + + + +const DefaultPartialEvaluatorOptions = Object.freeze({ + maxImageSize: -1, + disableFontFace: false, + ignoreErrors: false, + isEvalSupported: true, + isOffscreenCanvasSupported: false, + isImageDecoderSupported: false, + canvasMaxAreaInBytes: -1, + fontExtraProperties: false, + useSystemFonts: true, + useWasm: true, + useWorkerFetch: true, + cMapUrl: null, + iccUrl: null, + standardFontDataUrl: null, + wasmUrl: null +}); +const PatternType = { + TILING: 1, + SHADING: 2 +}; +const TEXT_CHUNK_BATCH_SIZE = 10; +const deferred = Promise.resolve(); +function normalizeBlendMode(value, parsingArray = false) { + if (Array.isArray(value)) { + for (const val of value) { + const maybeBM = normalizeBlendMode(val, true); + if (maybeBM) { + return maybeBM; + } + } + warn(`Unsupported blend mode Array: ${value}`); + return "source-over"; + } + if (!(value instanceof Name)) { + if (parsingArray) { + return null; + } + return "source-over"; + } + switch (value.name) { + case "Normal": + case "Compatible": + return "source-over"; + case "Multiply": + return "multiply"; + case "Screen": + return "screen"; + case "Overlay": + return "overlay"; + case "Darken": + return "darken"; + case "Lighten": + return "lighten"; + case "ColorDodge": + return "color-dodge"; + case "ColorBurn": + return "color-burn"; + case "HardLight": + return "hard-light"; + case "SoftLight": + return "soft-light"; + case "Difference": + return "difference"; + case "Exclusion": + return "exclusion"; + case "Hue": + return "hue"; + case "Saturation": + return "saturation"; + case "Color": + return "color"; + case "Luminosity": + return "luminosity"; + } + if (parsingArray) { + return null; + } + warn(`Unsupported blend mode: ${value.name}`); + return "source-over"; +} +function addCachedImageOps(opList, { + objId, + fn, + args, + optionalContent, + hasMask +}) { + if (objId) { + opList.addDependency(objId); + } + opList.addImageOps(fn, args, optionalContent, hasMask); + if (fn === OPS.paintImageMaskXObject && args[0]?.count > 0) { + args[0].count++; + } +} +class TimeSlotManager { + static TIME_SLOT_DURATION_MS = 20; + static CHECK_TIME_EVERY = 100; + constructor() { + this.reset(); + } + check() { + if (++this.checked < TimeSlotManager.CHECK_TIME_EVERY) { + return false; + } + this.checked = 0; + return this.endTime <= Date.now(); + } + reset() { + this.endTime = Date.now() + TimeSlotManager.TIME_SLOT_DURATION_MS; + this.checked = 0; + } +} +class PartialEvaluator { + constructor({ + xref, + handler, + pageIndex, + idFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + globalColorSpaceCache, + globalImageCache, + systemFontCache, + options = null + }) { + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.idFactory = idFactory; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.standardFontDataCache = standardFontDataCache; + this.globalColorSpaceCache = globalColorSpaceCache; + this.globalImageCache = globalImageCache; + this.systemFontCache = systemFontCache; + this.options = options || DefaultPartialEvaluatorOptions; + this.type3FontRefs = null; + this._regionalImageCache = new RegionalImageCache(); + this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); + } + get _pdfFunctionFactory() { + const pdfFunctionFactory = new PDFFunctionFactory({ + xref: this.xref, + isEvalSupported: this.options.isEvalSupported + }); + return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory); + } + get parsingType3Font() { + return !!this.type3FontRefs; + } + clone(newOptions = null) { + const newEvaluator = Object.create(this); + newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions); + return newEvaluator; + } + hasBlendModes(resources, nonBlendModesSet) { + if (!(resources instanceof Dict)) { + return false; + } + if (resources.objId && nonBlendModesSet.has(resources.objId)) { + return false; + } + const processed = new RefSet(nonBlendModesSet); + if (resources.objId) { + processed.put(resources.objId); + } + const nodes = [resources], + xref = this.xref; + while (nodes.length) { + const node = nodes.shift(); + const graphicStates = node.get("ExtGState"); + if (graphicStates instanceof Dict) { + for (let graphicState of graphicStates.getRawValues()) { + if (graphicState instanceof Ref) { + if (processed.has(graphicState)) { + continue; + } + try { + graphicState = xref.fetch(graphicState); + } catch (ex) { + processed.put(graphicState); + info(`hasBlendModes - ignoring ExtGState: "${ex}".`); + continue; + } + } + if (!(graphicState instanceof Dict)) { + continue; + } + if (graphicState.objId) { + processed.put(graphicState.objId); + } + const bm = graphicState.get("BM"); + if (bm instanceof Name) { + if (bm.name !== "Normal") { + return true; + } + continue; + } + if (bm !== undefined && Array.isArray(bm)) { + for (const element of bm) { + if (element instanceof Name && element.name !== "Normal") { + return true; + } + } + } + } + } + const xObjects = node.get("XObject"); + if (!(xObjects instanceof Dict)) { + continue; + } + for (let xObject of xObjects.getRawValues()) { + if (xObject instanceof Ref) { + if (processed.has(xObject)) { + continue; + } + try { + xObject = xref.fetch(xObject); + } catch (ex) { + processed.put(xObject); + info(`hasBlendModes - ignoring XObject: "${ex}".`); + continue; + } + } + if (!(xObject instanceof BaseStream)) { + continue; + } + if (xObject.dict.objId) { + processed.put(xObject.dict.objId); + } + const xResources = xObject.dict.get("Resources"); + if (!(xResources instanceof Dict)) { + continue; + } + if (xResources.objId && processed.has(xResources.objId)) { + continue; + } + nodes.push(xResources); + if (xResources.objId) { + processed.put(xResources.objId); + } + } + } + for (const ref of processed) { + nonBlendModesSet.put(ref); + } + return false; + } + async fetchBuiltInCMap(name) { + const cachedData = this.builtInCMapCache.get(name); + if (cachedData) { + return cachedData; + } + let data; + if (this.options.useWorkerFetch) { + data = { + cMapData: await fetchBinaryData(`${this.options.cMapUrl}${name}.bcmap`), + isCompressed: true + }; + } else { + data = await this.handler.sendWithPromise("FetchBinaryData", { + type: "cMapReaderFactory", + name + }); + } + this.builtInCMapCache.set(name, data); + return data; + } + async fetchStandardFontData(name) { + const cachedData = this.standardFontDataCache.get(name); + if (cachedData) { + return new Stream(cachedData); + } + if (this.options.useSystemFonts && name !== "Symbol" && name !== "ZapfDingbats") { + return null; + } + const standardFontNameToFileName = getFontNameToFileMap(), + filename = standardFontNameToFileName[name]; + let data; + try { + if (this.options.useWorkerFetch) { + data = await fetchBinaryData(`${this.options.standardFontDataUrl}${filename}`); + } else { + data = await this.handler.sendWithPromise("FetchBinaryData", { + type: "standardFontDataFactory", + filename + }); + } + } catch (ex) { + warn(ex); + return null; + } + this.standardFontDataCache.set(name, data); + return new Stream(data); + } + async buildFormXObject(resources, xobj, smask, operatorList, task, initialState, localColorSpaceCache, seenRefs) { + const { + dict + } = xobj; + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + const bbox = lookupNormalRect(dict.getArray("BBox"), null); + let optionalContent, groupOptions; + if (dict.has("OC")) { + optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); + } + if (optionalContent !== undefined) { + operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); + } + const group = dict.get("Group"); + if (group) { + groupOptions = { + matrix, + bbox, + smask, + isolated: false, + knockout: false + }; + const groupSubtype = group.get("S"); + let colorSpace = null; + if (isName(groupSubtype, "Transparency")) { + groupOptions.isolated = group.get("I") || false; + groupOptions.knockout = group.get("K") || false; + if (group.has("CS")) { + const cs = this._getColorSpace(group.getRaw("CS"), resources, localColorSpaceCache); + colorSpace = cs instanceof ColorSpace ? cs : await this._handleColorSpace(cs); + } + } + if (smask?.backdrop) { + colorSpace ||= ColorSpaceUtils.rgb; + smask.backdrop = colorSpace.getRgbHex(smask.backdrop, 0); + } + operatorList.addOp(OPS.beginGroup, [groupOptions]); + } + const f32matrix = matrix && new Float32Array(matrix); + const f32bbox = !group && bbox && new Float32Array(bbox) || null; + const args = [f32matrix, f32bbox]; + operatorList.addOp(OPS.paintFormXObjectBegin, args); + const localResources = dict.get("Resources"); + await this.getOperatorList({ + stream: xobj, + task, + resources: localResources instanceof Dict ? localResources : resources, + operatorList, + initialState, + prevRefs: seenRefs + }); + operatorList.addOp(OPS.paintFormXObjectEnd, []); + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + if (optionalContent !== undefined) { + operatorList.addOp(OPS.endMarkedContent, []); + } + } + _sendImgData(objId, imgData, cacheGlobally = false) { + const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null; + if (this.parsingType3Font || cacheGlobally) { + return this.handler.send("commonobj", [objId, "Image", imgData], transfers); + } + return this.handler.send("obj", [objId, this.pageIndex, "Image", imgData], transfers); + } + async buildPaintImageXObject({ + resources, + image, + isInline = false, + operatorList, + cacheKey, + localImageCache, + localColorSpaceCache + }) { + const { + maxImageSize, + ignoreErrors, + isOffscreenCanvasSupported + } = this.options; + const { + dict + } = image; + const imageRef = dict.objId; + const w = dict.get("W", "Width"); + const h = dict.get("H", "Height"); + if (!(w && typeof w === "number") || !(h && typeof h === "number")) { + warn("Image dimensions are missing, or not numbers."); + return; + } + if (maxImageSize !== -1 && w * h > maxImageSize) { + const msg = "Image exceeded maximum allowed size and was removed."; + if (!ignoreErrors) { + throw new Error(msg); + } + warn(msg); + return; + } + let optionalContent; + if (dict.has("OC")) { + optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); + } + const imageMask = dict.get("IM", "ImageMask") || false; + let imgData, fn, args; + if (imageMask) { + imgData = await PDFImage.createMask({ + image, + isOffscreenCanvasSupported: isOffscreenCanvasSupported && !this.parsingType3Font + }); + if (imgData.isSingleOpaquePixel) { + fn = OPS.paintSolidColorImageMask; + args = []; + operatorList.addImageOps(fn, args, optionalContent); + if (cacheKey) { + const cacheData = { + fn, + args, + optionalContent + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + } + } + return; + } + if (this.parsingType3Font) { + args = compileType3Glyph(imgData); + if (args) { + operatorList.addImageOps(OPS.constructPath, args, optionalContent); + return; + } + warn("Cannot compile Type3 glyph."); + operatorList.addImageOps(OPS.paintImageMaskXObject, [imgData], optionalContent); + return; + } + const objId = `mask_${this.idFactory.createObjId()}`; + operatorList.addDependency(objId); + imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length; + this._sendImgData(objId, imgData); + fn = OPS.paintImageMaskXObject; + args = [{ + data: objId, + width: imgData.width, + height: imgData.height, + interpolate: imgData.interpolate, + count: 1 + }]; + operatorList.addImageOps(fn, args, optionalContent); + if (cacheKey) { + const cacheData = { + objId, + fn, + args, + optionalContent + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + } + } + return; + } + const SMALL_IMAGE_DIMENSIONS = 200; + const hasMask = dict.has("SMask") || dict.has("Mask"); + if (isInline && w + h < SMALL_IMAGE_DIMENSIONS && !hasMask) { + try { + const imageObj = new PDFImage({ + xref: this.xref, + res: resources, + image, + isInline, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache + }); + imgData = await imageObj.createImageData(true, false); + operatorList.addImageOps(OPS.paintInlineImageXObject, [imgData], optionalContent); + } catch (reason) { + const msg = `Unable to decode inline image: "${reason}".`; + if (!ignoreErrors) { + throw new Error(msg); + } + warn(msg); + } + return; + } + let objId = `img_${this.idFactory.createObjId()}`, + cacheGlobally = false, + globalCacheData = null; + if (this.parsingType3Font) { + objId = `${this.idFactory.getDocId()}_type3_${objId}`; + } else if (cacheKey && imageRef) { + cacheGlobally = this.globalImageCache.shouldCache(imageRef, this.pageIndex); + if (cacheGlobally) { + assert(!isInline, "Cannot cache an inline image globally."); + objId = `${this.idFactory.getDocId()}_${objId}`; + } + } + operatorList.addDependency(objId); + fn = OPS.paintImageXObject; + args = [objId, w, h]; + operatorList.addImageOps(fn, args, optionalContent, hasMask); + if (cacheGlobally) { + globalCacheData = { + objId, + fn, + args, + optionalContent, + hasMask, + byteSize: 0 + }; + if (this.globalImageCache.hasDecodeFailed(imageRef)) { + this.globalImageCache.setData(imageRef, globalCacheData); + this._sendImgData(objId, null, cacheGlobally); + return; + } + if (w * h > 250000 || hasMask) { + const localLength = await this.handler.sendWithPromise("commonobj", [objId, "CopyLocalImage", { + imageRef + }]); + if (localLength) { + this.globalImageCache.setData(imageRef, globalCacheData); + this.globalImageCache.addByteSize(imageRef, localLength); + return; + } + } + } + PDFImage.buildImage({ + xref: this.xref, + res: resources, + image, + isInline, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache + }).then(async imageObj => { + imgData = await imageObj.createImageData(false, isOffscreenCanvasSupported); + imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length; + imgData.ref = imageRef; + if (cacheGlobally) { + this.globalImageCache.addByteSize(imageRef, imgData.dataLen); + } + return this._sendImgData(objId, imgData, cacheGlobally); + }).catch(reason => { + warn(`Unable to decode image "${objId}": "${reason}".`); + if (imageRef) { + this.globalImageCache.addDecodeFailed(imageRef); + } + return this._sendImgData(objId, null, cacheGlobally); + }); + if (cacheKey) { + const cacheData = { + objId, + fn, + args, + optionalContent, + hasMask + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + if (cacheGlobally) { + assert(globalCacheData, "The global cache-data must be available."); + this.globalImageCache.setData(imageRef, globalCacheData); + } + } + } + } + handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache, seenRefs) { + const smaskContent = smask.get("G"); + const smaskOptions = { + subtype: smask.get("S").name, + backdrop: smask.get("BC") + }; + const transferObj = smask.get("TR"); + if (isPDFFunction(transferObj)) { + const transferFn = this._pdfFunctionFactory.create(transferObj); + const transferMap = new Uint8Array(256); + const tmp = new Float32Array(1); + for (let i = 0; i < 256; i++) { + tmp[0] = i / 255; + transferFn(tmp, 0, tmp, 0); + transferMap[i] = tmp[0] * 255 | 0; + } + smaskOptions.transferMap = transferMap; + } + return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone({ + newPath: true + }), localColorSpaceCache, seenRefs); + } + handleTransferFunction(tr) { + let transferArray; + if (Array.isArray(tr)) { + transferArray = tr; + } else if (isPDFFunction(tr)) { + transferArray = [tr]; + } else { + return null; + } + const transferMaps = []; + let numFns = 0, + numEffectfulFns = 0; + for (const entry of transferArray) { + const transferObj = this.xref.fetchIfRef(entry); + numFns++; + if (isName(transferObj, "Identity")) { + transferMaps.push(null); + continue; + } else if (!isPDFFunction(transferObj)) { + return null; + } + const transferFn = this._pdfFunctionFactory.create(transferObj); + const transferMap = new Uint8Array(256), + tmp = new Float32Array(1); + for (let j = 0; j < 256; j++) { + tmp[0] = j / 255; + transferFn(tmp, 0, tmp, 0); + transferMap[j] = tmp[0] * 255 | 0; + } + transferMaps.push(transferMap); + numEffectfulFns++; + } + if (!(numFns === 1 || numFns === 4)) { + return null; + } + if (numEffectfulFns === 0) { + return null; + } + return transferMaps; + } + handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) { + const tilingOpList = new OperatorList(); + const patternResources = Dict.merge({ + xref: this.xref, + dictArray: [patternDict.get("Resources"), resources] + }); + return this.getOperatorList({ + stream: pattern, + task, + resources: patternResources, + operatorList: tilingOpList + }).then(function () { + const operatorListIR = tilingOpList.getIR(); + const tilingPatternIR = getTilingPatternIR(operatorListIR, patternDict, color); + operatorList.addDependencies(tilingOpList.dependencies); + operatorList.addOp(fn, tilingPatternIR); + if (patternDict.objId) { + localTilingPatternCache.set(null, patternDict.objId, { + operatorListIR, + dict: patternDict + }); + } + }).catch(reason => { + if (reason instanceof AbortException) { + return; + } + if (this.options.ignoreErrors) { + warn(`handleTilingType - ignoring pattern: "${reason}".`); + return; + } + throw reason; + }); + } + async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) { + const fontName = fontArgs?.[0] instanceof Name ? fontArgs[0].name : null; + const translated = await this.loadFont(fontName, fontRef, resources, task, fallbackFontDict, cssFontInfo); + if (translated.font.isType3Font) { + operatorList.addDependencies(translated.type3Dependencies); + } + state.font = translated.font; + translated.send(this.handler); + return translated.loadedName; + } + handleText(chars, state) { + const font = state.font; + const glyphs = font.charsToGlyphs(chars); + if (font.data) { + const isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG); + if (isAddToPathSet || state.fillColorSpace.name === "Pattern" || font.disableFontFace) { + PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options); + } + } + return glyphs; + } + ensureStateFont(state) { + if (state.font) { + return; + } + const reason = new FormatError("Missing setFont (Tf) operator before text rendering operator."); + if (this.options.ignoreErrors) { + warn(`ensureStateFont: "${reason}".`); + return; + } + throw reason; + } + async setGState({ + resources, + gState, + operatorList, + cacheKey, + task, + stateManager, + localGStateCache, + localColorSpaceCache, + seenRefs + }) { + const gStateRef = gState.objId; + let isSimpleGState = true; + const gStateObj = []; + let promise = Promise.resolve(); + for (const [key, value] of gState) { + switch (key) { + case "Type": + break; + case "LW": + if (typeof value !== "number") { + warn(`Invalid LW (line width): ${value}`); + break; + } + gStateObj.push([key, Math.abs(value)]); + break; + case "LC": + case "LJ": + case "ML": + case "D": + case "RI": + case "FL": + case "CA": + case "ca": + gStateObj.push([key, value]); + break; + case "Font": + isSimpleGState = false; + promise = promise.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + })); + break; + case "BM": + gStateObj.push([key, normalizeBlendMode(value)]); + break; + case "SMask": + if (isName(value, "None")) { + gStateObj.push([key, false]); + break; + } + if (value instanceof Dict) { + isSimpleGState = false; + promise = promise.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache, seenRefs)); + gStateObj.push([key, true]); + } else { + warn("Unsupported SMask type"); + } + break; + case "TR": + const transferMaps = this.handleTransferFunction(value); + gStateObj.push([key, transferMaps]); + break; + case "OP": + case "op": + case "OPM": + case "BG": + case "BG2": + case "UCR": + case "UCR2": + case "TR2": + case "HT": + case "SM": + case "SA": + case "AIS": + case "TK": + info("graphic state operator " + key); + break; + default: + info("Unknown graphic state operator " + key); + break; + } + } + await promise; + if (gStateObj.length > 0) { + operatorList.addOp(OPS.setGState, [gStateObj]); + } + if (isSimpleGState) { + localGStateCache.set(cacheKey, gStateRef, gStateObj); + } + } + loadFont(fontName, font, resources, task, fallbackFontDict = null, cssFontInfo = null) { + const errorFont = async () => new TranslatedFont({ + loadedName: "g_font_error", + font: new ErrorFont(`Font "${fontName}" is not available.`), + dict: font + }); + let fontRef; + if (font) { + if (font instanceof Ref) { + fontRef = font; + } + } else { + const fontRes = resources.get("Font"); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } + } + if (fontRef) { + if (this.type3FontRefs?.has(fontRef)) { + return errorFont(); + } + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + try { + font = this.xref.fetchIfRef(fontRef); + } catch (ex) { + warn(`loadFont - lookup failed: "${ex}".`); + } + } + if (!(font instanceof Dict)) { + if (!this.options.ignoreErrors && !this.parsingType3Font) { + warn(`Font "${fontName}" is not available.`); + return errorFont(); + } + warn(`Font "${fontName}" is not available -- attempting to fallback to a default font.`); + font = fallbackFontDict || PartialEvaluator.fallbackFontDict; + } + if (font.cacheKey && this.fontCache.has(font.cacheKey)) { + return this.fontCache.get(font.cacheKey); + } + const { + promise, + resolve + } = Promise.withResolvers(); + let preEvaluatedFont; + try { + preEvaluatedFont = this.preEvaluateFont(font); + preEvaluatedFont.cssFontInfo = cssFontInfo; + } catch (reason) { + warn(`loadFont - preEvaluateFont failed: "${reason}".`); + return errorFont(); + } + const { + descriptor, + hash + } = preEvaluatedFont; + const fontRefIsRef = fontRef instanceof Ref; + let fontID; + if (hash && descriptor instanceof Dict) { + const fontAliases = descriptor.fontAliases ||= Object.create(null); + if (fontAliases[hash]) { + const aliasFontRef = fontAliases[hash].aliasRef; + if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) { + this.fontCache.putAlias(fontRef, aliasFontRef); + return this.fontCache.get(fontRef); + } + } else { + fontAliases[hash] = { + fontID: this.idFactory.createFontId() + }; + } + if (fontRefIsRef) { + fontAliases[hash].aliasRef = fontRef; + } + fontID = fontAliases[hash].fontID; + } else { + fontID = this.idFactory.createFontId(); + } + assert(fontID?.startsWith("f"), 'The "fontID" must be (correctly) defined.'); + if (fontRefIsRef) { + this.fontCache.put(fontRef, promise); + } else { + font.cacheKey = `cacheKey_${fontID}`; + this.fontCache.put(font.cacheKey, promise); + } + font.loadedName = `${this.idFactory.getDocId()}_${fontID}`; + this.translateFont(preEvaluatedFont).then(async translatedFont => { + const translated = new TranslatedFont({ + loadedName: font.loadedName, + font: translatedFont, + dict: font + }); + if (translatedFont.isType3Font) { + try { + await translated.loadType3Data(this, resources, task); + } catch (reason) { + throw new Error(`Type3 font load error: ${reason}`); + } + } + resolve(translated); + }).catch(reason => { + warn(`loadFont - translateFont failed: "${reason}".`); + resolve(new TranslatedFont({ + loadedName: font.loadedName, + font: new ErrorFont(reason?.message), + dict: font + })); + }); + return promise; + } + buildPath(fn, args, state) { + const { + pathMinMax: minMax, + pathBuffer + } = state; + switch (fn | 0) { + case OPS.rectangle: + { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + const width = args[2]; + const height = args[3]; + const xw = x + width; + const yh = y + height; + if (width === 0 || height === 0) { + pathBuffer.push(DrawOPS.moveTo, x, y, DrawOPS.lineTo, xw, yh, DrawOPS.closePath); + } else { + pathBuffer.push(DrawOPS.moveTo, x, y, DrawOPS.lineTo, xw, y, DrawOPS.lineTo, xw, yh, DrawOPS.lineTo, x, yh, DrawOPS.closePath); + } + Util.rectBoundingBox(x, y, xw, yh, minMax); + break; + } + case OPS.moveTo: + { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + pathBuffer.push(DrawOPS.moveTo, x, y); + Util.pointBoundingBox(x, y, minMax); + break; + } + case OPS.lineTo: + { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + pathBuffer.push(DrawOPS.lineTo, x, y); + Util.pointBoundingBox(x, y, minMax); + break; + } + case OPS.curveTo: + { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x2, y2, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS.curveTo, x1, y1, x2, y2, x, y); + Util.bezierBoundingBox(startX, startY, x1, y1, x2, y2, x, y, minMax); + break; + } + case OPS.curveTo2: + { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS.curveTo, startX, startY, x1, y1, x, y); + Util.bezierBoundingBox(startX, startY, startX, startY, x1, y1, x, y, minMax); + break; + } + case OPS.curveTo3: + { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS.curveTo, x1, y1, x, y, x, y); + Util.bezierBoundingBox(startX, startY, x1, y1, x, y, x, y, minMax); + break; + } + case OPS.closePath: + pathBuffer.push(DrawOPS.closePath); + break; + } + } + _getColorSpace(cs, resources, localColorSpaceCache) { + return ColorSpaceUtils.parse({ + cs, + xref: this.xref, + resources, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache, + asyncIfNotCached: true + }); + } + async _handleColorSpace(csPromise) { + try { + return await csPromise; + } catch (ex) { + if (ex instanceof AbortException) { + return null; + } + if (this.options.ignoreErrors) { + warn(`_handleColorSpace - ignoring ColorSpace: "${ex}".`); + return null; + } + throw ex; + } + } + parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }) { + let id = localShadingPatternCache.get(shading); + if (id) { + return id; + } + let patternIR; + try { + const shadingFill = Pattern.parseShading(shading, this.xref, resources, this._pdfFunctionFactory, this.globalColorSpaceCache, localColorSpaceCache); + patternIR = shadingFill.getIR(); + } catch (reason) { + if (reason instanceof AbortException) { + return null; + } + if (this.options.ignoreErrors) { + warn(`parseShading - ignoring shading: "${reason}".`); + localShadingPatternCache.set(shading, null); + return null; + } + throw reason; + } + id = `pattern_${this.idFactory.createObjId()}`; + if (this.parsingType3Font) { + id = `${this.idFactory.getDocId()}_type3_${id}`; + } + localShadingPatternCache.set(shading, id); + if (this.parsingType3Font) { + const transfers = []; + const patternBuffer = PatternInfo.write(patternIR); + transfers.push(patternBuffer); + this.handler.send("commonobj", [id, "Pattern", patternBuffer], transfers); + } else { + this.handler.send("obj", [id, this.pageIndex, "Pattern", patternIR]); + } + return id; + } + handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) { + const patternName = args.pop(); + if (patternName instanceof Name) { + const rawPattern = patterns.getRaw(patternName.name); + const localTilingPattern = rawPattern instanceof Ref && localTilingPatternCache.getByRef(rawPattern); + if (localTilingPattern) { + try { + const color = cs.base ? cs.base.getRgbHex(args, 0) : null; + const tilingPatternIR = getTilingPatternIR(localTilingPattern.operatorListIR, localTilingPattern.dict, color); + operatorList.addOp(fn, tilingPatternIR); + return undefined; + } catch {} + } + const pattern = this.xref.fetchIfRef(rawPattern); + if (pattern) { + const dict = pattern instanceof BaseStream ? pattern.dict : pattern; + const typeNum = dict.get("PatternType"); + if (typeNum === PatternType.TILING) { + const color = cs.base ? cs.base.getRgbHex(args, 0) : null; + return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache); + } else if (typeNum === PatternType.SHADING) { + const shading = dict.get("Shading"); + const objId = this.parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }); + if (objId) { + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + operatorList.addOp(fn, ["Shading", objId, matrix]); + } + return undefined; + } + throw new FormatError(`Unknown PatternType: ${typeNum}`); + } + } + throw new FormatError(`Unknown PatternName: ${patternName}`); + } + _parseVisibilityExpression(array, nestingCounter, currentResult) { + const MAX_NESTING = 10; + if (++nestingCounter > MAX_NESTING) { + warn("Visibility expression is too deeply nested"); + return; + } + const length = array.length; + const operator = this.xref.fetchIfRef(array[0]); + if (length < 2 || !(operator instanceof Name)) { + warn("Invalid visibility expression"); + return; + } + switch (operator.name) { + case "And": + case "Or": + case "Not": + currentResult.push(operator.name); + break; + default: + warn(`Invalid operator ${operator.name} in visibility expression`); + return; + } + for (let i = 1; i < length; i++) { + const raw = array[i]; + const object = this.xref.fetchIfRef(raw); + if (Array.isArray(object)) { + const nestedResult = []; + currentResult.push(nestedResult); + this._parseVisibilityExpression(object, nestingCounter, nestedResult); + } else if (raw instanceof Ref) { + currentResult.push(raw.toString()); + } + } + } + async parseMarkedContentProps(contentProperties, resources) { + let optionalContent; + if (contentProperties instanceof Name) { + const properties = resources.get("Properties"); + optionalContent = properties.get(contentProperties.name); + } else if (contentProperties instanceof Dict) { + optionalContent = contentProperties; + } else { + throw new FormatError("Optional content properties malformed."); + } + const optionalContentType = optionalContent.get("Type")?.name; + if (optionalContentType === "OCG") { + return { + type: optionalContentType, + id: optionalContent.objId + }; + } else if (optionalContentType === "OCMD") { + const expression = optionalContent.get("VE"); + if (Array.isArray(expression)) { + const result = []; + this._parseVisibilityExpression(expression, 0, result); + if (result.length > 0) { + return { + type: "OCMD", + expression: result + }; + } + } + const optionalContentGroups = optionalContent.get("OCGs"); + if (Array.isArray(optionalContentGroups) || optionalContentGroups instanceof Dict) { + const groupIds = []; + if (Array.isArray(optionalContentGroups)) { + for (const ocg of optionalContentGroups) { + groupIds.push(ocg.toString()); + } + } else { + groupIds.push(optionalContentGroups.objId); + } + return { + type: optionalContentType, + ids: groupIds, + policy: optionalContent.get("P") instanceof Name ? optionalContent.get("P").name : null, + expression: null + }; + } else if (optionalContentGroups instanceof Ref) { + return { + type: optionalContentType, + id: optionalContentGroups.toString() + }; + } + } + return null; + } + getOperatorList({ + stream, + task, + resources, + operatorList, + initialState = null, + fallbackFontDict = null, + prevRefs = null + }) { + const objId = stream.dict?.objId; + const seenRefs = new RefSet(prevRefs); + if (objId) { + if (prevRefs?.has(objId)) { + throw new Error(`getOperatorList - ignoring circular reference: ${objId}`); + } + seenRefs.put(objId); + } + resources ||= Dict.empty; + initialState ||= new EvalState(); + if (!operatorList) { + throw new Error('getOperatorList: missing "operatorList" parameter'); + } + const self = this; + const xref = this.xref; + const localImageCache = new LocalImageCache(); + const localColorSpaceCache = new LocalColorSpaceCache(); + const localGStateCache = new LocalGStateCache(); + const localTilingPatternCache = new LocalTilingPatternCache(); + const localShadingPatternCache = new Map(); + const xobjs = resources.get("XObject") || Dict.empty; + const patterns = resources.get("Pattern") || Dict.empty; + const stateManager = new StateManager(initialState); + const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + const timeSlotManager = new TimeSlotManager(); + function closePendingRestoreOPS(argument) { + for (let i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { + operatorList.addOp(OPS.restore, []); + } + } + return new Promise(function promiseBody(resolve, reject) { + const next = function (promise) { + Promise.all([promise, operatorList.ready]).then(function () { + try { + promiseBody(resolve, reject); + } catch (ex) { + reject(ex); + } + }, reject); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + const operation = {}; + let stop, i, ii, cs, name, isValidName; + while (!(stop = timeSlotManager.check())) { + operation.args = null; + if (!preprocessor.read(operation)) { + break; + } + let args = operation.args; + let fn = operation.fn; + switch (fn | 0) { + case OPS.paintXObject: + isValidName = args[0] instanceof Name; + name = args[0].name; + if (isValidName) { + const localImage = localImageCache.getByName(name); + if (localImage) { + addCachedImageOps(operatorList, localImage); + args = null; + continue; + } + } + next(new Promise(function (resolveXObject, rejectXObject) { + if (!isValidName) { + throw new FormatError("XObject must be referred to by name."); + } + let xobj = xobjs.getRaw(name); + if (xobj instanceof Ref) { + const cachedImage = localImageCache.getByRef(xobj) || self._regionalImageCache.getByRef(xobj) || self.globalImageCache.getData(xobj, self.pageIndex); + if (cachedImage) { + addCachedImageOps(operatorList, cachedImage); + resolveXObject(); + return; + } + xobj = xref.fetch(xobj); + } + if (!(xobj instanceof BaseStream)) { + throw new FormatError("XObject should be a stream"); + } + const type = xobj.dict.get("Subtype"); + if (!(type instanceof Name)) { + throw new FormatError("XObject should have a Name subtype"); + } + if (type.name === "Form") { + stateManager.save(); + self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone({ + newPath: true + }), localColorSpaceCache, seenRefs).then(function () { + stateManager.restore(); + resolveXObject(); + }, rejectXObject); + return; + } else if (type.name === "Image") { + self.buildPaintImageXObject({ + resources, + image: xobj, + operatorList, + cacheKey: name, + localImageCache, + localColorSpaceCache + }).then(resolveXObject, rejectXObject); + return; + } else if (type.name === "PS") { + info("Ignored XObject subtype PS"); + } else { + throw new FormatError(`Unhandled XObject subtype ${type.name}`); + } + resolveXObject(); + }).catch(function (reason) { + if (reason instanceof AbortException) { + return; + } + if (self.options.ignoreErrors) { + warn(`getOperatorList - ignoring XObject: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS.setFont: + const fontSize = args[1]; + next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state, fallbackFontDict).then(function (loadedName) { + operatorList.addDependency(loadedName); + operatorList.addOp(OPS.setFont, [loadedName, fontSize]); + })); + return; + case OPS.endInlineImage: + const cacheKey = args[0].cacheKey; + if (cacheKey) { + const localImage = localImageCache.getByName(cacheKey); + if (localImage) { + addCachedImageOps(operatorList, localImage); + args = null; + continue; + } + } + next(self.buildPaintImageXObject({ + resources, + image: args[0], + isInline: true, + operatorList, + cacheKey, + localImageCache, + localColorSpaceCache + })); + return; + case OPS.showText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + args[0] = self.handleText(args[0], stateManager.state); + break; + case OPS.showSpacedText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + const combinedGlyphs = [], + state = stateManager.state; + for (const arrItem of args[0]) { + if (typeof arrItem === "string") { + combinedGlyphs.push(...self.handleText(arrItem, state)); + } else if (typeof arrItem === "number") { + combinedGlyphs.push(arrItem); + } + } + args[0] = combinedGlyphs; + fn = OPS.showText; + break; + case OPS.nextLineShowText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + operatorList.addOp(OPS.nextLine); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.nextLineSetSpacingShowText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + operatorList.addOp(OPS.nextLine); + operatorList.addOp(OPS.setWordSpacing, [args.shift()]); + operatorList.addOp(OPS.setCharSpacing, [args.shift()]); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.setTextRenderingMode: + stateManager.state.textRenderingMode = args[0]; + break; + case OPS.setFillColorSpace: + { + const fillCS = self._getColorSpace(args[0], resources, localColorSpaceCache); + if (fillCS instanceof ColorSpace) { + stateManager.state.fillColorSpace = fillCS; + continue; + } + next(self._handleColorSpace(fillCS).then(colorSpace => { + stateManager.state.fillColorSpace = colorSpace || ColorSpaceUtils.gray; + })); + return; + } + case OPS.setStrokeColorSpace: + { + const strokeCS = self._getColorSpace(args[0], resources, localColorSpaceCache); + if (strokeCS instanceof ColorSpace) { + stateManager.state.strokeColorSpace = strokeCS; + continue; + } + next(self._handleColorSpace(strokeCS).then(colorSpace => { + stateManager.state.strokeColorSpace = colorSpace || ColorSpaceUtils.gray; + })); + return; + } + case OPS.setFillColor: + cs = stateManager.state.fillColorSpace; + args = [cs.getRgbHex(args, 0)]; + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColor: + cs = stateManager.state.strokeColorSpace; + args = [cs.getRgbHex(args, 0)]; + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillGray: + stateManager.state.fillColorSpace = ColorSpaceUtils.gray; + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeGray: + stateManager.state.strokeColorSpace = ColorSpaceUtils.gray; + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillCMYKColor: + stateManager.state.fillColorSpace = ColorSpaceUtils.cmyk; + args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)]; + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeCMYKColor: + stateManager.state.strokeColorSpace = ColorSpaceUtils.cmyk; + args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)]; + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillRGBColor: + stateManager.state.fillColorSpace = ColorSpaceUtils.rgb; + args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)]; + break; + case OPS.setStrokeRGBColor: + stateManager.state.strokeColorSpace = ColorSpaceUtils.rgb; + args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)]; + break; + case OPS.setFillColorN: + cs = stateManager.state.patternFillColorSpace; + if (!cs) { + if (isNumberArray(args, null)) { + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS.setFillRGBColor; + break; + } + args = []; + fn = OPS.setFillTransparent; + break; + } + if (cs.name === "Pattern") { + next(self.handleColorN(operatorList, OPS.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); + return; + } + args = [cs.getRgbHex(args, 0)]; + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColorN: + cs = stateManager.state.patternStrokeColorSpace; + if (!cs) { + if (isNumberArray(args, null)) { + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS.setStrokeRGBColor; + break; + } + args = []; + fn = OPS.setStrokeTransparent; + break; + } + if (cs.name === "Pattern") { + next(self.handleColorN(operatorList, OPS.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); + return; + } + args = [cs.getRgbHex(args, 0)]; + fn = OPS.setStrokeRGBColor; + break; + case OPS.shadingFill: + let shading; + try { + const shadingRes = resources.get("Shading"); + if (!shadingRes) { + throw new FormatError("No shading resource found"); + } + shading = shadingRes.get(args[0].name); + if (!shading) { + throw new FormatError("No shading object found"); + } + } catch (reason) { + if (reason instanceof AbortException) { + continue; + } + if (self.options.ignoreErrors) { + warn(`getOperatorList - ignoring Shading: "${reason}".`); + continue; + } + throw reason; + } + const patternId = self.parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }); + if (!patternId) { + continue; + } + args = [patternId]; + fn = OPS.shadingFill; + break; + case OPS.setGState: + isValidName = args[0] instanceof Name; + name = args[0].name; + if (isValidName) { + const localGStateObj = localGStateCache.getByName(name); + if (localGStateObj) { + if (localGStateObj.length > 0) { + operatorList.addOp(OPS.setGState, [localGStateObj]); + } + args = null; + continue; + } + } + next(new Promise(function (resolveGState, rejectGState) { + if (!isValidName) { + throw new FormatError("GState must be referred to by name."); + } + const extGState = resources.get("ExtGState"); + if (!(extGState instanceof Dict)) { + throw new FormatError("ExtGState should be a dictionary."); + } + const gState = extGState.get(name); + if (!(gState instanceof Dict)) { + throw new FormatError("GState should be a dictionary."); + } + self.setGState({ + resources, + gState, + operatorList, + cacheKey: name, + task, + stateManager, + localGStateCache, + localColorSpaceCache, + seenRefs + }).then(resolveGState, rejectGState); + }).catch(function (reason) { + if (reason instanceof AbortException) { + return; + } + if (self.options.ignoreErrors) { + warn(`getOperatorList - ignoring ExtGState: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS.setLineWidth: + { + const [thickness] = args; + if (typeof thickness !== "number") { + warn(`Invalid setLineWidth: ${thickness}`); + continue; + } + args[0] = Math.abs(thickness); + break; + } + case OPS.setDash: + { + const dashPhase = args[1]; + if (typeof dashPhase !== "number") { + warn(`Invalid setDash: ${dashPhase}`); + continue; + } + const dashArray = args[0]; + if (!Array.isArray(dashArray)) { + warn(`Invalid setDash: ${dashArray}`); + continue; + } + if (dashArray.some(x => typeof x !== "number")) { + args[0] = dashArray.filter(x => typeof x === "number"); + } + break; + } + case OPS.moveTo: + case OPS.lineTo: + case OPS.curveTo: + case OPS.curveTo2: + case OPS.curveTo3: + case OPS.closePath: + case OPS.rectangle: + self.buildPath(fn, args, stateManager.state); + continue; + case OPS.stroke: + case OPS.closeStroke: + case OPS.fill: + case OPS.eoFill: + case OPS.fillStroke: + case OPS.eoFillStroke: + case OPS.closeFillStroke: + case OPS.closeEOFillStroke: + case OPS.endPath: + { + const { + state: { + pathBuffer, + pathMinMax + } + } = stateManager; + if (fn === OPS.closeStroke || fn === OPS.closeFillStroke || fn === OPS.closeEOFillStroke) { + pathBuffer.push(DrawOPS.closePath); + } + if (pathBuffer.length === 0) { + operatorList.addOp(OPS.constructPath, [fn, [null], null]); + } else { + operatorList.addOp(OPS.constructPath, [fn, [new Float32Array(pathBuffer)], pathMinMax.slice()]); + pathBuffer.length = 0; + pathMinMax.set([Infinity, Infinity, -Infinity, -Infinity], 0); + } + continue; + } + case OPS.setTextMatrix: + operatorList.addOp(fn, [new Float32Array(args)]); + continue; + case OPS.markPoint: + case OPS.markPointProps: + case OPS.beginCompat: + case OPS.endCompat: + continue; + case OPS.beginMarkedContentProps: + if (!(args[0] instanceof Name)) { + warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`); + operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]); + continue; + } + if (args[0].name === "OC") { + next(self.parseMarkedContentProps(args[1], resources).then(data => { + operatorList.addOp(OPS.beginMarkedContentProps, ["OC", data]); + }).catch(reason => { + if (reason instanceof AbortException) { + return; + } + if (self.options.ignoreErrors) { + warn(`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`); + operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]); + return; + } + throw reason; + })); + return; + } + args = [args[0].name, args[1] instanceof Dict ? args[1].get("MCID") : null]; + break; + case OPS.beginMarkedContent: + case OPS.endMarkedContent: + default: + if (args !== null) { + for (i = 0, ii = args.length; i < ii; i++) { + if (args[i] instanceof Dict) { + break; + } + } + if (i < ii) { + warn("getOperatorList - ignoring operator: " + fn); + continue; + } + } + } + operatorList.addOp(fn, args); + } + if (stop) { + next(deferred); + return; + } + closePendingRestoreOPS(); + resolve(); + }).catch(reason => { + if (reason instanceof AbortException) { + return; + } + if (this.options.ignoreErrors) { + warn(`getOperatorList - ignoring errors during "${task.name}" ` + `task: "${reason}".`); + closePendingRestoreOPS(); + return; + } + throw reason; + }); + } + getTextContent({ + stream, + task, + resources, + stateManager = null, + includeMarkedContent = false, + sink, + seenStyles = new Set(), + viewBox, + lang = null, + markedContentData = null, + disableNormalization = false, + keepWhiteSpace = false, + prevRefs = null, + intersector = null + }) { + const objId = stream.dict?.objId; + const seenRefs = new RefSet(prevRefs); + if (objId) { + if (prevRefs?.has(objId)) { + throw new Error(`getTextContent - ignoring circular reference: ${objId}`); + } + seenRefs.put(objId); + } + resources ||= Dict.empty; + stateManager ||= new StateManager(new TextState()); + if (includeMarkedContent) { + markedContentData ||= { + level: 0 + }; + } + const textContent = { + items: [], + styles: Object.create(null), + lang + }; + const textContentItem = { + initialized: false, + str: [], + totalWidth: 0, + totalHeight: 0, + width: 0, + height: 0, + vertical: false, + prevTransform: null, + textAdvanceScale: 0, + spaceInFlowMin: 0, + spaceInFlowMax: 0, + trackingSpaceMin: Infinity, + negativeSpaceMax: -Infinity, + notASpace: -Infinity, + transform: null, + fontName: null, + hasEOL: false + }; + const twoLastChars = [" ", " "]; + let twoLastCharsPos = 0; + function saveLastChar(char) { + const nextPos = (twoLastCharsPos + 1) % 2; + const ret = twoLastChars[twoLastCharsPos] !== " " && twoLastChars[nextPos] === " "; + twoLastChars[twoLastCharsPos] = char; + twoLastCharsPos = nextPos; + return !keepWhiteSpace && ret; + } + function shouldAddWhitepsace() { + return !keepWhiteSpace && twoLastChars[twoLastCharsPos] !== " " && twoLastChars[(twoLastCharsPos + 1) % 2] === " "; + } + function resetLastChars() { + twoLastChars[0] = twoLastChars[1] = " "; + twoLastCharsPos = 0; + } + const TRACKING_SPACE_FACTOR = 0.102; + const NOT_A_SPACE_FACTOR = 0.03; + const NEGATIVE_SPACE_FACTOR = -0.2; + const SPACE_IN_FLOW_MIN_FACTOR = 0.102; + const SPACE_IN_FLOW_MAX_FACTOR = 0.6; + const VERTICAL_SHIFT_RATIO = 0.25; + const self = this; + const xref = this.xref; + const showSpacedTextBuffer = []; + let xobjs = null; + const emptyXObjectCache = new LocalImageCache(); + const emptyGStateCache = new LocalGStateCache(); + const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + let textState; + function pushWhitespace({ + width = 0, + height = 0, + transform = textContentItem.prevTransform, + fontName = textContentItem.fontName + }) { + intersector?.addExtraChar(" "); + textContent.items.push({ + str: " ", + dir: "ltr", + width, + height, + transform, + fontName, + hasEOL: false + }); + } + function getCurrentTextTransform() { + const font = textState.font; + const tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise]; + if (font.isType3Font && (textState.fontSize <= 1 || font.isCharBBox) && !isArrayEqual(textState.fontMatrix, FONT_IDENTITY_MATRIX)) { + const glyphHeight = font.bbox[3] - font.bbox[1]; + if (glyphHeight > 0) { + tsm[3] *= glyphHeight * textState.fontMatrix[3]; + } + } + return Util.transform(textState.ctm, Util.transform(textState.textMatrix, tsm)); + } + function ensureTextContentItem() { + if (textContentItem.initialized) { + return textContentItem; + } + const { + font, + loadedName + } = textState; + if (!seenStyles.has(loadedName)) { + seenStyles.add(loadedName); + textContent.styles[loadedName] = { + fontFamily: font.fallbackName, + ascent: font.ascent, + descent: font.descent, + vertical: font.vertical + }; + if (self.options.fontExtraProperties && font.systemFontInfo) { + const style = textContent.styles[loadedName]; + style.fontSubstitution = font.systemFontInfo.css; + style.fontSubstitutionLoadedName = font.systemFontInfo.loadedName; + } + } + textContentItem.fontName = loadedName; + const trm = textContentItem.transform = getCurrentTextTransform(); + if (!font.vertical) { + textContentItem.width = textContentItem.totalWidth = 0; + textContentItem.height = textContentItem.totalHeight = Math.hypot(trm[2], trm[3]); + textContentItem.vertical = false; + } else { + textContentItem.width = textContentItem.totalWidth = Math.hypot(trm[0], trm[1]); + textContentItem.height = textContentItem.totalHeight = 0; + textContentItem.vertical = true; + } + const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); + const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); + textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; + const { + fontSize + } = textState; + textContentItem.trackingSpaceMin = fontSize * TRACKING_SPACE_FACTOR; + textContentItem.notASpace = fontSize * NOT_A_SPACE_FACTOR; + textContentItem.negativeSpaceMax = fontSize * NEGATIVE_SPACE_FACTOR; + textContentItem.spaceInFlowMin = fontSize * SPACE_IN_FLOW_MIN_FACTOR; + textContentItem.spaceInFlowMax = fontSize * SPACE_IN_FLOW_MAX_FACTOR; + textContentItem.hasEOL = false; + textContentItem.initialized = true; + return textContentItem; + } + function updateAdvanceScale() { + if (!textContentItem.initialized) { + return; + } + const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); + const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); + const scaleFactor = scaleCtmX * scaleLineX; + if (scaleFactor === textContentItem.textAdvanceScale) { + return; + } + if (!textContentItem.vertical) { + textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; + textContentItem.width = 0; + } else { + textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; + textContentItem.height = 0; + } + textContentItem.textAdvanceScale = scaleFactor; + } + function runBidiTransform(textChunk) { + let text = textChunk.str.join(""); + if (!disableNormalization) { + text = normalizeUnicode(text); + } + const bidiResult = bidi(text, -1, textChunk.vertical); + return { + str: bidiResult.str, + dir: bidiResult.dir, + width: Math.abs(textChunk.totalWidth), + height: Math.abs(textChunk.totalHeight), + transform: textChunk.transform, + fontName: textChunk.fontName, + hasEOL: textChunk.hasEOL + }; + } + async function handleSetFont(fontName, fontRef) { + const translated = await self.loadFont(fontName, fontRef, resources, task); + textState.loadedName = translated.loadedName; + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX; + } + function applyInverseRotation(x, y, matrix) { + const scale = Math.hypot(matrix[0], matrix[1]); + return [(matrix[0] * x + matrix[1] * y) / scale, (matrix[2] * x + matrix[3] * y) / scale]; + } + function compareWithLastPosition(glyphWidth) { + const currentTransform = getCurrentTextTransform(); + let posX = currentTransform[4]; + let posY = currentTransform[5]; + if (textState.font?.vertical) { + if (posX < viewBox[0] || posX > viewBox[2] || posY + glyphWidth < viewBox[1] || posY > viewBox[3]) { + return false; + } + } else if (posX + glyphWidth < viewBox[0] || posX > viewBox[2] || posY < viewBox[1] || posY > viewBox[3]) { + return false; + } + if (!textState.font || !textContentItem.prevTransform) { + return true; + } + let lastPosX = textContentItem.prevTransform[4]; + let lastPosY = textContentItem.prevTransform[5]; + if (lastPosX === posX && lastPosY === posY) { + return true; + } + let rotate = -1; + if (currentTransform[0] && currentTransform[1] === 0 && currentTransform[2] === 0) { + rotate = currentTransform[0] > 0 ? 0 : 180; + } else if (currentTransform[1] && currentTransform[0] === 0 && currentTransform[3] === 0) { + rotate = currentTransform[1] > 0 ? 90 : 270; + } + switch (rotate) { + case 0: + break; + case 90: + [posX, posY] = [posY, posX]; + [lastPosX, lastPosY] = [lastPosY, lastPosX]; + break; + case 180: + [posX, posY, lastPosX, lastPosY] = [-posX, -posY, -lastPosX, -lastPosY]; + break; + case 270: + [posX, posY] = [-posY, -posX]; + [lastPosX, lastPosY] = [-lastPosY, -lastPosX]; + break; + default: + [posX, posY] = applyInverseRotation(posX, posY, currentTransform); + [lastPosX, lastPosY] = applyInverseRotation(lastPosX, lastPosY, textContentItem.prevTransform); + } + if (textState.font.vertical) { + const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale; + const advanceX = posX - lastPosX; + const textOrientation = Math.sign(textContentItem.height); + if (advanceY < textOrientation * textContentItem.negativeSpaceMax) { + if (Math.abs(advanceX) > 0.5 * textContentItem.width) { + appendEOL(); + return true; + } + resetLastChars(); + flushTextContentItem(); + return true; + } + if (Math.abs(advanceX) > textContentItem.width) { + appendEOL(); + return true; + } + if (advanceY <= textOrientation * textContentItem.notASpace) { + resetLastChars(); + } + if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) { + if (shouldAddWhitepsace()) { + resetLastChars(); + flushTextContentItem(); + pushWhitespace({ + height: Math.abs(advanceY) + }); + } else { + textContentItem.height += advanceY; + } + } else if (!addFakeSpaces(advanceY, textContentItem.prevTransform, textOrientation)) { + if (textContentItem.str.length === 0) { + resetLastChars(); + pushWhitespace({ + height: Math.abs(advanceY) + }); + } else { + textContentItem.height += advanceY; + } + } + if (Math.abs(advanceX) > textContentItem.width * VERTICAL_SHIFT_RATIO) { + flushTextContentItem(); + } + return true; + } + const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale; + const advanceY = posY - lastPosY; + const textOrientation = Math.sign(textContentItem.width); + if (advanceX < textOrientation * textContentItem.negativeSpaceMax) { + if (Math.abs(advanceY) > 0.5 * textContentItem.height) { + appendEOL(); + return true; + } + resetLastChars(); + flushTextContentItem(); + return true; + } + if (Math.abs(advanceY) > textContentItem.height) { + appendEOL(); + return true; + } + if (advanceX <= textOrientation * textContentItem.notASpace) { + resetLastChars(); + } + if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) { + if (shouldAddWhitepsace()) { + resetLastChars(); + flushTextContentItem(); + pushWhitespace({ + width: Math.abs(advanceX) + }); + } else { + textContentItem.width += advanceX; + } + } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)) { + if (textContentItem.str.length === 0) { + resetLastChars(); + pushWhitespace({ + width: Math.abs(advanceX) + }); + } else { + textContentItem.width += advanceX; + } + } + if (Math.abs(advanceY) > textContentItem.height * VERTICAL_SHIFT_RATIO) { + flushTextContentItem(); + } + return true; + } + function buildTextContentItem({ + chars, + extraSpacing + }) { + const font = textState.font; + if (!chars) { + const charSpacing = textState.charSpacing + extraSpacing; + if (charSpacing) { + if (!font.vertical) { + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, -charSpacing); + } + } + if (keepWhiteSpace) { + compareWithLastPosition(0); + } + return; + } + const glyphs = font.charsToGlyphs(chars); + const scale = textState.fontMatrix[0] * textState.fontSize; + for (let i = 0, ii = glyphs.length; i < ii; i++) { + const glyph = glyphs[i]; + const { + category, + originalCharCode + } = glyph; + if (category.isInvisibleFormatMark) { + continue; + } + let charSpacing = textState.charSpacing + (i + 1 === ii ? extraSpacing : 0); + let glyphWidth = glyph.width; + if (font.vertical) { + glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth; + } + let scaledDim = glyphWidth * scale; + if (originalCharCode === 0x20) { + charSpacing += textState.wordSpacing; + } + if (!keepWhiteSpace && category.isWhitespace) { + if (!font.vertical) { + charSpacing += scaledDim; + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + charSpacing += -scaledDim; + textState.translateTextMatrix(0, -charSpacing); + } + saveLastChar(" "); + continue; + } + if (!category.isZeroWidthDiacritic && !compareWithLastPosition(scaledDim)) { + if (!font.vertical) { + textState.translateTextMatrix(scaledDim * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, scaledDim); + } + continue; + } + const textChunk = ensureTextContentItem(); + if (category.isZeroWidthDiacritic) { + scaledDim = 0; + } + if (!font.vertical) { + scaledDim *= textState.textHScale; + intersector?.addGlyph(getCurrentTextTransform(), scaledDim, 0, glyph.unicode); + textState.translateTextMatrix(scaledDim, 0); + textChunk.width += scaledDim; + } else { + intersector?.addGlyph(getCurrentTextTransform(), 0, scaledDim, glyph.unicode); + textState.translateTextMatrix(0, scaledDim); + scaledDim = Math.abs(scaledDim); + textChunk.height += scaledDim; + } + if (scaledDim) { + textChunk.prevTransform = getCurrentTextTransform(); + } + const glyphUnicode = glyph.unicode; + if (saveLastChar(glyphUnicode)) { + textChunk.str.push(" "); + intersector?.addExtraChar(" "); + } + if (!intersector) { + textChunk.str.push(glyphUnicode); + } + if (charSpacing) { + if (!font.vertical) { + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, -charSpacing); + } + } + } + } + function appendEOL() { + intersector?.addExtraChar("\n"); + resetLastChars(); + if (textContentItem.initialized) { + textContentItem.hasEOL = true; + flushTextContentItem(); + } else { + textContent.items.push({ + str: "", + dir: "ltr", + width: 0, + height: 0, + transform: getCurrentTextTransform(), + fontName: textState.loadedName, + hasEOL: true + }); + } + } + function addFakeSpaces(width, transf, textOrientation) { + if (textOrientation * textContentItem.spaceInFlowMin <= width && width <= textOrientation * textContentItem.spaceInFlowMax) { + if (textContentItem.initialized) { + resetLastChars(); + textContentItem.str.push(" "); + intersector?.addExtraChar(" "); + } + return false; + } + const fontName = textContentItem.fontName; + let height = 0; + if (textContentItem.vertical) { + height = width; + width = 0; + } + flushTextContentItem(); + resetLastChars(); + pushWhitespace({ + width: Math.abs(width), + height: Math.abs(height), + transform: transf || getCurrentTextTransform(), + fontName + }); + return true; + } + function flushTextContentItem() { + if (!textContentItem.initialized || !textContentItem.str) { + return; + } + if (!textContentItem.vertical) { + textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; + } else { + textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; + } + textContent.items.push(runBidiTransform(textContentItem)); + textContentItem.initialized = false; + textContentItem.str.length = 0; + } + function enqueueChunk(batch = false) { + const length = textContent.items.length; + if (length === 0) { + return; + } + if (batch && length < TEXT_CHUNK_BATCH_SIZE) { + return; + } + sink?.enqueue(textContent, length); + textContent.items = []; + textContent.styles = Object.create(null); + } + const timeSlotManager = new TimeSlotManager(); + return new Promise(function promiseBody(resolve, reject) { + const next = function (promise) { + enqueueChunk(true); + Promise.all([promise, sink?.ready]).then(function () { + try { + promiseBody(resolve, reject); + } catch (ex) { + reject(ex); + } + }, reject); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + const operation = {}; + let stop, + name, + isValidName, + args = []; + while (!(stop = timeSlotManager.check())) { + args.length = 0; + operation.args = args; + if (!preprocessor.read(operation)) { + break; + } + const previousState = textState; + textState = stateManager.state; + const fn = operation.fn; + args = operation.args; + switch (fn | 0) { + case OPS.setFont: + const fontNameArg = args[0].name, + fontSizeArg = args[1]; + if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) { + break; + } + flushTextContentItem(); + textState.fontName = fontNameArg; + textState.fontSize = fontSizeArg; + next(handleSetFont(fontNameArg, null)); + return; + case OPS.setTextRise: + textState.textRise = args[0]; + break; + case OPS.setHScale: + textState.textHScale = args[0] / 100; + break; + case OPS.setLeading: + textState.leading = args[0]; + break; + case OPS.moveText: + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.setLeadingMoveText: + textState.leading = -args[1]; + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.nextLine: + textState.carriageReturn(); + break; + case OPS.setTextMatrix: + textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + updateAdvanceScale(); + break; + case OPS.setCharSpacing: + textState.charSpacing = args[0]; + break; + case OPS.setWordSpacing: + textState.wordSpacing = args[0]; + break; + case OPS.beginText: + textState.textMatrix = IDENTITY_MATRIX.slice(); + textState.textLineMatrix = IDENTITY_MATRIX.slice(); + break; + case OPS.showSpacedText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + const spaceFactor = (textState.font.vertical ? 1 : -1) * textState.fontSize / 1000; + const elements = args[0]; + for (let i = 0, ii = elements.length; i < ii; i++) { + const item = elements[i]; + if (typeof item === "string") { + showSpacedTextBuffer.push(item); + } else if (typeof item === "number" && item !== 0) { + const str = showSpacedTextBuffer.join(""); + showSpacedTextBuffer.length = 0; + buildTextContentItem({ + chars: str, + extraSpacing: item * spaceFactor + }); + } + } + if (showSpacedTextBuffer.length > 0) { + const str = showSpacedTextBuffer.join(""); + showSpacedTextBuffer.length = 0; + buildTextContentItem({ + chars: str, + extraSpacing: 0 + }); + } + break; + case OPS.showText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + buildTextContentItem({ + chars: args[0], + extraSpacing: 0 + }); + break; + case OPS.nextLineShowText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + textState.carriageReturn(); + buildTextContentItem({ + chars: args[0], + extraSpacing: 0 + }); + break; + case OPS.nextLineSetSpacingShowText: + if (!stateManager.state.font) { + self.ensureStateFont(stateManager.state); + continue; + } + textState.wordSpacing = args[0]; + textState.charSpacing = args[1]; + textState.carriageReturn(); + buildTextContentItem({ + chars: args[2], + extraSpacing: 0 + }); + break; + case OPS.paintXObject: + flushTextContentItem(); + xobjs ??= resources.get("XObject") || Dict.empty; + isValidName = args[0] instanceof Name; + name = args[0].name; + if (isValidName && emptyXObjectCache.getByName(name)) { + break; + } + next(new Promise(function (resolveXObject, rejectXObject) { + if (!isValidName) { + throw new FormatError("XObject must be referred to by name."); + } + let xobj = xobjs.getRaw(name); + if (xobj instanceof Ref) { + if (emptyXObjectCache.getByRef(xobj)) { + resolveXObject(); + return; + } + const globalImage = self.globalImageCache.getData(xobj, self.pageIndex); + if (globalImage) { + resolveXObject(); + return; + } + xobj = xref.fetch(xobj); + } + if (!(xobj instanceof BaseStream)) { + throw new FormatError("XObject should be a stream"); + } + const { + dict + } = xobj; + const type = dict.get("Subtype"); + if (!(type instanceof Name)) { + throw new FormatError("XObject should have a Name subtype"); + } + if (type.name !== "Form") { + emptyXObjectCache.set(name, dict.objId, true); + resolveXObject(); + return; + } + const currentState = stateManager.state.clone(); + const xObjStateManager = new StateManager(currentState); + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + if (matrix) { + xObjStateManager.transform(matrix); + } + const localResources = dict.get("Resources"); + enqueueChunk(); + const sinkWrapper = { + enqueueInvoked: false, + enqueue(chunk, size) { + this.enqueueInvoked = true; + sink.enqueue(chunk, size); + }, + get desiredSize() { + return sink.desiredSize ?? 0; + }, + get ready() { + return sink.ready; + } + }; + self.getTextContent({ + stream: xobj, + task, + resources: localResources instanceof Dict ? localResources : resources, + stateManager: xObjStateManager, + includeMarkedContent, + sink: sink && sinkWrapper, + seenStyles, + viewBox, + lang, + markedContentData, + disableNormalization, + keepWhiteSpace, + prevRefs: seenRefs + }).then(function () { + if (!sinkWrapper.enqueueInvoked) { + emptyXObjectCache.set(name, dict.objId, true); + } + resolveXObject(); + }, rejectXObject); + }).catch(function (reason) { + if (reason instanceof AbortException) { + return; + } + if (self.options.ignoreErrors) { + warn(`getTextContent - ignoring XObject: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS.setGState: + isValidName = args[0] instanceof Name; + name = args[0].name; + if (isValidName && emptyGStateCache.getByName(name)) { + break; + } + next(new Promise(function (resolveGState, rejectGState) { + if (!isValidName) { + throw new FormatError("GState must be referred to by name."); + } + const extGState = resources.get("ExtGState"); + if (!(extGState instanceof Dict)) { + throw new FormatError("ExtGState should be a dictionary."); + } + const gState = extGState.get(name); + if (!(gState instanceof Dict)) { + throw new FormatError("GState should be a dictionary."); + } + const gStateFont = gState.get("Font"); + if (!gStateFont) { + emptyGStateCache.set(name, gState.objId, true); + resolveGState(); + return; + } + flushTextContentItem(); + textState.fontName = null; + textState.fontSize = gStateFont[1]; + handleSetFont(null, gStateFont[0]).then(resolveGState, rejectGState); + }).catch(function (reason) { + if (reason instanceof AbortException) { + return; + } + if (self.options.ignoreErrors) { + warn(`getTextContent - ignoring ExtGState: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS.beginMarkedContent: + flushTextContentItem(); + if (includeMarkedContent) { + markedContentData.level++; + textContent.items.push({ + type: "beginMarkedContent", + tag: args[0] instanceof Name ? args[0].name : null + }); + } + break; + case OPS.beginMarkedContentProps: + flushTextContentItem(); + if (includeMarkedContent) { + markedContentData.level++; + let mcid = null; + if (args[1] instanceof Dict) { + mcid = args[1].get("MCID"); + } + textContent.items.push({ + type: "beginMarkedContentProps", + id: Number.isInteger(mcid) ? `${self.idFactory.getPageObjId()}_mc${mcid}` : null, + tag: args[0] instanceof Name ? args[0].name : null + }); + } + break; + case OPS.endMarkedContent: + flushTextContentItem(); + if (includeMarkedContent) { + if (markedContentData.level === 0) { + break; + } + markedContentData.level--; + textContent.items.push({ + type: "endMarkedContent" + }); + } + break; + case OPS.restore: + if (previousState && (previousState.font !== textState.font || previousState.fontSize !== textState.fontSize || previousState.fontName !== textState.fontName)) { + flushTextContentItem(); + } + break; + } + if (textContent.items.length >= (sink?.desiredSize ?? 1)) { + stop = true; + break; + } + } + if (stop) { + next(deferred); + return; + } + flushTextContentItem(); + enqueueChunk(); + resolve(); + }).catch(reason => { + if (reason instanceof AbortException) { + return; + } + if (this.options.ignoreErrors) { + warn(`getTextContent - ignoring errors during "${task.name}" ` + `task: "${reason}".`); + flushTextContentItem(); + enqueueChunk(); + return; + } + throw reason; + }); + } + async extractDataStructures(dict, properties) { + const xref = this.xref; + let cidToGidBytes; + const toUnicodePromise = this.readToUnicode(properties.toUnicode); + if (properties.composite) { + const cidSystemInfo = dict.get("CIDSystemInfo"); + if (cidSystemInfo instanceof Dict) { + properties.cidSystemInfo = { + registry: stringToPDFString(cidSystemInfo.get("Registry")), + ordering: stringToPDFString(cidSystemInfo.get("Ordering")), + supplement: cidSystemInfo.get("Supplement") + }; + } + try { + const cidToGidMap = dict.get("CIDToGIDMap"); + if (cidToGidMap instanceof BaseStream) { + cidToGidBytes = cidToGidMap.getBytes(); + } + } catch (ex) { + if (!this.options.ignoreErrors) { + throw ex; + } + warn(`extractDataStructures - ignoring CIDToGIDMap data: "${ex}".`); + } + } + const differences = []; + let baseEncodingName = null; + let encoding; + if (dict.has("Encoding")) { + encoding = dict.get("Encoding"); + if (encoding instanceof Dict) { + baseEncodingName = encoding.get("BaseEncoding"); + baseEncodingName = baseEncodingName instanceof Name ? baseEncodingName.name : null; + if (encoding.has("Differences")) { + const diffEncoding = encoding.get("Differences"); + let index = 0; + for (const entry of diffEncoding) { + const data = xref.fetchIfRef(entry); + if (typeof data === "number") { + index = data; + } else if (data instanceof Name) { + differences[index++] = data.name; + } else { + throw new FormatError(`Invalid entry in 'Differences' array: ${data}`); + } + } + } + } else if (encoding instanceof Name) { + baseEncodingName = encoding.name; + } else { + const msg = "Encoding is not a Name nor a Dict"; + if (!this.options.ignoreErrors) { + throw new FormatError(msg); + } + warn(msg); + } + if (baseEncodingName !== "MacRomanEncoding" && baseEncodingName !== "MacExpertEncoding" && baseEncodingName !== "WinAnsiEncoding") { + baseEncodingName = null; + } + } + const nonEmbeddedFont = !properties.file || properties.isInternalFont, + isSymbolsFontName = getSymbolsFonts()[properties.name]; + if (baseEncodingName && nonEmbeddedFont && isSymbolsFontName) { + baseEncodingName = null; + } + if (baseEncodingName) { + properties.defaultEncoding = getEncoding(baseEncodingName); + } else { + let isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + const isNonsymbolicFont = !!(properties.flags & FontFlags.Nonsymbolic); + if (properties.type === "TrueType" && isSymbolicFont && isNonsymbolicFont && differences.length !== 0) { + properties.flags &= ~FontFlags.Symbolic; + isSymbolicFont = false; + } + encoding = StandardEncoding; + if (properties.type === "TrueType" && !isNonsymbolicFont) { + encoding = WinAnsiEncoding; + } + if (isSymbolicFont || isSymbolsFontName) { + encoding = MacRomanEncoding; + if (nonEmbeddedFont) { + if (/Symbol/i.test(properties.name)) { + encoding = SymbolSetEncoding; + } else if (/Dingbats/i.test(properties.name)) { + encoding = ZapfDingbatsEncoding; + } else if (/Wingdings/i.test(properties.name)) { + encoding = WinAnsiEncoding; + } + } + } + properties.defaultEncoding = encoding; + } + properties.differences = differences; + properties.baseEncodingName = baseEncodingName; + properties.hasEncoding = !!baseEncodingName || differences.length > 0; + properties.dict = dict; + properties.toUnicode = await toUnicodePromise; + const builtToUnicode = await this.buildToUnicode(properties); + properties.toUnicode = builtToUnicode; + if (cidToGidBytes) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode); + } + return properties; + } + _simpleFontToUnicode(properties, forceGlyphs = false) { + assert(!properties.composite, "Must be a simple font."); + const toUnicode = []; + const encoding = properties.defaultEncoding.slice(); + const baseEncodingName = properties.baseEncodingName; + const differences = properties.differences; + for (const charcode in differences) { + const glyphName = differences[charcode]; + if (glyphName === ".notdef") { + continue; + } + encoding[charcode] = glyphName; + } + const glyphsUnicodeMap = getGlyphsUnicode(); + for (const charcode in encoding) { + let glyphName = encoding[charcode]; + if (glyphName === "") { + continue; + } + let unicode = glyphsUnicodeMap[glyphName]; + if (unicode !== undefined) { + toUnicode[charcode] = String.fromCharCode(unicode); + continue; + } + let code = 0; + switch (glyphName[0]) { + case "G": + if (glyphName.length === 3) { + code = parseInt(glyphName.substring(1), 16); + } + break; + case "g": + if (glyphName.length === 5) { + code = parseInt(glyphName.substring(1), 16); + } + break; + case "C": + case "c": + if (glyphName.length >= 3 && glyphName.length <= 4) { + const codeStr = glyphName.substring(1); + if (forceGlyphs) { + code = parseInt(codeStr, 16); + break; + } + code = +codeStr; + if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) { + return this._simpleFontToUnicode(properties, true); + } + } + break; + case "u": + unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + code = unicode; + } + break; + default: + switch (glyphName) { + case "f_h": + case "f_t": + case "T_h": + toUnicode[charcode] = glyphName.replaceAll("_", ""); + continue; + } + break; + } + if (code > 0 && code <= 0x10ffff && Number.isInteger(code)) { + if (baseEncodingName && code === +charcode) { + const baseEncoding = getEncoding(baseEncodingName); + if (baseEncoding && (glyphName = baseEncoding[charcode])) { + toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); + continue; + } + } + toUnicode[charcode] = String.fromCodePoint(code); + } + } + return toUnicode; + } + async buildToUnicode(properties) { + properties.hasIncludedToUnicodeMap = properties.toUnicode?.length > 0; + if (properties.hasIncludedToUnicodeMap) { + if (!properties.composite && properties.hasEncoding) { + properties.fallbackToUnicode = this._simpleFontToUnicode(properties); + } + return properties.toUnicode; + } + if (!properties.composite) { + return new ToUnicodeMap(this._simpleFontToUnicode(properties)); + } + if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo?.registry === "Adobe" && (properties.cidSystemInfo.ordering === "GB1" || properties.cidSystemInfo.ordering === "CNS1" || properties.cidSystemInfo.ordering === "Japan1" || properties.cidSystemInfo.ordering === "Korea1"))) { + const { + registry, + ordering + } = properties.cidSystemInfo; + const ucs2CMapName = Name.get(`${registry}-${ordering}-UCS2`); + const ucs2CMap = await CMapFactory.create({ + encoding: ucs2CMapName, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + const toUnicode = [], + buf = []; + properties.cMap.forEach(function (charcode, cid) { + if (cid > 0xffff) { + throw new FormatError("Max size of CID is 65,535"); + } + const ucs2 = ucs2CMap.lookup(cid); + if (ucs2) { + buf.length = 0; + for (let i = 0, ii = ucs2.length; i < ii; i += 2) { + buf.push((ucs2.charCodeAt(i) << 8) + ucs2.charCodeAt(i + 1)); + } + toUnicode[charcode] = String.fromCharCode(...buf); + } + }); + return new ToUnicodeMap(toUnicode); + } + return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar); + } + async readToUnicode(cmapObj) { + if (!cmapObj) { + return null; + } + if (cmapObj instanceof Name) { + const cmap = await CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xffff); + } + return new ToUnicodeMap(cmap.getMap()); + } + if (cmapObj instanceof BaseStream) { + try { + const cmap = await CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xffff); + } + const map = new Array(cmap.length); + cmap.forEach(function (charCode, token) { + if (typeof token === "number") { + map[charCode] = String.fromCodePoint(token); + return; + } + if (token.length % 2 !== 0) { + token = "\u0000" + token; + } + const str = []; + for (let k = 0; k < token.length; k += 2) { + const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + if ((w1 & 0xf800) !== 0xd800) { + str.push(w1); + continue; + } + k += 2; + const w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); + } + map[charCode] = String.fromCodePoint(...str); + }); + return new ToUnicodeMap(map); + } catch (reason) { + if (reason instanceof AbortException) { + return null; + } + if (this.options.ignoreErrors) { + warn(`readToUnicode - ignoring ToUnicode data: "${reason}".`); + return null; + } + throw reason; + } + } + return null; + } + readCidToGidMap(glyphsData, toUnicode) { + const result = []; + for (let j = 0, jj = glyphsData.length; j < jj; j++) { + const glyphID = glyphsData[j++] << 8 | glyphsData[j]; + const code = j >> 1; + if (glyphID === 0 && !toUnicode.has(code)) { + continue; + } + result[code] = glyphID; + } + return result; + } + extractWidths(dict, descriptor, properties) { + const xref = this.xref; + let glyphsWidths = []; + let defaultWidth = 0; + const glyphsVMetrics = []; + let defaultVMetrics; + if (properties.composite) { + const dw = dict.get("DW"); + defaultWidth = typeof dw === "number" ? Math.ceil(dw) : 1000; + const widths = dict.get("W"); + if (Array.isArray(widths)) { + for (let i = 0, ii = widths.length; i < ii; i++) { + let start = xref.fetchIfRef(widths[i++]); + if (!Number.isInteger(start)) { + break; + } + const code = xref.fetchIfRef(widths[i]); + if (Array.isArray(code)) { + for (const c of code) { + const width = xref.fetchIfRef(c); + if (typeof width === "number") { + glyphsWidths[start] = width; + } + start++; + } + } else if (Number.isInteger(code)) { + const width = xref.fetchIfRef(widths[++i]); + if (typeof width !== "number") { + continue; + } + for (let j = start; j <= code; j++) { + glyphsWidths[j] = width; + } + } else { + break; + } + } + } + if (properties.vertical) { + const dw2 = dict.getArray("DW2"); + let vmetrics = isNumberArray(dw2, 2) ? dw2 : [880, -1000]; + defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; + vmetrics = dict.get("W2"); + if (Array.isArray(vmetrics)) { + for (let i = 0, ii = vmetrics.length; i < ii; i++) { + let start = xref.fetchIfRef(vmetrics[i++]); + if (!Number.isInteger(start)) { + break; + } + const code = xref.fetchIfRef(vmetrics[i]); + if (Array.isArray(code)) { + for (let j = 0, jj = code.length; j < jj; j++) { + const vmetric = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])]; + if (isNumberArray(vmetric, null)) { + glyphsVMetrics[start] = vmetric; + } + start++; + } + } else if (Number.isInteger(code)) { + const vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])]; + if (!isNumberArray(vmetric, null)) { + continue; + } + for (let j = start; j <= code; j++) { + glyphsVMetrics[j] = vmetric; + } + } else { + break; + } + } + } + } + } else { + const widths = dict.get("Widths"); + if (Array.isArray(widths)) { + let j = properties.firstChar; + for (const w of widths) { + const width = xref.fetchIfRef(w); + if (typeof width === "number") { + glyphsWidths[j] = width; + } + j++; + } + const missingWidth = descriptor.get("MissingWidth"); + defaultWidth = typeof missingWidth === "number" ? missingWidth : 0; + } else { + const baseFontName = dict.get("BaseFont"); + if (baseFontName instanceof Name) { + const metrics = this.getBaseFontMetrics(baseFontName.name); + glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties); + defaultWidth = metrics.defaultWidth; + } + } + } + let isMonospace = true; + let firstWidth = defaultWidth; + for (const glyph in glyphsWidths) { + const glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) { + continue; + } + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth !== glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) { + properties.flags |= FontFlags.FixedPitch; + } else { + properties.flags &= ~FontFlags.FixedPitch; + } + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + } + isSerifFont(baseFontName) { + const fontNameWoStyle = baseFontName.split("-", 1)[0]; + return fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle); + } + getBaseFontMetrics(name) { + let defaultWidth = 0; + let widths = Object.create(null); + let monospace = false; + const stdFontMap = getStdFontMap(); + let lookupName = stdFontMap[name] || name; + const Metrics = getMetrics(); + if (!(lookupName in Metrics)) { + lookupName = this.isSerifFont(name) ? "Times-Roman" : "Helvetica"; + } + const glyphWidths = Metrics[lookupName]; + if (typeof glyphWidths === "number") { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths(); + } + return { + defaultWidth, + monospace, + widths + }; + } + buildCharCodeToWidth(widthsByGlyphName, properties) { + const widths = Object.create(null); + const differences = properties.differences; + const encoding = properties.defaultEncoding; + for (let charCode = 0; charCode < 256; charCode++) { + if (charCode in differences && widthsByGlyphName[differences[charCode]]) { + widths[charCode] = widthsByGlyphName[differences[charCode]]; + continue; + } + if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { + widths[charCode] = widthsByGlyphName[encoding[charCode]]; + continue; + } + } + return widths; + } + preEvaluateFont(dict) { + const baseDict = dict; + let type = dict.get("Subtype"); + if (!(type instanceof Name)) { + throw new FormatError("invalid font Subtype"); + } + let composite = false; + let hash; + if (type.name === "Type0") { + const df = dict.get("DescendantFonts"); + if (!df) { + throw new FormatError("Descendant fonts are not specified"); + } + dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df; + if (!(dict instanceof Dict)) { + throw new FormatError("Descendant font is not a dictionary."); + } + type = dict.get("Subtype"); + if (!(type instanceof Name)) { + throw new FormatError("invalid font Subtype"); + } + composite = true; + } + let firstChar = dict.get("FirstChar"); + if (!Number.isInteger(firstChar)) { + firstChar = 0; + } + let lastChar = dict.get("LastChar"); + if (!Number.isInteger(lastChar)) { + lastChar = composite ? 0xffff : 0xff; + } + const descriptor = dict.get("FontDescriptor"); + const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode"); + if (descriptor) { + hash = new MurmurHash3_64(); + const encoding = baseDict.getRaw("Encoding"); + if (encoding instanceof Name) { + hash.update(encoding.name); + } else if (encoding instanceof Ref) { + hash.update(encoding.toString()); + } else if (encoding instanceof Dict) { + for (const entry of encoding.getRawValues()) { + if (entry instanceof Name) { + hash.update(entry.name); + } else if (entry instanceof Ref) { + hash.update(entry.toString()); + } else if (Array.isArray(entry)) { + const diffLength = entry.length, + diffBuf = new Array(diffLength); + for (let j = 0; j < diffLength; j++) { + const diffEntry = entry[j]; + if (diffEntry instanceof Name) { + diffBuf[j] = diffEntry.name; + } else if (typeof diffEntry === "number" || diffEntry instanceof Ref) { + diffBuf[j] = diffEntry.toString(); + } + } + hash.update(diffBuf.join()); + } + } + } + hash.update(`${firstChar}-${lastChar}`); + if (toUnicode instanceof BaseStream) { + const stream = toUnicode.stream || toUnicode; + const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start); + hash.update(uint8array); + } else if (toUnicode instanceof Name) { + hash.update(toUnicode.name); + } + const widths = dict.get("Widths") || baseDict.get("Widths"); + if (Array.isArray(widths)) { + const widthsBuf = []; + for (const entry of widths) { + if (typeof entry === "number" || entry instanceof Ref) { + widthsBuf.push(entry.toString()); + } + } + hash.update(widthsBuf.join()); + } + if (composite) { + hash.update("compositeFont"); + const compositeWidths = dict.get("W") || baseDict.get("W"); + if (Array.isArray(compositeWidths)) { + const widthsBuf = []; + for (const entry of compositeWidths) { + if (typeof entry === "number" || entry instanceof Ref) { + widthsBuf.push(entry.toString()); + } else if (Array.isArray(entry)) { + const subWidthsBuf = []; + for (const element of entry) { + if (typeof element === "number" || element instanceof Ref) { + subWidthsBuf.push(element.toString()); + } + } + widthsBuf.push(`[${subWidthsBuf.join()}]`); + } + } + hash.update(widthsBuf.join()); + } + const cidToGidMap = dict.getRaw("CIDToGIDMap") || baseDict.getRaw("CIDToGIDMap"); + if (cidToGidMap instanceof Name) { + hash.update(cidToGidMap.name); + } else if (cidToGidMap instanceof Ref) { + hash.update(cidToGidMap.toString()); + } else if (cidToGidMap instanceof BaseStream) { + hash.update(cidToGidMap.peekBytes()); + } + } + } + return { + descriptor, + dict, + baseDict, + composite, + type: type.name, + firstChar, + lastChar, + toUnicode, + hash: hash ? hash.hexdigest() : "" + }; + } + async translateFont({ + descriptor, + dict, + baseDict, + composite, + type, + firstChar, + lastChar, + toUnicode, + cssFontInfo + }) { + const isType3Font = type === "Type3"; + if (!descriptor) { + if (isType3Font) { + descriptor = Dict.empty; + } else { + let baseFontName = dict.get("BaseFont"); + if (!(baseFontName instanceof Name)) { + throw new FormatError("Base font is not specified"); + } + baseFontName = baseFontName.name.replaceAll(/[,_]/g, "-"); + const metrics = this.getBaseFontMetrics(baseFontName); + const fontNameWoStyle = baseFontName.split("-", 1)[0]; + const flags = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic); + const properties = { + type, + name: baseFontName, + loadedName: baseDict.loadedName, + systemFontInfo: null, + widths: metrics.widths, + defaultWidth: metrics.defaultWidth, + isSimulatedFlags: true, + flags, + firstChar, + lastChar, + toUnicode, + xHeight: 0, + capHeight: 0, + italicAngle: 0, + isType3Font + }; + const widths = dict.get("Widths"); + const standardFontName = getStandardFontName(baseFontName); + let file = null; + if (standardFontName) { + file = await this.fetchStandardFontData(standardFontName); + properties.isInternalFont = !!file; + } + if (!properties.isInternalFont && this.options.useSystemFonts) { + properties.systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, baseFontName, standardFontName, type); + } + const newProperties = await this.extractDataStructures(dict, properties); + if (Array.isArray(widths)) { + const glyphWidths = []; + let j = firstChar; + for (const w of widths) { + const width = this.xref.fetchIfRef(w); + if (typeof width === "number") { + glyphWidths[j] = width; + } + j++; + } + newProperties.widths = glyphWidths; + } else { + newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties); + } + return new Font(baseFontName, file, newProperties, this.options); + } + } + let fontName = descriptor.get("FontName"); + let baseFont = dict.get("BaseFont"); + if (typeof fontName === "string") { + fontName = Name.get(fontName); + } + if (typeof baseFont === "string") { + baseFont = Name.get(baseFont); + } + const fontNameStr = fontName?.name; + const baseFontStr = baseFont?.name; + if (isType3Font) { + if (!fontNameStr) { + fontName = Name.get(type); + } + } else if (fontNameStr !== baseFontStr) { + info(`The FontDescriptor's FontName is "${fontNameStr}" but ` + `should be the same as the Font's BaseFont "${baseFontStr}".`); + if (fontNameStr && baseFontStr && (baseFontStr.startsWith(fontNameStr) || !isKnownFontName(fontNameStr) && isKnownFontName(baseFontStr))) { + fontName = null; + } + fontName ||= baseFont; + } + if (!(fontName instanceof Name)) { + throw new FormatError("invalid font name"); + } + let fontFile, subtype, length1, length2, length3; + try { + fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3"); + if (fontFile) { + if (!(fontFile instanceof BaseStream)) { + throw new FormatError("FontFile should be a stream"); + } else if (fontFile.isEmpty) { + throw new FormatError("FontFile is empty"); + } + } + } catch (ex) { + if (!this.options.ignoreErrors) { + throw ex; + } + warn(`translateFont - fetching "${fontName.name}" font file: "${ex}".`); + fontFile = null; + } + let isInternalFont = false; + let glyphScaleFactors = null; + let systemFontInfo = null; + if (fontFile) { + if (fontFile.dict) { + const subtypeEntry = fontFile.dict.get("Subtype"); + if (subtypeEntry instanceof Name) { + subtype = subtypeEntry.name; + } + length1 = fontFile.dict.get("Length1"); + length2 = fontFile.dict.get("Length2"); + length3 = fontFile.dict.get("Length3"); + } + } else if (cssFontInfo) { + const standardFontName = getXfaFontName(fontName.name); + if (standardFontName) { + cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`; + cssFontInfo.metrics = standardFontName.metrics || null; + glyphScaleFactors = standardFontName.factors || null; + fontFile = await this.fetchStandardFontData(standardFontName.name); + isInternalFont = !!fontFile; + baseDict = dict = getXfaFontDict(fontName.name); + composite = true; + } + } else if (!isType3Font) { + const standardFontName = getStandardFontName(fontName.name); + if (standardFontName) { + fontFile = await this.fetchStandardFontData(standardFontName); + isInternalFont = !!fontFile; + } + if (!isInternalFont && this.options.useSystemFonts) { + systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName, type); + } + } + const fontMatrix = lookupMatrix(dict.getArray("FontMatrix"), FONT_IDENTITY_MATRIX); + const bbox = lookupNormalRect(descriptor.getArray("FontBBox") || dict.getArray("FontBBox"), isType3Font ? [0, 0, 0, 0] : undefined); + let ascent = descriptor.get("Ascent"); + if (typeof ascent !== "number") { + ascent = undefined; + } + let descent = descriptor.get("Descent"); + if (typeof descent !== "number") { + descent = undefined; + } + let xHeight = descriptor.get("XHeight"); + if (typeof xHeight !== "number") { + xHeight = 0; + } + let capHeight = descriptor.get("CapHeight"); + if (typeof capHeight !== "number") { + capHeight = 0; + } + let flags = descriptor.get("Flags"); + if (!Number.isInteger(flags)) { + flags = 0; + } + let italicAngle = descriptor.get("ItalicAngle"); + if (typeof italicAngle !== "number") { + italicAngle = 0; + } + const properties = { + type, + name: fontName.name, + subtype, + file: fontFile, + length1, + length2, + length3, + isInternalFont, + loadedName: baseDict.loadedName, + composite, + fixedPitch: false, + fontMatrix, + firstChar, + lastChar, + toUnicode, + bbox, + ascent, + descent, + xHeight, + capHeight, + flags, + italicAngle, + isType3Font, + cssFontInfo, + scaleFactors: glyphScaleFactors, + systemFontInfo + }; + if (composite) { + const cidEncoding = baseDict.get("Encoding"); + if (cidEncoding instanceof Name) { + properties.cidEncoding = cidEncoding.name; + } + const cMap = await CMapFactory.create({ + encoding: cidEncoding, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + properties.cMap = cMap; + properties.vertical = properties.cMap.vertical; + } + const newProperties = await this.extractDataStructures(dict, properties); + this.extractWidths(dict, descriptor, newProperties); + return new Font(fontName.name, fontFile, newProperties, this.options); + } + static buildFontPaths(font, glyphs, handler, evaluatorOptions) { + function buildPath(fontChar) { + const glyphName = `${font.loadedName}_path_${fontChar}`; + try { + if (font.renderer.hasBuiltPath(fontChar)) { + return; + } + handler.send("commonobj", [glyphName, "FontPath", font.renderer.getPathJs(fontChar)]); + } catch (reason) { + if (evaluatorOptions.ignoreErrors) { + warn(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`); + return; + } + throw reason; + } + } + for (const glyph of glyphs) { + buildPath(glyph.fontChar); + const accent = glyph.accent; + if (accent?.fontChar) { + buildPath(accent.fontChar); + } + } + } + static get fallbackFontDict() { + const dict = new Dict(); + dict.set("BaseFont", Name.get("Helvetica")); + dict.set("Type", Name.get("FallbackType")); + dict.set("Subtype", Name.get("FallbackType")); + dict.set("Encoding", Name.get("WinAnsiEncoding")); + return shadow(this, "fallbackFontDict", dict); + } +} +class TranslatedFont { + #sent = false; + #type3Loaded = null; + constructor({ + loadedName, + font, + dict + }) { + this.loadedName = loadedName; + this.font = font; + this.dict = dict; + this.type3Dependencies = font.isType3Font ? new Set() : null; + } + send(handler) { + if (this.#sent) { + return; + } + this.#sent = true; + const fontData = this.font.exportData(); + const transfer = []; + if (fontData.data) { + if (fontData.data.charProcOperatorList) { + fontData.charProcOperatorList = fontData.data.charProcOperatorList; + } + fontData.data = FontInfo.write(fontData.data); + transfer.push(fontData.data); + } + handler.send("commonobj", [this.loadedName, "Font", fontData], transfer); + } + fallback(handler, evaluatorOptions) { + if (!this.font.data) { + return; + } + this.font.disableFontFace = true; + PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, evaluatorOptions); + } + loadType3Data(evaluator, resources, task) { + if (this.#type3Loaded) { + return this.#type3Loaded; + } + const { + font, + type3Dependencies + } = this; + assert(font.isType3Font, "Must be a Type3 font."); + const type3Evaluator = evaluator.clone({ + ignoreErrors: false + }); + const type3FontRefs = new RefSet(evaluator.type3FontRefs); + if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) { + type3FontRefs.put(this.dict.objId); + } + type3Evaluator.type3FontRefs = type3FontRefs; + let loadCharProcsPromise = Promise.resolve(); + const charProcs = this.dict.get("CharProcs"); + const fontResources = this.dict.get("Resources") || resources; + const charProcOperatorList = Object.create(null); + const [x0, y0, x1, y1] = font.bbox, + width = x1 - x0, + height = y1 - y0; + const fontBBoxSize = Math.hypot(width, height); + for (const key of charProcs.getKeys()) { + loadCharProcsPromise = loadCharProcsPromise.then(() => { + const glyphStream = charProcs.get(key); + const operatorList = new OperatorList(); + return type3Evaluator.getOperatorList({ + stream: glyphStream, + task, + resources: fontResources, + operatorList + }).then(() => { + switch (operatorList.fnArray[0]) { + case OPS.setCharWidthAndBounds: + this.#removeType3ColorOperators(operatorList, fontBBoxSize); + break; + case OPS.setCharWidth: + if (!fontBBoxSize) { + this.#guessType3FontBBox(operatorList); + } + break; + } + charProcOperatorList[key] = operatorList.getIR(); + for (const dependency of operatorList.dependencies) { + type3Dependencies.add(dependency); + } + }).catch(function (reason) { + warn(`Type3 font resource "${key}" is not available.`); + const dummyOperatorList = new OperatorList(); + charProcOperatorList[key] = dummyOperatorList.getIR(); + }); + }); + } + this.#type3Loaded = loadCharProcsPromise.then(() => { + font.charProcOperatorList = charProcOperatorList; + if (this._bbox) { + font.isCharBBox = true; + font.bbox = this._bbox; + } + }); + return this.#type3Loaded; + } + #removeType3ColorOperators(operatorList, fontBBoxSize = NaN) { + const charBBox = Util.normalizeRect(operatorList.argsArray[0].slice(2)), + width = charBBox[2] - charBBox[0], + height = charBBox[3] - charBBox[1]; + const charBBoxSize = Math.hypot(width, height); + if (width === 0 || height === 0) { + operatorList.fnArray.splice(0, 1); + operatorList.argsArray.splice(0, 1); + } else if (fontBBoxSize === 0 || Math.round(charBBoxSize / fontBBoxSize) >= 10) { + this._bbox ??= [Infinity, Infinity, -Infinity, -Infinity]; + Util.rectBoundingBox(...charBBox, this._bbox); + } + let i = 0, + ii = operatorList.length; + while (i < ii) { + switch (operatorList.fnArray[i]) { + case OPS.setCharWidthAndBounds: + break; + case OPS.setStrokeColorSpace: + case OPS.setFillColorSpace: + case OPS.setStrokeColor: + case OPS.setStrokeColorN: + case OPS.setFillColor: + case OPS.setFillColorN: + case OPS.setStrokeGray: + case OPS.setFillGray: + case OPS.setStrokeRGBColor: + case OPS.setFillRGBColor: + case OPS.setStrokeCMYKColor: + case OPS.setFillCMYKColor: + case OPS.shadingFill: + case OPS.setRenderingIntent: + operatorList.fnArray.splice(i, 1); + operatorList.argsArray.splice(i, 1); + ii--; + continue; + case OPS.setGState: + const [gStateObj] = operatorList.argsArray[i]; + let j = 0, + jj = gStateObj.length; + while (j < jj) { + const [gStateKey] = gStateObj[j]; + switch (gStateKey) { + case "TR": + case "TR2": + case "HT": + case "BG": + case "BG2": + case "UCR": + case "UCR2": + gStateObj.splice(j, 1); + jj--; + continue; + } + j++; + } + break; + } + i++; + } + } + #guessType3FontBBox(operatorList) { + let i = 1; + const ii = operatorList.length; + while (i < ii) { + switch (operatorList.fnArray[i]) { + case OPS.constructPath: + const minMax = operatorList.argsArray[i][2]; + this._bbox ??= [Infinity, Infinity, -Infinity, -Infinity]; + Util.rectBoundingBox(...minMax, this._bbox); + break; + } + i++; + } + } +} +class StateManager { + constructor(initialState = new EvalState()) { + this.state = initialState; + this.stateStack = []; + } + save() { + const old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + } + restore() { + const prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + } + transform(args) { + this.state.ctm = Util.transform(this.state.ctm, args); + } +} +class TextState { + constructor() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.fontName = null; + this.fontSize = 0; + this.loadedName = null; + this.font = null; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.textMatrix = IDENTITY_MATRIX.slice(); + this.textLineMatrix = IDENTITY_MATRIX.slice(); + this.charSpacing = 0; + this.wordSpacing = 0; + this.leading = 0; + this.textHScale = 1; + this.textRise = 0; + } + setTextMatrix(a, b, c, d, e, f) { + const m = this.textMatrix; + m[0] = a; + m[1] = b; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + } + setTextLineMatrix(a, b, c, d, e, f) { + const m = this.textLineMatrix; + m[0] = a; + m[1] = b; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + } + translateTextMatrix(x, y) { + const m = this.textMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + } + translateTextLineMatrix(x, y) { + const m = this.textLineMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + } + carriageReturn() { + this.translateTextLineMatrix(0, -this.leading); + this.textMatrix = this.textLineMatrix.slice(); + } + clone() { + const clone = Object.create(this); + clone.textMatrix = this.textMatrix.slice(); + clone.textLineMatrix = this.textLineMatrix.slice(); + clone.fontMatrix = this.fontMatrix.slice(); + return clone; + } +} +class EvalState { + constructor() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.font = null; + this.textRenderingMode = TextRenderingMode.FILL; + this._fillColorSpace = this._strokeColorSpace = ColorSpaceUtils.gray; + this.patternFillColorSpace = null; + this.patternStrokeColorSpace = null; + this.currentPointX = this.currentPointY = 0; + this.pathMinMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + this.pathBuffer = []; + } + get fillColorSpace() { + return this._fillColorSpace; + } + set fillColorSpace(colorSpace) { + this._fillColorSpace = this.patternFillColorSpace = colorSpace; + } + get strokeColorSpace() { + return this._strokeColorSpace; + } + set strokeColorSpace(colorSpace) { + this._strokeColorSpace = this.patternStrokeColorSpace = colorSpace; + } + clone({ + newPath = false + } = {}) { + const clone = Object.create(this); + if (newPath) { + clone.pathBuffer = []; + clone.pathMinMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + } + return clone; + } +} +class EvaluatorPreprocessor { + static get opMap() { + return shadow(this, "opMap", Object.assign(Object.create(null), { + w: { + id: OPS.setLineWidth, + numArgs: 1, + variableArgs: false + }, + J: { + id: OPS.setLineCap, + numArgs: 1, + variableArgs: false + }, + j: { + id: OPS.setLineJoin, + numArgs: 1, + variableArgs: false + }, + M: { + id: OPS.setMiterLimit, + numArgs: 1, + variableArgs: false + }, + d: { + id: OPS.setDash, + numArgs: 2, + variableArgs: false + }, + ri: { + id: OPS.setRenderingIntent, + numArgs: 1, + variableArgs: false + }, + i: { + id: OPS.setFlatness, + numArgs: 1, + variableArgs: false + }, + gs: { + id: OPS.setGState, + numArgs: 1, + variableArgs: false + }, + q: { + id: OPS.save, + numArgs: 0, + variableArgs: false + }, + Q: { + id: OPS.restore, + numArgs: 0, + variableArgs: false + }, + cm: { + id: OPS.transform, + numArgs: 6, + variableArgs: false + }, + m: { + id: OPS.moveTo, + numArgs: 2, + variableArgs: false + }, + l: { + id: OPS.lineTo, + numArgs: 2, + variableArgs: false + }, + c: { + id: OPS.curveTo, + numArgs: 6, + variableArgs: false + }, + v: { + id: OPS.curveTo2, + numArgs: 4, + variableArgs: false + }, + y: { + id: OPS.curveTo3, + numArgs: 4, + variableArgs: false + }, + h: { + id: OPS.closePath, + numArgs: 0, + variableArgs: false + }, + re: { + id: OPS.rectangle, + numArgs: 4, + variableArgs: false + }, + S: { + id: OPS.stroke, + numArgs: 0, + variableArgs: false + }, + s: { + id: OPS.closeStroke, + numArgs: 0, + variableArgs: false + }, + f: { + id: OPS.fill, + numArgs: 0, + variableArgs: false + }, + F: { + id: OPS.fill, + numArgs: 0, + variableArgs: false + }, + "f*": { + id: OPS.eoFill, + numArgs: 0, + variableArgs: false + }, + B: { + id: OPS.fillStroke, + numArgs: 0, + variableArgs: false + }, + "B*": { + id: OPS.eoFillStroke, + numArgs: 0, + variableArgs: false + }, + b: { + id: OPS.closeFillStroke, + numArgs: 0, + variableArgs: false + }, + "b*": { + id: OPS.closeEOFillStroke, + numArgs: 0, + variableArgs: false + }, + n: { + id: OPS.endPath, + numArgs: 0, + variableArgs: false + }, + W: { + id: OPS.clip, + numArgs: 0, + variableArgs: false + }, + "W*": { + id: OPS.eoClip, + numArgs: 0, + variableArgs: false + }, + BT: { + id: OPS.beginText, + numArgs: 0, + variableArgs: false + }, + ET: { + id: OPS.endText, + numArgs: 0, + variableArgs: false + }, + Tc: { + id: OPS.setCharSpacing, + numArgs: 1, + variableArgs: false + }, + Tw: { + id: OPS.setWordSpacing, + numArgs: 1, + variableArgs: false + }, + Tz: { + id: OPS.setHScale, + numArgs: 1, + variableArgs: false + }, + TL: { + id: OPS.setLeading, + numArgs: 1, + variableArgs: false + }, + Tf: { + id: OPS.setFont, + numArgs: 2, + variableArgs: false + }, + Tr: { + id: OPS.setTextRenderingMode, + numArgs: 1, + variableArgs: false + }, + Ts: { + id: OPS.setTextRise, + numArgs: 1, + variableArgs: false + }, + Td: { + id: OPS.moveText, + numArgs: 2, + variableArgs: false + }, + TD: { + id: OPS.setLeadingMoveText, + numArgs: 2, + variableArgs: false + }, + Tm: { + id: OPS.setTextMatrix, + numArgs: 6, + variableArgs: false + }, + "T*": { + id: OPS.nextLine, + numArgs: 0, + variableArgs: false + }, + Tj: { + id: OPS.showText, + numArgs: 1, + variableArgs: false + }, + TJ: { + id: OPS.showSpacedText, + numArgs: 1, + variableArgs: false + }, + "'": { + id: OPS.nextLineShowText, + numArgs: 1, + variableArgs: false + }, + '"': { + id: OPS.nextLineSetSpacingShowText, + numArgs: 3, + variableArgs: false + }, + d0: { + id: OPS.setCharWidth, + numArgs: 2, + variableArgs: false + }, + d1: { + id: OPS.setCharWidthAndBounds, + numArgs: 6, + variableArgs: false + }, + CS: { + id: OPS.setStrokeColorSpace, + numArgs: 1, + variableArgs: false + }, + cs: { + id: OPS.setFillColorSpace, + numArgs: 1, + variableArgs: false + }, + SC: { + id: OPS.setStrokeColor, + numArgs: 4, + variableArgs: true + }, + SCN: { + id: OPS.setStrokeColorN, + numArgs: 33, + variableArgs: true + }, + sc: { + id: OPS.setFillColor, + numArgs: 4, + variableArgs: true + }, + scn: { + id: OPS.setFillColorN, + numArgs: 33, + variableArgs: true + }, + G: { + id: OPS.setStrokeGray, + numArgs: 1, + variableArgs: false + }, + g: { + id: OPS.setFillGray, + numArgs: 1, + variableArgs: false + }, + RG: { + id: OPS.setStrokeRGBColor, + numArgs: 3, + variableArgs: false + }, + rg: { + id: OPS.setFillRGBColor, + numArgs: 3, + variableArgs: false + }, + K: { + id: OPS.setStrokeCMYKColor, + numArgs: 4, + variableArgs: false + }, + k: { + id: OPS.setFillCMYKColor, + numArgs: 4, + variableArgs: false + }, + sh: { + id: OPS.shadingFill, + numArgs: 1, + variableArgs: false + }, + BI: { + id: OPS.beginInlineImage, + numArgs: 0, + variableArgs: false + }, + ID: { + id: OPS.beginImageData, + numArgs: 0, + variableArgs: false + }, + EI: { + id: OPS.endInlineImage, + numArgs: 1, + variableArgs: false + }, + Do: { + id: OPS.paintXObject, + numArgs: 1, + variableArgs: false + }, + MP: { + id: OPS.markPoint, + numArgs: 1, + variableArgs: false + }, + DP: { + id: OPS.markPointProps, + numArgs: 2, + variableArgs: false + }, + BMC: { + id: OPS.beginMarkedContent, + numArgs: 1, + variableArgs: false + }, + BDC: { + id: OPS.beginMarkedContentProps, + numArgs: 2, + variableArgs: false + }, + EMC: { + id: OPS.endMarkedContent, + numArgs: 0, + variableArgs: false + }, + BX: { + id: OPS.beginCompat, + numArgs: 0, + variableArgs: false + }, + EX: { + id: OPS.endCompat, + numArgs: 0, + variableArgs: false + }, + BM: null, + BD: null, + true: null, + fa: null, + fal: null, + fals: null, + false: null, + nu: null, + nul: null, + null: null + })); + } + static MAX_INVALID_PATH_OPS = 10; + constructor(stream, xref, stateManager = new StateManager()) { + this.parser = new Parser({ + lexer: new Lexer(stream, EvaluatorPreprocessor.opMap), + xref + }); + this.stateManager = stateManager; + this.nonProcessedArgs = []; + this._isPathOp = false; + this._numInvalidPathOPS = 0; + } + get savedStatesDepth() { + return this.stateManager.stateStack.length; + } + read(operation) { + let args = operation.args; + while (true) { + const obj = this.parser.getObj(); + if (obj instanceof Cmd) { + const cmd = obj.cmd; + const opSpec = EvaluatorPreprocessor.opMap[cmd]; + if (!opSpec) { + warn(`Unknown command "${cmd}".`); + continue; + } + const fn = opSpec.id; + const numArgs = opSpec.numArgs; + let argsLength = args !== null ? args.length : 0; + if (!this._isPathOp) { + this._numInvalidPathOPS = 0; + } + this._isPathOp = fn >= OPS.moveTo && fn <= OPS.endPath; + if (!opSpec.variableArgs) { + if (argsLength !== numArgs) { + const nonProcessedArgs = this.nonProcessedArgs; + while (argsLength > numArgs) { + nonProcessedArgs.push(args.shift()); + argsLength--; + } + while (argsLength < numArgs && nonProcessedArgs.length !== 0) { + if (args === null) { + args = []; + } + args.unshift(nonProcessedArgs.pop()); + argsLength++; + } + } + if (argsLength < numArgs) { + const partialMsg = `command ${cmd}: expected ${numArgs} args, ` + `but received ${argsLength} args.`; + if (this._isPathOp && ++this._numInvalidPathOPS > EvaluatorPreprocessor.MAX_INVALID_PATH_OPS) { + throw new FormatError(`Invalid ${partialMsg}`); + } + warn(`Skipping ${partialMsg}`); + if (args !== null) { + args.length = 0; + } + continue; + } + } else if (argsLength > numArgs) { + info(`Command ${cmd}: expected [0, ${numArgs}] args, ` + `but received ${argsLength} args.`); + } + this.preprocessCommand(fn, args); + operation.fn = fn; + operation.args = args; + return true; + } + if (obj === EOF) { + return false; + } + if (obj !== null) { + if (args === null) { + args = []; + } + args.push(obj); + if (args.length > 33) { + throw new FormatError("Too many arguments"); + } + } + } + } + preprocessCommand(fn, args) { + switch (fn | 0) { + case OPS.save: + this.stateManager.save(); + break; + case OPS.restore: + this.stateManager.restore(); + break; + case OPS.transform: + this.stateManager.transform(args); + break; + } + } +} + +;// ./src/core/default_appearance.js + + + + + + + + +class DefaultAppearanceEvaluator extends EvaluatorPreprocessor { + constructor(str) { + super(new StringStream(str)); + } + parse() { + const operation = { + fn: 0, + args: [] + }; + const result = { + fontSize: 0, + fontName: "", + fontColor: new Uint8ClampedArray(3) + }; + try { + while (true) { + operation.args.length = 0; + if (!this.read(operation)) { + break; + } + if (this.savedStatesDepth !== 0) { + continue; + } + const { + fn, + args + } = operation; + switch (fn | 0) { + case OPS.setFont: + const [fontName, fontSize] = args; + if (fontName instanceof Name) { + result.fontName = fontName.name; + } + if (typeof fontSize === "number" && fontSize > 0) { + result.fontSize = fontSize; + } + break; + case OPS.setFillRGBColor: + ColorSpaceUtils.rgb.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.setFillGray: + ColorSpaceUtils.gray.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.setFillCMYKColor: + ColorSpaceUtils.cmyk.getRgbItem(args, 0, result.fontColor, 0); + break; + } + } + } catch (reason) { + warn(`parseDefaultAppearance - ignoring errors: "${reason}".`); + } + return result; + } +} +function parseDefaultAppearance(str) { + return new DefaultAppearanceEvaluator(str).parse(); +} +class AppearanceStreamEvaluator extends EvaluatorPreprocessor { + constructor(stream, evaluatorOptions, xref, globalColorSpaceCache) { + super(stream); + this.stream = stream; + this.evaluatorOptions = evaluatorOptions; + this.xref = xref; + this.globalColorSpaceCache = globalColorSpaceCache; + this.resources = stream.dict?.get("Resources"); + } + parse() { + const operation = { + fn: 0, + args: [] + }; + let result = { + scaleFactor: 1, + fontSize: 0, + fontName: "", + fontColor: new Uint8ClampedArray(3), + fillColorSpace: ColorSpaceUtils.gray + }; + let breakLoop = false; + const stack = []; + try { + while (true) { + operation.args.length = 0; + if (breakLoop || !this.read(operation)) { + break; + } + const { + fn, + args + } = operation; + switch (fn | 0) { + case OPS.save: + stack.push({ + scaleFactor: result.scaleFactor, + fontSize: result.fontSize, + fontName: result.fontName, + fontColor: result.fontColor.slice(), + fillColorSpace: result.fillColorSpace + }); + break; + case OPS.restore: + result = stack.pop() || result; + break; + case OPS.setTextMatrix: + result.scaleFactor *= Math.hypot(args[0], args[1]); + break; + case OPS.setFont: + const [fontName, fontSize] = args; + if (fontName instanceof Name) { + result.fontName = fontName.name; + } + if (typeof fontSize === "number" && fontSize > 0) { + result.fontSize = fontSize * result.scaleFactor; + } + break; + case OPS.setFillColorSpace: + result.fillColorSpace = ColorSpaceUtils.parse({ + cs: args[0], + xref: this.xref, + resources: this.resources, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache: this._localColorSpaceCache + }); + break; + case OPS.setFillColor: + const cs = result.fillColorSpace; + cs.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.setFillRGBColor: + ColorSpaceUtils.rgb.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.setFillGray: + ColorSpaceUtils.gray.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.setFillCMYKColor: + ColorSpaceUtils.cmyk.getRgbItem(args, 0, result.fontColor, 0); + break; + case OPS.showText: + case OPS.showSpacedText: + case OPS.nextLineShowText: + case OPS.nextLineSetSpacingShowText: + breakLoop = true; + break; + } + } + } catch (reason) { + warn(`parseAppearanceStream - ignoring errors: "${reason}".`); + } + this.stream.reset(); + delete result.scaleFactor; + delete result.fillColorSpace; + return result; + } + get _localColorSpaceCache() { + return shadow(this, "_localColorSpaceCache", new LocalColorSpaceCache()); + } + get _pdfFunctionFactory() { + const pdfFunctionFactory = new PDFFunctionFactory({ + xref: this.xref, + isEvalSupported: this.evaluatorOptions.isEvalSupported + }); + return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory); + } +} +function parseAppearanceStream(stream, evaluatorOptions, xref, globalColorSpaceCache) { + return new AppearanceStreamEvaluator(stream, evaluatorOptions, xref, globalColorSpaceCache).parse(); +} +function getPdfColor(color, isFill) { + if (color[0] === color[1] && color[1] === color[2]) { + const gray = color[0] / 255; + return `${numberToString(gray)} ${isFill ? "g" : "G"}`; + } + return Array.from(color, c => numberToString(c / 255)).join(" ") + ` ${isFill ? "rg" : "RG"}`; +} +function createDefaultAppearance({ + fontSize, + fontName, + fontColor +}) { + return `/${escapePDFName(fontName)} ${fontSize} Tf ${getPdfColor(fontColor, true)}`; +} +class FakeUnicodeFont { + constructor(xref, fontFamily) { + this.xref = xref; + this.widths = null; + this.firstChar = Infinity; + this.lastChar = -Infinity; + this.fontFamily = fontFamily; + const canvas = new OffscreenCanvas(1, 1); + this.ctxMeasure = canvas.getContext("2d", { + willReadFrequently: true + }); + if (!FakeUnicodeFont._fontNameId) { + FakeUnicodeFont._fontNameId = 1; + } + this.fontName = Name.get(`InvalidPDFjsFont_${fontFamily}_${FakeUnicodeFont._fontNameId++}`); + } + get fontDescriptorRef() { + if (!FakeUnicodeFont._fontDescriptorRef) { + const fontDescriptor = new Dict(this.xref); + fontDescriptor.setIfName("Type", "FontDescriptor"); + fontDescriptor.set("FontName", this.fontName); + fontDescriptor.set("FontFamily", "MyriadPro Regular"); + fontDescriptor.set("FontBBox", [0, 0, 0, 0]); + fontDescriptor.setIfName("FontStretch", "Normal"); + fontDescriptor.set("FontWeight", 400); + fontDescriptor.set("ItalicAngle", 0); + FakeUnicodeFont._fontDescriptorRef = this.xref.getNewPersistentRef(fontDescriptor); + } + return FakeUnicodeFont._fontDescriptorRef; + } + get descendantFontRef() { + const descendantFont = new Dict(this.xref); + descendantFont.set("BaseFont", this.fontName); + descendantFont.setIfName("Type", "Font"); + descendantFont.setIfName("Subtype", "CIDFontType0"); + descendantFont.setIfName("CIDToGIDMap", "Identity"); + descendantFont.set("FirstChar", this.firstChar); + descendantFont.set("LastChar", this.lastChar); + descendantFont.set("FontDescriptor", this.fontDescriptorRef); + descendantFont.set("DW", 1000); + const widths = []; + const chars = [...this.widths.entries()].sort(); + let currentChar = null; + let currentWidths = null; + for (const [char, width] of chars) { + if (!currentChar) { + currentChar = char; + currentWidths = [width]; + continue; + } + if (char === currentChar + currentWidths.length) { + currentWidths.push(width); + } else { + widths.push(currentChar, currentWidths); + currentChar = char; + currentWidths = [width]; + } + } + if (currentChar) { + widths.push(currentChar, currentWidths); + } + descendantFont.set("W", widths); + const cidSystemInfo = new Dict(this.xref); + cidSystemInfo.set("Ordering", "Identity"); + cidSystemInfo.set("Registry", "Adobe"); + cidSystemInfo.set("Supplement", 0); + descendantFont.set("CIDSystemInfo", cidSystemInfo); + return this.xref.getNewPersistentRef(descendantFont); + } + get baseFontRef() { + const baseFont = new Dict(this.xref); + baseFont.set("BaseFont", this.fontName); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type0"); + baseFont.setIfName("Encoding", "Identity-H"); + baseFont.set("DescendantFonts", [this.descendantFontRef]); + baseFont.setIfName("ToUnicode", "Identity-H"); + return this.xref.getNewPersistentRef(baseFont); + } + get resources() { + const resources = new Dict(this.xref); + const font = new Dict(this.xref); + font.set(this.fontName.name, this.baseFontRef); + resources.set("Font", font); + return resources; + } + _createContext() { + this.widths = new Map(); + this.ctxMeasure.font = `1000px ${this.fontFamily}`; + return this.ctxMeasure; + } + createFontResources(text) { + const ctx = this._createContext(); + for (const line of text.split(/\r\n?|\n/)) { + for (const char of line.split("")) { + const code = char.charCodeAt(0); + if (this.widths.has(code)) { + continue; + } + const metrics = ctx.measureText(char); + const width = Math.ceil(metrics.width); + this.widths.set(code, width); + this.firstChar = Math.min(code, this.firstChar); + this.lastChar = Math.max(code, this.lastChar); + } + } + return this.resources; + } + static getFirstPositionInfo(rect, rotation, fontSize) { + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + const lineHeight = LINE_FACTOR * fontSize; + const lineDescent = LINE_DESCENT_FACTOR * fontSize; + return { + coords: [0, h + lineDescent - lineHeight], + bbox: [0, 0, w, h], + matrix: rotation !== 0 ? getRotationMatrix(rotation, h, lineHeight) : undefined + }; + } + createAppearance(text, rect, rotation, fontSize, bgColor, strokeAlpha) { + const ctx = this._createContext(); + const lines = []; + let maxWidth = -Infinity; + for (const line of text.split(/\r\n?|\n/)) { + lines.push(line); + const lineWidth = ctx.measureText(line).width; + maxWidth = Math.max(maxWidth, lineWidth); + for (const code of codePointIter(line)) { + const char = String.fromCodePoint(code); + let width = this.widths.get(code); + if (width === undefined) { + const metrics = ctx.measureText(char); + width = Math.ceil(metrics.width); + this.widths.set(code, width); + this.firstChar = Math.min(code, this.firstChar); + this.lastChar = Math.max(code, this.lastChar); + } + } + } + maxWidth *= fontSize / 1000; + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + let hscale = 1; + if (maxWidth > w) { + hscale = w / maxWidth; + } + let vscale = 1; + const lineHeight = LINE_FACTOR * fontSize; + const lineDescent = LINE_DESCENT_FACTOR * fontSize; + const maxHeight = lineHeight * lines.length; + if (maxHeight > h) { + vscale = h / maxHeight; + } + const fscale = Math.min(hscale, vscale); + const newFontSize = fontSize * fscale; + const buffer = ["q", `0 0 ${numberToString(w)} ${numberToString(h)} re W n`, `BT`, `1 0 0 1 0 ${numberToString(h + lineDescent)} Tm 0 Tc ${getPdfColor(bgColor, true)}`, `/${this.fontName.name} ${numberToString(newFontSize)} Tf`]; + const { + resources + } = this; + strokeAlpha = typeof strokeAlpha === "number" && strokeAlpha >= 0 && strokeAlpha <= 1 ? strokeAlpha : 1; + if (strokeAlpha !== 1) { + buffer.push("/R0 gs"); + const extGState = new Dict(this.xref); + const r0 = new Dict(this.xref); + r0.set("ca", strokeAlpha); + r0.set("CA", strokeAlpha); + r0.setIfName("Type", "ExtGState"); + extGState.set("R0", r0); + resources.set("ExtGState", extGState); + } + const vShift = numberToString(lineHeight); + for (const line of lines) { + buffer.push(`0 -${vShift} Td <${stringToUTF16HexString(line)}> Tj`); + } + buffer.push("ET", "Q"); + const appearance = buffer.join("\n"); + const appearanceStreamDict = new Dict(this.xref); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", [0, 0, w, h]); + appearanceStreamDict.set("Length", appearance.length); + appearanceStreamDict.set("Resources", resources); + if (rotation) { + const matrix = getRotationMatrix(rotation, w, h); + appearanceStreamDict.set("Matrix", matrix); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } +} + +;// ./src/shared/scripting_utils.js +function makeColorComp(n) { + return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0"); +} +function scaleAndClamp(x) { + return Math.max(0, Math.min(255, 255 * x)); +} +class ColorConverters { + static CMYK_G([c, y, m, k]) { + return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)]; + } + static G_CMYK([g]) { + return ["CMYK", 0, 0, 0, 1 - g]; + } + static G_RGB([g]) { + return ["RGB", g, g, g]; + } + static G_rgb([g]) { + g = scaleAndClamp(g); + return [g, g, g]; + } + static G_HTML([g]) { + const G = makeColorComp(g); + return `#${G}${G}${G}`; + } + static RGB_G([r, g, b]) { + return ["G", 0.3 * r + 0.59 * g + 0.11 * b]; + } + static RGB_rgb(color) { + return color.map(scaleAndClamp); + } + static RGB_HTML(color) { + return `#${color.map(makeColorComp).join("")}`; + } + static T_HTML() { + return "#00000000"; + } + static T_rgb() { + return [null]; + } + static CMYK_RGB([c, y, m, k]) { + return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)]; + } + static CMYK_rgb([c, y, m, k]) { + return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))]; + } + static CMYK_HTML(components) { + const rgb = this.CMYK_RGB(components).slice(1); + return this.RGB_HTML(rgb); + } + static RGB_CMYK([r, g, b]) { + const c = 1 - r; + const m = 1 - g; + const y = 1 - b; + const k = Math.min(c, m, y); + return ["CMYK", c, m, y, k]; + } +} +const DateFormats = ["m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy", "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy", "m/d/yy h:MM tt", "m/d/yy HH:MM"]; +const TimeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"]; + +;// ./src/core/name_number_tree.js + + +class NameOrNumberTree { + constructor(root, xref, type) { + this.root = root; + this.xref = xref; + this._type = type; + } + getAll(isRaw = false) { + const map = new Map(); + if (!this.root) { + return map; + } + const xref = this.xref; + const processed = new RefSet(); + processed.put(this.root); + const queue = [this.root]; + while (queue.length > 0) { + const obj = xref.fetchIfRef(queue.shift()); + if (!(obj instanceof Dict)) { + continue; + } + if (obj.has("Kids")) { + const kids = obj.get("Kids"); + if (!Array.isArray(kids)) { + continue; + } + for (const kid of kids) { + if (processed.has(kid)) { + throw new FormatError(`Duplicate entry in "${this._type}" tree.`); + } + queue.push(kid); + processed.put(kid); + } + continue; + } + const entries = obj.get(this._type); + if (!Array.isArray(entries)) { + continue; + } + for (let i = 0, ii = entries.length; i < ii; i += 2) { + map.set(xref.fetchIfRef(entries[i]), isRaw ? entries[i + 1] : xref.fetchIfRef(entries[i + 1])); + } + } + return map; + } + getRaw(key) { + if (!this.root) { + return null; + } + const xref = this.xref; + let kidsOrEntries = xref.fetchIfRef(this.root); + let loopCount = 0; + const MAX_LEVELS = 10; + while (kidsOrEntries.has("Kids")) { + if (++loopCount > MAX_LEVELS) { + warn(`Search depth limit reached for "${this._type}" tree.`); + return null; + } + const kids = kidsOrEntries.get("Kids"); + if (!Array.isArray(kids)) { + return null; + } + let l = 0, + r = kids.length - 1; + while (l <= r) { + const m = l + r >> 1; + const kid = xref.fetchIfRef(kids[m]); + const limits = kid.get("Limits"); + if (key < xref.fetchIfRef(limits[0])) { + r = m - 1; + } else if (key > xref.fetchIfRef(limits[1])) { + l = m + 1; + } else { + kidsOrEntries = kid; + break; + } + } + if (l > r) { + return null; + } + } + const entries = kidsOrEntries.get(this._type); + if (Array.isArray(entries)) { + let l = 0, + r = entries.length - 2; + while (l <= r) { + const tmp = l + r >> 1, + m = tmp + (tmp & 1); + const currentKey = xref.fetchIfRef(entries[m]); + if (key < currentKey) { + r = m - 2; + } else if (key > currentKey) { + l = m + 2; + } else { + return entries[m + 1]; + } + } + } + return null; + } + get(key) { + return this.xref.fetchIfRef(this.getRaw(key)); + } +} +class NameTree extends NameOrNumberTree { + constructor(root, xref) { + super(root, xref, "Names"); + } +} +class NumberTree extends NameOrNumberTree { + constructor(root, xref) { + super(root, xref, "Nums"); + } +} + +;// ./src/core/cleanup_helper.js + + + + +function clearGlobalCaches() { + clearPatternCaches(); + clearPrimitiveCaches(); + clearUnicodeCaches(); + JpxImage.cleanup(); +} + +;// ./src/core/file_spec.js + + + +function pickPlatformItem(dict) { + if (!(dict instanceof Dict)) { + return null; + } + if (dict.has("UF")) { + return dict.get("UF"); + } else if (dict.has("F")) { + return dict.get("F"); + } else if (dict.has("Unix")) { + return dict.get("Unix"); + } else if (dict.has("Mac")) { + return dict.get("Mac"); + } else if (dict.has("DOS")) { + return dict.get("DOS"); + } + return null; +} +function stripPath(str) { + return str.substring(str.lastIndexOf("/") + 1); +} +class FileSpec { + #contentAvailable = false; + constructor(root, xref, skipContent = false) { + if (!(root instanceof Dict)) { + return; + } + this.xref = xref; + this.root = root; + if (root.has("FS")) { + this.fs = root.get("FS"); + } + if (root.has("RF")) { + warn("Related file specifications are not supported"); + } + if (!skipContent) { + if (root.has("EF")) { + this.#contentAvailable = true; + } else { + warn("Non-embedded file specifications are not supported"); + } + } + } + get filename() { + let filename = ""; + const item = pickPlatformItem(this.root); + if (item && typeof item === "string") { + filename = stringToPDFString(item, true).replaceAll("\\\\", "\\").replaceAll("\\/", "/").replaceAll("\\", "/"); + } + return shadow(this, "filename", filename || "unnamed"); + } + get content() { + if (!this.#contentAvailable) { + return null; + } + this._contentRef ||= pickPlatformItem(this.root?.get("EF")); + let content = null; + if (this._contentRef) { + const fileObj = this.xref.fetchIfRef(this._contentRef); + if (fileObj instanceof BaseStream) { + content = fileObj.getBytes(); + } else { + warn("Embedded file specification points to non-existing/invalid content"); + } + } else { + warn("Embedded file specification does not have any content"); + } + return content; + } + get description() { + let description = ""; + const desc = this.root?.get("Desc"); + if (desc && typeof desc === "string") { + description = stringToPDFString(desc); + } + return shadow(this, "description", description); + } + get serializable() { + return { + rawFilename: this.filename, + filename: stripPath(this.filename), + content: this.content, + description: this.description + }; + } +} + +;// ./src/core/xml_parser.js + +const XMLParserErrorCode = { + NoError: 0, + EndOfDocument: -1, + UnterminatedCdat: -2, + UnterminatedXmlDeclaration: -3, + UnterminatedDoctypeDeclaration: -4, + UnterminatedComment: -5, + MalformedElement: -6, + OutOfMemory: -7, + UnterminatedAttributeValue: -8, + UnterminatedElement: -9, + ElementNeverBegun: -10 +}; +function isWhitespace(s, index) { + const ch = s[index]; + return ch === " " || ch === "\n" || ch === "\r" || ch === "\t"; +} +function isWhitespaceString(s) { + for (let i = 0, ii = s.length; i < ii; i++) { + if (!isWhitespace(s, i)) { + return false; + } + } + return true; +} +class XMLParserBase { + _resolveEntities(s) { + return s.replaceAll(/&([^;]+);/g, (all, entity) => { + if (entity.substring(0, 2) === "#x") { + return String.fromCodePoint(parseInt(entity.substring(2), 16)); + } else if (entity.substring(0, 1) === "#") { + return String.fromCodePoint(parseInt(entity.substring(1), 10)); + } + switch (entity) { + case "lt": + return "<"; + case "gt": + return ">"; + case "amp": + return "&"; + case "quot": + return '"'; + case "apos": + return "'"; + } + return this.onResolveEntity(entity); + }); + } + _parseContent(s, start) { + const attributes = []; + let pos = start; + function skipWs() { + while (pos < s.length && isWhitespace(s, pos)) { + ++pos; + } + } + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "/") { + ++pos; + } + const name = s.substring(start, pos); + skipWs(); + while (pos < s.length && s[pos] !== ">" && s[pos] !== "/" && s[pos] !== "?") { + skipWs(); + let attrName = "", + attrValue = ""; + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== "=") { + attrName += s[pos]; + ++pos; + } + skipWs(); + if (s[pos] !== "=") { + return null; + } + ++pos; + skipWs(); + const attrEndChar = s[pos]; + if (attrEndChar !== '"' && attrEndChar !== "'") { + return null; + } + const attrEndIndex = s.indexOf(attrEndChar, ++pos); + if (attrEndIndex < 0) { + return null; + } + attrValue = s.substring(pos, attrEndIndex); + attributes.push({ + name: attrName, + value: this._resolveEntities(attrValue) + }); + pos = attrEndIndex + 1; + skipWs(); + } + return { + name, + attributes, + parsed: pos - start + }; + } + _parseProcessingInstruction(s, start) { + let pos = start; + function skipWs() { + while (pos < s.length && isWhitespace(s, pos)) { + ++pos; + } + } + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "?" && s[pos] !== "/") { + ++pos; + } + const name = s.substring(start, pos); + skipWs(); + const attrStart = pos; + while (pos < s.length && (s[pos] !== "?" || s[pos + 1] !== ">")) { + ++pos; + } + const value = s.substring(attrStart, pos); + return { + name, + value, + parsed: pos - start + }; + } + parseXml(s) { + let i = 0; + while (i < s.length) { + const ch = s[i]; + let j = i; + if (ch === "<") { + ++j; + const ch2 = s[j]; + let q; + switch (ch2) { + case "/": + ++j; + q = s.indexOf(">", j); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedElement); + return; + } + this.onEndElement(s.substring(j, q)); + j = q + 1; + break; + case "?": + ++j; + const pi = this._parseProcessingInstruction(s, j); + if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== "?>") { + this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration); + return; + } + this.onPi(pi.name, pi.value); + j += pi.parsed + 2; + break; + case "!": + if (s.substring(j + 1, j + 3) === "--") { + q = s.indexOf("-->", j + 3); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedComment); + return; + } + this.onComment(s.substring(j + 3, q)); + j = q + 3; + } else if (s.substring(j + 1, j + 8) === "[CDATA[") { + q = s.indexOf("]]>", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedCdat); + return; + } + this.onCdata(s.substring(j + 8, q)); + j = q + 3; + } else if (s.substring(j + 1, j + 8) === "DOCTYPE") { + const q2 = s.indexOf("[", j + 8); + let complexDoctype = false; + q = s.indexOf(">", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); + return; + } + if (q2 > 0 && q > q2) { + q = s.indexOf("]>", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); + return; + } + complexDoctype = true; + } + const doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0)); + this.onDoctype(doctypeContent); + j = q + (complexDoctype ? 2 : 1); + } else { + this.onError(XMLParserErrorCode.MalformedElement); + return; + } + break; + default: + const content = this._parseContent(s, j); + if (content === null) { + this.onError(XMLParserErrorCode.MalformedElement); + return; + } + let isClosed = false; + if (s.substring(j + content.parsed, j + content.parsed + 2) === "/>") { + isClosed = true; + } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== ">") { + this.onError(XMLParserErrorCode.UnterminatedElement); + return; + } + this.onBeginElement(content.name, content.attributes, isClosed); + j += content.parsed + (isClosed ? 2 : 1); + break; + } + } else { + while (j < s.length && s[j] !== "<") { + j++; + } + const text = s.substring(i, j); + this.onText(this._resolveEntities(text)); + } + i = j; + } + } + onResolveEntity(name) { + return `&${name};`; + } + onPi(name, value) {} + onComment(text) {} + onCdata(text) {} + onDoctype(doctypeContent) {} + onText(text) {} + onBeginElement(name, attributes, isEmpty) {} + onEndElement(name) {} + onError(code) {} +} +class SimpleDOMNode { + constructor(nodeName, nodeValue) { + this.nodeName = nodeName; + this.nodeValue = nodeValue; + Object.defineProperty(this, "parentNode", { + value: null, + writable: true + }); + } + get firstChild() { + return this.childNodes?.[0]; + } + get nextSibling() { + const childNodes = this.parentNode.childNodes; + if (!childNodes) { + return undefined; + } + const index = childNodes.indexOf(this); + if (index === -1) { + return undefined; + } + return childNodes[index + 1]; + } + get textContent() { + if (!this.childNodes) { + return this.nodeValue || ""; + } + return this.childNodes.map(child => child.textContent).join(""); + } + get children() { + return this.childNodes || []; + } + hasChildNodes() { + return this.childNodes?.length > 0; + } + searchNode(paths, pos) { + if (pos >= paths.length) { + return this; + } + const component = paths[pos]; + if (component.name.startsWith("#") && pos < paths.length - 1) { + return this.searchNode(paths, pos + 1); + } + const stack = []; + let node = this; + while (true) { + if (component.name === node.nodeName) { + if (component.pos === 0) { + const res = node.searchNode(paths, pos + 1); + if (res !== null) { + return res; + } + } else if (stack.length === 0) { + return null; + } else { + const [parent] = stack.pop(); + let siblingPos = 0; + for (const child of parent.childNodes) { + if (component.name === child.nodeName) { + if (siblingPos === component.pos) { + return child.searchNode(paths, pos + 1); + } + siblingPos++; + } + } + return node.searchNode(paths, pos + 1); + } + } + if (node.childNodes?.length > 0) { + stack.push([node, 0]); + node = node.childNodes[0]; + } else if (stack.length === 0) { + return null; + } else { + while (stack.length !== 0) { + const [parent, currentPos] = stack.pop(); + const newPos = currentPos + 1; + if (newPos < parent.childNodes.length) { + stack.push([parent, newPos]); + node = parent.childNodes[newPos]; + break; + } + } + if (stack.length === 0) { + return null; + } + } + } + } + dump(buffer) { + if (this.nodeName === "#text") { + buffer.push(encodeToXmlString(this.nodeValue)); + return; + } + buffer.push(`<${this.nodeName}`); + if (this.attributes) { + for (const attribute of this.attributes) { + buffer.push(` ${attribute.name}="${encodeToXmlString(attribute.value)}"`); + } + } + if (this.hasChildNodes()) { + buffer.push(">"); + for (const child of this.childNodes) { + child.dump(buffer); + } + buffer.push(``); + } else if (this.nodeValue) { + buffer.push(`>${encodeToXmlString(this.nodeValue)}`); + } else { + buffer.push("/>"); + } + } +} +class SimpleXMLParser extends XMLParserBase { + constructor({ + hasAttributes = false, + lowerCaseName = false + }) { + super(); + this._currentFragment = null; + this._stack = null; + this._errorCode = XMLParserErrorCode.NoError; + this._hasAttributes = hasAttributes; + this._lowerCaseName = lowerCaseName; + } + parseFromString(data) { + this._currentFragment = []; + this._stack = []; + this._errorCode = XMLParserErrorCode.NoError; + this.parseXml(data); + if (this._errorCode !== XMLParserErrorCode.NoError) { + return undefined; + } + const [documentElement] = this._currentFragment; + if (!documentElement) { + return undefined; + } + return { + documentElement + }; + } + onText(text) { + if (isWhitespaceString(text)) { + return; + } + const node = new SimpleDOMNode("#text", text); + this._currentFragment.push(node); + } + onCdata(text) { + const node = new SimpleDOMNode("#text", text); + this._currentFragment.push(node); + } + onBeginElement(name, attributes, isEmpty) { + if (this._lowerCaseName) { + name = name.toLowerCase(); + } + const node = new SimpleDOMNode(name); + node.childNodes = []; + if (this._hasAttributes) { + node.attributes = attributes; + } + this._currentFragment.push(node); + if (isEmpty) { + return; + } + this._stack.push(this._currentFragment); + this._currentFragment = node.childNodes; + } + onEndElement(name) { + this._currentFragment = this._stack.pop() || []; + const lastElement = this._currentFragment.at(-1); + if (!lastElement) { + return null; + } + for (const childNode of lastElement.childNodes) { + childNode.parentNode = lastElement; + } + return lastElement; + } + onError(code) { + this._errorCode = code; + } +} + +;// ./src/core/metadata_parser.js + +class MetadataParser { + constructor(data) { + data = this._repair(data); + const parser = new SimpleXMLParser({ + lowerCaseName: true + }); + const xmlDocument = parser.parseFromString(data); + this._metadataMap = new Map(); + this._data = data; + if (xmlDocument) { + this._parse(xmlDocument); + } + } + _repair(data) { + return data.replace(/^[^<]+/, "").replaceAll(/>\\376\\377([^<]+)/g, function (all, codes) { + const bytes = codes.replaceAll(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) { + return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); + }).replaceAll(/&(amp|apos|gt|lt|quot);/g, function (str, name) { + switch (name) { + case "amp": + return "&"; + case "apos": + return "'"; + case "gt": + return ">"; + case "lt": + return "<"; + case "quot": + return '"'; + } + throw new Error(`_repair: ${name} isn't defined.`); + }); + const charBuf = [">"]; + for (let i = 0, ii = bytes.length; i < ii; i += 2) { + const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); + if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) { + charBuf.push(String.fromCharCode(code)); + } else { + charBuf.push("&#x" + (0x10000 + code).toString(16).substring(1) + ";"); + } + } + return charBuf.join(""); + }); + } + _getSequence(entry) { + const name = entry.nodeName; + if (name !== "rdf:bag" && name !== "rdf:seq" && name !== "rdf:alt") { + return null; + } + return entry.childNodes.filter(node => node.nodeName === "rdf:li"); + } + _parseArray(entry) { + if (!entry.hasChildNodes()) { + return; + } + const [seqNode] = entry.childNodes; + const sequence = this._getSequence(seqNode) || []; + this._metadataMap.set(entry.nodeName, sequence.map(node => node.textContent.trim())); + } + _parse(xmlDocument) { + let rdf = xmlDocument.documentElement; + if (rdf.nodeName !== "rdf:rdf") { + rdf = rdf.firstChild; + while (rdf && rdf.nodeName !== "rdf:rdf") { + rdf = rdf.nextSibling; + } + } + if (!rdf || rdf.nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) { + return; + } + for (const desc of rdf.childNodes) { + if (desc.nodeName !== "rdf:description") { + continue; + } + for (const entry of desc.childNodes) { + const name = entry.nodeName; + switch (name) { + case "#text": + continue; + case "dc:creator": + case "dc:subject": + this._parseArray(entry); + continue; + } + this._metadataMap.set(name, entry.textContent.trim()); + } + } + } + get serializable() { + return { + parsedData: this._metadataMap, + rawData: this._data + }; + } +} + +;// ./src/core/struct_tree.js + + + + + +const MAX_DEPTH = 40; +const StructElementType = { + PAGE_CONTENT: 1, + STREAM_CONTENT: 2, + OBJECT: 3, + ANNOTATION: 4, + ELEMENT: 5 +}; +class StructTreeRoot { + constructor(xref, rootDict, rootRef) { + this.xref = xref; + this.dict = rootDict; + this.ref = rootRef instanceof Ref ? rootRef : null; + this.roleMap = new Map(); + this.structParentIds = null; + this.kidRefToPosition = undefined; + this.parentTree = null; + } + getKidPosition(kidRef) { + if (this.kidRefToPosition === undefined) { + const obj = this.dict.get("K"); + if (Array.isArray(obj)) { + const map = this.kidRefToPosition = new Map(); + for (let i = 0, ii = obj.length; i < ii; i++) { + const ref = obj[i]; + if (ref) { + map.set(ref.toString(), i); + } + } + } else if (obj instanceof Dict) { + this.kidRefToPosition = new Map([[obj.objId, 0]]); + } else if (!obj) { + this.kidRefToPosition = new Map(); + } else { + this.kidRefToPosition = null; + } + } + return this.kidRefToPosition ? this.kidRefToPosition.get(kidRef) ?? NaN : -1; + } + init() { + this.readRoleMap(); + const parentTree = this.dict.get("ParentTree"); + if (!parentTree) { + return; + } + this.parentTree = new NumberTree(parentTree, this.xref); + } + #addIdToPage(pageRef, id, type) { + if (!(pageRef instanceof Ref) || id < 0) { + return; + } + this.structParentIds ||= new RefSetCache(); + let ids = this.structParentIds.get(pageRef); + if (!ids) { + ids = []; + this.structParentIds.put(pageRef, ids); + } + ids.push([id, type]); + } + addAnnotationIdToPage(pageRef, id) { + this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION); + } + readRoleMap() { + const roleMapDict = this.dict.get("RoleMap"); + if (!(roleMapDict instanceof Dict)) { + return; + } + for (const [key, value] of roleMapDict) { + if (value instanceof Name) { + this.roleMap.set(key, value.name); + } + } + } + static async canCreateStructureTree({ + catalogRef, + pdfManager, + newAnnotationsByPage + }) { + if (!(catalogRef instanceof Ref)) { + warn("Cannot save the struct tree: no catalog reference."); + return false; + } + let nextKey = 0; + let hasNothingToUpdate = true; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const { + ref: pageRef + } = await pdfManager.getPage(pageIndex); + if (!(pageRef instanceof Ref)) { + warn(`Cannot save the struct tree: page ${pageIndex} has no ref.`); + hasNothingToUpdate = true; + break; + } + for (const element of elements) { + if (element.accessibilityData?.type) { + element.parentTreeId = nextKey++; + hasNothingToUpdate = false; + } + } + } + if (hasNothingToUpdate) { + for (const elements of newAnnotationsByPage.values()) { + for (const element of elements) { + delete element.parentTreeId; + } + } + return false; + } + return true; + } + static async createStructureTree({ + newAnnotationsByPage, + xref, + catalogRef, + pdfManager, + changes + }) { + const root = await pdfManager.ensureCatalog("cloneDict"); + const cache = new RefSetCache(); + cache.put(catalogRef, root); + const structTreeRootRef = xref.getNewTemporaryRef(); + root.set("StructTreeRoot", structTreeRootRef); + const structTreeRoot = new Dict(xref); + structTreeRoot.set("Type", Name.get("StructTreeRoot")); + const parentTreeRef = xref.getNewTemporaryRef(); + structTreeRoot.set("ParentTree", parentTreeRef); + const kids = []; + structTreeRoot.set("K", kids); + cache.put(structTreeRootRef, structTreeRoot); + const parentTree = new Dict(xref); + const nums = []; + parentTree.set("Nums", nums); + const nextKey = await this.#writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot: null, + kids, + nums, + xref, + pdfManager, + changes, + cache + }); + structTreeRoot.set("ParentTreeNextKey", nextKey); + cache.put(parentTreeRef, parentTree); + for (const [ref, obj] of cache.items()) { + changes.put(ref, { + data: obj + }); + } + } + async canUpdateStructTree({ + pdfManager, + newAnnotationsByPage + }) { + if (!this.ref) { + warn("Cannot update the struct tree: no root reference."); + return false; + } + let nextKey = this.dict.get("ParentTreeNextKey"); + if (!Number.isInteger(nextKey) || nextKey < 0) { + warn("Cannot update the struct tree: invalid next key."); + return false; + } + const parentTree = this.dict.get("ParentTree"); + if (!(parentTree instanceof Dict)) { + warn("Cannot update the struct tree: ParentTree isn't a dict."); + return false; + } + const nums = parentTree.get("Nums"); + if (!Array.isArray(nums)) { + warn("Cannot update the struct tree: nums isn't an array."); + return false; + } + const numberTree = new NumberTree(parentTree, this.xref); + for (const pageIndex of newAnnotationsByPage.keys()) { + const { + pageDict + } = await pdfManager.getPage(pageIndex); + if (!pageDict.has("StructParents")) { + continue; + } + const id = pageDict.get("StructParents"); + if (!Number.isInteger(id) || !Array.isArray(numberTree.get(id))) { + warn(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`); + return false; + } + } + let hasNothingToUpdate = true; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const { + pageDict + } = await pdfManager.getPage(pageIndex); + StructTreeRoot.#collectParents({ + elements, + xref: this.xref, + pageDict, + numberTree + }); + for (const element of elements) { + if (element.accessibilityData?.type) { + if (!(element.accessibilityData.structParent >= 0)) { + element.parentTreeId = nextKey++; + } + hasNothingToUpdate = false; + } + } + } + if (hasNothingToUpdate) { + for (const elements of newAnnotationsByPage.values()) { + for (const element of elements) { + delete element.parentTreeId; + delete element.structTreeParent; + } + } + return false; + } + return true; + } + async updateStructureTree({ + newAnnotationsByPage, + pdfManager, + changes + }) { + const { + ref: structTreeRootRef, + xref + } = this; + const structTreeRoot = this.dict.clone(); + const cache = new RefSetCache(); + cache.put(structTreeRootRef, structTreeRoot); + let parentTreeRef = structTreeRoot.getRaw("ParentTree"); + let parentTree; + if (parentTreeRef instanceof Ref) { + parentTree = xref.fetch(parentTreeRef); + } else { + parentTree = parentTreeRef; + parentTreeRef = xref.getNewTemporaryRef(); + structTreeRoot.set("ParentTree", parentTreeRef); + } + parentTree = parentTree.clone(); + cache.put(parentTreeRef, parentTree); + let nums = parentTree.getRaw("Nums"); + let numsRef = null; + if (nums instanceof Ref) { + numsRef = nums; + nums = xref.fetch(numsRef); + } + nums = nums.slice(); + if (!numsRef) { + parentTree.set("Nums", nums); + } + const newNextKey = await StructTreeRoot.#writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot: this, + kids: null, + nums, + xref, + pdfManager, + changes, + cache + }); + if (newNextKey === -1) { + return; + } + structTreeRoot.set("ParentTreeNextKey", newNextKey); + if (numsRef) { + cache.put(numsRef, nums); + } + for (const [ref, obj] of cache.items()) { + changes.put(ref, { + data: obj + }); + } + } + static async #writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot, + kids, + nums, + xref, + pdfManager, + changes, + cache + }) { + const objr = Name.get("OBJR"); + let nextKey = -1; + let structTreePageObjs; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const page = await pdfManager.getPage(pageIndex); + const { + ref: pageRef + } = page; + const isPageRef = pageRef instanceof Ref; + for (const { + accessibilityData, + ref, + parentTreeId, + structTreeParent + } of elements) { + if (!accessibilityData?.type) { + continue; + } + const { + structParent + } = accessibilityData; + if (structTreeRoot && Number.isInteger(structParent) && structParent >= 0) { + let objs = (structTreePageObjs ||= new Map()).get(pageIndex); + if (objs === undefined) { + const structTreePage = new StructTreePage(structTreeRoot, page.pageDict); + objs = structTreePage.collectObjects(pageRef); + structTreePageObjs.set(pageIndex, objs); + } + const objRef = objs?.get(structParent); + if (objRef) { + const tagDict = xref.fetch(objRef).clone(); + StructTreeRoot.#writeProperties(tagDict, accessibilityData); + changes.put(objRef, { + data: tagDict + }); + continue; + } + } + nextKey = Math.max(nextKey, parentTreeId); + const tagRef = xref.getNewTemporaryRef(); + const tagDict = new Dict(xref); + StructTreeRoot.#writeProperties(tagDict, accessibilityData); + await this.#updateParentTag({ + structTreeParent, + tagDict, + newTagRef: tagRef, + structTreeRootRef, + fallbackKids: kids, + xref, + cache + }); + const objDict = new Dict(xref); + tagDict.set("K", objDict); + objDict.set("Type", objr); + if (isPageRef) { + objDict.set("Pg", pageRef); + } + objDict.set("Obj", ref); + cache.put(tagRef, tagDict); + nums.push(parentTreeId, tagRef); + } + } + return nextKey + 1; + } + static #writeProperties(tagDict, { + type, + title, + lang, + alt, + expanded, + actualText + }) { + tagDict.set("S", Name.get(type)); + if (title) { + tagDict.set("T", stringToAsciiOrUTF16BE(title)); + } + if (lang) { + tagDict.set("Lang", stringToAsciiOrUTF16BE(lang)); + } + if (alt) { + tagDict.set("Alt", stringToAsciiOrUTF16BE(alt)); + } + if (expanded) { + tagDict.set("E", stringToAsciiOrUTF16BE(expanded)); + } + if (actualText) { + tagDict.set("ActualText", stringToAsciiOrUTF16BE(actualText)); + } + } + static #collectParents({ + elements, + xref, + pageDict, + numberTree + }) { + const idToElements = new Map(); + for (const element of elements) { + if (element.structTreeParentId) { + const id = parseInt(element.structTreeParentId.split("_mc")[1], 10); + let elems = idToElements.get(id); + if (!elems) { + elems = []; + idToElements.set(id, elems); + } + elems.push(element); + } + } + const id = pageDict.get("StructParents"); + if (!Number.isInteger(id)) { + return; + } + const parentArray = numberTree.get(id); + const updateElement = (kid, pageKid, kidRef) => { + const elems = idToElements.get(kid); + if (elems) { + const parentRef = pageKid.getRaw("P"); + const parentDict = xref.fetchIfRef(parentRef); + if (parentRef instanceof Ref && parentDict instanceof Dict) { + const params = { + ref: kidRef, + dict: pageKid + }; + for (const element of elems) { + element.structTreeParent = params; + } + } + return true; + } + return false; + }; + for (const kidRef of parentArray) { + if (!(kidRef instanceof Ref)) { + continue; + } + const pageKid = xref.fetch(kidRef); + const k = pageKid.get("K"); + if (Number.isInteger(k)) { + updateElement(k, pageKid, kidRef); + continue; + } + if (!Array.isArray(k)) { + continue; + } + for (let kid of k) { + kid = xref.fetchIfRef(kid); + if (Number.isInteger(kid) && updateElement(kid, pageKid, kidRef)) { + break; + } + if (!(kid instanceof Dict)) { + continue; + } + if (!isName(kid.get("Type"), "MCR")) { + break; + } + const mcid = kid.get("MCID"); + if (Number.isInteger(mcid) && updateElement(mcid, pageKid, kidRef)) { + break; + } + } + } + } + static async #updateParentTag({ + structTreeParent, + tagDict, + newTagRef, + structTreeRootRef, + fallbackKids, + xref, + cache + }) { + let ref = null; + let parentRef; + if (structTreeParent) { + ({ + ref + } = structTreeParent); + parentRef = structTreeParent.dict.getRaw("P") || structTreeRootRef; + } else { + parentRef = structTreeRootRef; + } + tagDict.set("P", parentRef); + const parentDict = xref.fetchIfRef(parentRef); + if (!parentDict) { + fallbackKids.push(newTagRef); + return; + } + let cachedParentDict = cache.get(parentRef); + if (!cachedParentDict) { + cachedParentDict = parentDict.clone(); + cache.put(parentRef, cachedParentDict); + } + const parentKidsRaw = cachedParentDict.getRaw("K"); + let cachedParentKids = parentKidsRaw instanceof Ref ? cache.get(parentKidsRaw) : null; + if (!cachedParentKids) { + cachedParentKids = xref.fetchIfRef(parentKidsRaw); + cachedParentKids = Array.isArray(cachedParentKids) ? cachedParentKids.slice() : [parentKidsRaw]; + const parentKidsRef = xref.getNewTemporaryRef(); + cachedParentDict.set("K", parentKidsRef); + cache.put(parentKidsRef, cachedParentKids); + } + const index = cachedParentKids.indexOf(ref); + cachedParentKids.splice(index >= 0 ? index + 1 : cachedParentKids.length, 0, newTagRef); + } +} +class StructElementNode { + constructor(tree, dict) { + this.tree = tree; + this.xref = tree.xref; + this.dict = dict; + this.kids = []; + this.parseKids(); + } + get role() { + const nameObj = this.dict.get("S"); + const name = nameObj instanceof Name ? nameObj.name : ""; + const { + root + } = this.tree; + return root.roleMap.get(name) ?? name; + } + get mathML() { + let AFs = this.dict.get("AF") || []; + if (!Array.isArray(AFs)) { + AFs = [AFs]; + } + for (let af of AFs) { + af = this.xref.fetchIfRef(af); + if (!(af instanceof Dict)) { + continue; + } + if (!isName(af.get("Type"), "Filespec")) { + continue; + } + if (!isName(af.get("AFRelationship"), "Supplement")) { + continue; + } + const ef = af.get("EF"); + if (!(ef instanceof Dict)) { + continue; + } + const fileStream = ef.get("UF") || ef.get("F"); + if (!(fileStream instanceof BaseStream)) { + continue; + } + if (!isName(fileStream.dict.get("Type"), "EmbeddedFile")) { + continue; + } + if (!isName(fileStream.dict.get("Subtype"), "application/mathml+xml")) { + continue; + } + return stringToUTF8String(fileStream.getString()); + } + const A = this.dict.get("A"); + if (A instanceof Dict) { + const O = A.get("O"); + if (isName(O, "MSFT_Office")) { + const mathml = A.get("MSFT_MathML"); + return mathml ? stringToPDFString(mathml) : null; + } + } + return null; + } + parseKids() { + let pageObjId = null; + const objRef = this.dict.getRaw("Pg"); + if (objRef instanceof Ref) { + pageObjId = objRef.toString(); + } + const kids = this.dict.get("K"); + if (Array.isArray(kids)) { + for (const kid of kids) { + const element = this.parseKid(pageObjId, this.xref.fetchIfRef(kid)); + if (element) { + this.kids.push(element); + } + } + } else { + const element = this.parseKid(pageObjId, kids); + if (element) { + this.kids.push(element); + } + } + } + parseKid(pageObjId, kid) { + if (Number.isInteger(kid)) { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + return new StructElement({ + type: StructElementType.PAGE_CONTENT, + mcid: kid, + pageObjId + }); + } + if (!(kid instanceof Dict)) { + return null; + } + const pageRef = kid.getRaw("Pg"); + if (pageRef instanceof Ref) { + pageObjId = pageRef.toString(); + } + const type = kid.get("Type") instanceof Name ? kid.get("Type").name : null; + if (type === "MCR") { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + const kidRef = kid.getRaw("Stm"); + return new StructElement({ + type: StructElementType.STREAM_CONTENT, + refObjId: kidRef instanceof Ref ? kidRef.toString() : null, + pageObjId, + mcid: kid.get("MCID") + }); + } + if (type === "OBJR") { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + const kidRef = kid.getRaw("Obj"); + return new StructElement({ + type: StructElementType.OBJECT, + refObjId: kidRef instanceof Ref ? kidRef.toString() : null, + pageObjId + }); + } + return new StructElement({ + type: StructElementType.ELEMENT, + dict: kid + }); + } +} +class StructElement { + constructor({ + type, + dict = null, + mcid = null, + pageObjId = null, + refObjId = null + }) { + this.type = type; + this.dict = dict; + this.mcid = mcid; + this.pageObjId = pageObjId; + this.refObjId = refObjId; + this.parentNode = null; + } +} +class StructTreePage { + constructor(structTreeRoot, pageDict) { + this.root = structTreeRoot; + this.xref = structTreeRoot?.xref ?? null; + this.rootDict = structTreeRoot?.dict ?? null; + this.pageDict = pageDict; + this.nodes = []; + } + collectObjects(pageRef) { + if (!this.root || !this.rootDict || !(pageRef instanceof Ref)) { + return null; + } + const parentTree = this.rootDict.get("ParentTree"); + if (!parentTree) { + return null; + } + const ids = this.root.structParentIds?.get(pageRef); + if (!ids) { + return null; + } + const map = new Map(); + const numberTree = new NumberTree(parentTree, this.xref); + for (const [elemId] of ids) { + const obj = numberTree.getRaw(elemId); + if (obj instanceof Ref) { + map.set(elemId, obj); + } + } + return map; + } + parse(pageRef) { + if (!this.root || !this.rootDict || !(pageRef instanceof Ref)) { + return; + } + const { + parentTree + } = this.root; + if (!parentTree) { + return; + } + const id = this.pageDict.get("StructParents"); + const ids = this.root.structParentIds?.get(pageRef); + if (!Number.isInteger(id) && !ids) { + return; + } + const map = new Map(); + if (Number.isInteger(id)) { + const parentArray = parentTree.get(id); + if (Array.isArray(parentArray)) { + for (const ref of parentArray) { + if (ref instanceof Ref) { + this.addNode(this.xref.fetch(ref), map); + } + } + } + } + if (!ids) { + return; + } + for (const [elemId, type] of ids) { + const obj = parentTree.get(elemId); + if (obj) { + const elem = this.addNode(this.xref.fetchIfRef(obj), map); + if (elem?.kids?.length === 1 && elem.kids[0].type === StructElementType.OBJECT) { + elem.kids[0].type = type; + } + } + } + } + addNode(dict, map, level = 0) { + if (level > MAX_DEPTH) { + warn("StructTree MAX_DEPTH reached."); + return null; + } + if (!(dict instanceof Dict)) { + return null; + } + if (map.has(dict)) { + return map.get(dict); + } + const element = new StructElementNode(this, dict); + map.set(dict, element); + switch (element.role) { + case "L": + case "LBody": + case "LI": + case "Table": + case "THead": + case "TBody": + case "TFoot": + case "TR": + { + for (const kid of element.kids) { + if (kid.type === StructElementType.ELEMENT) { + this.addNode(kid.dict, map, level - 1); + } + } + } + } + const parent = dict.get("P"); + if (!(parent instanceof Dict) || isName(parent.get("Type"), "StructTreeRoot")) { + if (!this.addTopLevelNode(dict, element)) { + map.delete(dict); + } + return element; + } + const parentNode = this.addNode(parent, map, level + 1); + if (!parentNode) { + return element; + } + let save = false; + for (const kid of parentNode.kids) { + if (kid.type === StructElementType.ELEMENT && kid.dict === dict) { + kid.parentNode = element; + save = true; + } + } + if (!save) { + map.delete(dict); + } + return element; + } + addTopLevelNode(dict, element) { + const index = this.root.getKidPosition(dict.objId); + if (isNaN(index)) { + return false; + } + if (index !== -1) { + this.nodes[index] = element; + } + return true; + } + get serializable() { + function nodeToSerializable(node, parent, level = 0) { + if (level > MAX_DEPTH) { + warn("StructTree too deep to be fully serialized."); + return; + } + const obj = Object.create(null); + obj.role = node.role; + obj.children = []; + parent.children.push(obj); + let alt = node.dict.get("Alt"); + if (typeof alt !== "string") { + alt = node.dict.get("ActualText"); + } + if (typeof alt === "string") { + obj.alt = stringToPDFString(alt); + } + if (obj.role === "Formula") { + const { + mathML + } = node; + if (mathML) { + obj.mathML = mathML; + } + } + const a = node.dict.get("A"); + if (a instanceof Dict) { + const bbox = lookupNormalRect(a.getArray("BBox"), null); + if (bbox) { + obj.bbox = bbox; + } else { + const width = a.get("Width"); + const height = a.get("Height"); + if (typeof width === "number" && width > 0 && typeof height === "number" && height > 0) { + obj.bbox = [0, 0, width, height]; + } + } + } + const lang = node.dict.get("Lang"); + if (typeof lang === "string") { + obj.lang = stringToPDFString(lang); + } + for (const kid of node.kids) { + const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null; + if (kidElement) { + nodeToSerializable(kidElement, obj, level + 1); + continue; + } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) { + obj.children.push({ + type: "content", + id: `p${kid.pageObjId}_mc${kid.mcid}` + }); + } else if (kid.type === StructElementType.OBJECT) { + obj.children.push({ + type: "object", + id: kid.refObjId + }); + } else if (kid.type === StructElementType.ANNOTATION) { + obj.children.push({ + type: "annotation", + id: `${AnnotationPrefix}${kid.refObjId}` + }); + } + } + } + const root = Object.create(null); + root.children = []; + root.role = "Root"; + for (const child of this.nodes) { + if (!child) { + continue; + } + nodeToSerializable(child, root); + } + return root; + } +} + +;// ./src/core/catalog.js + + + + + + + + + + + +const isRef = v => v instanceof Ref; +const isValidExplicitDest = _isValidExplicitDest.bind(null, isRef, isName); +function fetchDest(dest) { + if (dest instanceof Dict) { + dest = dest.get("D"); + } + return isValidExplicitDest(dest) ? dest : null; +} +function fetchRemoteDest(action) { + let dest = action.get("D"); + if (dest) { + if (dest instanceof Name) { + dest = dest.name; + } + if (typeof dest === "string") { + return stringToPDFString(dest, true); + } else if (isValidExplicitDest(dest)) { + return JSON.stringify(dest); + } + } + return null; +} +class Catalog { + #actualNumPages = null; + #catDict = null; + builtInCMapCache = new Map(); + fontCache = new RefSetCache(); + globalColorSpaceCache = new GlobalColorSpaceCache(); + globalImageCache = new GlobalImageCache(); + nonBlendModesSet = new RefSet(); + pageDictCache = new RefSetCache(); + pageIndexCache = new RefSetCache(); + pageKidsCountCache = new RefSetCache(); + standardFontDataCache = new Map(); + systemFontCache = new Map(); + constructor(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.#catDict = xref.getCatalogObj(); + if (!(this.#catDict instanceof Dict)) { + throw new FormatError("Catalog object is not a dictionary."); + } + this.toplevelPagesDict; + } + cloneDict() { + return this.#catDict.clone(); + } + get version() { + const version = this.#catDict.get("Version"); + if (version instanceof Name) { + if (PDF_VERSION_REGEXP.test(version.name)) { + return shadow(this, "version", version.name); + } + warn(`Invalid PDF catalog version: ${version.name}`); + } + return shadow(this, "version", null); + } + get lang() { + const lang = this.#catDict.get("Lang"); + return shadow(this, "lang", lang && typeof lang === "string" ? stringToPDFString(lang) : null); + } + get needsRendering() { + const needsRendering = this.#catDict.get("NeedsRendering"); + return shadow(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false); + } + get collection() { + let collection = null; + try { + const obj = this.#catDict.get("Collection"); + if (obj instanceof Dict && obj.size > 0) { + collection = obj; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info("Cannot fetch Collection entry; assuming no collection is present."); + } + return shadow(this, "collection", collection); + } + get acroForm() { + let acroForm = null; + try { + const obj = this.#catDict.get("AcroForm"); + if (obj instanceof Dict && obj.size > 0) { + acroForm = obj; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info("Cannot fetch AcroForm entry; assuming no forms are present."); + } + return shadow(this, "acroForm", acroForm); + } + get acroFormRef() { + const value = this.#catDict.getRaw("AcroForm"); + return shadow(this, "acroFormRef", value instanceof Ref ? value : null); + } + get metadata() { + const streamRef = this.#catDict.getRaw("Metadata"); + if (!(streamRef instanceof Ref)) { + return shadow(this, "metadata", null); + } + let metadata = null; + try { + const stream = this.xref.fetch(streamRef, !this.xref.encrypt?.encryptMetadata); + if (stream instanceof BaseStream && stream.dict instanceof Dict) { + const type = stream.dict.get("Type"); + const subtype = stream.dict.get("Subtype"); + if (isName(type, "Metadata") && isName(subtype, "XML")) { + const data = stringToUTF8String(stream.getString()); + if (data) { + metadata = new MetadataParser(data).serializable; + } + } + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info(`Skipping invalid Metadata: "${ex}".`); + } + return shadow(this, "metadata", metadata); + } + get markInfo() { + let markInfo = null; + try { + markInfo = this.#readMarkInfo(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Unable to read mark info."); + } + return shadow(this, "markInfo", markInfo); + } + #readMarkInfo() { + const obj = this.#catDict.get("MarkInfo"); + if (!(obj instanceof Dict)) { + return null; + } + const markInfo = { + Marked: false, + UserProperties: false, + Suspects: false + }; + for (const key in markInfo) { + const value = obj.get(key); + if (typeof value === "boolean") { + markInfo[key] = value; + } + } + return markInfo; + } + get hasStructTree() { + return this.#catDict.has("StructTreeRoot"); + } + get structTreeRoot() { + let structTree = null; + try { + structTree = this.#readStructTreeRoot(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Unable read to structTreeRoot info."); + } + return shadow(this, "structTreeRoot", structTree); + } + #readStructTreeRoot() { + const rawObj = this.#catDict.getRaw("StructTreeRoot"); + const obj = this.xref.fetchIfRef(rawObj); + if (!(obj instanceof Dict)) { + return null; + } + const root = new StructTreeRoot(this.xref, obj, rawObj); + root.init(); + return root; + } + get toplevelPagesDict() { + const pagesObj = this.#catDict.get("Pages"); + if (!(pagesObj instanceof Dict)) { + throw new FormatError("Invalid top-level pages dictionary."); + } + return shadow(this, "toplevelPagesDict", pagesObj); + } + get documentOutline() { + let obj = null; + try { + obj = this.#readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Unable to read document outline."); + } + return shadow(this, "documentOutline", obj); + } + #readDocumentOutline() { + let obj = this.#catDict.get("Outlines"); + if (!(obj instanceof Dict)) { + return null; + } + obj = obj.getRaw("First"); + if (!(obj instanceof Ref)) { + return null; + } + const root = { + items: [] + }; + const queue = [{ + obj, + parent: root + }]; + const processed = new RefSet(); + processed.put(obj); + const xref = this.xref, + blackColor = new Uint8ClampedArray(3); + while (queue.length > 0) { + const i = queue.shift(); + const outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) { + continue; + } + if (!outlineDict.has("Title")) { + warn("Invalid outline item encountered."); + } + const data = { + url: null, + dest: null, + action: null + }; + Catalog.parseDestDictionary({ + destDict: outlineDict, + resultObj: data, + docBaseUrl: this.baseUrl, + docAttachments: this.attachments + }); + const title = outlineDict.get("Title"); + const flags = outlineDict.get("F") || 0; + const color = outlineDict.getArray("C"); + const count = outlineDict.get("Count"); + let rgbColor = blackColor; + if (isNumberArray(color, 3) && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { + rgbColor = ColorSpaceUtils.rgb.getRgb(color, 0); + } + const outlineItem = { + action: data.action, + attachment: data.attachment, + dest: data.dest, + url: data.url, + unsafeUrl: data.unsafeUrl, + newWindow: data.newWindow, + setOCGState: data.setOCGState, + title: typeof title === "string" ? stringToPDFString(title) : "", + color: rgbColor, + count: Number.isInteger(count) ? count : undefined, + bold: !!(flags & 2), + italic: !!(flags & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.getRaw("First"); + if (obj instanceof Ref && !processed.has(obj)) { + queue.push({ + obj, + parent: outlineItem + }); + processed.put(obj); + } + obj = outlineDict.getRaw("Next"); + if (obj instanceof Ref && !processed.has(obj)) { + queue.push({ + obj, + parent: i.parent + }); + processed.put(obj); + } + } + return root.items.length > 0 ? root.items : null; + } + get permissions() { + let permissions = null; + try { + permissions = this.#readPermissions(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Unable to read permissions."); + } + return shadow(this, "permissions", permissions); + } + #readPermissions() { + const encrypt = this.xref.trailer.get("Encrypt"); + if (!(encrypt instanceof Dict)) { + return null; + } + let flags = encrypt.get("P"); + if (typeof flags !== "number") { + return null; + } + flags += 2 ** 32; + const permissions = []; + for (const key in PermissionFlag) { + const value = PermissionFlag[key]; + if (flags & value) { + permissions.push(value); + } + } + return permissions; + } + get optionalContentConfig() { + let config = null; + try { + const properties = this.#catDict.get("OCProperties"); + if (!properties) { + return shadow(this, "optionalContentConfig", null); + } + const defaultConfig = properties.get("D"); + if (!defaultConfig) { + return shadow(this, "optionalContentConfig", null); + } + const groupsData = properties.get("OCGs"); + if (!Array.isArray(groupsData)) { + return shadow(this, "optionalContentConfig", null); + } + const groupRefCache = new RefSetCache(); + for (const groupRef of groupsData) { + if (!(groupRef instanceof Ref) || groupRefCache.has(groupRef)) { + continue; + } + groupRefCache.put(groupRef, this.#readOptionalContentGroup(groupRef)); + } + config = this.#readOptionalContentConfig(defaultConfig, groupRefCache); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`Unable to read optional content config: ${ex}`); + } + return shadow(this, "optionalContentConfig", config); + } + #readOptionalContentGroup(groupRef) { + const group = this.xref.fetch(groupRef); + const obj = { + id: groupRef.toString(), + name: null, + intent: null, + usage: { + print: null, + view: null + }, + rbGroups: [] + }; + const name = group.get("Name"); + if (typeof name === "string") { + obj.name = stringToPDFString(name); + } + let intent = group.getArray("Intent"); + if (!Array.isArray(intent)) { + intent = [intent]; + } + if (intent.every(i => i instanceof Name)) { + obj.intent = intent.map(i => i.name); + } + const usage = group.get("Usage"); + if (!(usage instanceof Dict)) { + return obj; + } + const usageObj = obj.usage; + const print = usage.get("Print"); + if (print instanceof Dict) { + const printState = print.get("PrintState"); + if (printState instanceof Name) { + switch (printState.name) { + case "ON": + case "OFF": + usageObj.print = { + printState: printState.name + }; + } + } + } + const view = usage.get("View"); + if (view instanceof Dict) { + const viewState = view.get("ViewState"); + if (viewState instanceof Name) { + switch (viewState.name) { + case "ON": + case "OFF": + usageObj.view = { + viewState: viewState.name + }; + } + } + } + return obj; + } + #readOptionalContentConfig(config, groupRefCache) { + function parseOnOff(refs) { + const onParsed = []; + if (Array.isArray(refs)) { + for (const value of refs) { + if (value instanceof Ref && groupRefCache.has(value)) { + onParsed.push(value.toString()); + } + } + } + return onParsed; + } + function parseOrder(refs, nestedLevels = 0) { + if (!Array.isArray(refs)) { + return null; + } + const order = []; + for (const value of refs) { + if (value instanceof Ref && groupRefCache.has(value)) { + parsedOrderRefs.put(value); + order.push(value.toString()); + continue; + } + const nestedOrder = parseNestedOrder(value, nestedLevels); + if (nestedOrder) { + order.push(nestedOrder); + } + } + if (nestedLevels > 0) { + return order; + } + const hiddenGroups = []; + for (const [groupRef] of groupRefCache.items()) { + if (parsedOrderRefs.has(groupRef)) { + continue; + } + hiddenGroups.push(groupRef.toString()); + } + if (hiddenGroups.length) { + order.push({ + name: null, + order: hiddenGroups + }); + } + return order; + } + function parseNestedOrder(ref, nestedLevels) { + if (++nestedLevels > MAX_NESTED_LEVELS) { + warn("parseNestedOrder - reached MAX_NESTED_LEVELS."); + return null; + } + const value = xref.fetchIfRef(ref); + if (!Array.isArray(value)) { + return null; + } + const nestedName = xref.fetchIfRef(value[0]); + if (typeof nestedName !== "string") { + return null; + } + const nestedOrder = parseOrder(value.slice(1), nestedLevels); + if (!nestedOrder?.length) { + return null; + } + return { + name: stringToPDFString(nestedName), + order: nestedOrder + }; + } + function parseRBGroups(rbGroups) { + if (!Array.isArray(rbGroups)) { + return; + } + for (const value of rbGroups) { + const rbGroup = xref.fetchIfRef(value); + if (!Array.isArray(rbGroup) || !rbGroup.length) { + continue; + } + const parsedRbGroup = new Set(); + for (const ref of rbGroup) { + if (ref instanceof Ref && groupRefCache.has(ref) && !parsedRbGroup.has(ref.toString())) { + parsedRbGroup.add(ref.toString()); + groupRefCache.get(ref).rbGroups.push(parsedRbGroup); + } + } + } + } + const xref = this.xref, + parsedOrderRefs = new RefSet(), + MAX_NESTED_LEVELS = 10; + parseRBGroups(config.get("RBGroups")); + return { + name: typeof config.get("Name") === "string" ? stringToPDFString(config.get("Name")) : null, + creator: typeof config.get("Creator") === "string" ? stringToPDFString(config.get("Creator")) : null, + baseState: config.get("BaseState") instanceof Name ? config.get("BaseState").name : null, + on: parseOnOff(config.get("ON")), + off: parseOnOff(config.get("OFF")), + order: parseOrder(config.get("Order")), + groups: [...groupRefCache] + }; + } + setActualNumPages(num = null) { + this.#actualNumPages = num; + } + get hasActualNumPages() { + return this.#actualNumPages !== null; + } + get _pagesCount() { + const obj = this.toplevelPagesDict.get("Count"); + if (!Number.isInteger(obj)) { + throw new FormatError("Page count in top-level pages dictionary is not an integer."); + } + return shadow(this, "_pagesCount", obj); + } + get numPages() { + return this.#actualNumPages ?? this._pagesCount; + } + get destinations() { + const rawDests = this.#readDests(), + dests = Object.create(null); + for (const obj of rawDests) { + if (obj instanceof NameTree) { + for (const [key, value] of obj.getAll()) { + const dest = fetchDest(value); + if (dest) { + dests[stringToPDFString(key, true)] = dest; + } + } + } else if (obj instanceof Dict) { + for (const [key, value] of obj) { + const dest = fetchDest(value); + if (dest) { + dests[stringToPDFString(key, true)] ||= dest; + } + } + } + } + return shadow(this, "destinations", dests); + } + getDestination(id) { + if (this.hasOwnProperty("destinations")) { + return this.destinations[id] ?? null; + } + const rawDests = this.#readDests(); + for (const obj of rawDests) { + if (obj instanceof NameTree || obj instanceof Dict) { + const dest = fetchDest(obj.get(id)); + if (dest) { + return dest; + } + } + } + if (rawDests.length) { + const dest = this.destinations[id]; + if (dest) { + return dest; + } + } + return null; + } + #readDests() { + const obj = this.#catDict.get("Names"); + const rawDests = []; + if (obj?.has("Dests")) { + rawDests.push(new NameTree(obj.getRaw("Dests"), this.xref)); + } + if (this.#catDict.has("Dests")) { + rawDests.push(this.#catDict.get("Dests")); + } + return rawDests; + } + get rawPageLabels() { + const obj = this.#catDict.getRaw("PageLabels"); + if (!obj) { + return null; + } + const numberTree = new NumberTree(obj, this.xref); + return numberTree.getAll(); + } + get pageLabels() { + let obj = null; + try { + obj = this.#readPageLabels(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn("Unable to read page labels."); + } + return shadow(this, "pageLabels", obj); + } + #readPageLabels() { + const nums = this.rawPageLabels; + if (!nums) { + return null; + } + const pageLabels = new Array(this.numPages); + let style = null, + prefix = ""; + let currentLabel = "", + currentIndex = 1; + for (let i = 0, ii = this.numPages; i < ii; i++) { + const labelDict = nums.get(i); + if (labelDict !== undefined) { + if (!(labelDict instanceof Dict)) { + throw new FormatError("PageLabel is not a dictionary."); + } + if (labelDict.has("Type") && !isName(labelDict.get("Type"), "PageLabel")) { + throw new FormatError("Invalid type in PageLabel dictionary."); + } + if (labelDict.has("S")) { + const s = labelDict.get("S"); + if (!(s instanceof Name)) { + throw new FormatError("Invalid style in PageLabel dictionary."); + } + style = s.name; + } else { + style = null; + } + if (labelDict.has("P")) { + const p = labelDict.get("P"); + if (typeof p !== "string") { + throw new FormatError("Invalid prefix in PageLabel dictionary."); + } + prefix = stringToPDFString(p); + } else { + prefix = ""; + } + if (labelDict.has("St")) { + const st = labelDict.get("St"); + if (!(Number.isInteger(st) && st >= 1)) { + throw new FormatError("Invalid start in PageLabel dictionary."); + } + currentIndex = st; + } else { + currentIndex = 1; + } + } + switch (style) { + case "D": + currentLabel = currentIndex; + break; + case "R": + case "r": + currentLabel = toRomanNumerals(currentIndex, style === "r"); + break; + case "A": + case "a": + const LIMIT = 26; + const A_UPPER_CASE = 0x41, + A_LOWER_CASE = 0x61; + const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE; + const letterIndex = currentIndex - 1; + const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT); + currentLabel = character.repeat(Math.floor(letterIndex / LIMIT) + 1); + break; + default: + if (style) { + throw new FormatError(`Invalid style "${style}" in PageLabel dictionary.`); + } + currentLabel = ""; + } + pageLabels[i] = prefix + currentLabel; + currentIndex++; + } + return pageLabels; + } + get pageLayout() { + const obj = this.#catDict.get("PageLayout"); + let pageLayout = ""; + if (obj instanceof Name) { + switch (obj.name) { + case "SinglePage": + case "OneColumn": + case "TwoColumnLeft": + case "TwoColumnRight": + case "TwoPageLeft": + case "TwoPageRight": + pageLayout = obj.name; + } + } + return shadow(this, "pageLayout", pageLayout); + } + get pageMode() { + const obj = this.#catDict.get("PageMode"); + let pageMode = "UseNone"; + if (obj instanceof Name) { + switch (obj.name) { + case "UseNone": + case "UseOutlines": + case "UseThumbs": + case "FullScreen": + case "UseOC": + case "UseAttachments": + pageMode = obj.name; + } + } + return shadow(this, "pageMode", pageMode); + } + get viewerPreferences() { + const obj = this.#catDict.get("ViewerPreferences"); + if (!(obj instanceof Dict)) { + return shadow(this, "viewerPreferences", null); + } + let prefs = null; + for (const [key, value] of obj) { + let prefValue; + switch (key) { + case "HideToolbar": + case "HideMenubar": + case "HideWindowUI": + case "FitWindow": + case "CenterWindow": + case "DisplayDocTitle": + case "PickTrayByPDFSize": + if (typeof value === "boolean") { + prefValue = value; + } + break; + case "NonFullScreenPageMode": + if (value instanceof Name) { + switch (value.name) { + case "UseNone": + case "UseOutlines": + case "UseThumbs": + case "UseOC": + prefValue = value.name; + break; + default: + prefValue = "UseNone"; + } + } + break; + case "Direction": + if (value instanceof Name) { + switch (value.name) { + case "L2R": + case "R2L": + prefValue = value.name; + break; + default: + prefValue = "L2R"; + } + } + break; + case "ViewArea": + case "ViewClip": + case "PrintArea": + case "PrintClip": + if (value instanceof Name) { + switch (value.name) { + case "MediaBox": + case "CropBox": + case "BleedBox": + case "TrimBox": + case "ArtBox": + prefValue = value.name; + break; + default: + prefValue = "CropBox"; + } + } + break; + case "PrintScaling": + if (value instanceof Name) { + switch (value.name) { + case "None": + case "AppDefault": + prefValue = value.name; + break; + default: + prefValue = "AppDefault"; + } + } + break; + case "Duplex": + if (value instanceof Name) { + switch (value.name) { + case "Simplex": + case "DuplexFlipShortEdge": + case "DuplexFlipLongEdge": + prefValue = value.name; + break; + default: + prefValue = "None"; + } + } + break; + case "PrintPageRange": + if (Array.isArray(value) && value.length % 2 === 0) { + const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages); + if (isValid) { + prefValue = value; + } + } + break; + case "NumCopies": + if (Number.isInteger(value) && value > 0) { + prefValue = value; + } + break; + default: + warn(`Ignoring non-standard key in ViewerPreferences: ${key}.`); + continue; + } + if (prefValue === undefined) { + warn(`Bad value, for key "${key}", in ViewerPreferences: ${value}.`); + continue; + } + prefs ??= Object.create(null); + prefs[key] = prefValue; + } + return shadow(this, "viewerPreferences", prefs); + } + get openAction() { + const obj = this.#catDict.get("OpenAction"); + const openAction = Object.create(null); + if (obj instanceof Dict) { + const destDict = new Dict(this.xref); + destDict.set("A", obj); + const resultObj = { + url: null, + dest: null, + action: null + }; + Catalog.parseDestDictionary({ + destDict, + resultObj + }); + if (Array.isArray(resultObj.dest)) { + openAction.dest = resultObj.dest; + } else if (resultObj.action) { + openAction.action = resultObj.action; + } + } else if (isValidExplicitDest(obj)) { + openAction.dest = obj; + } + return shadow(this, "openAction", objectSize(openAction) > 0 ? openAction : null); + } + get attachments() { + const obj = this.#catDict.get("Names"); + let attachments = null; + if (obj instanceof Dict && obj.has("EmbeddedFiles")) { + const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref); + for (const [key, value] of nameTree.getAll()) { + const fs = new FileSpec(value, this.xref); + attachments ??= Object.create(null); + attachments[stringToPDFString(key, true)] = fs.serializable; + } + } + return shadow(this, "attachments", attachments); + } + get xfaImages() { + const obj = this.#catDict.get("Names"); + let xfaImages = null; + if (obj instanceof Dict && obj.has("XFAImages")) { + const nameTree = new NameTree(obj.getRaw("XFAImages"), this.xref); + for (const [key, value] of nameTree.getAll()) { + if (value instanceof BaseStream) { + xfaImages ??= new Map(); + xfaImages.set(stringToPDFString(key, true), value.getBytes()); + } + } + } + return shadow(this, "xfaImages", xfaImages); + } + #collectJavaScript() { + const obj = this.#catDict.get("Names"); + let javaScript = null; + function appendIfJavaScriptDict(name, jsDict) { + if (!(jsDict instanceof Dict)) { + return; + } + if (!isName(jsDict.get("S"), "JavaScript")) { + return; + } + let js = jsDict.get("JS"); + if (js instanceof BaseStream) { + js = js.getString(); + } else if (typeof js !== "string") { + return; + } + js = stringToPDFString(js, true).replaceAll("\x00", ""); + if (js) { + (javaScript ||= new Map()).set(name, js); + } + } + if (obj instanceof Dict && obj.has("JavaScript")) { + const nameTree = new NameTree(obj.getRaw("JavaScript"), this.xref); + for (const [key, value] of nameTree.getAll()) { + appendIfJavaScriptDict(stringToPDFString(key, true), value); + } + } + const openAction = this.#catDict.get("OpenAction"); + if (openAction) { + appendIfJavaScriptDict("OpenAction", openAction); + } + return javaScript; + } + get jsActions() { + const javaScript = this.#collectJavaScript(); + let actions = collectActions(this.xref, this.#catDict, DocumentActionEventType); + if (javaScript) { + actions ||= Object.create(null); + for (const [key, val] of javaScript) { + if (key in actions) { + actions[key].push(val); + } else { + actions[key] = [val]; + } + } + } + return shadow(this, "jsActions", actions); + } + async cleanup(manuallyTriggered = false) { + clearGlobalCaches(); + this.globalColorSpaceCache.clear(); + this.globalImageCache.clear(manuallyTriggered); + this.pageKidsCountCache.clear(); + this.pageIndexCache.clear(); + this.pageDictCache.clear(); + this.nonBlendModesSet.clear(); + for (const { + dict + } of await Promise.all(this.fontCache)) { + delete dict.cacheKey; + } + this.fontCache.clear(); + this.builtInCMapCache.clear(); + this.standardFontDataCache.clear(); + this.systemFontCache.clear(); + } + async getPageDict(pageIndex) { + const nodesToVisit = [this.toplevelPagesDict]; + const visitedNodes = new RefSet(); + const pagesRef = this.#catDict.getRaw("Pages"); + if (pagesRef instanceof Ref) { + visitedNodes.put(pagesRef); + } + const xref = this.xref, + pageKidsCountCache = this.pageKidsCountCache, + pageIndexCache = this.pageIndexCache, + pageDictCache = this.pageDictCache; + let currentPageIndex = 0; + while (nodesToVisit.length) { + const currentNode = nodesToVisit.pop(); + if (currentNode instanceof Ref) { + const count = pageKidsCountCache.get(currentNode); + if (count >= 0 && currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + if (visitedNodes.has(currentNode)) { + throw new FormatError("Pages tree contains circular reference."); + } + visitedNodes.put(currentNode); + const obj = await (pageDictCache.get(currentNode) || xref.fetchAsync(currentNode)); + if (obj instanceof Dict) { + let type = obj.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !obj.has("Kids")) { + if (!pageKidsCountCache.has(currentNode)) { + pageKidsCountCache.put(currentNode, 1); + } + if (!pageIndexCache.has(currentNode)) { + pageIndexCache.put(currentNode, currentPageIndex); + } + if (currentPageIndex === pageIndex) { + return [obj, currentNode]; + } + currentPageIndex++; + continue; + } + } + nodesToVisit.push(obj); + continue; + } + if (!(currentNode instanceof Dict)) { + throw new FormatError("Page dictionary kid reference points to wrong type of object."); + } + const { + objId + } = currentNode; + let count = currentNode.getRaw("Count"); + if (count instanceof Ref) { + count = await xref.fetchAsync(count); + } + if (Number.isInteger(count) && count >= 0) { + if (objId && !pageKidsCountCache.has(objId)) { + pageKidsCountCache.put(objId, count); + } + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + } + let kids = currentNode.getRaw("Kids"); + if (kids instanceof Ref) { + kids = await xref.fetchAsync(kids); + } + if (!Array.isArray(kids)) { + let type = currentNode.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !currentNode.has("Kids")) { + if (currentPageIndex === pageIndex) { + return [currentNode, null]; + } + currentPageIndex++; + continue; + } + throw new FormatError("Page dictionary kids object is not an array."); + } + for (let last = kids.length - 1; last >= 0; last--) { + const lastKid = kids[last]; + nodesToVisit.push(lastKid); + if (currentNode === this.toplevelPagesDict && lastKid instanceof Ref && !pageDictCache.has(lastKid)) { + pageDictCache.put(lastKid, xref.fetchAsync(lastKid)); + } + } + } + throw new Error(`Page index ${pageIndex} not found.`); + } + async getAllPageDicts(recoveryMode = false) { + const { + ignoreErrors + } = this.pdfManager.evaluatorOptions; + const queue = [{ + currentNode: this.toplevelPagesDict, + posInKids: 0 + }]; + const visitedNodes = new RefSet(); + const pagesRef = this.#catDict.getRaw("Pages"); + if (pagesRef instanceof Ref) { + visitedNodes.put(pagesRef); + } + const map = new Map(), + xref = this.xref, + pageIndexCache = this.pageIndexCache; + let pageIndex = 0; + function addPageDict(pageDict, pageRef) { + if (pageRef && !pageIndexCache.has(pageRef)) { + pageIndexCache.put(pageRef, pageIndex); + } + map.set(pageIndex++, [pageDict, pageRef]); + } + function addPageError(error) { + if (error instanceof XRefEntryException && !recoveryMode) { + throw error; + } + if (recoveryMode && ignoreErrors && pageIndex === 0) { + warn(`getAllPageDicts - Skipping invalid first page: "${error}".`); + error = Dict.empty; + } + map.set(pageIndex++, [error, null]); + } + while (queue.length > 0) { + const queueItem = queue.at(-1); + const { + currentNode, + posInKids + } = queueItem; + let kids = currentNode.getRaw("Kids"); + if (kids instanceof Ref) { + try { + kids = await xref.fetchAsync(kids); + } catch (ex) { + addPageError(ex); + break; + } + } + if (!Array.isArray(kids)) { + addPageError(new FormatError("Page dictionary kids object is not an array.")); + break; + } + if (posInKids >= kids.length) { + queue.pop(); + continue; + } + const kidObj = kids[posInKids]; + let obj; + if (kidObj instanceof Ref) { + if (visitedNodes.has(kidObj)) { + addPageError(new FormatError("Pages tree contains circular reference.")); + break; + } + visitedNodes.put(kidObj); + try { + obj = await xref.fetchAsync(kidObj); + } catch (ex) { + addPageError(ex); + break; + } + } else { + obj = kidObj; + } + if (!(obj instanceof Dict)) { + addPageError(new FormatError("Page dictionary kid reference points to wrong type of object.")); + break; + } + let type = obj.getRaw("Type"); + if (type instanceof Ref) { + try { + type = await xref.fetchAsync(type); + } catch (ex) { + addPageError(ex); + break; + } + } + if (isName(type, "Page") || !obj.has("Kids")) { + addPageDict(obj, kidObj instanceof Ref ? kidObj : null); + } else { + queue.push({ + currentNode: obj, + posInKids: 0 + }); + } + queueItem.posInKids++; + } + return map; + } + getPageIndex(pageRef) { + const cachedPageIndex = this.pageIndexCache.get(pageRef); + if (cachedPageIndex !== undefined) { + return Promise.resolve(cachedPageIndex); + } + const xref = this.xref; + function pagesBeforeRef(kidRef) { + let total = 0, + parentRef; + return xref.fetchAsync(kidRef).then(function (node) { + if (isRefsEqual(kidRef, pageRef) && !isDict(node, "Page") && !(node instanceof Dict && !node.has("Type") && node.has("Contents"))) { + throw new FormatError("The reference does not point to a /Page dictionary."); + } + if (!node) { + return null; + } + if (!(node instanceof Dict)) { + throw new FormatError("Node must be a dictionary."); + } + parentRef = node.getRaw("Parent"); + return node.getAsync("Parent"); + }).then(function (parent) { + if (!parent) { + return null; + } + if (!(parent instanceof Dict)) { + throw new FormatError("Parent must be a dictionary."); + } + return parent.getAsync("Kids"); + }).then(function (kids) { + if (!kids) { + return null; + } + const kidPromises = []; + let found = false; + for (const kid of kids) { + if (!(kid instanceof Ref)) { + throw new FormatError("Kid must be a reference."); + } + if (isRefsEqual(kid, kidRef)) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function (obj) { + if (!(obj instanceof Dict)) { + throw new FormatError("Kid node must be a dictionary."); + } + if (obj.has("Count")) { + total += obj.get("Count"); + } else { + total++; + } + })); + } + if (!found) { + throw new FormatError("Kid reference not found in parent's kids."); + } + return Promise.all(kidPromises).then(() => [total, parentRef]); + }); + } + let total = 0; + const next = ref => pagesBeforeRef(ref).then(args => { + if (!args) { + this.pageIndexCache.put(pageRef, total); + return total; + } + const [count, parentRef] = args; + total += count; + return next(parentRef); + }); + return next(pageRef); + } + get baseUrl() { + const uri = this.#catDict.get("URI"); + if (uri instanceof Dict) { + const base = uri.get("Base"); + if (typeof base === "string") { + const absoluteUrl = createValidAbsoluteUrl(base, null, { + tryConvertEncoding: true + }); + if (absoluteUrl) { + return shadow(this, "baseUrl", absoluteUrl.href); + } + } + } + return shadow(this, "baseUrl", this.pdfManager.docBaseUrl); + } + static parseDestDictionary({ + destDict, + resultObj, + docBaseUrl = null, + docAttachments = null + }) { + if (!(destDict instanceof Dict)) { + warn("parseDestDictionary: `destDict` must be a dictionary."); + return; + } + let action = destDict.get("A"), + url, + dest; + if (!(action instanceof Dict)) { + if (destDict.has("Dest")) { + action = destDict.get("Dest"); + } else { + action = destDict.get("AA"); + if (action instanceof Dict) { + if (action.has("D")) { + action = action.get("D"); + } else if (action.has("U")) { + action = action.get("U"); + } + } + } + } + if (action instanceof Dict) { + const actionType = action.get("S"); + if (!(actionType instanceof Name)) { + warn("parseDestDictionary: Invalid type in Action dictionary."); + return; + } + const actionName = actionType.name; + switch (actionName) { + case "ResetForm": + const flags = action.get("Flags"); + const include = ((typeof flags === "number" ? flags : 0) & 1) === 0; + const fields = []; + const refs = []; + for (const obj of action.get("Fields") || []) { + if (obj instanceof Ref) { + refs.push(obj.toString()); + } else if (typeof obj === "string") { + fields.push(stringToPDFString(obj)); + } + } + resultObj.resetForm = { + fields, + refs, + include + }; + break; + case "URI": + url = action.get("URI"); + if (url instanceof Name) { + url = "/" + url.name; + } + break; + case "GoTo": + dest = action.get("D"); + break; + case "Launch": + case "GoToR": + const urlDict = action.get("F"); + if (urlDict instanceof Dict) { + const fs = new FileSpec(urlDict, null, true); + const { + rawFilename + } = fs.serializable; + url = rawFilename; + } else if (typeof urlDict === "string") { + url = urlDict; + } + const remoteDest = fetchRemoteDest(action); + if (remoteDest && typeof url === "string") { + url = url.split("#", 1)[0] + "#" + remoteDest; + } + const newWindow = action.get("NewWindow"); + if (typeof newWindow === "boolean") { + resultObj.newWindow = newWindow; + } + break; + case "GoToE": + const target = action.get("T"); + let attachment; + if (docAttachments && target instanceof Dict) { + const relationship = target.get("R"); + const name = target.get("N"); + if (isName(relationship, "C") && typeof name === "string") { + attachment = docAttachments[stringToPDFString(name, true)]; + } + } + if (attachment) { + resultObj.attachment = attachment; + const attachmentDest = fetchRemoteDest(action); + if (attachmentDest) { + resultObj.attachmentDest = attachmentDest; + } + } else { + warn(`parseDestDictionary - unimplemented "GoToE" action.`); + } + break; + case "Named": + const namedAction = action.get("N"); + if (namedAction instanceof Name) { + resultObj.action = namedAction.name; + } + break; + case "SetOCGState": + const state = action.get("State"); + const preserveRB = action.get("PreserveRB"); + if (!Array.isArray(state) || state.length === 0) { + break; + } + const stateArr = []; + for (const elem of state) { + if (elem instanceof Name) { + switch (elem.name) { + case "ON": + case "OFF": + case "Toggle": + stateArr.push(elem.name); + break; + } + } else if (elem instanceof Ref) { + stateArr.push(elem.toString()); + } + } + if (stateArr.length !== state.length) { + break; + } + resultObj.setOCGState = { + state: stateArr, + preserveRB: typeof preserveRB === "boolean" ? preserveRB : true + }; + break; + case "JavaScript": + const jsAction = action.get("JS"); + let js; + if (jsAction instanceof BaseStream) { + js = jsAction.getString(); + } else if (typeof jsAction === "string") { + js = jsAction; + } + const jsURL = js && recoverJsURL(stringToPDFString(js, true)); + if (jsURL) { + url = jsURL.url; + resultObj.newWindow = jsURL.newWindow; + break; + } + default: + if (actionName === "JavaScript" || actionName === "SubmitForm") { + break; + } + warn(`parseDestDictionary - unsupported action: "${actionName}".`); + break; + } + } else if (destDict.has("Dest")) { + dest = destDict.get("Dest"); + } + if (typeof url === "string") { + const absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl, { + addDefaultProtocol: true, + tryConvertEncoding: true + }); + if (absoluteUrl) { + resultObj.url = absoluteUrl.href; + } + resultObj.unsafeUrl = url; + } + if (dest) { + if (dest instanceof Name) { + dest = dest.name; + } + if (typeof dest === "string") { + resultObj.dest = stringToPDFString(dest, true); + } else if (isValidExplicitDest(dest)) { + resultObj.dest = dest; + } + } + } +} + +;// ./src/core/object_loader.js + + + + +function mayHaveChildren(value) { + return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value); +} +function addChildren(node, nodesToVisit) { + if (node instanceof Dict) { + node = node.getRawValues(); + } else if (node instanceof BaseStream) { + node = node.dict.getRawValues(); + } else if (!Array.isArray(node)) { + return; + } + for (const rawValue of node) { + if (mayHaveChildren(rawValue)) { + nodesToVisit.push(rawValue); + } + } +} +class ObjectLoader { + refSet = new RefSet(); + constructor(dict, keys, xref) { + this.dict = dict; + this.keys = keys; + this.xref = xref; + } + async load() { + const { + keys, + dict + } = this; + const nodesToVisit = []; + for (const key of keys) { + const rawValue = dict.getRaw(key); + if (rawValue !== undefined) { + nodesToVisit.push(rawValue); + } + } + await this.#walk(nodesToVisit); + this.refSet = null; + } + async #walk(nodesToVisit) { + const nodesToRevisit = []; + const pendingRequests = []; + while (nodesToVisit.length) { + let currentNode = nodesToVisit.pop(); + if (currentNode instanceof Ref) { + if (this.refSet.has(currentNode)) { + continue; + } + try { + this.refSet.put(currentNode); + currentNode = this.xref.fetch(currentNode); + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + warn(`ObjectLoader.#walk - requesting all data: "${ex}".`); + await this.xref.stream.manager.requestAllChunks(); + return; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ + begin: ex.begin, + end: ex.end + }); + } + } + if (currentNode instanceof BaseStream) { + const baseStreams = currentNode.getBaseStreams(); + if (baseStreams) { + let foundMissingData = false; + for (const stream of baseStreams) { + if (stream.isDataLoaded) { + continue; + } + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + } + addChildren(currentNode, nodesToVisit); + } + if (pendingRequests.length) { + await this.xref.stream.manager.requestRanges(pendingRequests); + for (const node of nodesToRevisit) { + if (node instanceof Ref) { + this.refSet.remove(node); + } + } + await this.#walk(nodesToRevisit); + } + } + static async load(obj, keys, xref) { + if (xref.stream.isDataLoaded) { + return; + } + const objLoader = new ObjectLoader(obj, keys, xref); + await objLoader.load(); + } +} + +;// ./src/core/xfa/symbol_utils.js +const $acceptWhitespace = Symbol(); +const $addHTML = Symbol(); +const $appendChild = Symbol(); +const $childrenToHTML = Symbol(); +const $clean = Symbol(); +const $cleanPage = Symbol(); +const $cleanup = Symbol(); +const $clone = Symbol(); +const $consumed = Symbol(); +const $content = Symbol("content"); +const $data = Symbol("data"); +const $dump = Symbol(); +const $extra = Symbol("extra"); +const $finalize = Symbol(); +const $flushHTML = Symbol(); +const $getAttributeIt = Symbol(); +const $getAttributes = Symbol(); +const $getAvailableSpace = Symbol(); +const $getChildrenByClass = Symbol(); +const $getChildrenByName = Symbol(); +const $getChildrenByNameIt = Symbol(); +const $getDataValue = Symbol(); +const $getExtra = Symbol(); +const $getRealChildrenByNameIt = Symbol(); +const $getChildren = Symbol(); +const $getContainedChildren = Symbol(); +const $getNextPage = Symbol(); +const $getSubformParent = Symbol(); +const $getParent = Symbol(); +const $getTemplateRoot = Symbol(); +const $globalData = Symbol(); +const $hasSettableValue = Symbol(); +const $ids = Symbol(); +const $indexOf = Symbol(); +const $insertAt = Symbol(); +const $isCDATAXml = Symbol(); +const $isBindable = Symbol(); +const $isDataValue = Symbol(); +const $isDescendent = Symbol(); +const $isNsAgnostic = Symbol(); +const $isSplittable = Symbol(); +const $isThereMoreWidth = Symbol(); +const $isTransparent = Symbol(); +const $isUsable = Symbol(); +const $lastAttribute = Symbol(); +const $namespaceId = Symbol("namespaceId"); +const $nodeName = Symbol("nodeName"); +const $nsAttributes = Symbol(); +const $onChild = Symbol(); +const $onChildCheck = Symbol(); +const $onText = Symbol(); +const $pushGlyphs = Symbol(); +const $popPara = Symbol(); +const $pushPara = Symbol(); +const $removeChild = Symbol(); +const $root = Symbol("root"); +const $resolvePrototypes = Symbol(); +const $searchNode = Symbol(); +const $setId = Symbol(); +const $setSetAttributes = Symbol(); +const $setValue = Symbol(); +const $tabIndex = Symbol(); +const $text = Symbol(); +const $toPages = Symbol(); +const $toHTML = Symbol(); +const $toString = Symbol(); +const $toStyle = Symbol(); +const $uid = Symbol("uid"); + +;// ./src/core/xfa/namespaces.js +const $buildXFAObject = Symbol(); +const NamespaceIds = { + config: { + id: 0, + check: ns => ns.startsWith("http://www.xfa.org/schema/xci/") + }, + connectionSet: { + id: 1, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/") + }, + datasets: { + id: 2, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-data/") + }, + form: { + id: 3, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-form/") + }, + localeSet: { + id: 4, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/") + }, + pdf: { + id: 5, + check: ns => ns === "http://ns.adobe.com/xdp/pdf/" + }, + signature: { + id: 6, + check: ns => ns === "http://www.w3.org/2000/09/xmldsig#" + }, + sourceSet: { + id: 7, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-source-set/") + }, + stylesheet: { + id: 8, + check: ns => ns === "http://www.w3.org/1999/XSL/Transform" + }, + template: { + id: 9, + check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-template/") + }, + xdc: { + id: 10, + check: ns => ns.startsWith("http://www.xfa.org/schema/xdc/") + }, + xdp: { + id: 11, + check: ns => ns === "http://ns.adobe.com/xdp/" + }, + xfdf: { + id: 12, + check: ns => ns === "http://ns.adobe.com/xfdf/" + }, + xhtml: { + id: 13, + check: ns => ns === "http://www.w3.org/1999/xhtml" + }, + xmpmeta: { + id: 14, + check: ns => ns === "http://ns.adobe.com/xmpmeta/" + } +}; + +;// ./src/core/xfa/utils.js + +const dimConverters = { + pt: x => x, + cm: x => x / 2.54 * 72, + mm: x => x / (10 * 2.54) * 72, + in: x => x * 72, + px: x => x +}; +const measurementPattern = /([+-]?\d+\.?\d*)(.*)/; +function stripQuotes(str) { + if (str.startsWith("'") || str.startsWith('"')) { + return str.slice(1, -1); + } + return str; +} +function getInteger({ + data, + defaultValue, + validate +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + const n = parseInt(data, 10); + if (!isNaN(n) && validate(n)) { + return n; + } + return defaultValue; +} +function getFloat({ + data, + defaultValue, + validate +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + const n = parseFloat(data); + if (!isNaN(n) && validate(n)) { + return n; + } + return defaultValue; +} +function getKeyword({ + data, + defaultValue, + validate +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + if (validate(data)) { + return data; + } + return defaultValue; +} +function getStringOption(data, options) { + return getKeyword({ + data, + defaultValue: options[0], + validate: k => options.includes(k) + }); +} +function getMeasurement(str, def = "0") { + def ||= "0"; + if (!str) { + return getMeasurement(def); + } + const match = str.trim().match(measurementPattern); + if (!match) { + return getMeasurement(def); + } + const [, valueStr, unit] = match; + const value = parseFloat(valueStr); + if (isNaN(value)) { + return getMeasurement(def); + } + if (value === 0) { + return 0; + } + const conv = dimConverters[unit]; + if (conv) { + return conv(value); + } + return value; +} +function getRatio(data) { + if (!data) { + return { + num: 1, + den: 1 + }; + } + const ratio = data.split(":", 2).map(x => parseFloat(x.trim())).filter(x => !isNaN(x)); + if (ratio.length === 1) { + ratio.push(1); + } + if (ratio.length === 0) { + return { + num: 1, + den: 1 + }; + } + const [num, den] = ratio; + return { + num, + den + }; +} +function getRelevant(data) { + if (!data) { + return []; + } + return data.trim().split(/\s+/).map(e => ({ + excluded: e[0] === "-", + viewname: e.substring(1) + })); +} +function getColor(data, def = [0, 0, 0]) { + let [r, g, b] = def; + if (!data) { + return { + r, + g, + b + }; + } + const color = data.split(",", 3).map(c => MathClamp(parseInt(c.trim(), 10), 0, 255)).map(c => isNaN(c) ? 0 : c); + if (color.length < 3) { + return { + r, + g, + b + }; + } + [r, g, b] = color; + return { + r, + g, + b + }; +} +function getBBox(data) { + const def = -1; + if (!data) { + return { + x: def, + y: def, + width: def, + height: def + }; + } + const bbox = data.split(",", 4).map(m => getMeasurement(m.trim(), "-1")); + if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) { + return { + x: def, + y: def, + width: def, + height: def + }; + } + const [x, y, width, height] = bbox; + return { + x, + y, + width, + height + }; +} +class HTMLResult { + static get FAILURE() { + return shadow(this, "FAILURE", new HTMLResult(false, null, null, null)); + } + static get EMPTY() { + return shadow(this, "EMPTY", new HTMLResult(true, null, null, null)); + } + constructor(success, html, bbox, breakNode) { + this.success = success; + this.html = html; + this.bbox = bbox; + this.breakNode = breakNode; + } + isBreak() { + return !!this.breakNode; + } + static breakNode(node) { + return new HTMLResult(false, null, null, node); + } + static success(html, bbox = null) { + return new HTMLResult(true, html, bbox, null); + } +} + +;// ./src/core/xfa/fonts.js + + + +class FontFinder { + constructor(pdfFonts) { + this.fonts = new Map(); + this.cache = new Map(); + this.warned = new Set(); + this.defaultFont = null; + this.add(pdfFonts); + } + add(pdfFonts, reallyMissingFonts = null) { + for (const pdfFont of pdfFonts) { + this.addPdfFont(pdfFont); + } + for (const pdfFont of this.fonts.values()) { + if (!pdfFont.regular) { + pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic; + } + } + if (!reallyMissingFonts || reallyMissingFonts.size === 0) { + return; + } + const myriad = this.fonts.get("PdfJS-Fallback-PdfJS-XFA"); + for (const missing of reallyMissingFonts) { + this.fonts.set(missing, myriad); + } + } + addPdfFont(pdfFont) { + const cssFontInfo = pdfFont.cssFontInfo; + const name = cssFontInfo.fontFamily; + let font = this.fonts.get(name); + if (!font) { + font = Object.create(null); + this.fonts.set(name, font); + if (!this.defaultFont) { + this.defaultFont = font; + } + } + let property = ""; + const fontWeight = parseFloat(cssFontInfo.fontWeight); + if (parseFloat(cssFontInfo.italicAngle) !== 0) { + property = fontWeight >= 700 ? "bolditalic" : "italic"; + } else if (fontWeight >= 700) { + property = "bold"; + } + if (!property) { + if (pdfFont.name.includes("Bold") || pdfFont.psName?.includes("Bold")) { + property = "bold"; + } + if (pdfFont.name.includes("Italic") || pdfFont.name.endsWith("It") || pdfFont.psName?.includes("Italic") || pdfFont.psName?.endsWith("It")) { + property += "italic"; + } + } + if (!property) { + property = "regular"; + } + font[property] = pdfFont; + } + getDefault() { + return this.defaultFont; + } + find(fontName, mustWarn = true) { + let font = this.fonts.get(fontName) || this.cache.get(fontName); + if (font) { + return font; + } + const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi; + let name = fontName.replaceAll(pattern, ""); + font = this.fonts.get(name); + if (font) { + this.cache.set(fontName, font); + return font; + } + name = name.toLowerCase(); + const maybe = []; + for (const [family, pdfFont] of this.fonts.entries()) { + if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + if (maybe.length === 0) { + for (const [, pdfFont] of this.fonts.entries()) { + if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length === 0) { + name = name.replaceAll(/psmt|mt/gi, ""); + for (const [family, pdfFont] of this.fonts.entries()) { + if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length === 0) { + for (const pdfFont of this.fonts.values()) { + if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length >= 1) { + if (maybe.length !== 1 && mustWarn) { + warn(`XFA - Too many choices to guess the correct font: ${fontName}`); + } + this.cache.set(fontName, maybe[0]); + return maybe[0]; + } + if (mustWarn && !this.warned.has(fontName)) { + this.warned.add(fontName); + warn(`XFA - Cannot find the font: ${fontName}`); + } + return null; + } +} +function selectFont(xfaFont, typeface) { + if (xfaFont.posture === "italic") { + if (xfaFont.weight === "bold") { + return typeface.bolditalic; + } + return typeface.italic; + } else if (xfaFont.weight === "bold") { + return typeface.bold; + } + return typeface.regular; +} +function fonts_getMetrics(xfaFont, real = false) { + let pdfFont = null; + if (xfaFont) { + const name = stripQuotes(xfaFont.typeface); + const typeface = xfaFont[$globalData].fontFinder.find(name); + pdfFont = selectFont(xfaFont, typeface); + } + if (!pdfFont) { + return { + lineHeight: 12, + lineGap: 2, + lineNoGap: 10 + }; + } + const size = xfaFont.size || 10; + const lineHeight = pdfFont.lineHeight ? Math.max(real ? 0 : 1.2, pdfFont.lineHeight) : 1.2; + const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; + return { + lineHeight: lineHeight * size, + lineGap: lineGap * size, + lineNoGap: Math.max(1, lineHeight - lineGap) * size + }; +} + +;// ./src/core/xfa/text.js + +const WIDTH_FACTOR = 1.02; +class text_FontInfo { + constructor(xfaFont, margin, lineHeight, fontFinder) { + this.lineHeight = lineHeight; + this.paraMargin = margin || { + top: 0, + bottom: 0, + left: 0, + right: 0 + }; + if (!xfaFont) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + return; + } + this.xfaFont = { + typeface: xfaFont.typeface, + posture: xfaFont.posture, + weight: xfaFont.weight, + size: xfaFont.size, + letterSpacing: xfaFont.letterSpacing + }; + const typeface = fontFinder.find(xfaFont.typeface); + if (!typeface) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + return; + } + this.pdfFont = selectFont(xfaFont, typeface); + if (!this.pdfFont) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + } + } + defaultFont(fontFinder) { + const font = fontFinder.find("Helvetica", false) || fontFinder.find("Myriad Pro", false) || fontFinder.find("Arial", false) || fontFinder.getDefault(); + if (font?.regular) { + const pdfFont = font.regular; + const info = pdfFont.cssFontInfo; + const xfaFont = { + typeface: info.fontFamily, + posture: "normal", + weight: "normal", + size: 10, + letterSpacing: 0 + }; + return [pdfFont, xfaFont]; + } + const xfaFont = { + typeface: "Courier", + posture: "normal", + weight: "normal", + size: 10, + letterSpacing: 0 + }; + return [null, xfaFont]; + } +} +class FontSelector { + constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) { + this.fontFinder = fontFinder; + this.stack = [new text_FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)]; + } + pushData(xfaFont, margin, lineHeight) { + const lastFont = this.stack.at(-1); + for (const name of ["typeface", "posture", "weight", "size", "letterSpacing"]) { + if (!xfaFont[name]) { + xfaFont[name] = lastFont.xfaFont[name]; + } + } + for (const name of ["top", "bottom", "left", "right"]) { + if (isNaN(margin[name])) { + margin[name] = lastFont.paraMargin[name]; + } + } + const fontInfo = new text_FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder); + if (!fontInfo.pdfFont) { + fontInfo.pdfFont = lastFont.pdfFont; + } + this.stack.push(fontInfo); + } + popFont() { + this.stack.pop(); + } + topFont() { + return this.stack.at(-1); + } +} +class TextMeasure { + constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) { + this.glyphs = []; + this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts); + this.extraHeight = 0; + } + pushData(xfaFont, margin, lineHeight) { + this.fontSelector.pushData(xfaFont, margin, lineHeight); + } + popFont(xfaFont) { + return this.fontSelector.popFont(); + } + addPara() { + const lastFont = this.fontSelector.topFont(); + this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom; + } + addString(str) { + if (!str) { + return; + } + const lastFont = this.fontSelector.topFont(); + const fontSize = lastFont.xfaFont.size; + if (lastFont.pdfFont) { + const letterSpacing = lastFont.xfaFont.letterSpacing; + const pdfFont = lastFont.pdfFont; + const fontLineHeight = pdfFont.lineHeight || 1.2; + const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize; + const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; + const noGap = fontLineHeight - lineGap; + const firstLineHeight = Math.max(1, noGap) * fontSize; + const scale = fontSize / 1000; + const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(" ")[0].width; + for (const line of str.split(/[\u2029\n]/)) { + const encodedLine = pdfFont.encodeString(line).join(""); + const glyphs = pdfFont.charsToGlyphs(encodedLine); + for (const glyph of glyphs) { + const width = glyph.width || fallbackWidth; + this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]); + } + this.glyphs.push([0, 0, 0, "\n", true]); + } + this.glyphs.pop(); + return; + } + for (const line of str.split(/[\u2029\n]/)) { + for (const char of line.split("")) { + this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char, false]); + } + this.glyphs.push([0, 0, 0, "\n", true]); + } + this.glyphs.pop(); + } + compute(maxWidth) { + let lastSpacePos = -1, + lastSpaceWidth = 0, + width = 0, + height = 0, + currentLineWidth = 0, + currentLineHeight = 0; + let isBroken = false; + let isFirstLine = true; + for (let i = 0, ii = this.glyphs.length; i < ii; i++) { + const [glyphWidth, lineHeight, firstLineHeight, char, isEOL] = this.glyphs[i]; + const isSpace = char === " "; + const glyphHeight = isFirstLine ? firstLineHeight : lineHeight; + if (isEOL) { + width = Math.max(width, currentLineWidth); + currentLineWidth = 0; + height += currentLineHeight; + currentLineHeight = glyphHeight; + lastSpacePos = -1; + lastSpaceWidth = 0; + isFirstLine = false; + continue; + } + if (isSpace) { + if (currentLineWidth + glyphWidth > maxWidth) { + width = Math.max(width, currentLineWidth); + currentLineWidth = 0; + height += currentLineHeight; + currentLineHeight = glyphHeight; + lastSpacePos = -1; + lastSpaceWidth = 0; + isBroken = true; + isFirstLine = false; + } else { + currentLineHeight = Math.max(glyphHeight, currentLineHeight); + lastSpaceWidth = currentLineWidth; + currentLineWidth += glyphWidth; + lastSpacePos = i; + } + continue; + } + if (currentLineWidth + glyphWidth > maxWidth) { + height += currentLineHeight; + currentLineHeight = glyphHeight; + if (lastSpacePos !== -1) { + i = lastSpacePos; + width = Math.max(width, lastSpaceWidth); + currentLineWidth = 0; + lastSpacePos = -1; + lastSpaceWidth = 0; + } else { + width = Math.max(width, currentLineWidth); + currentLineWidth = glyphWidth; + } + isBroken = true; + isFirstLine = false; + continue; + } + currentLineWidth += glyphWidth; + currentLineHeight = Math.max(glyphHeight, currentLineHeight); + } + width = Math.max(width, currentLineWidth); + height += currentLineHeight + this.extraHeight; + return { + width: WIDTH_FACTOR * width, + height, + isBroken + }; + } +} + +;// ./src/core/xfa/som.js + + +const namePattern = /^[^.[]+/; +const indexPattern = /^[^\]]+/; +const operators = { + dot: 0, + dotDot: 1, + dotHash: 2, + dotBracket: 3, + dotParen: 4 +}; +const shortcuts = new Map([["$data", (root, current) => root.datasets ? root.datasets.data : root], ["$record", (root, current) => (root.datasets ? root.datasets.data : root)[$getChildren]()[0]], ["$template", (root, current) => root.template], ["$connectionSet", (root, current) => root.connectionSet], ["$form", (root, current) => root.form], ["$layout", (root, current) => root.layout], ["$host", (root, current) => root.host], ["$dataWindow", (root, current) => root.dataWindow], ["$event", (root, current) => root.event], ["!", (root, current) => root.datasets], ["$xfa", (root, current) => root], ["xfa", (root, current) => root], ["$", (root, current) => current]]); +const somCache = new WeakMap(); +function parseIndex(index) { + index = index.trim(); + if (index === "*") { + return Infinity; + } + return parseInt(index, 10) || 0; +} +function parseExpression(expr, dotDotAllowed, noExpr = true) { + let match = expr.match(namePattern); + if (!match) { + return null; + } + let [name] = match; + const parsed = [{ + name, + cacheName: "." + name, + index: 0, + js: null, + formCalc: null, + operator: operators.dot + }]; + let pos = name.length; + while (pos < expr.length) { + const spos = pos; + const char = expr.charAt(pos++); + if (char === "[") { + match = expr.slice(pos).match(indexPattern); + if (!match) { + warn("XFA - Invalid index in SOM expression"); + return null; + } + parsed.at(-1).index = parseIndex(match[0]); + pos += match[0].length + 1; + continue; + } + let operator; + switch (expr.charAt(pos)) { + case ".": + if (!dotDotAllowed) { + return null; + } + pos++; + operator = operators.dotDot; + break; + case "#": + pos++; + operator = operators.dotHash; + break; + case "[": + if (noExpr) { + warn("XFA - SOM expression contains a FormCalc subexpression which is not supported for now."); + return null; + } + operator = operators.dotBracket; + break; + case "(": + if (noExpr) { + warn("XFA - SOM expression contains a JavaScript subexpression which is not supported for now."); + return null; + } + operator = operators.dotParen; + break; + default: + operator = operators.dot; + break; + } + match = expr.slice(pos).match(namePattern); + if (!match) { + break; + } + [name] = match; + pos += name.length; + parsed.push({ + name, + cacheName: expr.slice(spos, pos), + operator, + index: 0, + js: null, + formCalc: null + }); + } + return parsed; +} +function searchNode(root, container, expr, dotDotAllowed = true, useCache = true) { + const parsed = parseExpression(expr, dotDotAllowed); + if (!parsed) { + return null; + } + const fn = shortcuts.get(parsed[0].name); + let i = 0; + let isQualified; + if (fn) { + isQualified = true; + root = [fn(root, container)]; + i = 1; + } else { + isQualified = container === null; + root = [container || root]; + } + for (let ii = parsed.length; i < ii; i++) { + const { + name, + cacheName, + operator, + index + } = parsed[i]; + const nodes = []; + for (const node of root) { + if (!node.isXFAObject) { + continue; + } + let children, cached; + if (useCache) { + cached = somCache.get(node); + if (!cached) { + cached = new Map(); + somCache.set(node, cached); + } + children = cached.get(cacheName); + } + if (!children) { + switch (operator) { + case operators.dot: + children = node[$getChildrenByName](name, false); + break; + case operators.dotDot: + children = node[$getChildrenByName](name, true); + break; + case operators.dotHash: + children = node[$getChildrenByClass](name); + children = children.isXFAObjectArray ? children.children : [children]; + break; + default: + break; + } + if (useCache) { + cached.set(cacheName, children); + } + } + if (children.length > 0) { + nodes.push(children); + } + } + if (nodes.length === 0 && !isQualified && i === 0) { + const parent = container[$getParent](); + container = parent; + if (!container) { + return null; + } + i = -1; + root = [container]; + continue; + } + root = isFinite(index) ? nodes.filter(node => index < node.length).map(node => node[index]) : nodes.flat(); + } + if (root.length === 0) { + return null; + } + return root; +} +function createDataNode(root, container, expr) { + const parsed = parseExpression(expr); + if (!parsed) { + return null; + } + if (parsed.some(x => x.operator === operators.dotDot)) { + return null; + } + const fn = shortcuts.get(parsed[0].name); + let i = 0; + if (fn) { + root = fn(root, container); + i = 1; + } else { + root = container || root; + } + for (let ii = parsed.length; i < ii; i++) { + const { + name, + operator, + index + } = parsed[i]; + if (!isFinite(index)) { + parsed[i].index = 0; + return root.createNodes(parsed.slice(i)); + } + let children; + switch (operator) { + case operators.dot: + children = root[$getChildrenByName](name, false); + break; + case operators.dotDot: + children = root[$getChildrenByName](name, true); + break; + case operators.dotHash: + children = root[$getChildrenByClass](name); + children = children.isXFAObjectArray ? children.children : [children]; + break; + default: + break; + } + if (children.length === 0) { + return root.createNodes(parsed.slice(i)); + } + if (index < children.length) { + const child = children[index]; + if (!child.isXFAObject) { + warn(`XFA - Cannot create a node.`); + return null; + } + root = child; + } else { + parsed[i].index = index - children.length; + return root.createNodes(parsed.slice(i)); + } + } + return null; +} + +;// ./src/core/xfa/xfa_object.js + + + + + + +const _applyPrototype = Symbol(); +const _attributes = Symbol(); +const _attributeNames = Symbol(); +const _children = Symbol("_children"); +const _cloneAttribute = Symbol(); +const _dataValue = Symbol(); +const _defaultValue = Symbol(); +const _filteredChildrenGenerator = Symbol(); +const _getPrototype = Symbol(); +const _getUnsetAttributes = Symbol(); +const _hasChildren = Symbol(); +const _max = Symbol(); +const _options = Symbol(); +const _parent = Symbol("parent"); +const _resolvePrototypesHelper = Symbol(); +const _setAttributes = Symbol(); +const _validator = Symbol(); +let uid = 0; +const NS_DATASETS = NamespaceIds.datasets.id; +class XFAObject { + constructor(nsId, name, hasChildren = false) { + this[$namespaceId] = nsId; + this[$nodeName] = name; + this[_hasChildren] = hasChildren; + this[_parent] = null; + this[_children] = []; + this[$uid] = `${name}${uid++}`; + this[$globalData] = null; + } + get isXFAObject() { + return true; + } + get isXFAObjectArray() { + return false; + } + createNodes(path) { + let root = this, + node = null; + for (const { + name, + index + } of path) { + for (let i = 0, ii = isFinite(index) ? index : 0; i <= ii; i++) { + const nsId = root[$namespaceId] === NS_DATASETS ? -1 : root[$namespaceId]; + node = new XmlObject(nsId, name); + root[$appendChild](node); + } + root = node; + } + return node; + } + [$onChild](child) { + if (!this[_hasChildren] || !this[$onChildCheck](child)) { + return false; + } + const name = child[$nodeName]; + const node = this[name]; + if (node instanceof XFAObjectArray) { + if (node.push(child)) { + this[$appendChild](child); + return true; + } + } else { + if (node !== null) { + this[$removeChild](node); + } + this[name] = child; + this[$appendChild](child); + return true; + } + let id = ""; + if (this.id) { + id = ` (id: ${this.id})`; + } else if (this.name) { + id = ` (name: ${this.name} ${this.h.value})`; + } + warn(`XFA - node "${this[$nodeName]}"${id} has already enough "${name}"!`); + return false; + } + [$onChildCheck](child) { + return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId]; + } + [$isNsAgnostic]() { + return false; + } + [$acceptWhitespace]() { + return false; + } + [$isCDATAXml]() { + return false; + } + [$isBindable]() { + return false; + } + [$popPara]() { + if (this.para) { + this[$getTemplateRoot]()[$extra].paraStack.pop(); + } + } + [$pushPara]() { + this[$getTemplateRoot]()[$extra].paraStack.push(this.para); + } + [$setId](ids) { + if (this.id && this[$namespaceId] === NamespaceIds.template.id) { + ids.set(this.id, this); + } + } + [$getTemplateRoot]() { + return this[$globalData].template; + } + [$isSplittable]() { + return false; + } + [$isThereMoreWidth]() { + return false; + } + [$appendChild](child) { + child[_parent] = this; + this[_children].push(child); + if (!child[$globalData] && this[$globalData]) { + child[$globalData] = this[$globalData]; + } + } + [$removeChild](child) { + const i = this[_children].indexOf(child); + this[_children].splice(i, 1); + } + [$hasSettableValue]() { + return this.hasOwnProperty("value"); + } + [$setValue](_) {} + [$onText](_) {} + [$finalize]() {} + [$clean](builder) { + delete this[_hasChildren]; + if (this[$cleanup]) { + builder.clean(this[$cleanup]); + delete this[$cleanup]; + } + } + [$indexOf](child) { + return this[_children].indexOf(child); + } + [$insertAt](i, child) { + child[_parent] = this; + this[_children].splice(i, 0, child); + if (!child[$globalData] && this[$globalData]) { + child[$globalData] = this[$globalData]; + } + } + [$isTransparent]() { + return !this.name; + } + [$lastAttribute]() { + return ""; + } + [$text]() { + if (this[_children].length === 0) { + return this[$content]; + } + return this[_children].map(c => c[$text]()).join(""); + } + get [_attributeNames]() { + const proto = Object.getPrototypeOf(this); + if (!proto._attributes) { + const attributes = proto._attributes = new Set(); + for (const name of Object.getOwnPropertyNames(this)) { + if (this[name] === null || this[name] instanceof XFAObject || this[name] instanceof XFAObjectArray) { + break; + } + attributes.add(name); + } + } + return shadow(this, _attributeNames, proto._attributes); + } + [$isDescendent](parent) { + let node = this; + while (node) { + if (node === parent) { + return true; + } + node = node[$getParent](); + } + return false; + } + [$getParent]() { + return this[_parent]; + } + [$getSubformParent]() { + return this[$getParent](); + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[name]; + } + [$dump]() { + const dumped = Object.create(null); + if (this[$content]) { + dumped.$content = this[$content]; + } + for (const name of Object.getOwnPropertyNames(this)) { + const value = this[name]; + if (value === null) { + continue; + } + if (value instanceof XFAObject) { + dumped[name] = value[$dump](); + } else if (value instanceof XFAObjectArray) { + if (!value.isEmpty()) { + dumped[name] = value.dump(); + } + } else { + dumped[name] = value; + } + } + return dumped; + } + [$toStyle]() { + return null; + } + [$toHTML]() { + return HTMLResult.EMPTY; + } + *[$getContainedChildren]() { + for (const node of this[$getChildren]()) { + yield node; + } + } + *[_filteredChildrenGenerator](filter, include) { + for (const node of this[$getContainedChildren]()) { + if (!filter || include === filter.has(node[$nodeName])) { + const availableSpace = this[$getAvailableSpace](); + const res = node[$toHTML](availableSpace); + if (!res.success) { + this[$extra].failingNode = node; + } + yield res; + } + } + } + [$flushHTML]() { + return null; + } + [$addHTML](html, bbox) { + this[$extra].children.push(html); + } + [$getAvailableSpace]() {} + [$childrenToHTML]({ + filter = null, + include = true + }) { + if (!this[$extra].generator) { + this[$extra].generator = this[_filteredChildrenGenerator](filter, include); + } else { + const availableSpace = this[$getAvailableSpace](); + const res = this[$extra].failingNode[$toHTML](availableSpace); + if (!res.success) { + return res; + } + if (res.html) { + this[$addHTML](res.html, res.bbox); + } + delete this[$extra].failingNode; + } + while (true) { + const gen = this[$extra].generator.next(); + if (gen.done) { + break; + } + const res = gen.value; + if (!res.success) { + return res; + } + if (res.html) { + this[$addHTML](res.html, res.bbox); + } + } + this[$extra].generator = null; + return HTMLResult.EMPTY; + } + [$setSetAttributes](attributes) { + this[_setAttributes] = new Set(Object.keys(attributes)); + } + [_getUnsetAttributes](protoAttributes) { + const allAttr = this[_attributeNames]; + const setAttr = this[_setAttributes]; + return [...protoAttributes].filter(x => allAttr.has(x) && !setAttr.has(x)); + } + [$resolvePrototypes](ids, ancestors = new Set()) { + for (const child of this[_children]) { + child[_resolvePrototypesHelper](ids, ancestors); + } + } + [_resolvePrototypesHelper](ids, ancestors) { + const proto = this[_getPrototype](ids, ancestors); + if (proto) { + this[_applyPrototype](proto, ids, ancestors); + } else { + this[$resolvePrototypes](ids, ancestors); + } + } + [_getPrototype](ids, ancestors) { + const { + use, + usehref + } = this; + if (!use && !usehref) { + return null; + } + let proto = null; + let somExpression = null; + let id = null; + let ref = use; + if (usehref) { + ref = usehref; + if (usehref.startsWith("#som(") && usehref.endsWith(")")) { + somExpression = usehref.slice("#som(".length, -1); + } else if (usehref.startsWith(".#som(") && usehref.endsWith(")")) { + somExpression = usehref.slice(".#som(".length, -1); + } else if (usehref.startsWith("#")) { + id = usehref.slice(1); + } else if (usehref.startsWith(".#")) { + id = usehref.slice(2); + } + } else if (use.startsWith("#")) { + id = use.slice(1); + } else { + somExpression = use; + } + this.use = this.usehref = ""; + if (id) { + proto = ids.get(id); + } else { + proto = searchNode(ids.get($root), this, somExpression, true, false); + if (proto) { + proto = proto[0]; + } + } + if (!proto) { + warn(`XFA - Invalid prototype reference: ${ref}.`); + return null; + } + if (proto[$nodeName] !== this[$nodeName]) { + warn(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`); + return null; + } + if (ancestors.has(proto)) { + warn(`XFA - Cycle detected in prototypes use.`); + return null; + } + ancestors.add(proto); + const protoProto = proto[_getPrototype](ids, ancestors); + if (protoProto) { + proto[_applyPrototype](protoProto, ids, ancestors); + } + proto[$resolvePrototypes](ids, ancestors); + ancestors.delete(proto); + return proto; + } + [_applyPrototype](proto, ids, ancestors) { + if (ancestors.has(proto)) { + warn(`XFA - Cycle detected in prototypes use.`); + return; + } + if (!this[$content] && proto[$content]) { + this[$content] = proto[$content]; + } + const newAncestors = new Set(ancestors); + newAncestors.add(proto); + for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) { + this[unsetAttrName] = proto[unsetAttrName]; + if (this[_setAttributes]) { + this[_setAttributes].add(unsetAttrName); + } + } + for (const name of Object.getOwnPropertyNames(this)) { + if (this[_attributeNames].has(name)) { + continue; + } + const value = this[name]; + const protoValue = proto[name]; + if (value instanceof XFAObjectArray) { + for (const child of value[_children]) { + child[_resolvePrototypesHelper](ids, ancestors); + } + for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) { + const child = proto[_children][i][$clone](); + if (value.push(child)) { + child[_parent] = this; + this[_children].push(child); + child[_resolvePrototypesHelper](ids, ancestors); + } else { + break; + } + } + continue; + } + if (value !== null) { + value[$resolvePrototypes](ids, ancestors); + if (protoValue) { + value[_applyPrototype](protoValue, ids, ancestors); + } + continue; + } + if (protoValue !== null) { + const child = protoValue[$clone](); + child[_parent] = this; + this[name] = child; + this[_children].push(child); + child[_resolvePrototypesHelper](ids, ancestors); + } + } + } + static [_cloneAttribute](obj) { + if (Array.isArray(obj)) { + return obj.map(x => XFAObject[_cloneAttribute](x)); + } + if (typeof obj === "object" && obj !== null) { + return Object.assign({}, obj); + } + return obj; + } + [$clone]() { + const clone = Object.create(Object.getPrototypeOf(this)); + for (const $symbol of Object.getOwnPropertySymbols(this)) { + try { + clone[$symbol] = this[$symbol]; + } catch { + shadow(clone, $symbol, this[$symbol]); + } + } + clone[$uid] = `${clone[$nodeName]}${uid++}`; + clone[_children] = []; + for (const name of Object.getOwnPropertyNames(this)) { + if (this[_attributeNames].has(name)) { + clone[name] = XFAObject[_cloneAttribute](this[name]); + continue; + } + const value = this[name]; + clone[name] = value instanceof XFAObjectArray ? new XFAObjectArray(value[_max]) : null; + } + for (const child of this[_children]) { + const name = child[$nodeName]; + const clonedChild = child[$clone](); + clone[_children].push(clonedChild); + clonedChild[_parent] = clone; + if (clone[name] === null) { + clone[name] = clonedChild; + } else { + clone[name][_children].push(clonedChild); + } + } + return clone; + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[_children].filter(c => c[$nodeName] === name); + } + [$getChildrenByClass](name) { + return this[name]; + } + [$getChildrenByName](name, allTransparent, first = true) { + return Array.from(this[$getChildrenByNameIt](name, allTransparent, first)); + } + *[$getChildrenByNameIt](name, allTransparent, first = true) { + if (name === "parent") { + yield this[_parent]; + return; + } + for (const child of this[_children]) { + if (child[$nodeName] === name) { + yield child; + } + if (child.name === name) { + yield child; + } + if (allTransparent || child[$isTransparent]()) { + yield* child[$getChildrenByNameIt](name, allTransparent, false); + } + } + if (first && this[_attributeNames].has(name)) { + yield new XFAAttribute(this, name, this[name]); + } + } +} +class XFAObjectArray { + constructor(max = Infinity) { + this[_max] = max; + this[_children] = []; + } + get isXFAObject() { + return false; + } + get isXFAObjectArray() { + return true; + } + push(child) { + const len = this[_children].length; + if (len <= this[_max]) { + this[_children].push(child); + return true; + } + warn(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`); + return false; + } + isEmpty() { + return this[_children].length === 0; + } + dump() { + return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map(x => x[$dump]()); + } + [$clone]() { + const clone = new XFAObjectArray(this[_max]); + clone[_children] = this[_children].map(c => c[$clone]()); + return clone; + } + get children() { + return this[_children]; + } + clear() { + this[_children].length = 0; + } +} +class XFAAttribute { + constructor(node, name, value) { + this[_parent] = node; + this[$nodeName] = name; + this[$content] = value; + this[$consumed] = false; + this[$uid] = `attribute${uid++}`; + } + [$getParent]() { + return this[_parent]; + } + [$isDataValue]() { + return true; + } + [$getDataValue]() { + return this[$content].trim(); + } + [$setValue](value) { + value = value.value || ""; + this[$content] = value.toString(); + } + [$text]() { + return this[$content]; + } + [$isDescendent](parent) { + return this[_parent] === parent || this[_parent][$isDescendent](parent); + } +} +class XmlObject extends XFAObject { + constructor(nsId, name, attributes = {}) { + super(nsId, name); + this[$content] = ""; + this[_dataValue] = null; + if (name !== "#text") { + const map = new Map(); + this[_attributes] = map; + for (const [attrName, value] of Object.entries(attributes)) { + map.set(attrName, new XFAAttribute(this, attrName, value)); + } + if (attributes.hasOwnProperty($nsAttributes)) { + const dataNode = attributes[$nsAttributes].xfa.dataNode; + if (dataNode !== undefined) { + if (dataNode === "dataGroup") { + this[_dataValue] = false; + } else if (dataNode === "dataValue") { + this[_dataValue] = true; + } + } + } + } + this[$consumed] = false; + } + [$toString](buf) { + const tagName = this[$nodeName]; + if (tagName === "#text") { + buf.push(encodeToXmlString(this[$content])); + return; + } + const utf8TagName = utf8StringToString(tagName); + const prefix = this[$namespaceId] === NS_DATASETS ? "xfa:" : ""; + buf.push(`<${prefix}${utf8TagName}`); + for (const [name, value] of this[_attributes].entries()) { + const utf8Name = utf8StringToString(name); + buf.push(` ${utf8Name}="${encodeToXmlString(value[$content])}"`); + } + if (this[_dataValue] !== null) { + if (this[_dataValue]) { + buf.push(` xfa:dataNode="dataValue"`); + } else { + buf.push(` xfa:dataNode="dataGroup"`); + } + } + if (!this[$content] && this[_children].length === 0) { + buf.push("/>"); + return; + } + buf.push(">"); + if (this[$content]) { + if (typeof this[$content] === "string") { + buf.push(encodeToXmlString(this[$content])); + } else { + this[$content][$toString](buf); + } + } else { + for (const child of this[_children]) { + child[$toString](buf); + } + } + buf.push(``); + } + [$onChild](child) { + if (this[$content]) { + const node = new XmlObject(this[$namespaceId], "#text"); + this[$appendChild](node); + node[$content] = this[$content]; + this[$content] = ""; + } + this[$appendChild](child); + return true; + } + [$onText](str) { + this[$content] += str; + } + [$finalize]() { + if (this[$content] && this[_children].length > 0) { + const node = new XmlObject(this[$namespaceId], "#text"); + this[$appendChild](node); + node[$content] = this[$content]; + delete this[$content]; + } + } + [$toHTML]() { + if (this[$nodeName] === "#text") { + return HTMLResult.success({ + name: "#text", + value: this[$content] + }); + } + return HTMLResult.EMPTY; + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[_children].filter(c => c[$nodeName] === name); + } + [$getAttributes]() { + return this[_attributes]; + } + [$getChildrenByClass](name) { + const value = this[_attributes].get(name); + if (value !== undefined) { + return value; + } + return this[$getChildren](name); + } + *[$getChildrenByNameIt](name, allTransparent) { + const value = this[_attributes].get(name); + if (value) { + yield value; + } + for (const child of this[_children]) { + if (child[$nodeName] === name) { + yield child; + } + if (allTransparent) { + yield* child[$getChildrenByNameIt](name, allTransparent); + } + } + } + *[$getAttributeIt](name, skipConsumed) { + const value = this[_attributes].get(name); + if (value && (!skipConsumed || !value[$consumed])) { + yield value; + } + for (const child of this[_children]) { + yield* child[$getAttributeIt](name, skipConsumed); + } + } + *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) { + for (const child of this[_children]) { + if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) { + yield child; + } + if (allTransparent) { + yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed); + } + } + } + [$isDataValue]() { + if (this[_dataValue] === null) { + return this[_children].length === 0 || this[_children][0][$namespaceId] === NamespaceIds.xhtml.id; + } + return this[_dataValue]; + } + [$getDataValue]() { + if (this[_dataValue] === null) { + if (this[_children].length === 0) { + return this[$content].trim(); + } + if (this[_children][0][$namespaceId] === NamespaceIds.xhtml.id) { + return this[_children][0][$text]().trim(); + } + return null; + } + return this[$content].trim(); + } + [$setValue](value) { + value = value.value || ""; + this[$content] = value.toString(); + } + [$dump](hasNS = false) { + const dumped = Object.create(null); + if (hasNS) { + dumped.$ns = this[$namespaceId]; + } + if (this[$content]) { + dumped.$content = this[$content]; + } + dumped.$name = this[$nodeName]; + dumped.children = []; + for (const child of this[_children]) { + dumped.children.push(child[$dump](hasNS)); + } + dumped.attributes = Object.create(null); + for (const [name, value] of this[_attributes]) { + dumped.attributes[name] = value[$content]; + } + return dumped; + } +} +class ContentObject extends XFAObject { + constructor(nsId, name) { + super(nsId, name); + this[$content] = ""; + } + [$onText](text) { + this[$content] += text; + } + [$finalize]() {} +} +class OptionObject extends ContentObject { + constructor(nsId, name, options) { + super(nsId, name); + this[_options] = options; + } + [$finalize]() { + this[$content] = getKeyword({ + data: this[$content], + defaultValue: this[_options][0], + validate: k => this[_options].includes(k) + }); + } + [$clean](builder) { + super[$clean](builder); + delete this[_options]; + } +} +class StringObject extends ContentObject { + [$finalize]() { + this[$content] = this[$content].trim(); + } +} +class IntegerObject extends ContentObject { + constructor(nsId, name, defaultValue, validator) { + super(nsId, name); + this[_defaultValue] = defaultValue; + this[_validator] = validator; + } + [$finalize]() { + this[$content] = getInteger({ + data: this[$content], + defaultValue: this[_defaultValue], + validate: this[_validator] + }); + } + [$clean](builder) { + super[$clean](builder); + delete this[_defaultValue]; + delete this[_validator]; + } +} +class Option01 extends IntegerObject { + constructor(nsId, name) { + super(nsId, name, 0, n => n === 1); + } +} +class Option10 extends IntegerObject { + constructor(nsId, name) { + super(nsId, name, 1, n => n === 0); + } +} + +;// ./src/core/xfa/html_utils.js + + + + + + +function measureToString(m) { + if (typeof m === "string") { + return "0px"; + } + return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`; +} +const converters = { + anchorType(node, style) { + const parent = node[$getSubformParent](); + if (!parent || parent.layout && parent.layout !== "position") { + return; + } + if (!("transform" in style)) { + style.transform = ""; + } + switch (node.anchorType) { + case "bottomCenter": + style.transform += "translate(-50%, -100%)"; + break; + case "bottomLeft": + style.transform += "translate(0,-100%)"; + break; + case "bottomRight": + style.transform += "translate(-100%,-100%)"; + break; + case "middleCenter": + style.transform += "translate(-50%,-50%)"; + break; + case "middleLeft": + style.transform += "translate(0,-50%)"; + break; + case "middleRight": + style.transform += "translate(-100%,-50%)"; + break; + case "topCenter": + style.transform += "translate(-50%,0)"; + break; + case "topRight": + style.transform += "translate(-100%,0)"; + break; + } + }, + dimensions(node, style) { + const parent = node[$getSubformParent](); + let width = node.w; + const height = node.h; + if (parent.layout?.includes("row")) { + const extra = parent[$extra]; + const colSpan = node.colSpan; + let w; + if (colSpan === -1) { + w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn)); + extra.currentColumn = 0; + } else { + w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan)); + extra.currentColumn = (extra.currentColumn + node.colSpan) % extra.columnWidths.length; + } + if (!isNaN(w)) { + width = node.w = w; + } + } + style.width = width !== "" ? measureToString(width) : "auto"; + style.height = height !== "" ? measureToString(height) : "auto"; + }, + position(node, style) { + const parent = node[$getSubformParent](); + if (parent?.layout && parent.layout !== "position") { + return; + } + style.position = "absolute"; + style.left = measureToString(node.x); + style.top = measureToString(node.y); + }, + rotate(node, style) { + if (node.rotate) { + if (!("transform" in style)) { + style.transform = ""; + } + style.transform += `rotate(-${node.rotate}deg)`; + style.transformOrigin = "top left"; + } + }, + presence(node, style) { + switch (node.presence) { + case "invisible": + style.visibility = "hidden"; + break; + case "hidden": + case "inactive": + style.display = "none"; + break; + } + }, + hAlign(node, style) { + if (node[$nodeName] === "para") { + switch (node.hAlign) { + case "justifyAll": + style.textAlign = "justify-all"; + break; + case "radix": + style.textAlign = "left"; + break; + default: + style.textAlign = node.hAlign; + } + } else { + switch (node.hAlign) { + case "left": + style.alignSelf = "start"; + break; + case "center": + style.alignSelf = "center"; + break; + case "right": + style.alignSelf = "end"; + break; + } + } + }, + margin(node, style) { + if (node.margin) { + style.margin = node.margin[$toStyle]().margin; + } + } +}; +function setMinMaxDimensions(node, style) { + const parent = node[$getSubformParent](); + if (parent.layout === "position") { + if (node.minW > 0) { + style.minWidth = measureToString(node.minW); + } + if (node.maxW > 0) { + style.maxWidth = measureToString(node.maxW); + } + if (node.minH > 0) { + style.minHeight = measureToString(node.minH); + } + if (node.maxH > 0) { + style.maxHeight = measureToString(node.maxH); + } + } +} +function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) { + const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder); + if (typeof text === "string") { + measure.addString(text); + } else { + text[$pushGlyphs](measure); + } + return measure.compute(width); +} +function layoutNode(node, availableSpace) { + let height = null; + let width = null; + let isBroken = false; + if ((!node.w || !node.h) && node.value) { + let marginH = 0; + let marginV = 0; + if (node.margin) { + marginH = node.margin.leftInset + node.margin.rightInset; + marginV = node.margin.topInset + node.margin.bottomInset; + } + let lineHeight = null; + let margin = null; + if (node.para) { + margin = Object.create(null); + lineHeight = node.para.lineHeight === "" ? null : node.para.lineHeight; + margin.top = node.para.spaceAbove === "" ? 0 : node.para.spaceAbove; + margin.bottom = node.para.spaceBelow === "" ? 0 : node.para.spaceBelow; + margin.left = node.para.marginLeft === "" ? 0 : node.para.marginLeft; + margin.right = node.para.marginRight === "" ? 0 : node.para.marginRight; + } + let font = node.font; + if (!font) { + const root = node[$getTemplateRoot](); + let parent = node[$getParent](); + while (parent && parent !== root) { + if (parent.font) { + font = parent.font; + break; + } + parent = parent[$getParent](); + } + } + const maxWidth = (node.w || availableSpace.width) - marginH; + const fontFinder = node[$globalData].fontFinder; + if (node.value.exData && node.value.exData[$content] && node.value.exData.contentType === "text/html") { + const res = layoutText(node.value.exData[$content], font, margin, lineHeight, fontFinder, maxWidth); + width = res.width; + height = res.height; + isBroken = res.isBroken; + } else { + const text = node.value[$text](); + if (text) { + const res = layoutText(text, font, margin, lineHeight, fontFinder, maxWidth); + width = res.width; + height = res.height; + isBroken = res.isBroken; + } + } + if (width !== null && !node.w) { + width += marginH; + } + if (height !== null && !node.h) { + height += marginV; + } + } + return { + w: width, + h: height, + isBroken + }; +} +function computeBbox(node, html, availableSpace) { + let bbox; + if (node.w !== "" && node.h !== "") { + bbox = [node.x, node.y, node.w, node.h]; + } else { + if (!availableSpace) { + return null; + } + let width = node.w; + if (width === "") { + if (node.maxW === 0) { + const parent = node[$getSubformParent](); + width = parent.layout === "position" && parent.w !== "" ? 0 : node.minW; + } else { + width = Math.min(node.maxW, availableSpace.width); + } + html.attributes.style.width = measureToString(width); + } + let height = node.h; + if (height === "") { + if (node.maxH === 0) { + const parent = node[$getSubformParent](); + height = parent.layout === "position" && parent.h !== "" ? 0 : node.minH; + } else { + height = Math.min(node.maxH, availableSpace.height); + } + html.attributes.style.height = measureToString(height); + } + bbox = [node.x, node.y, width, height]; + } + return bbox; +} +function fixDimensions(node) { + const parent = node[$getSubformParent](); + if (parent.layout?.includes("row")) { + const extra = parent[$extra]; + const colSpan = node.colSpan; + let width; + if (colSpan === -1) { + width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn)); + } else { + width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan)); + } + if (!isNaN(width)) { + node.w = width; + } + } + if (parent.layout && parent.layout !== "position") { + node.x = node.y = 0; + } + if (node.layout === "table") { + if (node.w === "" && Array.isArray(node.columnWidths)) { + node.w = Math.sumPrecise(node.columnWidths); + } + } +} +function layoutClass(node) { + switch (node.layout) { + case "position": + return "xfaPosition"; + case "lr-tb": + return "xfaLrTb"; + case "rl-row": + return "xfaRlRow"; + case "rl-tb": + return "xfaRlTb"; + case "row": + return "xfaRow"; + case "table": + return "xfaTable"; + case "tb": + return "xfaTb"; + default: + return "xfaPosition"; + } +} +function toStyle(node, ...names) { + const style = Object.create(null); + for (const name of names) { + const value = node[name]; + if (value === null) { + continue; + } + if (converters.hasOwnProperty(name)) { + converters[name](node, style); + continue; + } + if (value instanceof XFAObject) { + const newStyle = value[$toStyle](); + if (newStyle) { + Object.assign(style, newStyle); + } else { + warn(`(DEBUG) - XFA - style for ${name} not implemented yet`); + } + } + } + return style; +} +function createWrapper(node, html) { + const { + attributes + } = html; + const { + style + } = attributes; + const wrapper = { + name: "div", + attributes: { + class: ["xfaWrapper"], + style: Object.create(null) + }, + children: [] + }; + attributes.class.push("xfaWrapped"); + if (node.border) { + const { + widths, + insets + } = node.border[$extra]; + let width, height; + let top = insets[0]; + let left = insets[3]; + const insetsH = insets[0] + insets[2]; + const insetsW = insets[1] + insets[3]; + switch (node.border.hand) { + case "even": + top -= widths[0] / 2; + left -= widths[3] / 2; + width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`; + height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`; + break; + case "left": + top -= widths[0]; + left -= widths[3]; + width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`; + height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`; + break; + case "right": + width = insetsW ? `calc(100% - ${insetsW}px)` : "100%"; + height = insetsH ? `calc(100% - ${insetsH}px)` : "100%"; + break; + } + const classNames = ["xfaBorder"]; + if (isPrintOnly(node.border)) { + classNames.push("xfaPrintOnly"); + } + const border = { + name: "div", + attributes: { + class: classNames, + style: { + top: `${top}px`, + left: `${left}px`, + width, + height + } + }, + children: [] + }; + for (const key of ["border", "borderWidth", "borderColor", "borderRadius", "borderStyle"]) { + if (style[key] !== undefined) { + border.attributes.style[key] = style[key]; + delete style[key]; + } + } + wrapper.children.push(border, html); + } else { + wrapper.children.push(html); + } + for (const key of ["background", "backgroundClip", "top", "left", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "transform", "transformOrigin", "visibility"]) { + if (style[key] !== undefined) { + wrapper.attributes.style[key] = style[key]; + delete style[key]; + } + } + wrapper.attributes.style.position = style.position === "absolute" ? "absolute" : "relative"; + delete style.position; + if (style.alignSelf) { + wrapper.attributes.style.alignSelf = style.alignSelf; + delete style.alignSelf; + } + return wrapper; +} +function fixTextIndent(styles) { + const indent = getMeasurement(styles.textIndent, "0px"); + if (indent >= 0) { + return; + } + const align = styles.textAlign === "right" ? "right" : "left"; + const name = "padding" + (align === "left" ? "Left" : "Right"); + const padding = getMeasurement(styles[name], "0px"); + styles[name] = `${padding - indent}px`; +} +function setAccess(node, classNames) { + switch (node.access) { + case "nonInteractive": + classNames.push("xfaNonInteractive"); + break; + case "readOnly": + classNames.push("xfaReadOnly"); + break; + case "protected": + classNames.push("xfaDisabled"); + break; + } +} +function isPrintOnly(node) { + return node.relevant.length > 0 && !node.relevant[0].excluded && node.relevant[0].viewname === "print"; +} +function getCurrentPara(node) { + const stack = node[$getTemplateRoot]()[$extra].paraStack; + return stack.length ? stack.at(-1) : null; +} +function setPara(node, nodeStyle, value) { + if (value.attributes.class?.includes("xfaRich")) { + if (nodeStyle) { + if (node.h === "") { + nodeStyle.height = "auto"; + } + if (node.w === "") { + nodeStyle.width = "auto"; + } + } + const para = getCurrentPara(node); + if (para) { + const valueStyle = value.attributes.style; + valueStyle.display = "flex"; + valueStyle.flexDirection = "column"; + switch (para.vAlign) { + case "top": + valueStyle.justifyContent = "start"; + break; + case "bottom": + valueStyle.justifyContent = "end"; + break; + case "middle": + valueStyle.justifyContent = "center"; + break; + } + const paraStyle = para[$toStyle](); + for (const [key, val] of Object.entries(paraStyle)) { + if (!(key in valueStyle)) { + valueStyle[key] = val; + } + } + } + } +} +function setFontFamily(xfaFont, node, fontFinder, style) { + if (!fontFinder) { + delete style.fontFamily; + return; + } + const name = stripQuotes(xfaFont.typeface); + style.fontFamily = `"${name}"`; + const typeface = fontFinder.find(name); + if (typeface) { + const { + fontFamily + } = typeface.regular.cssFontInfo; + if (fontFamily !== name) { + style.fontFamily = `"${fontFamily}"`; + } + const para = getCurrentPara(node); + if (para && para.lineHeight !== "") { + return; + } + if (style.lineHeight) { + return; + } + const pdfFont = selectFont(xfaFont, typeface); + if (pdfFont) { + style.lineHeight = Math.max(1.2, pdfFont.lineHeight); + } + } +} +function fixURL(str) { + const absoluteUrl = createValidAbsoluteUrl(str, null, { + addDefaultProtocol: true, + tryConvertEncoding: true + }); + return absoluteUrl ? absoluteUrl.href : null; +} + +;// ./src/core/xfa/layout.js + + + +function createLine(node, children) { + return { + name: "div", + attributes: { + class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"] + }, + children + }; +} +function flushHTML(node) { + if (!node[$extra]) { + return null; + } + const attributes = node[$extra].attributes; + const html = { + name: "div", + attributes, + children: node[$extra].children + }; + if (node[$extra].failingNode) { + const htmlFromFailing = node[$extra].failingNode[$flushHTML](); + if (htmlFromFailing) { + if (node.layout.endsWith("-tb")) { + html.children.push(createLine(node, [htmlFromFailing])); + } else { + html.children.push(htmlFromFailing); + } + } + } + if (html.children.length === 0) { + return null; + } + return html; +} +function addHTML(node, html, bbox) { + const extra = node[$extra]; + const availableSpace = extra.availableSpace; + const [x, y, w, h] = bbox; + switch (node.layout) { + case "position": + { + extra.width = Math.max(extra.width, x + w); + extra.height = Math.max(extra.height, y + h); + extra.children.push(html); + break; + } + case "lr-tb": + case "rl-tb": + if (!extra.line || extra.attempt === 1) { + extra.line = createLine(node, []); + extra.children.push(extra.line); + extra.numberInLine = 0; + } + extra.numberInLine += 1; + extra.line.children.push(html); + if (extra.attempt === 0) { + extra.currentWidth += w; + extra.height = Math.max(extra.height, extra.prevHeight + h); + } else { + extra.currentWidth = w; + extra.prevHeight = extra.height; + extra.height += h; + extra.attempt = 0; + } + extra.width = Math.max(extra.width, extra.currentWidth); + break; + case "rl-row": + case "row": + { + extra.children.push(html); + extra.width += w; + extra.height = Math.max(extra.height, h); + const height = measureToString(extra.height); + for (const child of extra.children) { + child.attributes.style.height = height; + } + break; + } + case "table": + { + extra.width = MathClamp(w, extra.width, availableSpace.width); + extra.height += h; + extra.children.push(html); + break; + } + case "tb": + { + extra.width = MathClamp(w, extra.width, availableSpace.width); + extra.height += h; + extra.children.push(html); + break; + } + } +} +function getAvailableSpace(node) { + const availableSpace = node[$extra].availableSpace; + const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0; + const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0; + switch (node.layout) { + case "lr-tb": + case "rl-tb": + if (node[$extra].attempt === 0) { + return { + width: availableSpace.width - marginH - node[$extra].currentWidth, + height: availableSpace.height - marginV - node[$extra].prevHeight + }; + } + return { + width: availableSpace.width - marginH, + height: availableSpace.height - marginV - node[$extra].height + }; + case "rl-row": + case "row": + const width = Math.sumPrecise(node[$extra].columnWidths.slice(node[$extra].currentColumn)); + return { + width, + height: availableSpace.height - marginH + }; + case "table": + case "tb": + return { + width: availableSpace.width - marginH, + height: availableSpace.height - marginV - node[$extra].height + }; + case "position": + default: + return availableSpace; + } +} +function getTransformedBBox(node) { + let w = node.w === "" ? NaN : node.w; + let h = node.h === "" ? NaN : node.h; + let [centerX, centerY] = [0, 0]; + switch (node.anchorType || "") { + case "bottomCenter": + [centerX, centerY] = [w / 2, h]; + break; + case "bottomLeft": + [centerX, centerY] = [0, h]; + break; + case "bottomRight": + [centerX, centerY] = [w, h]; + break; + case "middleCenter": + [centerX, centerY] = [w / 2, h / 2]; + break; + case "middleLeft": + [centerX, centerY] = [0, h / 2]; + break; + case "middleRight": + [centerX, centerY] = [w, h / 2]; + break; + case "topCenter": + [centerX, centerY] = [w / 2, 0]; + break; + case "topRight": + [centerX, centerY] = [w, 0]; + break; + } + let x, y; + switch (node.rotate || 0) { + case 0: + [x, y] = [-centerX, -centerY]; + break; + case 90: + [x, y] = [-centerY, centerX]; + [w, h] = [h, -w]; + break; + case 180: + [x, y] = [centerX, centerY]; + [w, h] = [-w, -h]; + break; + case 270: + [x, y] = [centerY, -centerX]; + [w, h] = [-h, w]; + break; + } + return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)]; +} +function checkDimensions(node, space) { + if (node[$getTemplateRoot]()[$extra].firstUnsplittable === null) { + return true; + } + if (node.w === 0 || node.h === 0) { + return true; + } + const ERROR = 2; + const parent = node[$getSubformParent](); + const attempt = parent[$extra]?.attempt || 0; + const [, y, w, h] = getTransformedBBox(node); + switch (parent.layout) { + case "lr-tb": + case "rl-tb": + if (attempt === 0) { + if (!node[$getTemplateRoot]()[$extra].noLayoutFailure) { + if (node.h !== "" && Math.round(h - space.height) > ERROR) { + return false; + } + if (node.w !== "") { + if (Math.round(w - space.width) <= ERROR) { + return true; + } + if (parent[$extra].numberInLine === 0) { + return space.height > ERROR; + } + return false; + } + return space.width > ERROR; + } + if (node.w !== "") { + return Math.round(w - space.width) <= ERROR; + } + return space.width > ERROR; + } + if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node.h !== "" && Math.round(h - space.height) > ERROR) { + return false; + } + if (node.w === "" || Math.round(w - space.width) <= ERROR) { + return space.height > ERROR; + } + if (parent[$isThereMoreWidth]()) { + return false; + } + return space.height > ERROR; + case "table": + case "tb": + if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node.h !== "" && !node[$isSplittable]()) { + return Math.round(h - space.height) <= ERROR; + } + if (node.w === "" || Math.round(w - space.width) <= ERROR) { + return space.height > ERROR; + } + if (parent[$isThereMoreWidth]()) { + return false; + } + return space.height > ERROR; + case "position": + if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node.h === "" || Math.round(h + y - space.height) <= ERROR) { + return true; + } + const area = node[$getTemplateRoot]()[$extra].currentContentArea; + return h + y > area.h; + case "rl-row": + case "row": + if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node.h !== "") { + return Math.round(h - space.height) <= ERROR; + } + return true; + default: + return true; + } +} + +;// ./src/core/xfa/template.js + + + + + + + + + + +const TEMPLATE_NS_ID = NamespaceIds.template.id; +const SVG_NS = "http://www.w3.org/2000/svg"; +const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2; +const MAX_EMPTY_PAGES = 3; +const DEFAULT_TAB_INDEX = 5000; +const HEADING_PATTERN = /^H(\d+)$/; +const MIMES = new Set(["image/gif", "image/jpeg", "image/jpg", "image/pjpeg", "image/png", "image/apng", "image/x-png", "image/bmp", "image/x-ms-bmp", "image/tiff", "image/tif", "application/octet-stream"]); +const IMAGES_HEADERS = [[[0x42, 0x4d], "image/bmp"], [[0xff, 0xd8, 0xff], "image/jpeg"], [[0x49, 0x49, 0x2a, 0x00], "image/tiff"], [[0x4d, 0x4d, 0x00, 0x2a], "image/tiff"], [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], "image/gif"], [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], "image/png"]]; +function getBorderDims(node) { + if (!node || !node.border) { + return { + w: 0, + h: 0 + }; + } + const borderExtra = node.border[$getExtra](); + if (!borderExtra) { + return { + w: 0, + h: 0 + }; + } + return { + w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2], + h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3] + }; +} +function hasMargin(node) { + return node.margin && (node.margin.topInset || node.margin.rightInset || node.margin.bottomInset || node.margin.leftInset); +} +function _setValue(templateNode, value) { + if (!templateNode.value) { + const nodeValue = new Value({}); + templateNode[$appendChild](nodeValue); + templateNode.value = nodeValue; + } + templateNode.value[$setValue](value); +} +function* getContainedChildren(node) { + for (const child of node[$getChildren]()) { + if (child instanceof SubformSet) { + yield* child[$getContainedChildren](); + continue; + } + yield child; + } +} +function isRequired(node) { + return node.validate?.nullTest === "error"; +} +function setTabIndex(node) { + while (node) { + if (!node.traversal) { + node[$tabIndex] = node[$getParent]()[$tabIndex]; + return; + } + if (node[$tabIndex]) { + return; + } + let next = null; + for (const child of node.traversal[$getChildren]()) { + if (child.operation === "next") { + next = child; + break; + } + } + if (!next || !next.ref) { + node[$tabIndex] = node[$getParent]()[$tabIndex]; + return; + } + const root = node[$getTemplateRoot](); + node[$tabIndex] = ++root[$tabIndex]; + const ref = root[$searchNode](next.ref, node); + if (!ref) { + return; + } + node = ref[0]; + } +} +function applyAssist(obj, attributes) { + const assist = obj.assist; + if (assist) { + const assistTitle = assist[$toHTML](); + if (assistTitle) { + attributes.title = assistTitle; + } + const role = assist.role; + const match = role.match(HEADING_PATTERN); + if (match) { + const ariaRole = "heading"; + const ariaLevel = match[1]; + attributes.role = ariaRole; + attributes["aria-level"] = ariaLevel; + } + } + if (obj.layout === "table") { + attributes.role = "table"; + } else if (obj.layout === "row") { + attributes.role = "row"; + } else { + const parent = obj[$getParent](); + if (parent.layout === "row") { + attributes.role = parent.assist?.role === "TH" ? "columnheader" : "cell"; + } + } +} +function ariaLabel(obj) { + if (!obj.assist) { + return null; + } + const assist = obj.assist; + if (assist.speak && assist.speak[$content] !== "") { + return assist.speak[$content]; + } + if (assist.toolTip) { + return assist.toolTip[$content]; + } + return null; +} +function valueToHtml(value) { + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: Object.create(null) + }, + children: [{ + name: "span", + attributes: { + style: Object.create(null) + }, + value + }] + }); +} +function setFirstUnsplittable(node) { + const root = node[$getTemplateRoot](); + if (root[$extra].firstUnsplittable === null) { + root[$extra].firstUnsplittable = node; + root[$extra].noLayoutFailure = true; + } +} +function unsetFirstUnsplittable(node) { + const root = node[$getTemplateRoot](); + if (root[$extra].firstUnsplittable === node) { + root[$extra].noLayoutFailure = false; + } +} +function handleBreak(node) { + if (node[$extra]) { + return false; + } + node[$extra] = Object.create(null); + if (node.targetType === "auto") { + return false; + } + const root = node[$getTemplateRoot](); + let target = null; + if (node.target) { + target = root[$searchNode](node.target, node[$getParent]()); + if (!target) { + return false; + } + target = target[0]; + } + const { + currentPageArea, + currentContentArea + } = root[$extra]; + if (node.targetType === "pageArea") { + if (!(target instanceof PageArea)) { + target = null; + } + if (node.startNew) { + node[$extra].target = target || currentPageArea; + return true; + } else if (target && target !== currentPageArea) { + node[$extra].target = target; + return true; + } + return false; + } + if (!(target instanceof ContentArea)) { + target = null; + } + const pageArea = target && target[$getParent](); + let index; + let nextPageArea = pageArea; + if (node.startNew) { + if (target) { + const contentAreas = pageArea.contentArea.children; + const indexForCurrent = contentAreas.indexOf(currentContentArea); + const indexForTarget = contentAreas.indexOf(target); + if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) { + nextPageArea = null; + } + index = indexForTarget - 1; + } else { + index = currentPageArea.contentArea.children.indexOf(currentContentArea); + } + } else if (target && target !== currentContentArea) { + const contentAreas = pageArea.contentArea.children; + index = contentAreas.indexOf(target) - 1; + nextPageArea = pageArea === currentPageArea ? null : pageArea; + } else { + return false; + } + node[$extra].target = nextPageArea; + node[$extra].index = index; + return true; +} +function handleOverflow(node, extraNode, space) { + const root = node[$getTemplateRoot](); + const saved = root[$extra].noLayoutFailure; + const savedMethod = extraNode[$getSubformParent]; + extraNode[$getSubformParent] = () => node; + root[$extra].noLayoutFailure = true; + const res = extraNode[$toHTML](space); + node[$addHTML](res.html, res.bbox); + root[$extra].noLayoutFailure = saved; + extraNode[$getSubformParent] = savedMethod; +} +class AppearanceFilter extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "appearanceFilter"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Arc extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "arc", true); + this.circular = getInteger({ + data: attributes.circular, + defaultValue: 0, + validate: x => x === 1 + }); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.startAngle = getFloat({ + data: attributes.startAngle, + defaultValue: 0, + validate: x => true + }); + this.sweepAngle = getFloat({ + data: attributes.sweepAngle, + defaultValue: 360, + validate: x => true + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.edge = null; + this.fill = null; + } + [$toHTML]() { + const edge = this.edge || new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = Object.create(null); + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } else { + style.fill = "transparent"; + } + style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); + style.stroke = edgeStyle.color; + let arc; + const attributes = { + xmlns: SVG_NS, + style: { + width: "100%", + height: "100%", + overflow: "visible" + } + }; + if (this.sweepAngle === 360) { + arc = { + name: "ellipse", + attributes: { + xmlns: SVG_NS, + cx: "50%", + cy: "50%", + rx: "50%", + ry: "50%", + style + } + }; + } else { + const startAngle = this.startAngle * Math.PI / 180; + const sweepAngle = this.sweepAngle * Math.PI / 180; + const largeArc = this.sweepAngle > 180 ? 1 : 0; + const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))]; + arc = { + name: "path", + attributes: { + xmlns: SVG_NS, + d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`, + vectorEffect: "non-scaling-stroke", + style + } + }; + Object.assign(attributes, { + viewBox: "0 0 100 100", + preserveAspectRatio: "none" + }); + } + const svg = { + name: "svg", + children: [arc], + attributes + }; + const parent = this[$getParent]()[$getParent](); + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } +} +class Area extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "area", true); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: n => n >= 1 || n === -1 + }); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.desc = null; + this.extras = null; + this.area = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$isTransparent]() { + return true; + } + [$isBindable]() { + return true; + } + [$addHTML](html, bbox) { + const [x, y, w, h] = bbox; + this[$extra].width = Math.max(this[$extra].width, x + w); + this[$extra].height = Math.max(this[$extra].height, y + h); + this[$extra].children.push(html); + } + [$getAvailableSpace]() { + return this[$extra].availableSpace; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "position"); + const attributes = { + style, + id: this[$uid], + class: ["xfaArea"] + }; + if (isPrintOnly(this)) { + attributes.class.push("xfaPrintOnly"); + } + if (this.name) { + attributes.xfaName = this.name; + } + const children = []; + this[$extra] = { + children, + width: 0, + height: 0, + availableSpace + }; + const result = this[$childrenToHTML]({ + filter: new Set(["area", "draw", "field", "exclGroup", "subform", "subformSet"]), + include: true + }); + if (!result.success) { + if (result.isBreak()) { + return result; + } + delete this[$extra]; + return HTMLResult.FAILURE; + } + style.width = measureToString(this[$extra].width); + style.height = measureToString(this[$extra].height); + const html = { + name: "div", + attributes, + children + }; + const bbox = [this.x, this.y, this[$extra].width, this[$extra].height]; + delete this[$extra]; + return HTMLResult.success(html, bbox); + } +} +class Assist extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "assist", true); + this.id = attributes.id || ""; + this.role = attributes.role || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.speak = null; + this.toolTip = null; + } + [$toHTML]() { + return this.toolTip?.[$content] || null; + } +} +class Barcode extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "barcode", true); + this.charEncoding = getKeyword({ + data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : "", + defaultValue: "", + validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) + }); + this.checksum = getStringOption(attributes.checksum, ["none", "1mod10", "1mod10_1mod11", "2mod10", "auto"]); + this.dataColumnCount = getInteger({ + data: attributes.dataColumnCount, + defaultValue: -1, + validate: x => x >= 0 + }); + this.dataLength = getInteger({ + data: attributes.dataLength, + defaultValue: -1, + validate: x => x >= 0 + }); + this.dataPrep = getStringOption(attributes.dataPrep, ["none", "flateCompress"]); + this.dataRowCount = getInteger({ + data: attributes.dataRowCount, + defaultValue: -1, + validate: x => x >= 0 + }); + this.endChar = attributes.endChar || ""; + this.errorCorrectionLevel = getInteger({ + data: attributes.errorCorrectionLevel, + defaultValue: -1, + validate: x => x >= 0 && x <= 8 + }); + this.id = attributes.id || ""; + this.moduleHeight = getMeasurement(attributes.moduleHeight, "5mm"); + this.moduleWidth = getMeasurement(attributes.moduleWidth, "0.25mm"); + this.printCheckDigit = getInteger({ + data: attributes.printCheckDigit, + defaultValue: 0, + validate: x => x === 1 + }); + this.rowColumnRatio = getRatio(attributes.rowColumnRatio); + this.startChar = attributes.startChar || ""; + this.textLocation = getStringOption(attributes.textLocation, ["below", "above", "aboveEmbedded", "belowEmbedded", "none"]); + this.truncate = getInteger({ + data: attributes.truncate, + defaultValue: 0, + validate: x => x === 1 + }); + this.type = getStringOption(attributes.type ? attributes.type.toLowerCase() : "", ["aztec", "codabar", "code2of5industrial", "code2of5interleaved", "code2of5matrix", "code2of5standard", "code3of9", "code3of9extended", "code11", "code49", "code93", "code128", "code128a", "code128b", "code128c", "code128sscc", "datamatrix", "ean8", "ean8add2", "ean8add5", "ean13", "ean13add2", "ean13add5", "ean13pwcd", "fim", "logmars", "maxicode", "msi", "pdf417", "pdf417macro", "plessey", "postauscust2", "postauscust3", "postausreplypaid", "postausstandard", "postukrm4scc", "postusdpbc", "postusimb", "postusstandard", "postus5zip", "qrcode", "rfid", "rss14", "rss14expanded", "rss14limited", "rss14stacked", "rss14stackedomni", "rss14truncated", "telepen", "ucc128", "ucc128random", "ucc128sscc", "upca", "upcaadd2", "upcaadd5", "upcapwcd", "upce", "upceadd2", "upceadd5", "upcean2", "upcean5", "upsmaxicode"]); + this.upsMode = getStringOption(attributes.upsMode, ["usCarrier", "internationalCarrier", "secureSymbol", "standardSymbol"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.wideNarrowRatio = getRatio(attributes.wideNarrowRatio); + this.encrypt = null; + this.extras = null; + } +} +class Bind extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bind", true); + this.match = getStringOption(attributes.match, ["once", "dataRef", "global", "none"]); + this.ref = attributes.ref || ""; + this.picture = null; + } +} +class BindItems extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bindItems"); + this.connection = attributes.connection || ""; + this.labelRef = attributes.labelRef || ""; + this.ref = attributes.ref || ""; + this.valueRef = attributes.valueRef || ""; + } +} +class Bookend extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bookend"); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class BooleanElement extends Option01 { + constructor(attributes) { + super(TEMPLATE_NS_ID, "boolean"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] === 1 ? "1" : "0"); + } +} +class Border extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "border", true); + this.break = getStringOption(attributes.break, ["close", "open"]); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.corner = new XFAObjectArray(4); + this.edge = new XFAObjectArray(4); + this.extras = null; + this.fill = null; + this.margin = null; + } + [$getExtra]() { + if (!this[$extra]) { + const edges = this.edge.children.slice(); + if (edges.length < 4) { + const defaultEdge = edges.at(-1) || new Edge({}); + for (let i = edges.length; i < 4; i++) { + edges.push(defaultEdge); + } + } + const widths = edges.map(edge => edge.thickness); + const insets = [0, 0, 0, 0]; + if (this.margin) { + insets[0] = this.margin.topInset; + insets[1] = this.margin.rightInset; + insets[2] = this.margin.bottomInset; + insets[3] = this.margin.leftInset; + } + this[$extra] = { + widths, + insets, + edges + }; + } + return this[$extra]; + } + [$toStyle]() { + const { + edges + } = this[$getExtra](); + const edgeStyles = edges.map(node => { + const style = node[$toStyle](); + style.color ||= "#000000"; + return style; + }); + const style = Object.create(null); + if (this.margin) { + Object.assign(style, this.margin[$toStyle]()); + } + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } + if (this.corner.children.some(node => node.radius !== 0)) { + const cornerStyles = this.corner.children.map(node => node[$toStyle]()); + if (cornerStyles.length === 2 || cornerStyles.length === 3) { + const last = cornerStyles.at(-1); + for (let i = cornerStyles.length; i < 4; i++) { + cornerStyles.push(last); + } + } + style.borderRadius = cornerStyles.map(s => s.radius).join(" "); + } + switch (this.presence) { + case "invisible": + case "hidden": + style.borderStyle = ""; + break; + case "inactive": + style.borderStyle = "none"; + break; + default: + style.borderStyle = edgeStyles.map(s => s.style).join(" "); + break; + } + style.borderWidth = edgeStyles.map(s => s.width).join(" "); + style.borderColor = edgeStyles.map(s => s.color).join(" "); + return style; + } +} +class Break extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "break", true); + this.after = getStringOption(attributes.after, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); + this.afterTarget = attributes.afterTarget || ""; + this.before = getStringOption(attributes.before, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); + this.beforeTarget = attributes.beforeTarget || ""; + this.bookendLeader = attributes.bookendLeader || ""; + this.bookendTrailer = attributes.bookendTrailer || ""; + this.id = attributes.id || ""; + this.overflowLeader = attributes.overflowLeader || ""; + this.overflowTarget = attributes.overflowTarget || ""; + this.overflowTrailer = attributes.overflowTrailer || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: x => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } +} +class BreakAfter extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "breakAfter", true); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: x => x === 1 + }); + this.target = attributes.target || ""; + this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.script = null; + } +} +class BreakBefore extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "breakBefore", true); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: x => x === 1 + }); + this.target = attributes.target || ""; + this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.script = null; + } + [$toHTML](availableSpace) { + this[$extra] = {}; + return HTMLResult.FAILURE; + } +} +class Button extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "button", true); + this.highlight = getStringOption(attributes.highlight, ["inverted", "none", "outline", "push"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toHTML](availableSpace) { + const parent = this[$getParent](); + const grandpa = parent[$getParent](); + const htmlButton = { + name: "button", + attributes: { + id: this[$uid], + class: ["xfaButton"], + style: {} + }, + children: [] + }; + for (const event of grandpa.event.children) { + if (event.activity !== "click" || !event.script) { + continue; + } + const jsURL = recoverJsURL(event.script[$content]); + if (!jsURL) { + continue; + } + const href = fixURL(jsURL.url); + if (!href) { + continue; + } + htmlButton.children.push({ + name: "a", + attributes: { + id: "link" + this[$uid], + href, + newWindow: jsURL.newWindow, + class: ["xfaLink"], + style: {} + }, + children: [] + }); + } + return HTMLResult.success(htmlButton); + } +} +class Calculate extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "calculate", true); + this.id = attributes.id || ""; + this.override = getStringOption(attributes.override, ["disabled", "error", "ignore", "warning"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.message = null; + this.script = null; + } +} +class Caption extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "caption", true); + this.id = attributes.id || ""; + this.placement = getStringOption(attributes.placement, ["left", "bottom", "inline", "right", "top"]); + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.reserve = Math.ceil(getMeasurement(attributes.reserve)); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.font = null; + this.margin = null; + this.para = null; + this.value = null; + } + [$setValue](value) { + _setValue(this, value); + } + [$getExtra](availableSpace) { + if (!this[$extra]) { + let { + width, + height + } = availableSpace; + switch (this.placement) { + case "left": + case "right": + case "inline": + width = this.reserve <= 0 ? width : this.reserve; + break; + case "top": + case "bottom": + height = this.reserve <= 0 ? height : this.reserve; + break; + } + this[$extra] = layoutNode(this, { + width, + height + }); + } + return this[$extra]; + } + [$toHTML](availableSpace) { + if (!this.value) { + return HTMLResult.EMPTY; + } + this[$pushPara](); + const value = this.value[$toHTML](availableSpace).html; + if (!value) { + this[$popPara](); + return HTMLResult.EMPTY; + } + const savedReserve = this.reserve; + if (this.reserve <= 0) { + const { + w, + h + } = this[$getExtra](availableSpace); + switch (this.placement) { + case "left": + case "right": + case "inline": + this.reserve = w; + break; + case "top": + case "bottom": + this.reserve = h; + break; + } + } + const children = []; + if (typeof value === "string") { + children.push({ + name: "#text", + value + }); + } else { + children.push(value); + } + const style = toStyle(this, "font", "margin", "visibility"); + switch (this.placement) { + case "left": + case "right": + if (this.reserve > 0) { + style.width = measureToString(this.reserve); + } + break; + case "top": + case "bottom": + if (this.reserve > 0) { + style.height = measureToString(this.reserve); + } + break; + } + setPara(this, null, value); + this[$popPara](); + this.reserve = savedReserve; + return HTMLResult.success({ + name: "div", + attributes: { + style, + class: ["xfaCaption"] + }, + children + }); + } +} +class Certificate extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "certificate"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Certificates extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "certificates", true); + this.credentialServerPolicy = getStringOption(attributes.credentialServerPolicy, ["optional", "required"]); + this.id = attributes.id || ""; + this.url = attributes.url || ""; + this.urlPolicy = attributes.urlPolicy || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encryption = null; + this.issuers = null; + this.keyUsage = null; + this.oids = null; + this.signing = null; + this.subjectDNs = null; + } +} +class CheckButton extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "checkButton", true); + this.id = attributes.id || ""; + this.mark = getStringOption(attributes.mark, ["default", "check", "circle", "cross", "diamond", "square", "star"]); + this.shape = getStringOption(attributes.shape, ["square", "round"]); + this.size = getMeasurement(attributes.size, "10pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "margin"); + const size = measureToString(this.size); + style.width = style.height = size; + let type; + let className; + let groupId; + const field = this[$getParent]()[$getParent](); + const items = field.items.children.length && field.items.children[0][$toHTML]().html || []; + const exportedValue = { + on: (items[0] !== undefined ? items[0] : "on").toString(), + off: (items[1] !== undefined ? items[1] : "off").toString() + }; + const value = field.value?.[$text]() || "off"; + const checked = value === exportedValue.on || undefined; + const container = field[$getSubformParent](); + const fieldId = field[$uid]; + let dataId; + if (container instanceof ExclGroup) { + groupId = container[$uid]; + type = "radio"; + className = "xfaRadio"; + dataId = container[$data]?.[$uid] || container[$uid]; + } else { + type = "checkbox"; + className = "xfaCheckbox"; + dataId = field[$data]?.[$uid] || field[$uid]; + } + const input = { + name: "input", + attributes: { + class: [className], + style, + fieldId, + dataId, + type, + checked, + xfaOn: exportedValue.on, + xfaOff: exportedValue.off, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (groupId) { + input.attributes.name = groupId; + } + if (isRequired(field)) { + input.attributes["aria-required"] = true; + input.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [input] + }); + } +} +class ChoiceList extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "choiceList", true); + this.commitOn = getStringOption(attributes.commitOn, ["select", "exit"]); + this.id = attributes.id || ""; + this.open = getStringOption(attributes.open, ["userControl", "always", "multiSelect", "onEntry"]); + this.textEntry = getInteger({ + data: attributes.textEntry, + defaultValue: 0, + validate: x => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "margin"); + const ui = this[$getParent](); + const field = ui[$getParent](); + const fontSize = field.font?.size || 10; + const optionStyle = { + fontSize: `calc(${fontSize}px * var(--total-scale-factor))` + }; + const children = []; + if (field.items.children.length > 0) { + const items = field.items; + let displayedIndex = 0; + let saveIndex = 0; + if (items.children.length === 2) { + displayedIndex = items.children[0].save; + saveIndex = 1 - displayedIndex; + } + const displayed = items.children[displayedIndex][$toHTML]().html; + const values = items.children[saveIndex][$toHTML]().html; + let selected = false; + const value = field.value?.[$text]() || ""; + for (let i = 0, ii = displayed.length; i < ii; i++) { + const option = { + name: "option", + attributes: { + value: values[i] || displayed[i], + style: optionStyle + }, + value: displayed[i] + }; + if (values[i] === value) { + option.attributes.selected = selected = true; + } + children.push(option); + } + if (!selected) { + children.splice(0, 0, { + name: "option", + attributes: { + hidden: true, + selected: true + }, + value: " " + }); + } + } + const selectAttributes = { + class: ["xfaSelect"], + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + style, + "aria-label": ariaLabel(field), + "aria-required": false + }; + if (isRequired(field)) { + selectAttributes["aria-required"] = true; + selectAttributes.required = true; + } + if (this.open === "multiSelect") { + selectAttributes.multiple = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [{ + name: "select", + children, + attributes: selectAttributes + }] + }); + } +} +class Color extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "color", true); + this.cSpace = getStringOption(attributes.cSpace, ["SRGB"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.value = attributes.value ? getColor(attributes.value) : ""; + this.extras = null; + } + [$hasSettableValue]() { + return false; + } + [$toStyle]() { + return this.value ? Util.makeHexColor(this.value.r, this.value.g, this.value.b) : null; + } +} +class Comb extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "comb"); + this.id = attributes.id || ""; + this.numberOfCells = getInteger({ + data: attributes.numberOfCells, + defaultValue: 0, + validate: x => x >= 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Connect extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "connect", true); + this.connection = attributes.connection || ""; + this.id = attributes.id || ""; + this.ref = attributes.ref || ""; + this.usage = getStringOption(attributes.usage, ["exportAndImport", "exportOnly", "importOnly"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.picture = null; + } +} +class ContentArea extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "contentArea", true); + this.h = getMeasurement(attributes.h); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = getMeasurement(attributes.w); + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.desc = null; + this.extras = null; + } + [$toHTML](availableSpace) { + const left = measureToString(this.x); + const top = measureToString(this.y); + const style = { + left, + top, + width: measureToString(this.w), + height: measureToString(this.h) + }; + const classNames = ["xfaContentarea"]; + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + return HTMLResult.success({ + name: "div", + children: [], + attributes: { + style, + class: classNames, + id: this[$uid] + } + }); + } +} +class Corner extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "corner", true); + this.id = attributes.id || ""; + this.inverted = getInteger({ + data: attributes.inverted, + defaultValue: 0, + validate: x => x === 1 + }); + this.join = getStringOption(attributes.join, ["square", "round"]); + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.radius = getMeasurement(attributes.radius); + this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); + this.thickness = getMeasurement(attributes.thickness, "0.5pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle]() { + const style = toStyle(this, "visibility"); + style.radius = measureToString(this.join === "square" ? 0 : this.radius); + return style; + } +} +class DateElement extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "date"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date = this[$content].trim(); + this[$content] = date ? new Date(date) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } +} +class DateTime extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "dateTime"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date = this[$content].trim(); + this[$content] = date ? new Date(date) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } +} +class DateTimeEdit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "dateTimeEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.picker = getStringOption(attributes.picker, ["host", "none"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + const field = this[$getParent]()[$getParent](); + const html = { + name: "input", + attributes: { + type: "text", + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } +} +class Decimal extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "decimal"); + this.fracDigits = getInteger({ + data: attributes.fracDigits, + defaultValue: 2, + validate: x => true + }); + this.id = attributes.id || ""; + this.leadDigits = getInteger({ + data: attributes.leadDigits, + defaultValue: -1, + validate: x => true + }); + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number = parseFloat(this[$content].trim()); + this[$content] = isNaN(number) ? null : number; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } +} +class DefaultUi extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "defaultUi", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } +} +class Desc extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "desc", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } +} +class DigestMethod extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "digestMethod", ["", "SHA1", "SHA256", "SHA512", "RIPEMD160"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class DigestMethods extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "digestMethods", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.digestMethod = new XFAObjectArray(); + } +} +class Draw extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "draw", true); + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: n => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.rotate = getInteger({ + data: attributes.rotate, + defaultValue: 0, + validate: x => x % 90 === 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.border = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.font = null; + this.keep = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.ui = null; + this.value = null; + this.setProperty = new XFAObjectArray(); + } + [$setValue](value) { + _setValue(this, value); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.presence === "hidden" || this.presence === "inactive") { + return HTMLResult.EMPTY; + } + fixDimensions(this); + this[$pushPara](); + const savedW = this.w; + const savedH = this.h; + const { + w, + h, + isBroken + } = layoutNode(this, availableSpace); + if (w && this.w === "") { + if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { + this[$popPara](); + return HTMLResult.FAILURE; + } + this.w = w; + } + if (h && this.h === "") { + this.h = h; + } + setFirstUnsplittable(this); + if (!checkDimensions(this, availableSpace)) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.FAILURE; + } + unsetFirstUnsplittable(this); + const style = toStyle(this, "font", "hAlign", "dimensions", "position", "presence", "rotate", "anchorType", "border", "margin"); + setMinMaxDimensions(this, style); + if (style.margin) { + style.padding = style.margin; + delete style.margin; + } + const classNames = ["xfaDraw"]; + if (this.font) { + classNames.push("xfaFont"); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + const attributes = { + style, + id: this[$uid], + class: classNames + }; + if (this.name) { + attributes.xfaName = this.name; + } + const html = { + name: "div", + attributes, + children: [] + }; + applyAssist(this, attributes); + const bbox = computeBbox(this, html, availableSpace); + const value = this.value ? this.value[$toHTML](availableSpace).html : null; + if (value === null) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.success(createWrapper(this, html), bbox); + } + html.children.push(value); + setPara(this, style, value); + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.success(createWrapper(this, html), bbox); + } +} +class Edge extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "edge", true); + this.cap = getStringOption(attributes.cap, ["square", "butt", "round"]); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); + this.thickness = getMeasurement(attributes.thickness, "0.5pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle]() { + const style = toStyle(this, "visibility"); + Object.assign(style, { + linecap: this.cap, + width: measureToString(this.thickness), + color: this.color ? this.color[$toStyle]() : "#000000", + style: "" + }); + if (this.presence !== "visible") { + style.style = "none"; + } else { + switch (this.stroke) { + case "solid": + style.style = "solid"; + break; + case "dashDot": + style.style = "dashed"; + break; + case "dashDotDot": + style.style = "dashed"; + break; + case "dashed": + style.style = "dashed"; + break; + case "dotted": + style.style = "dotted"; + break; + case "embossed": + style.style = "ridge"; + break; + case "etched": + style.style = "groove"; + break; + case "lowered": + style.style = "inset"; + break; + case "raised": + style.style = "outset"; + break; + } + } + return style; + } +} +class Encoding extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encoding", ["adbe.x509.rsa_sha1", "adbe.pkcs7.detached", "adbe.pkcs7.sha1"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Encodings extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encodings", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encoding = new XFAObjectArray(); + } +} +class Encrypt extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encrypt", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = null; + } +} +class EncryptData extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptData", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["encrypt", "decrypt"]); + this.target = attributes.target || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.filter = null; + this.manifest = null; + } +} +class Encryption extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryption", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } +} +class EncryptionMethod extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptionMethod", ["", "AES256-CBC", "TRIPLEDES-CBC", "AES128-CBC", "AES192-CBC"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class EncryptionMethods extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptionMethods", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encryptionMethod = new XFAObjectArray(); + } +} +class Event extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "event", true); + this.activity = getStringOption(attributes.activity, ["click", "change", "docClose", "docReady", "enter", "exit", "full", "indexChange", "initialize", "mouseDown", "mouseEnter", "mouseExit", "mouseUp", "postExecute", "postOpen", "postPrint", "postSave", "postSign", "postSubmit", "preExecute", "preOpen", "prePrint", "preSave", "preSign", "preSubmit", "ready", "validationState"]); + this.id = attributes.id || ""; + this.listen = getStringOption(attributes.listen, ["refOnly", "refAndDescendents"]); + this.name = attributes.name || ""; + this.ref = attributes.ref || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.encryptData = null; + this.execute = null; + this.script = null; + this.signData = null; + this.submit = null; + } +} +class ExData extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exData"); + this.contentType = attributes.contentType || ""; + this.href = attributes.href || ""; + this.id = attributes.id || ""; + this.maxLength = getInteger({ + data: attributes.maxLength, + defaultValue: -1, + validate: x => x >= -1 + }); + this.name = attributes.name || ""; + this.rid = attributes.rid || ""; + this.transferEncoding = getStringOption(attributes.transferEncoding, ["none", "base64", "package"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$isCDATAXml]() { + return this.contentType === "text/html"; + } + [$onChild](child) { + if (this.contentType === "text/html" && child[$namespaceId] === NamespaceIds.xhtml.id) { + this[$content] = child; + return true; + } + if (this.contentType === "text/xml") { + this[$content] = child; + return true; + } + return false; + } + [$toHTML](availableSpace) { + if (this.contentType !== "text/html" || !this[$content]) { + return HTMLResult.EMPTY; + } + return this[$content][$toHTML](availableSpace); + } +} +class ExObject extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exObject", true); + this.archive = attributes.archive || ""; + this.classId = attributes.classId || ""; + this.codeBase = attributes.codeBase || ""; + this.codeType = attributes.codeType || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } +} +class ExclGroup extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exclGroup", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.accessKey = attributes.accessKey || ""; + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: n => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.border = null; + this.calculate = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.validate = null; + this.connect = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + } + [$isBindable]() { + return true; + } + [$hasSettableValue]() { + return true; + } + [$setValue](value) { + for (const field of this.field.children) { + if (!field.value) { + const nodeValue = new Value({}); + field[$appendChild](nodeValue); + field.value = nodeValue; + } + field.value[$setValue](value); + } + } + [$isThereMoreWidth]() { + return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); + } + [$isSplittable]() { + const parent = this[$getSubformParent](); + if (!parent[$isSplittable]()) { + return false; + } + if (this[$extra]._isSplittable !== undefined) { + return this[$extra]._isSplittable; + } + if (this.layout === "position" || this.layout.includes("row")) { + this[$extra]._isSplittable = false; + return false; + } + if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { + return false; + } + this[$extra]._isSplittable = true; + return true; + } + [$flushHTML]() { + return flushHTML(this); + } + [$addHTML](html, bbox) { + addHTML(this, html, bbox); + } + [$getAvailableSpace]() { + return getAvailableSpace(this); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { + return HTMLResult.EMPTY; + } + fixDimensions(this); + const children = []; + const attributes = { + id: this[$uid], + class: [] + }; + setAccess(this, attributes.class); + this[$extra] ||= Object.create(null); + Object.assign(this[$extra], { + children, + attributes, + attempt: 0, + line: null, + numberInLine: 0, + availableSpace: { + width: Math.min(this.w || Infinity, availableSpace.width), + height: Math.min(this.h || Infinity, availableSpace.height) + }, + width: 0, + height: 0, + prevHeight: 0, + currentWidth: 0 + }); + const isSplittable = this[$isSplittable](); + if (!isSplittable) { + setFirstUnsplittable(this); + } + if (!checkDimensions(this, availableSpace)) { + return HTMLResult.FAILURE; + } + const filter = new Set(["field"]); + if (this.layout.includes("row")) { + const columnWidths = this[$getSubformParent]().columnWidths; + if (Array.isArray(columnWidths) && columnWidths.length > 0) { + this[$extra].columnWidths = columnWidths; + this[$extra].currentColumn = 0; + } + } + const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); + const classNames = ["xfaExclgroup"]; + const cl = layoutClass(this); + if (cl) { + classNames.push(cl); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + attributes.style = style; + attributes.class = classNames; + if (this.name) { + attributes.xfaName = this.name; + } + this[$pushPara](); + const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; + const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; + for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { + if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { + this[$extra].numberInLine = 0; + } + const result = this[$childrenToHTML]({ + filter, + include: true + }); + if (result.success) { + break; + } + if (result.isBreak()) { + this[$popPara](); + return result; + } + if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !this[$getTemplateRoot]()[$extra].noLayoutFailure) { + this[$extra].attempt = maxRun; + break; + } + } + this[$popPara](); + if (!isSplittable) { + unsetFirstUnsplittable(this); + } + if (this[$extra].attempt === maxRun) { + if (!isSplittable) { + delete this[$extra]; + } + return HTMLResult.FAILURE; + } + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + const width = Math.max(this[$extra].width + marginH, this.w || 0); + const height = Math.max(this[$extra].height + marginV, this.h || 0); + const bbox = [this.x, this.y, width, height]; + if (this.w === "") { + style.width = measureToString(width); + } + if (this.h === "") { + style.height = measureToString(height); + } + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + delete this[$extra]; + return HTMLResult.success(createWrapper(this, html), bbox); + } +} +class Execute extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "execute"); + this.connection = attributes.connection || ""; + this.executeType = getStringOption(attributes.executeType, ["import", "remerge"]); + this.id = attributes.id || ""; + this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Extras extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "extras", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.extras = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } +} +class Field extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "field", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.accessKey = attributes.accessKey || ""; + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: n => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.rotate = getInteger({ + data: attributes.rotate, + defaultValue: 0, + validate: x => x % 90 === 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.border = null; + this.calculate = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.font = null; + this.format = null; + this.items = new XFAObjectArray(2); + this.keep = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.ui = null; + this.validate = null; + this.value = null; + this.bindItems = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + } + [$isBindable]() { + return true; + } + [$setValue](value) { + _setValue(this, value); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (!this.ui) { + this.ui = new Ui({}); + this.ui[$globalData] = this[$globalData]; + this[$appendChild](this.ui); + let node; + switch (this.items.children.length) { + case 0: + node = new TextEdit({}); + this.ui.textEdit = node; + break; + case 1: + node = new CheckButton({}); + this.ui.checkButton = node; + break; + case 2: + node = new ChoiceList({}); + this.ui.choiceList = node; + break; + } + this.ui[$appendChild](node); + } + if (!this.ui || this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { + return HTMLResult.EMPTY; + } + if (this.caption) { + delete this.caption[$extra]; + } + this[$pushPara](); + const caption = this.caption ? this.caption[$toHTML](availableSpace).html : null; + const savedW = this.w; + const savedH = this.h; + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + let borderDims = null; + if (this.w === "" || this.h === "") { + let width = null; + let height = null; + let uiW = 0; + let uiH = 0; + if (this.ui.checkButton) { + uiW = uiH = this.ui.checkButton.size; + } else { + const { + w, + h + } = layoutNode(this, availableSpace); + if (w !== null) { + uiW = w; + uiH = h; + } else { + uiH = fonts_getMetrics(this.font, true).lineNoGap; + } + } + borderDims = getBorderDims(this.ui[$getExtra]()); + uiW += borderDims.w; + uiH += borderDims.h; + if (this.caption) { + const { + w, + h, + isBroken + } = this.caption[$getExtra](availableSpace); + if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { + this[$popPara](); + return HTMLResult.FAILURE; + } + width = w; + height = h; + switch (this.caption.placement) { + case "left": + case "right": + case "inline": + width += uiW; + break; + case "top": + case "bottom": + height += uiH; + break; + } + } else { + width = uiW; + height = uiH; + } + if (width && this.w === "") { + width += marginH; + this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW); + } + if (height && this.h === "") { + height += marginV; + this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH); + } + } + this[$popPara](); + fixDimensions(this); + setFirstUnsplittable(this); + if (!checkDimensions(this, availableSpace)) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.FAILURE; + } + unsetFirstUnsplittable(this); + const style = toStyle(this, "font", "dimensions", "position", "rotate", "anchorType", "presence", "margin", "hAlign"); + setMinMaxDimensions(this, style); + const classNames = ["xfaField"]; + if (this.font) { + classNames.push("xfaFont"); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + const attributes = { + style, + id: this[$uid], + class: classNames + }; + if (style.margin) { + style.padding = style.margin; + delete style.margin; + } + setAccess(this, classNames); + if (this.name) { + attributes.xfaName = this.name; + } + const children = []; + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + const borderStyle = this.border ? this.border[$toStyle]() : null; + const bbox = computeBbox(this, html, availableSpace); + const ui = this.ui[$toHTML]().html; + if (!ui) { + Object.assign(style, borderStyle); + return HTMLResult.success(createWrapper(this, html), bbox); + } + if (this[$tabIndex]) { + if (ui.children?.[0]) { + ui.children[0].attributes.tabindex = this[$tabIndex]; + } else { + ui.attributes.tabindex = this[$tabIndex]; + } + } + ui.attributes.style ||= Object.create(null); + let aElement = null; + if (this.ui.button) { + if (ui.children.length === 1) { + [aElement] = ui.children.splice(0, 1); + } + Object.assign(ui.attributes.style, borderStyle); + } else { + Object.assign(style, borderStyle); + } + children.push(ui); + if (this.value) { + if (this.ui.imageEdit) { + ui.children.push(this.value[$toHTML]().html); + } else if (!this.ui.button) { + let value = ""; + if (this.value.exData) { + value = this.value.exData[$text](); + } else if (this.value.text) { + value = this.value.text[$getExtra](); + } else { + const htmlValue = this.value[$toHTML]().html; + if (htmlValue !== null) { + value = htmlValue.children[0].value; + } + } + if (this.ui.textEdit && this.value.text?.maxChars) { + ui.children[0].attributes.maxLength = this.value.text.maxChars; + } + if (value) { + if (this.ui.numericEdit) { + value = parseFloat(value); + value = isNaN(value) ? "" : value.toString(); + } + if (ui.children[0].name === "textarea") { + ui.children[0].attributes.textContent = value; + } else { + ui.children[0].attributes.value = value; + } + } + } + } + if (!this.ui.imageEdit && ui.children?.[0] && this.h) { + borderDims = borderDims || getBorderDims(this.ui[$getExtra]()); + let captionHeight = 0; + if (this.caption && ["top", "bottom"].includes(this.caption.placement)) { + captionHeight = this.caption.reserve; + if (captionHeight <= 0) { + captionHeight = this.caption[$getExtra](availableSpace).h; + } + const inputHeight = this.h - captionHeight - marginV - borderDims.h; + ui.children[0].attributes.style.height = measureToString(inputHeight); + } else { + ui.children[0].attributes.style.height = "100%"; + } + } + if (aElement) { + ui.children.push(aElement); + } + if (!caption) { + if (ui.attributes.class) { + ui.attributes.class.push("xfaLeft"); + } + this.w = savedW; + this.h = savedH; + return HTMLResult.success(createWrapper(this, html), bbox); + } + if (this.ui.button) { + if (style.padding) { + delete style.padding; + } + if (caption.name === "div") { + caption.name = "span"; + } + ui.children.push(caption); + return HTMLResult.success(html, bbox); + } else if (this.ui.checkButton) { + caption.attributes.class[0] = "xfaCaptionForCheckButton"; + } + ui.attributes.class ||= []; + ui.children.splice(0, 0, caption); + switch (this.caption.placement) { + case "left": + ui.attributes.class.push("xfaLeft"); + break; + case "right": + ui.attributes.class.push("xfaRight"); + break; + case "top": + ui.attributes.class.push("xfaTop"); + break; + case "bottom": + ui.attributes.class.push("xfaBottom"); + break; + case "inline": + ui.attributes.class.push("xfaLeft"); + break; + } + this.w = savedW; + this.h = savedH; + return HTMLResult.success(createWrapper(this, html), bbox); + } +} +class Fill extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "fill", true); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + this.linear = null; + this.pattern = null; + this.radial = null; + this.solid = null; + this.stipple = null; + } + [$toStyle]() { + const parent = this[$getParent](); + const grandpa = parent[$getParent](); + const ggrandpa = grandpa[$getParent](); + const style = Object.create(null); + let propName = "color"; + let altPropName = propName; + if (parent instanceof Border) { + propName = "background-color"; + altPropName = "background"; + if (ggrandpa instanceof Ui) { + style.backgroundColor = "white"; + } + } + if (parent instanceof Rectangle || parent instanceof Arc) { + propName = altPropName = "fill"; + style.fill = "white"; + } + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "extras" || name === "color") { + continue; + } + const obj = this[name]; + if (!(obj instanceof XFAObject)) { + continue; + } + const color = obj[$toStyle](this.color); + if (color) { + style[color.startsWith("#") ? propName : altPropName] = color; + } + return style; + } + if (this.color?.value) { + const color = this.color[$toStyle](); + style[color.startsWith("#") ? propName : altPropName] = color; + } + return style; + } +} +class Filter extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "filter", true); + this.addRevocationInfo = getStringOption(attributes.addRevocationInfo, ["", "required", "optional", "none"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.version = getInteger({ + data: this.version, + defaultValue: 5, + validate: x => x >= 1 && x <= 5 + }); + this.appearanceFilter = null; + this.certificates = null; + this.digestMethods = null; + this.encodings = null; + this.encryptionMethods = null; + this.handler = null; + this.lockDocument = null; + this.mdp = null; + this.reasons = null; + this.timeStamp = null; + } +} +class Float extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "float"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number = parseFloat(this[$content].trim()); + this[$content] = isNaN(number) ? null : number; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } +} +class template_Font extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "font", true); + this.baselineShift = getMeasurement(attributes.baselineShift); + this.fontHorizontalScale = getFloat({ + data: attributes.fontHorizontalScale, + defaultValue: 100, + validate: x => x >= 0 + }); + this.fontVerticalScale = getFloat({ + data: attributes.fontVerticalScale, + defaultValue: 100, + validate: x => x >= 0 + }); + this.id = attributes.id || ""; + this.kerningMode = getStringOption(attributes.kerningMode, ["none", "pair"]); + this.letterSpacing = getMeasurement(attributes.letterSpacing, "0"); + this.lineThrough = getInteger({ + data: attributes.lineThrough, + defaultValue: 0, + validate: x => x === 1 || x === 2 + }); + this.lineThroughPeriod = getStringOption(attributes.lineThroughPeriod, ["all", "word"]); + this.overline = getInteger({ + data: attributes.overline, + defaultValue: 0, + validate: x => x === 1 || x === 2 + }); + this.overlinePeriod = getStringOption(attributes.overlinePeriod, ["all", "word"]); + this.posture = getStringOption(attributes.posture, ["normal", "italic"]); + this.size = getMeasurement(attributes.size, "10pt"); + this.typeface = attributes.typeface || "Courier"; + this.underline = getInteger({ + data: attributes.underline, + defaultValue: 0, + validate: x => x === 1 || x === 2 + }); + this.underlinePeriod = getStringOption(attributes.underlinePeriod, ["all", "word"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.weight = getStringOption(attributes.weight, ["normal", "bold"]); + this.extras = null; + this.fill = null; + } + [$clean](builder) { + super[$clean](builder); + this[$globalData].usedTypefaces.add(this.typeface); + } + [$toStyle]() { + const style = toStyle(this, "fill"); + const color = style.color; + if (color) { + if (color === "#000000") { + delete style.color; + } else if (!color.startsWith("#")) { + style.background = color; + style.backgroundClip = "text"; + style.color = "transparent"; + } + } + if (this.baselineShift) { + style.verticalAlign = measureToString(this.baselineShift); + } + style.fontKerning = this.kerningMode === "none" ? "none" : "normal"; + style.letterSpacing = measureToString(this.letterSpacing); + if (this.lineThrough !== 0) { + style.textDecoration = "line-through"; + if (this.lineThrough === 2) { + style.textDecorationStyle = "double"; + } + } + if (this.overline !== 0) { + style.textDecoration = "overline"; + if (this.overline === 2) { + style.textDecorationStyle = "double"; + } + } + style.fontStyle = this.posture; + style.fontSize = measureToString(0.99 * this.size); + setFontFamily(this, this, this[$globalData].fontFinder, style); + if (this.underline !== 0) { + style.textDecoration = "underline"; + if (this.underline === 2) { + style.textDecorationStyle = "double"; + } + } + style.fontWeight = this.weight; + return style; + } +} +class Format extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "format", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.picture = null; + } +} +class Handler extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "handler"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Hyphenation extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "hyphenation"); + this.excludeAllCaps = getInteger({ + data: attributes.excludeAllCaps, + defaultValue: 0, + validate: x => x === 1 + }); + this.excludeInitialCap = getInteger({ + data: attributes.excludeInitialCap, + defaultValue: 0, + validate: x => x === 1 + }); + this.hyphenate = getInteger({ + data: attributes.hyphenate, + defaultValue: 0, + validate: x => x === 1 + }); + this.id = attributes.id || ""; + this.pushCharacterCount = getInteger({ + data: attributes.pushCharacterCount, + defaultValue: 3, + validate: x => x >= 0 + }); + this.remainCharacterCount = getInteger({ + data: attributes.remainCharacterCount, + defaultValue: 3, + validate: x => x >= 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.wordCharacterCount = getInteger({ + data: attributes.wordCharacterCount, + defaultValue: 7, + validate: x => x >= 0 + }); + } +} +class Image extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "image"); + this.aspect = getStringOption(attributes.aspect, ["fit", "actual", "height", "none", "width"]); + this.contentType = attributes.contentType || ""; + this.href = attributes.href || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.transferEncoding = getStringOption(attributes.transferEncoding, ["base64", "none", "package"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$toHTML]() { + if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) { + return HTMLResult.EMPTY; + } + let buffer = this[$globalData].images?.get(this.href); + if (!buffer && (this.href || !this[$content])) { + return HTMLResult.EMPTY; + } + if (!buffer && this.transferEncoding === "base64") { + buffer = fromBase64Util(this[$content]); + } + if (!buffer) { + return HTMLResult.EMPTY; + } + if (!this.contentType) { + for (const [header, type] of IMAGES_HEADERS) { + if (buffer.length > header.length && header.every((x, i) => x === buffer[i])) { + this.contentType = type; + break; + } + } + if (!this.contentType) { + return HTMLResult.EMPTY; + } + } + const blob = new Blob([buffer], { + type: this.contentType + }); + let style; + switch (this.aspect) { + case "fit": + case "actual": + break; + case "height": + style = { + height: "100%", + objectFit: "fill" + }; + break; + case "none": + style = { + width: "100%", + height: "100%", + objectFit: "fill" + }; + break; + case "width": + style = { + width: "100%", + objectFit: "fill" + }; + break; + } + const parent = this[$getParent](); + return HTMLResult.success({ + name: "img", + attributes: { + class: ["xfaImage"], + style, + src: URL.createObjectURL(blob), + alt: parent ? ariaLabel(parent[$getParent]()) : null + } + }); + } +} +class ImageEdit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "imageEdit", true); + this.data = getStringOption(attributes.data, ["link", "embed"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + if (this.data === "embed") { + return HTMLResult.success({ + name: "div", + children: [], + attributes: {} + }); + } + return HTMLResult.EMPTY; + } +} +class Integer extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "integer"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number = parseInt(this[$content].trim(), 10); + this[$content] = isNaN(number) ? null : number; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } +} +class Issuers extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "issuers", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } +} +class Items extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "items", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.ref = attributes.ref || ""; + this.save = getInteger({ + data: attributes.save, + defaultValue: 0, + validate: x => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + [$toHTML]() { + const output = []; + for (const child of this[$getChildren]()) { + output.push(child[$text]()); + } + return HTMLResult.success(output); + } +} +class Keep extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "keep", true); + this.id = attributes.id || ""; + const options = ["none", "contentArea", "pageArea"]; + this.intact = getStringOption(attributes.intact, options); + this.next = getStringOption(attributes.next, options); + this.previous = getStringOption(attributes.previous, options); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } +} +class KeyUsage extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "keyUsage"); + const options = ["", "yes", "no"]; + this.crlSign = getStringOption(attributes.crlSign, options); + this.dataEncipherment = getStringOption(attributes.dataEncipherment, options); + this.decipherOnly = getStringOption(attributes.decipherOnly, options); + this.digitalSignature = getStringOption(attributes.digitalSignature, options); + this.encipherOnly = getStringOption(attributes.encipherOnly, options); + this.id = attributes.id || ""; + this.keyAgreement = getStringOption(attributes.keyAgreement, options); + this.keyCertSign = getStringOption(attributes.keyCertSign, options); + this.keyEncipherment = getStringOption(attributes.keyEncipherment, options); + this.nonRepudiation = getStringOption(attributes.nonRepudiation, options); + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Line extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "line", true); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.slope = getStringOption(attributes.slope, ["\\", "/"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.edge = null; + } + [$toHTML]() { + const parent = this[$getParent]()[$getParent](); + const edge = this.edge || new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = Object.create(null); + const thickness = edge.presence === "visible" ? edge.thickness : 0; + style.strokeWidth = measureToString(thickness); + style.stroke = edgeStyle.color; + let x1, y1, x2, y2; + let width = "100%"; + let height = "100%"; + if (parent.w <= thickness) { + [x1, y1, x2, y2] = ["50%", 0, "50%", "100%"]; + width = style.strokeWidth; + } else if (parent.h <= thickness) { + [x1, y1, x2, y2] = [0, "50%", "100%", "50%"]; + height = style.strokeWidth; + } else if (this.slope === "\\") { + [x1, y1, x2, y2] = [0, 0, "100%", "100%"]; + } else { + [x1, y1, x2, y2] = [0, "100%", "100%", 0]; + } + const line = { + name: "line", + attributes: { + xmlns: SVG_NS, + x1, + y1, + x2, + y2, + style + } + }; + const svg = { + name: "svg", + children: [line], + attributes: { + xmlns: SVG_NS, + width, + height, + style: { + overflow: "visible" + } + } + }; + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } +} +class Linear extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "linear", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["toRight", "toBottom", "toLeft", "toTop"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const transf = this.type.replace(/([RBLT])/, " $1").toLowerCase(); + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + return `linear-gradient(${transf}, ${startColor}, ${endColor})`; + } +} +class LockDocument extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "lockDocument"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + this[$content] = getStringOption(this[$content], ["auto", "0", "1"]); + } +} +class Manifest extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "manifest", true); + this.action = getStringOption(attributes.action, ["include", "all", "exclude"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.ref = new XFAObjectArray(); + } +} +class Margin extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "margin", true); + this.bottomInset = getMeasurement(attributes.bottomInset, "0"); + this.id = attributes.id || ""; + this.leftInset = getMeasurement(attributes.leftInset, "0"); + this.rightInset = getMeasurement(attributes.rightInset, "0"); + this.topInset = getMeasurement(attributes.topInset, "0"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toStyle]() { + return { + margin: measureToString(this.topInset) + " " + measureToString(this.rightInset) + " " + measureToString(this.bottomInset) + " " + measureToString(this.leftInset) + }; + } +} +class Mdp extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "mdp"); + this.id = attributes.id || ""; + this.permissions = getInteger({ + data: attributes.permissions, + defaultValue: 2, + validate: x => x === 1 || x === 3 + }); + this.signatureType = getStringOption(attributes.signatureType, ["filler", "author"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Medium extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "medium"); + this.id = attributes.id || ""; + this.imagingBBox = getBBox(attributes.imagingBBox); + this.long = getMeasurement(attributes.long); + this.orientation = getStringOption(attributes.orientation, ["portrait", "landscape"]); + this.short = getMeasurement(attributes.short); + this.stock = attributes.stock || ""; + this.trayIn = getStringOption(attributes.trayIn, ["auto", "delegate", "pageFront"]); + this.trayOut = getStringOption(attributes.trayOut, ["auto", "delegate"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Message extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "message", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.text = new XFAObjectArray(); + } +} +class NumericEdit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "numericEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + const field = this[$getParent]()[$getParent](); + const html = { + name: "input", + attributes: { + type: "text", + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } +} +class Occur extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "occur", true); + this.id = attributes.id || ""; + this.initial = attributes.initial !== "" ? getInteger({ + data: attributes.initial, + defaultValue: "", + validate: x => true + }) : ""; + this.max = attributes.max !== "" ? getInteger({ + data: attributes.max, + defaultValue: -1, + validate: x => true + }) : ""; + this.min = attributes.min !== "" ? getInteger({ + data: attributes.min, + defaultValue: 1, + validate: x => true + }) : ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$clean]() { + const parent = this[$getParent](); + const originalMin = this.min; + if (this.min === "") { + this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1; + } + if (this.max === "") { + if (originalMin === "") { + this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1; + } else { + this.max = this.min; + } + } + if (this.max !== -1 && this.max < this.min) { + this.max = this.min; + } + if (this.initial === "") { + this.initial = parent instanceof Template ? 1 : this.min; + } + } +} +class Oid extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "oid"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Oids extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "oids", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.oid = new XFAObjectArray(); + } +} +class Overflow extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "overflow"); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.target = attributes.target || ""; + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$getExtra]() { + if (!this[$extra]) { + const parent = this[$getParent](); + const root = this[$getTemplateRoot](); + const target = root[$searchNode](this.target, parent); + const leader = root[$searchNode](this.leader, parent); + const trailer = root[$searchNode](this.trailer, parent); + this[$extra] = { + target: target?.[0] || null, + leader: leader?.[0] || null, + trailer: trailer?.[0] || null, + addLeader: false, + addTrailer: false + }; + } + return this[$extra]; + } +} +class PageArea extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pageArea", true); + this.blankOrNotBlank = getStringOption(attributes.blankOrNotBlank, ["any", "blank", "notBlank"]); + this.id = attributes.id || ""; + this.initialNumber = getInteger({ + data: attributes.initialNumber, + defaultValue: 1, + validate: x => true + }); + this.name = attributes.name || ""; + this.numbered = getInteger({ + data: attributes.numbered, + defaultValue: 1, + validate: x => true + }); + this.oddOrEven = getStringOption(attributes.oddOrEven, ["any", "even", "odd"]); + this.pagePosition = getStringOption(attributes.pagePosition, ["any", "first", "last", "only", "rest"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.desc = null; + this.extras = null; + this.medium = null; + this.occur = null; + this.area = new XFAObjectArray(); + this.contentArea = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + } + [$isUsable]() { + if (!this[$extra]) { + this[$extra] = { + numberOfUse: 0 + }; + return true; + } + return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; + } + [$cleanPage]() { + delete this[$extra]; + } + [$getNextPage]() { + this[$extra] ||= { + numberOfUse: 0 + }; + const parent = this[$getParent](); + if (parent.relation === "orderedOccurrence") { + if (this[$isUsable]()) { + this[$extra].numberOfUse += 1; + return this; + } + } + return parent[$getNextPage](); + } + [$getAvailableSpace]() { + return this[$extra].space || { + width: 0, + height: 0 + }; + } + [$toHTML]() { + this[$extra] ||= { + numberOfUse: 1 + }; + const children = []; + this[$extra].children = children; + const style = Object.create(null); + if (this.medium && this.medium.short && this.medium.long) { + style.width = measureToString(this.medium.short); + style.height = measureToString(this.medium.long); + this[$extra].space = { + width: this.medium.short, + height: this.medium.long + }; + if (this.medium.orientation === "landscape") { + const x = style.width; + style.width = style.height; + style.height = x; + this[$extra].space = { + width: this.medium.long, + height: this.medium.short + }; + } + } else { + warn("XFA - No medium specified in pageArea: please file a bug."); + } + this[$childrenToHTML]({ + filter: new Set(["area", "draw", "field", "subform"]), + include: true + }); + this[$childrenToHTML]({ + filter: new Set(["contentArea"]), + include: true + }); + return HTMLResult.success({ + name: "div", + children, + attributes: { + class: ["xfaPage"], + id: this[$uid], + style, + xfaName: this.name + } + }); + } +} +class PageSet extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pageSet", true); + this.duplexImposition = getStringOption(attributes.duplexImposition, ["longEdge", "shortEdge"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relation = getStringOption(attributes.relation, ["orderedOccurrence", "duplexPaginated", "simplexPaginated"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.occur = null; + this.pageArea = new XFAObjectArray(); + this.pageSet = new XFAObjectArray(); + } + [$cleanPage]() { + for (const page of this.pageArea.children) { + page[$cleanPage](); + } + for (const page of this.pageSet.children) { + page[$cleanPage](); + } + } + [$isUsable]() { + return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; + } + [$getNextPage]() { + this[$extra] ||= { + numberOfUse: 1, + pageIndex: -1, + pageSetIndex: -1 + }; + if (this.relation === "orderedOccurrence") { + if (this[$extra].pageIndex + 1 < this.pageArea.children.length) { + this[$extra].pageIndex += 1; + const pageArea = this.pageArea.children[this[$extra].pageIndex]; + return pageArea[$getNextPage](); + } + if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) { + this[$extra].pageSetIndex += 1; + return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage](); + } + if (this[$isUsable]()) { + this[$extra].numberOfUse += 1; + this[$extra].pageIndex = -1; + this[$extra].pageSetIndex = -1; + return this[$getNextPage](); + } + const parent = this[$getParent](); + if (parent instanceof PageSet) { + return parent[$getNextPage](); + } + this[$cleanPage](); + return this[$getNextPage](); + } + const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber; + const parity = pageNumber % 2 === 0 ? "even" : "odd"; + const position = pageNumber === 0 ? "first" : "rest"; + let page = this.pageArea.children.find(p => p.oddOrEven === parity && p.pagePosition === position); + if (page) { + return page; + } + page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === position); + if (page) { + return page; + } + page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === "any"); + if (page) { + return page; + } + return this.pageArea.children[0]; + } +} +class Para extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "para", true); + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.lineHeight = attributes.lineHeight ? getMeasurement(attributes.lineHeight, "0pt") : ""; + this.marginLeft = attributes.marginLeft ? getMeasurement(attributes.marginLeft, "0pt") : ""; + this.marginRight = attributes.marginRight ? getMeasurement(attributes.marginRight, "0pt") : ""; + this.orphans = getInteger({ + data: attributes.orphans, + defaultValue: 0, + validate: x => x >= 0 + }); + this.preserve = attributes.preserve || ""; + this.radixOffset = attributes.radixOffset ? getMeasurement(attributes.radixOffset, "0pt") : ""; + this.spaceAbove = attributes.spaceAbove ? getMeasurement(attributes.spaceAbove, "0pt") : ""; + this.spaceBelow = attributes.spaceBelow ? getMeasurement(attributes.spaceBelow, "0pt") : ""; + this.tabDefault = attributes.tabDefault ? getMeasurement(this.tabDefault) : ""; + this.tabStops = (attributes.tabStops || "").trim().split(/\s+/).map((x, i) => i % 2 === 1 ? getMeasurement(x) : x); + this.textIndent = attributes.textIndent ? getMeasurement(attributes.textIndent, "0pt") : ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.vAlign = getStringOption(attributes.vAlign, ["top", "bottom", "middle"]); + this.widows = getInteger({ + data: attributes.widows, + defaultValue: 0, + validate: x => x >= 0 + }); + this.hyphenation = null; + } + [$toStyle]() { + const style = toStyle(this, "hAlign"); + if (this.marginLeft !== "") { + style.paddingLeft = measureToString(this.marginLeft); + } + if (this.marginRight !== "") { + style.paddingRight = measureToString(this.marginRight); + } + if (this.spaceAbove !== "") { + style.paddingTop = measureToString(this.spaceAbove); + } + if (this.spaceBelow !== "") { + style.paddingBottom = measureToString(this.spaceBelow); + } + if (this.textIndent !== "") { + style.textIndent = measureToString(this.textIndent); + fixTextIndent(style); + } + if (this.lineHeight > 0) { + style.lineHeight = measureToString(this.lineHeight); + } + if (this.tabDefault !== "") { + style.tabSize = measureToString(this.tabDefault); + } + if (this.tabStops.length > 0) {} + if (this.hyphenatation) { + Object.assign(style, this.hyphenatation[$toStyle]()); + } + return style; + } +} +class PasswordEdit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "passwordEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.passwordChar = attributes.passwordChar || "*"; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } +} +class template_Pattern extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pattern", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["crossHatch", "crossDiagonal", "diagonalLeft", "diagonalRight", "horizontal", "vertical"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + const width = 5; + const cmd = "repeating-linear-gradient"; + const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`; + switch (this.type) { + case "crossHatch": + return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`; + case "crossDiagonal": + return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`; + case "diagonalLeft": + return `${cmd}(45deg,${colors})`; + case "diagonalRight": + return `${cmd}(-45deg,${colors})`; + case "horizontal": + return `${cmd}(to top,${colors})`; + case "vertical": + return `${cmd}(to right,${colors})`; + } + return ""; + } +} +class Picture extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "picture"); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Proto extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "proto", true); + this.appearanceFilter = new XFAObjectArray(); + this.arc = new XFAObjectArray(); + this.area = new XFAObjectArray(); + this.assist = new XFAObjectArray(); + this.barcode = new XFAObjectArray(); + this.bindItems = new XFAObjectArray(); + this.bookend = new XFAObjectArray(); + this.boolean = new XFAObjectArray(); + this.border = new XFAObjectArray(); + this.break = new XFAObjectArray(); + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.button = new XFAObjectArray(); + this.calculate = new XFAObjectArray(); + this.caption = new XFAObjectArray(); + this.certificate = new XFAObjectArray(); + this.certificates = new XFAObjectArray(); + this.checkButton = new XFAObjectArray(); + this.choiceList = new XFAObjectArray(); + this.color = new XFAObjectArray(); + this.comb = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.contentArea = new XFAObjectArray(); + this.corner = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.dateTimeEdit = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.defaultUi = new XFAObjectArray(); + this.desc = new XFAObjectArray(); + this.digestMethod = new XFAObjectArray(); + this.digestMethods = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.edge = new XFAObjectArray(); + this.encoding = new XFAObjectArray(); + this.encodings = new XFAObjectArray(); + this.encrypt = new XFAObjectArray(); + this.encryptData = new XFAObjectArray(); + this.encryption = new XFAObjectArray(); + this.encryptionMethod = new XFAObjectArray(); + this.encryptionMethods = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.execute = new XFAObjectArray(); + this.extras = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.fill = new XFAObjectArray(); + this.filter = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.font = new XFAObjectArray(); + this.format = new XFAObjectArray(); + this.handler = new XFAObjectArray(); + this.hyphenation = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.imageEdit = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.issuers = new XFAObjectArray(); + this.items = new XFAObjectArray(); + this.keep = new XFAObjectArray(); + this.keyUsage = new XFAObjectArray(); + this.line = new XFAObjectArray(); + this.linear = new XFAObjectArray(); + this.lockDocument = new XFAObjectArray(); + this.manifest = new XFAObjectArray(); + this.margin = new XFAObjectArray(); + this.mdp = new XFAObjectArray(); + this.medium = new XFAObjectArray(); + this.message = new XFAObjectArray(); + this.numericEdit = new XFAObjectArray(); + this.occur = new XFAObjectArray(); + this.oid = new XFAObjectArray(); + this.oids = new XFAObjectArray(); + this.overflow = new XFAObjectArray(); + this.pageArea = new XFAObjectArray(); + this.pageSet = new XFAObjectArray(); + this.para = new XFAObjectArray(); + this.passwordEdit = new XFAObjectArray(); + this.pattern = new XFAObjectArray(); + this.picture = new XFAObjectArray(); + this.radial = new XFAObjectArray(); + this.reason = new XFAObjectArray(); + this.reasons = new XFAObjectArray(); + this.rectangle = new XFAObjectArray(); + this.ref = new XFAObjectArray(); + this.script = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + this.signData = new XFAObjectArray(); + this.signature = new XFAObjectArray(); + this.signing = new XFAObjectArray(); + this.solid = new XFAObjectArray(); + this.speak = new XFAObjectArray(); + this.stipple = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + this.subjectDN = new XFAObjectArray(); + this.subjectDNs = new XFAObjectArray(); + this.submit = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.textEdit = new XFAObjectArray(); + this.time = new XFAObjectArray(); + this.timeStamp = new XFAObjectArray(); + this.toolTip = new XFAObjectArray(); + this.traversal = new XFAObjectArray(); + this.traverse = new XFAObjectArray(); + this.ui = new XFAObjectArray(); + this.validate = new XFAObjectArray(); + this.value = new XFAObjectArray(); + this.variables = new XFAObjectArray(); + } +} +class Radial extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "radial", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["toEdge", "toCenter"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + const colors = this.type === "toEdge" ? `${startColor},${endColor}` : `${endColor},${startColor}`; + return `radial-gradient(circle at center, ${colors})`; + } +} +class Reason extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "reason"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Reasons extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "reasons", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.reason = new XFAObjectArray(); + } +} +class Rectangle extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "rectangle", true); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.corner = new XFAObjectArray(4); + this.edge = new XFAObjectArray(4); + this.fill = null; + } + [$toHTML]() { + const edge = this.edge.children.length ? this.edge.children[0] : new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = Object.create(null); + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } else { + style.fill = "transparent"; + } + style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); + style.stroke = edgeStyle.color; + const corner = this.corner.children.length ? this.corner.children[0] : new Corner({}); + const cornerStyle = corner[$toStyle](); + const rect = { + name: "rect", + attributes: { + xmlns: SVG_NS, + width: "100%", + height: "100%", + x: 0, + y: 0, + rx: cornerStyle.radius, + ry: cornerStyle.radius, + style + } + }; + const svg = { + name: "svg", + children: [rect], + attributes: { + xmlns: SVG_NS, + style: { + overflow: "visible" + }, + width: "100%", + height: "100%" + } + }; + const parent = this[$getParent]()[$getParent](); + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } +} +class RefElement extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "ref"); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Script extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "script"); + this.binding = attributes.binding || ""; + this.contentType = attributes.contentType || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class SetProperty extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "setProperty"); + this.connection = attributes.connection || ""; + this.ref = attributes.ref || ""; + this.target = attributes.target || ""; + } +} +class SignData extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signData", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["sign", "clear", "verify"]); + this.ref = attributes.ref || ""; + this.target = attributes.target || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.filter = null; + this.manifest = null; + } +} +class Signature extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signature", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["PDF1.3", "PDF1.6"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.filter = null; + this.manifest = null; + this.margin = null; + } +} +class Signing extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signing", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } +} +class Solid extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "solid", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toStyle](startColor) { + return startColor ? startColor[$toStyle]() : "#FFFFFF"; + } +} +class Speak extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "speak"); + this.disable = getInteger({ + data: attributes.disable, + defaultValue: 0, + validate: x => x === 1 + }); + this.id = attributes.id || ""; + this.priority = getStringOption(attributes.priority, ["custom", "caption", "name", "toolTip"]); + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Stipple extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "stipple", true); + this.id = attributes.id || ""; + this.rate = getInteger({ + data: attributes.rate, + defaultValue: 50, + validate: x => x >= 0 && x <= 100 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](bgColor) { + const alpha = this.rate / 100; + return Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha)); + } +} +class Subform extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subform", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.allowMacro = getInteger({ + data: attributes.allowMacro, + defaultValue: 0, + validate: x => x === 1 + }); + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: n => n >= 1 || n === -1 + }); + this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map(x => x === "-1" ? -1 : getMeasurement(x)); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.mergeMode = getStringOption(attributes.mergeMode, ["consumeData", "matchTemplate"]); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.restoreState = getStringOption(attributes.restoreState, ["manual", "auto"]); + this.scope = getStringOption(attributes.scope, ["name", "none"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.bookend = null; + this.border = null; + this.break = null; + this.calculate = null; + this.desc = null; + this.extras = null; + this.keep = null; + this.margin = null; + this.occur = null; + this.overflow = null; + this.pageSet = null; + this.para = null; + this.traversal = null; + this.validate = null; + this.variables = null; + this.area = new XFAObjectArray(); + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.proto = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + [$getSubformParent]() { + const parent = this[$getParent](); + if (parent instanceof SubformSet) { + return parent[$getSubformParent](); + } + return parent; + } + [$isBindable]() { + return true; + } + [$isThereMoreWidth]() { + return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$flushHTML]() { + return flushHTML(this); + } + [$addHTML](html, bbox) { + addHTML(this, html, bbox); + } + [$getAvailableSpace]() { + return getAvailableSpace(this); + } + [$isSplittable]() { + const parent = this[$getSubformParent](); + if (!parent[$isSplittable]()) { + return false; + } + if (this[$extra]._isSplittable !== undefined) { + return this[$extra]._isSplittable; + } + if (this.layout === "position" || this.layout.includes("row")) { + this[$extra]._isSplittable = false; + return false; + } + if (this.keep && this.keep.intact !== "none") { + this[$extra]._isSplittable = false; + return false; + } + if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { + return false; + } + this[$extra]._isSplittable = true; + return true; + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.break) { + if (this.break.after !== "auto" || this.break.afterTarget !== "") { + const node = new BreakAfter({ + targetType: this.break.after, + target: this.break.afterTarget, + startNew: this.break.startNew.toString() + }); + node[$globalData] = this[$globalData]; + this[$appendChild](node); + this.breakAfter.push(node); + } + if (this.break.before !== "auto" || this.break.beforeTarget !== "") { + const node = new BreakBefore({ + targetType: this.break.before, + target: this.break.beforeTarget, + startNew: this.break.startNew.toString() + }); + node[$globalData] = this[$globalData]; + this[$appendChild](node); + this.breakBefore.push(node); + } + if (this.break.overflowTarget !== "") { + const node = new Overflow({ + target: this.break.overflowTarget, + leader: this.break.overflowLeader, + trailer: this.break.overflowTrailer + }); + node[$globalData] = this[$globalData]; + this[$appendChild](node); + this.overflow.push(node); + } + this[$removeChild](this.break); + this.break = null; + } + if (this.presence === "hidden" || this.presence === "inactive") { + return HTMLResult.EMPTY; + } + if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) { + warn("XFA - Several breakBefore or breakAfter in subforms: please file a bug."); + } + if (this.breakBefore.children.length >= 1) { + const breakBefore = this.breakBefore.children[0]; + if (handleBreak(breakBefore)) { + return HTMLResult.breakNode(breakBefore); + } + } + if (this[$extra]?.afterBreakAfter) { + return HTMLResult.EMPTY; + } + fixDimensions(this); + const children = []; + const attributes = { + id: this[$uid], + class: [] + }; + setAccess(this, attributes.class); + this[$extra] ||= Object.create(null); + Object.assign(this[$extra], { + children, + line: null, + attributes, + attempt: 0, + numberInLine: 0, + availableSpace: { + width: Math.min(this.w || Infinity, availableSpace.width), + height: Math.min(this.h || Infinity, availableSpace.height) + }, + width: 0, + height: 0, + prevHeight: 0, + currentWidth: 0 + }); + const root = this[$getTemplateRoot](); + const savedNoLayoutFailure = root[$extra].noLayoutFailure; + const isSplittable = this[$isSplittable](); + if (!isSplittable) { + setFirstUnsplittable(this); + } + if (!checkDimensions(this, availableSpace)) { + return HTMLResult.FAILURE; + } + const filter = new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]); + if (this.layout.includes("row")) { + const columnWidths = this[$getSubformParent]().columnWidths; + if (Array.isArray(columnWidths) && columnWidths.length > 0) { + this[$extra].columnWidths = columnWidths; + this[$extra].currentColumn = 0; + } + } + const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); + const classNames = ["xfaSubform"]; + const cl = layoutClass(this); + if (cl) { + classNames.push(cl); + } + attributes.style = style; + attributes.class = classNames; + if (this.name) { + attributes.xfaName = this.name; + } + if (this.overflow) { + const overflowExtra = this.overflow[$getExtra](); + if (overflowExtra.addLeader) { + overflowExtra.addLeader = false; + handleOverflow(this, overflowExtra.leader, availableSpace); + } + } + this[$pushPara](); + const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; + const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; + for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { + if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { + this[$extra].numberInLine = 0; + } + const result = this[$childrenToHTML]({ + filter, + include: true + }); + if (result.success) { + break; + } + if (result.isBreak()) { + this[$popPara](); + return result; + } + if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root[$extra].noLayoutFailure) { + this[$extra].attempt = maxRun; + break; + } + } + this[$popPara](); + if (!isSplittable) { + unsetFirstUnsplittable(this); + } + root[$extra].noLayoutFailure = savedNoLayoutFailure; + if (this[$extra].attempt === maxRun) { + if (this.overflow) { + this[$getTemplateRoot]()[$extra].overflowNode = this.overflow; + } + if (!isSplittable) { + delete this[$extra]; + } + return HTMLResult.FAILURE; + } + if (this.overflow) { + const overflowExtra = this.overflow[$getExtra](); + if (overflowExtra.addTrailer) { + overflowExtra.addTrailer = false; + handleOverflow(this, overflowExtra.trailer, availableSpace); + } + } + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + const width = Math.max(this[$extra].width + marginH, this.w || 0); + const height = Math.max(this[$extra].height + marginV, this.h || 0); + const bbox = [this.x, this.y, width, height]; + if (this.w === "") { + style.width = measureToString(width); + } + if (this.h === "") { + style.height = measureToString(height); + } + if ((style.width === "0px" || style.height === "0px") && children.length === 0) { + return HTMLResult.EMPTY; + } + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + const result = HTMLResult.success(createWrapper(this, html), bbox); + if (this.breakAfter.children.length >= 1) { + const breakAfter = this.breakAfter.children[0]; + if (handleBreak(breakAfter)) { + this[$extra].afterBreakAfter = result; + return HTMLResult.breakNode(breakAfter); + } + } + delete this[$extra]; + return result; + } +} +class SubformSet extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subformSet", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relation = getStringOption(attributes.relation, ["ordered", "choice", "unordered"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.bookend = null; + this.break = null; + this.desc = null; + this.extras = null; + this.occur = null; + this.overflow = null; + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$getSubformParent]() { + let parent = this[$getParent](); + while (!(parent instanceof Subform)) { + parent = parent[$getParent](); + } + return parent; + } + [$isBindable]() { + return true; + } +} +class SubjectDN extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subjectDN"); + this.delimiter = attributes.delimiter || ","; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + this[$content] = new Map(this[$content].split(this.delimiter).map(kv => { + kv = kv.split("=", 2); + kv[0] = kv[0].trim(); + return kv; + })); + } +} +class SubjectDNs extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subjectDNs", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.subjectDN = new XFAObjectArray(); + } +} +class Submit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "submit", true); + this.embedPDF = getInteger({ + data: attributes.embedPDF, + defaultValue: 0, + validate: x => x === 1 + }); + this.format = getStringOption(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]); + this.id = attributes.id || ""; + this.target = attributes.target || ""; + this.textEncoding = getKeyword({ + data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "", + defaultValue: "", + validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.xdpContent = attributes.xdpContent || ""; + this.encrypt = null; + this.encryptData = new XFAObjectArray(); + this.signData = new XFAObjectArray(); + } +} +class Template extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "template", true); + this.baseProfile = getStringOption(attributes.baseProfile, ["full", "interactiveForms"]); + this.extras = null; + this.subform = new XFAObjectArray(); + } + [$finalize]() { + if (this.subform.children.length === 0) { + warn("XFA - No subforms in template node."); + } + if (this.subform.children.length >= 2) { + warn("XFA - Several subforms in template node: please file a bug."); + } + this[$tabIndex] = DEFAULT_TAB_INDEX; + } + [$isSplittable]() { + return true; + } + [$searchNode](expr, container) { + if (expr.startsWith("#")) { + return [this[$ids].get(expr.slice(1))]; + } + return searchNode(this, container, expr, true, true); + } + *[$toPages]() { + if (!this.subform.children.length) { + return HTMLResult.success({ + name: "div", + children: [] + }); + } + this[$extra] = { + overflowNode: null, + firstUnsplittable: null, + currentContentArea: null, + currentPageArea: null, + noLayoutFailure: false, + pageNumber: 1, + pagePosition: "first", + oddOrEven: "odd", + blankOrNotBlank: "nonBlank", + paraStack: [] + }; + const root = this.subform.children[0]; + root.pageSet[$cleanPage](); + const pageAreas = root.pageSet.pageArea.children; + const mainHtml = { + name: "div", + children: [] + }; + let pageArea = null; + let breakBefore = null; + let breakBeforeTarget = null; + if (root.breakBefore.children.length >= 1) { + breakBefore = root.breakBefore.children[0]; + breakBeforeTarget = breakBefore.target; + } else if (root.subform.children.length >= 1 && root.subform.children[0].breakBefore.children.length >= 1) { + breakBefore = root.subform.children[0].breakBefore.children[0]; + breakBeforeTarget = breakBefore.target; + } else if (root.break?.beforeTarget) { + breakBefore = root.break; + breakBeforeTarget = breakBefore.beforeTarget; + } else if (root.subform.children.length >= 1 && root.subform.children[0].break?.beforeTarget) { + breakBefore = root.subform.children[0].break; + breakBeforeTarget = breakBefore.beforeTarget; + } + if (breakBefore) { + const target = this[$searchNode](breakBeforeTarget, breakBefore[$getParent]()); + if (target instanceof PageArea) { + pageArea = target; + breakBefore[$extra] = {}; + } + } + pageArea ||= pageAreas[0]; + pageArea[$extra] = { + numberOfUse: 1 + }; + const pageAreaParent = pageArea[$getParent](); + pageAreaParent[$extra] = { + numberOfUse: 1, + pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea), + pageSetIndex: 0 + }; + let targetPageArea; + let leader = null; + let trailer = null; + let hasSomething = true; + let hasSomethingCounter = 0; + let startIndex = 0; + while (true) { + if (!hasSomething) { + mainHtml.children.pop(); + if (++hasSomethingCounter === MAX_EMPTY_PAGES) { + warn("XFA - Something goes wrong: please file a bug."); + return mainHtml; + } + } else { + hasSomethingCounter = 0; + } + targetPageArea = null; + this[$extra].currentPageArea = pageArea; + const page = pageArea[$toHTML]().html; + mainHtml.children.push(page); + if (leader) { + this[$extra].noLayoutFailure = true; + page.children.push(leader[$toHTML](pageArea[$extra].space).html); + leader = null; + } + if (trailer) { + this[$extra].noLayoutFailure = true; + page.children.push(trailer[$toHTML](pageArea[$extra].space).html); + trailer = null; + } + const contentAreas = pageArea.contentArea.children; + const htmlContentAreas = page.children.filter(node => node.attributes.class.includes("xfaContentarea")); + hasSomething = false; + this[$extra].firstUnsplittable = null; + this[$extra].noLayoutFailure = false; + const flush = index => { + const html = root[$flushHTML](); + if (html) { + hasSomething ||= html.children?.length > 0; + htmlContentAreas[index].children.push(html); + } + }; + for (let i = startIndex, ii = contentAreas.length; i < ii; i++) { + const contentArea = this[$extra].currentContentArea = contentAreas[i]; + const space = { + width: contentArea.w, + height: contentArea.h + }; + startIndex = 0; + if (leader) { + htmlContentAreas[i].children.push(leader[$toHTML](space).html); + leader = null; + } + if (trailer) { + htmlContentAreas[i].children.push(trailer[$toHTML](space).html); + trailer = null; + } + const html = root[$toHTML](space); + if (html.success) { + if (html.html) { + hasSomething ||= html.html.children?.length > 0; + htmlContentAreas[i].children.push(html.html); + } else if (!hasSomething && mainHtml.children.length > 1) { + mainHtml.children.pop(); + } + return mainHtml; + } + if (html.isBreak()) { + const node = html.breakNode; + flush(i); + if (node.targetType === "auto") { + continue; + } + if (node.leader) { + leader = this[$searchNode](node.leader, node[$getParent]()); + leader = leader ? leader[0] : null; + } + if (node.trailer) { + trailer = this[$searchNode](node.trailer, node[$getParent]()); + trailer = trailer ? trailer[0] : null; + } + if (node.targetType === "pageArea") { + targetPageArea = node[$extra].target; + i = Infinity; + } else if (!node[$extra].target) { + i = node[$extra].index; + } else { + targetPageArea = node[$extra].target; + startIndex = node[$extra].index + 1; + i = Infinity; + } + continue; + } + if (this[$extra].overflowNode) { + const node = this[$extra].overflowNode; + this[$extra].overflowNode = null; + const overflowExtra = node[$getExtra](); + const target = overflowExtra.target; + overflowExtra.addLeader = overflowExtra.leader !== null; + overflowExtra.addTrailer = overflowExtra.trailer !== null; + flush(i); + const currentIndex = i; + i = Infinity; + if (target instanceof PageArea) { + targetPageArea = target; + } else if (target instanceof ContentArea) { + const index = contentAreas.indexOf(target); + if (index !== -1) { + if (index > currentIndex) { + i = index - 1; + } else { + startIndex = index; + } + } else { + targetPageArea = target[$getParent](); + startIndex = targetPageArea.contentArea.children.indexOf(target); + } + } + continue; + } + flush(i); + } + this[$extra].pageNumber += 1; + if (targetPageArea) { + if (targetPageArea[$isUsable]()) { + targetPageArea[$extra].numberOfUse += 1; + } else { + targetPageArea = null; + } + } + pageArea = targetPageArea || pageArea[$getNextPage](); + yield null; + } + } +} +class Text extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "text"); + this.id = attributes.id || ""; + this.maxChars = getInteger({ + data: attributes.maxChars, + defaultValue: 0, + validate: x => x >= 0 + }); + this.name = attributes.name || ""; + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$acceptWhitespace]() { + return true; + } + [$onChild](child) { + if (child[$namespaceId] === NamespaceIds.xhtml.id) { + this[$content] = child; + return true; + } + warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`); + return false; + } + [$onText](str) { + if (this[$content] instanceof XFAObject) { + return; + } + super[$onText](str); + } + [$finalize]() { + if (typeof this[$content] === "string") { + this[$content] = this[$content].replaceAll("\r\n", "\n"); + } + } + [$getExtra]() { + if (typeof this[$content] === "string") { + return this[$content].split(/[\u2029\u2028\n]/).filter(line => !!line).join("\n"); + } + return this[$content][$text](); + } + [$toHTML](availableSpace) { + if (typeof this[$content] === "string") { + const html = valueToHtml(this[$content]).html; + if (this[$content].includes("\u2029")) { + html.name = "div"; + html.children = []; + this[$content].split("\u2029").map(para => para.split(/[\u2028\n]/).flatMap(line => [{ + name: "span", + value: line + }, { + name: "br" + }])).forEach(lines => { + html.children.push({ + name: "p", + children: lines + }); + }); + } else if (/[\u2028\n]/.test(this[$content])) { + html.name = "div"; + html.children = []; + this[$content].split(/[\u2028\n]/).forEach(line => { + html.children.push({ + name: "span", + value: line + }, { + name: "br" + }); + }); + } + return HTMLResult.success(html); + } + return this[$content][$toHTML](availableSpace); + } +} +class TextEdit extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "textEdit", true); + this.allowRichText = getInteger({ + data: attributes.allowRichText, + defaultValue: 0, + validate: x => x === 1 + }); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.multiLine = getInteger({ + data: attributes.multiLine, + defaultValue: "", + validate: x => x === 0 || x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.vScrollPolicy = getStringOption(attributes.vScrollPolicy, ["auto", "off", "on"]); + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + let html; + const field = this[$getParent]()[$getParent](); + if (this.multiLine === "") { + this.multiLine = field instanceof Draw ? 1 : 0; + } + if (this.multiLine === 1) { + html = { + name: "textarea", + attributes: { + dataId: field[$data]?.[$uid] || field[$uid], + fieldId: field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + } else { + html = { + name: "input", + attributes: { + type: "text", + dataId: field[$data]?.[$uid] || field[$uid], + fieldId: field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + } + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } +} +class Time extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "time"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date = this[$content].trim(); + this[$content] = date ? new Date(date) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } +} +class TimeStamp extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "timeStamp"); + this.id = attributes.id || ""; + this.server = attributes.server || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class ToolTip extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "toolTip"); + this.id = attributes.id || ""; + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Traversal extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "traversal", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.traverse = new XFAObjectArray(); + } +} +class Traverse extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "traverse", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["next", "back", "down", "first", "left", "right", "up"]); + this.ref = attributes.ref || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.script = null; + } + get name() { + return this.operation; + } + [$isTransparent]() { + return false; + } +} +class Ui extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "ui", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.picture = null; + this.barcode = null; + this.button = null; + this.checkButton = null; + this.choiceList = null; + this.dateTimeEdit = null; + this.defaultUi = null; + this.imageEdit = null; + this.numericEdit = null; + this.passwordEdit = null; + this.signature = null; + this.textEdit = null; + } + [$getExtra]() { + if (this[$extra] === undefined) { + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "extras" || name === "picture") { + continue; + } + const obj = this[name]; + if (!(obj instanceof XFAObject)) { + continue; + } + this[$extra] = obj; + return obj; + } + this[$extra] = null; + } + return this[$extra]; + } + [$toHTML](availableSpace) { + const obj = this[$getExtra](); + if (obj) { + return obj[$toHTML](availableSpace); + } + return HTMLResult.EMPTY; + } +} +class Validate extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "validate", true); + this.formatTest = getStringOption(attributes.formatTest, ["warning", "disabled", "error"]); + this.id = attributes.id || ""; + this.nullTest = getStringOption(attributes.nullTest, ["disabled", "error", "warning"]); + this.scriptTest = getStringOption(attributes.scriptTest, ["error", "disabled", "warning"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.message = null; + this.picture = null; + this.script = null; + } +} +class Value extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "value", true); + this.id = attributes.id || ""; + this.override = getInteger({ + data: attributes.override, + defaultValue: 0, + validate: x => x === 1 + }); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.arc = null; + this.boolean = null; + this.date = null; + this.dateTime = null; + this.decimal = null; + this.exData = null; + this.float = null; + this.image = null; + this.integer = null; + this.line = null; + this.rectangle = null; + this.text = null; + this.time = null; + } + [$setValue](value) { + const parent = this[$getParent](); + if (parent instanceof Field) { + if (parent.ui?.imageEdit) { + if (!this.image) { + this.image = new Image({}); + this[$appendChild](this.image); + } + this.image[$content] = value[$content]; + return; + } + } + const valueName = value[$nodeName]; + if (this[valueName] !== null) { + this[valueName][$content] = value[$content]; + return; + } + for (const name of Object.getOwnPropertyNames(this)) { + const obj = this[name]; + if (obj instanceof XFAObject) { + this[name] = null; + this[$removeChild](obj); + } + } + this[value[$nodeName]] = value; + this[$appendChild](value); + } + [$text]() { + if (this.exData) { + if (typeof this.exData[$content] === "string") { + return this.exData[$content].trim(); + } + return this.exData[$content][$text]().trim(); + } + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "image") { + continue; + } + const obj = this[name]; + if (obj instanceof XFAObject) { + return (obj[$content] || "").toString().trim(); + } + } + return null; + } + [$toHTML](availableSpace) { + for (const name of Object.getOwnPropertyNames(this)) { + const obj = this[name]; + if (!(obj instanceof XFAObject)) { + continue; + } + return obj[$toHTML](availableSpace); + } + return HTMLResult.EMPTY; + } +} +class Variables extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "variables", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.manifest = new XFAObjectArray(); + this.script = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + [$isTransparent]() { + return true; + } +} +class TemplateNamespace { + static [$buildXFAObject](name, attributes) { + if (TemplateNamespace.hasOwnProperty(name)) { + const node = TemplateNamespace[name](attributes); + node[$setSetAttributes](attributes); + return node; + } + return undefined; + } + static appearanceFilter(attrs) { + return new AppearanceFilter(attrs); + } + static arc(attrs) { + return new Arc(attrs); + } + static area(attrs) { + return new Area(attrs); + } + static assist(attrs) { + return new Assist(attrs); + } + static barcode(attrs) { + return new Barcode(attrs); + } + static bind(attrs) { + return new Bind(attrs); + } + static bindItems(attrs) { + return new BindItems(attrs); + } + static bookend(attrs) { + return new Bookend(attrs); + } + static boolean(attrs) { + return new BooleanElement(attrs); + } + static border(attrs) { + return new Border(attrs); + } + static break(attrs) { + return new Break(attrs); + } + static breakAfter(attrs) { + return new BreakAfter(attrs); + } + static breakBefore(attrs) { + return new BreakBefore(attrs); + } + static button(attrs) { + return new Button(attrs); + } + static calculate(attrs) { + return new Calculate(attrs); + } + static caption(attrs) { + return new Caption(attrs); + } + static certificate(attrs) { + return new Certificate(attrs); + } + static certificates(attrs) { + return new Certificates(attrs); + } + static checkButton(attrs) { + return new CheckButton(attrs); + } + static choiceList(attrs) { + return new ChoiceList(attrs); + } + static color(attrs) { + return new Color(attrs); + } + static comb(attrs) { + return new Comb(attrs); + } + static connect(attrs) { + return new Connect(attrs); + } + static contentArea(attrs) { + return new ContentArea(attrs); + } + static corner(attrs) { + return new Corner(attrs); + } + static date(attrs) { + return new DateElement(attrs); + } + static dateTime(attrs) { + return new DateTime(attrs); + } + static dateTimeEdit(attrs) { + return new DateTimeEdit(attrs); + } + static decimal(attrs) { + return new Decimal(attrs); + } + static defaultUi(attrs) { + return new DefaultUi(attrs); + } + static desc(attrs) { + return new Desc(attrs); + } + static digestMethod(attrs) { + return new DigestMethod(attrs); + } + static digestMethods(attrs) { + return new DigestMethods(attrs); + } + static draw(attrs) { + return new Draw(attrs); + } + static edge(attrs) { + return new Edge(attrs); + } + static encoding(attrs) { + return new Encoding(attrs); + } + static encodings(attrs) { + return new Encodings(attrs); + } + static encrypt(attrs) { + return new Encrypt(attrs); + } + static encryptData(attrs) { + return new EncryptData(attrs); + } + static encryption(attrs) { + return new Encryption(attrs); + } + static encryptionMethod(attrs) { + return new EncryptionMethod(attrs); + } + static encryptionMethods(attrs) { + return new EncryptionMethods(attrs); + } + static event(attrs) { + return new Event(attrs); + } + static exData(attrs) { + return new ExData(attrs); + } + static exObject(attrs) { + return new ExObject(attrs); + } + static exclGroup(attrs) { + return new ExclGroup(attrs); + } + static execute(attrs) { + return new Execute(attrs); + } + static extras(attrs) { + return new Extras(attrs); + } + static field(attrs) { + return new Field(attrs); + } + static fill(attrs) { + return new Fill(attrs); + } + static filter(attrs) { + return new Filter(attrs); + } + static float(attrs) { + return new Float(attrs); + } + static font(attrs) { + return new template_Font(attrs); + } + static format(attrs) { + return new Format(attrs); + } + static handler(attrs) { + return new Handler(attrs); + } + static hyphenation(attrs) { + return new Hyphenation(attrs); + } + static image(attrs) { + return new Image(attrs); + } + static imageEdit(attrs) { + return new ImageEdit(attrs); + } + static integer(attrs) { + return new Integer(attrs); + } + static issuers(attrs) { + return new Issuers(attrs); + } + static items(attrs) { + return new Items(attrs); + } + static keep(attrs) { + return new Keep(attrs); + } + static keyUsage(attrs) { + return new KeyUsage(attrs); + } + static line(attrs) { + return new Line(attrs); + } + static linear(attrs) { + return new Linear(attrs); + } + static lockDocument(attrs) { + return new LockDocument(attrs); + } + static manifest(attrs) { + return new Manifest(attrs); + } + static margin(attrs) { + return new Margin(attrs); + } + static mdp(attrs) { + return new Mdp(attrs); + } + static medium(attrs) { + return new Medium(attrs); + } + static message(attrs) { + return new Message(attrs); + } + static numericEdit(attrs) { + return new NumericEdit(attrs); + } + static occur(attrs) { + return new Occur(attrs); + } + static oid(attrs) { + return new Oid(attrs); + } + static oids(attrs) { + return new Oids(attrs); + } + static overflow(attrs) { + return new Overflow(attrs); + } + static pageArea(attrs) { + return new PageArea(attrs); + } + static pageSet(attrs) { + return new PageSet(attrs); + } + static para(attrs) { + return new Para(attrs); + } + static passwordEdit(attrs) { + return new PasswordEdit(attrs); + } + static pattern(attrs) { + return new template_Pattern(attrs); + } + static picture(attrs) { + return new Picture(attrs); + } + static proto(attrs) { + return new Proto(attrs); + } + static radial(attrs) { + return new Radial(attrs); + } + static reason(attrs) { + return new Reason(attrs); + } + static reasons(attrs) { + return new Reasons(attrs); + } + static rectangle(attrs) { + return new Rectangle(attrs); + } + static ref(attrs) { + return new RefElement(attrs); + } + static script(attrs) { + return new Script(attrs); + } + static setProperty(attrs) { + return new SetProperty(attrs); + } + static signData(attrs) { + return new SignData(attrs); + } + static signature(attrs) { + return new Signature(attrs); + } + static signing(attrs) { + return new Signing(attrs); + } + static solid(attrs) { + return new Solid(attrs); + } + static speak(attrs) { + return new Speak(attrs); + } + static stipple(attrs) { + return new Stipple(attrs); + } + static subform(attrs) { + return new Subform(attrs); + } + static subformSet(attrs) { + return new SubformSet(attrs); + } + static subjectDN(attrs) { + return new SubjectDN(attrs); + } + static subjectDNs(attrs) { + return new SubjectDNs(attrs); + } + static submit(attrs) { + return new Submit(attrs); + } + static template(attrs) { + return new Template(attrs); + } + static text(attrs) { + return new Text(attrs); + } + static textEdit(attrs) { + return new TextEdit(attrs); + } + static time(attrs) { + return new Time(attrs); + } + static timeStamp(attrs) { + return new TimeStamp(attrs); + } + static toolTip(attrs) { + return new ToolTip(attrs); + } + static traversal(attrs) { + return new Traversal(attrs); + } + static traverse(attrs) { + return new Traverse(attrs); + } + static ui(attrs) { + return new Ui(attrs); + } + static validate(attrs) { + return new Validate(attrs); + } + static value(attrs) { + return new Value(attrs); + } + static variables(attrs) { + return new Variables(attrs); + } +} + +;// ./src/core/xfa/bind.js + + + + + + +const bind_NS_DATASETS = NamespaceIds.datasets.id; +function createText(content) { + const node = new Text({}); + node[$content] = content; + return node; +} +class Binder { + constructor(root) { + this.root = root; + this.datasets = root.datasets; + this.data = root.datasets?.data || new XmlObject(NamespaceIds.datasets.id, "data"); + this.emptyMerge = this.data[$getChildren]().length === 0; + this.root.form = this.form = root.template[$clone](); + } + _isConsumeData() { + return !this.emptyMerge && this._mergeMode; + } + _isMatchTemplate() { + return !this._isConsumeData(); + } + bind() { + this._bindElement(this.form, this.data); + return this.form; + } + getData() { + return this.data; + } + _bindValue(formNode, data, picture) { + formNode[$data] = data; + if (formNode[$hasSettableValue]()) { + if (data[$isDataValue]()) { + const value = data[$getDataValue](); + formNode[$setValue](createText(value)); + } else if (formNode instanceof Field && formNode.ui?.choiceList?.open === "multiSelect") { + const value = data[$getChildren]().map(child => child[$content].trim()).join("\n"); + formNode[$setValue](createText(value)); + } else if (this._isConsumeData()) { + warn(`XFA - Nodes haven't the same type.`); + } + } else if (!data[$isDataValue]() || this._isMatchTemplate()) { + this._bindElement(formNode, data); + } else { + warn(`XFA - Nodes haven't the same type.`); + } + } + _findDataByNameToConsume(name, isValue, dataNode, global) { + if (!name) { + return null; + } + let generator, match; + for (let i = 0; i < 3; i++) { + generator = dataNode[$getRealChildrenByNameIt](name, false, true); + while (true) { + match = generator.next().value; + if (!match) { + break; + } + if (isValue === match[$isDataValue]()) { + return match; + } + } + if (dataNode[$namespaceId] === NamespaceIds.datasets.id && dataNode[$nodeName] === "data") { + break; + } + dataNode = dataNode[$getParent](); + } + if (!global) { + return null; + } + generator = this.data[$getRealChildrenByNameIt](name, true, false); + match = generator.next().value; + if (match) { + return match; + } + generator = this.data[$getAttributeIt](name, true); + match = generator.next().value; + if (match?.[$isDataValue]()) { + return match; + } + return null; + } + _setProperties(formNode, dataNode) { + if (!formNode.hasOwnProperty("setProperty")) { + return; + } + for (const { + ref, + target, + connection + } of formNode.setProperty.children) { + if (connection) { + continue; + } + if (!ref) { + continue; + } + const nodes = searchNode(this.root, dataNode, ref, false, false); + if (!nodes) { + warn(`XFA - Invalid reference: ${ref}.`); + continue; + } + const [node] = nodes; + if (!node[$isDescendent](this.data)) { + warn(`XFA - Invalid node: must be a data node.`); + continue; + } + const targetNodes = searchNode(this.root, formNode, target, false, false); + if (!targetNodes) { + warn(`XFA - Invalid target: ${target}.`); + continue; + } + const [targetNode] = targetNodes; + if (!targetNode[$isDescendent](formNode)) { + warn(`XFA - Invalid target: must be a property or subproperty.`); + continue; + } + const targetParent = targetNode[$getParent](); + if (targetNode instanceof SetProperty || targetParent instanceof SetProperty) { + warn(`XFA - Invalid target: cannot be a setProperty or one of its properties.`); + continue; + } + if (targetNode instanceof BindItems || targetParent instanceof BindItems) { + warn(`XFA - Invalid target: cannot be a bindItems or one of its properties.`); + continue; + } + const content = node[$text](); + const name = targetNode[$nodeName]; + if (targetNode instanceof XFAAttribute) { + const attrs = Object.create(null); + attrs[name] = content; + const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]); + targetParent[name] = obj[name]; + continue; + } + if (!targetNode.hasOwnProperty($content)) { + warn(`XFA - Invalid node to use in setProperty`); + continue; + } + targetNode[$data] = node; + targetNode[$content] = content; + targetNode[$finalize](); + } + } + _bindItems(formNode, dataNode) { + if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) { + return; + } + for (const item of formNode.items.children) { + formNode[$removeChild](item); + } + formNode.items.clear(); + const labels = new Items({}); + const values = new Items({}); + formNode[$appendChild](labels); + formNode.items.push(labels); + formNode[$appendChild](values); + formNode.items.push(values); + for (const { + ref, + labelRef, + valueRef, + connection + } of formNode.bindItems.children) { + if (connection) { + continue; + } + if (!ref) { + continue; + } + const nodes = searchNode(this.root, dataNode, ref, false, false); + if (!nodes) { + warn(`XFA - Invalid reference: ${ref}.`); + continue; + } + for (const node of nodes) { + if (!node[$isDescendent](this.datasets)) { + warn(`XFA - Invalid ref (${ref}): must be a datasets child.`); + continue; + } + const labelNodes = searchNode(this.root, node, labelRef, true, false); + if (!labelNodes) { + warn(`XFA - Invalid label: ${labelRef}.`); + continue; + } + const [labelNode] = labelNodes; + if (!labelNode[$isDescendent](this.datasets)) { + warn(`XFA - Invalid label: must be a datasets child.`); + continue; + } + const valueNodes = searchNode(this.root, node, valueRef, true, false); + if (!valueNodes) { + warn(`XFA - Invalid value: ${valueRef}.`); + continue; + } + const [valueNode] = valueNodes; + if (!valueNode[$isDescendent](this.datasets)) { + warn(`XFA - Invalid value: must be a datasets child.`); + continue; + } + const label = createText(labelNode[$text]()); + const value = createText(valueNode[$text]()); + labels[$appendChild](label); + labels.text.push(label); + values[$appendChild](value); + values.text.push(value); + } + } + } + _bindOccurrences(formNode, matches, picture) { + let baseClone; + if (matches.length > 1) { + baseClone = formNode[$clone](); + baseClone[$removeChild](baseClone.occur); + baseClone.occur = null; + } + this._bindValue(formNode, matches[0], picture); + this._setProperties(formNode, matches[0]); + this._bindItems(formNode, matches[0]); + if (matches.length === 1) { + return; + } + const parent = formNode[$getParent](); + const name = formNode[$nodeName]; + const pos = parent[$indexOf](formNode); + for (let i = 1, ii = matches.length; i < ii; i++) { + const match = matches[i]; + const clone = baseClone[$clone](); + parent[name].push(clone); + parent[$insertAt](pos + i, clone); + this._bindValue(clone, match, picture); + this._setProperties(clone, match); + this._bindItems(clone, match); + } + } + _createOccurrences(formNode) { + if (!this.emptyMerge) { + return; + } + const { + occur + } = formNode; + if (!occur || occur.initial <= 1) { + return; + } + const parent = formNode[$getParent](); + const name = formNode[$nodeName]; + if (!(parent[name] instanceof XFAObjectArray)) { + return; + } + let currentNumber; + if (formNode.name) { + currentNumber = parent[name].children.filter(e => e.name === formNode.name).length; + } else { + currentNumber = parent[name].children.length; + } + const pos = parent[$indexOf](formNode) + 1; + const ii = occur.initial - currentNumber; + if (ii) { + const nodeClone = formNode[$clone](); + nodeClone[$removeChild](nodeClone.occur); + nodeClone.occur = null; + parent[name].push(nodeClone); + parent[$insertAt](pos, nodeClone); + for (let i = 1; i < ii; i++) { + const clone = nodeClone[$clone](); + parent[name].push(clone); + parent[$insertAt](pos + i, clone); + } + } + } + _getOccurInfo(formNode) { + const { + name, + occur + } = formNode; + if (!occur || !name) { + return [1, 1]; + } + const max = occur.max === -1 ? Infinity : occur.max; + return [occur.min, max]; + } + _setAndBind(formNode, dataNode) { + this._setProperties(formNode, dataNode); + this._bindItems(formNode, dataNode); + this._bindElement(formNode, dataNode); + } + _bindElement(formNode, dataNode) { + const uselessNodes = []; + this._createOccurrences(formNode); + for (const child of formNode[$getChildren]()) { + if (child[$data]) { + continue; + } + if (this._mergeMode === undefined && child[$nodeName] === "subform") { + this._mergeMode = child.mergeMode === "consumeData"; + const dataChildren = dataNode[$getChildren](); + if (dataChildren.length > 0) { + this._bindOccurrences(child, [dataChildren[0]], null); + } else if (this.emptyMerge) { + const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; + const dataChild = child[$data] = new XmlObject(nsId, child.name || "root"); + dataNode[$appendChild](dataChild); + this._bindElement(child, dataChild); + } + continue; + } + if (!child[$isBindable]()) { + continue; + } + let global = false; + let picture = null; + let ref = null; + let match = null; + if (child.bind) { + switch (child.bind.match) { + case "none": + this._setAndBind(child, dataNode); + continue; + case "global": + global = true; + break; + case "dataRef": + if (!child.bind.ref) { + warn(`XFA - ref is empty in node ${child[$nodeName]}.`); + this._setAndBind(child, dataNode); + continue; + } + ref = child.bind.ref; + break; + default: + break; + } + if (child.bind.picture) { + picture = child.bind.picture[$content]; + } + } + const [min, max] = this._getOccurInfo(child); + if (ref) { + match = searchNode(this.root, dataNode, ref, true, false); + if (match === null) { + match = createDataNode(this.data, dataNode, ref); + if (!match) { + continue; + } + if (this._isConsumeData()) { + match[$consumed] = true; + } + this._setAndBind(child, match); + continue; + } else { + if (this._isConsumeData()) { + match = match.filter(node => !node[$consumed]); + } + if (match.length > max) { + match = match.slice(0, max); + } else if (match.length === 0) { + match = null; + } + if (match && this._isConsumeData()) { + match.forEach(node => { + node[$consumed] = true; + }); + } + } + } else { + if (!child.name) { + this._setAndBind(child, dataNode); + continue; + } + if (this._isConsumeData()) { + const matches = []; + while (matches.length < max) { + const found = this._findDataByNameToConsume(child.name, child[$hasSettableValue](), dataNode, global); + if (!found) { + break; + } + found[$consumed] = true; + matches.push(found); + } + match = matches.length > 0 ? matches : null; + } else { + match = dataNode[$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value; + if (!match) { + if (min === 0) { + uselessNodes.push(child); + continue; + } + const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; + match = child[$data] = new XmlObject(nsId, child.name); + if (this.emptyMerge) { + match[$consumed] = true; + } + dataNode[$appendChild](match); + this._setAndBind(child, match); + continue; + } + if (this.emptyMerge) { + match[$consumed] = true; + } + match = [match]; + } + } + if (match) { + this._bindOccurrences(child, match, picture); + } else if (min > 0) { + this._setAndBind(child, dataNode); + } else { + uselessNodes.push(child); + } + } + uselessNodes.forEach(node => node[$getParent]()[$removeChild](node)); + } +} + +;// ./src/core/xfa/data.js + +class DataHandler { + constructor(root, data) { + this.data = data; + this.dataset = root.datasets || null; + } + serialize(storage) { + const stack = [[-1, this.data[$getChildren]()]]; + while (stack.length > 0) { + const last = stack.at(-1); + const [i, children] = last; + if (i + 1 === children.length) { + stack.pop(); + continue; + } + const child = children[++last[0]]; + const storageEntry = storage.get(child[$uid]); + if (storageEntry) { + child[$setValue](storageEntry); + } else { + const attributes = child[$getAttributes](); + for (const value of attributes.values()) { + const entry = storage.get(value[$uid]); + if (entry) { + value[$setValue](entry); + break; + } + } + } + const nodes = child[$getChildren](); + if (nodes.length > 0) { + stack.push([-1, nodes]); + } + } + const buf = [``]; + if (this.dataset) { + for (const child of this.dataset[$getChildren]()) { + if (child[$nodeName] !== "data") { + child[$toString](buf); + } + } + } + this.data[$toString](buf); + buf.push(""); + return buf.join(""); + } +} + +;// ./src/core/xfa/config.js + + + + + +const CONFIG_NS_ID = NamespaceIds.config.id; +class Acrobat extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "acrobat", true); + this.acrobat7 = null; + this.autoSave = null; + this.common = null; + this.validate = null; + this.validateApprovalSignatures = null; + this.submitUrl = new XFAObjectArray(); + } +} +class Acrobat7 extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "acrobat7", true); + this.dynamicRender = null; + } +} +class ADBE_JSConsole extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]); + } +} +class ADBE_JSDebugger extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]); + } +} +class AddSilentPrint extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "addSilentPrint"); + } +} +class AddViewerPreferences extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "addViewerPreferences"); + } +} +class AdjustData extends Option10 { + constructor(attributes) { + super(CONFIG_NS_ID, "adjustData"); + } +} +class AdobeExtensionLevel extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "adobeExtensionLevel", 0, n => n >= 1 && n <= 8); + } +} +class Agent extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "agent", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.common = new XFAObjectArray(); + } +} +class AlwaysEmbed extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "alwaysEmbed"); + } +} +class Amd extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "amd"); + } +} +class config_Area extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "area"); + this.level = getInteger({ + data: attributes.level, + defaultValue: 0, + validate: n => n >= 1 && n <= 3 + }); + this.name = getStringOption(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]); + } +} +class Attributes extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]); + } +} +class AutoSave extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]); + } +} +class Base extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "base"); + } +} +class BatchOutput extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "batchOutput"); + this.format = getStringOption(attributes.format, ["none", "concat", "zip", "zipCompress"]); + } +} +class BehaviorOverride extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "behaviorOverride"); + } + [$finalize]() { + this[$content] = new Map(this[$content].trim().split(/\s+/).filter(x => x.includes(":")).map(x => x.split(":", 2))); + } +} +class Cache extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "cache", true); + this.templateCache = null; + } +} +class Change extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "change"); + } +} +class Common extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "common", true); + this.data = null; + this.locale = null; + this.localeSet = null; + this.messaging = null; + this.suppressBanner = null; + this.template = null; + this.validationMessaging = null; + this.versionControl = null; + this.log = new XFAObjectArray(); + } +} +class Compress extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "compress"); + this.scope = getStringOption(attributes.scope, ["imageOnly", "document"]); + } +} +class CompressLogicalStructure extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "compressLogicalStructure"); + } +} +class CompressObjectStream extends Option10 { + constructor(attributes) { + super(CONFIG_NS_ID, "compressObjectStream"); + } +} +class Compression extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "compression", true); + this.compressLogicalStructure = null; + this.compressObjectStream = null; + this.level = null; + this.type = null; + } +} +class Config extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "config", true); + this.acrobat = null; + this.present = null; + this.trace = null; + this.agent = new XFAObjectArray(); + } +} +class Conformance extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "conformance", ["A", "B"]); + } +} +class ContentCopy extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "contentCopy"); + } +} +class Copies extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "copies", 1, n => n >= 1); + } +} +class Creator extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "creator"); + } +} +class CurrentPage extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "currentPage", 0, n => n >= 0); + } +} +class Data extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "data", true); + this.adjustData = null; + this.attributes = null; + this.incrementalLoad = null; + this.outputXSL = null; + this.range = null; + this.record = null; + this.startNode = null; + this.uri = null; + this.window = null; + this.xsl = null; + this.excludeNS = new XFAObjectArray(); + this.transform = new XFAObjectArray(); + } +} +class Debug extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "debug", true); + this.uri = null; + } +} +class DefaultTypeface extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "defaultTypeface"); + this.writingScript = getStringOption(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]); + } +} +class Destination extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]); + } +} +class DocumentAssembly extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "documentAssembly"); + } +} +class Driver extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "driver", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.fontInfo = null; + this.xdc = null; + } +} +class DuplexOption extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]); + } +} +class DynamicRender extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]); + } +} +class Embed extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "embed"); + } +} +class config_Encrypt extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "encrypt"); + } +} +class config_Encryption extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "encryption", true); + this.encrypt = null; + this.encryptionLevel = null; + this.permissions = null; + } +} +class EncryptionLevel extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]); + } +} +class Enforce extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "enforce"); + } +} +class Equate extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "equate"); + this.force = getInteger({ + data: attributes.force, + defaultValue: 1, + validate: n => n === 0 + }); + this.from = attributes.from || ""; + this.to = attributes.to || ""; + } +} +class EquateRange extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "equateRange"); + this.from = attributes.from || ""; + this.to = attributes.to || ""; + this._unicodeRange = attributes.unicodeRange || ""; + } + get unicodeRange() { + const ranges = []; + const unicodeRegex = /U\+([0-9a-fA-F]+)/; + const unicodeRange = this._unicodeRange; + for (let range of unicodeRange.split(",").map(x => x.trim()).filter(x => !!x)) { + range = range.split("-", 2).map(x => { + const found = x.match(unicodeRegex); + if (!found) { + return 0; + } + return parseInt(found[1], 16); + }); + if (range.length === 1) { + range.push(range[0]); + } + ranges.push(range); + } + return shadow(this, "unicodeRange", ranges); + } +} +class Exclude extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "exclude"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/).filter(x => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x)); + } +} +class ExcludeNS extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "excludeNS"); + } +} +class FlipLabel extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]); + } +} +class config_FontInfo extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "fontInfo", true); + this.embed = null; + this.map = null; + this.subsetBelow = null; + this.alwaysEmbed = new XFAObjectArray(); + this.defaultTypeface = new XFAObjectArray(); + this.neverEmbed = new XFAObjectArray(); + } +} +class FormFieldFilling extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "formFieldFilling"); + } +} +class GroupParent extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "groupParent"); + } +} +class IfEmpty extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]); + } +} +class IncludeXDPContent extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "includeXDPContent"); + } +} +class IncrementalLoad extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]); + } +} +class IncrementalMerge extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "incrementalMerge"); + } +} +class Interactive extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "interactive"); + } +} +class Jog extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]); + } +} +class LabelPrinter extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "labelPrinter", true); + this.name = getStringOption(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]); + this.batchOutput = null; + this.flipLabel = null; + this.fontInfo = null; + this.xdc = null; + } +} +class Layout extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "layout", ["paginate", "panel"]); + } +} +class Level extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "level", 0, n => n > 0); + } +} +class Linearized extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "linearized"); + } +} +class Locale extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "locale"); + } +} +class LocaleSet extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "localeSet"); + } +} +class Log extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "log", true); + this.mode = null; + this.threshold = null; + this.to = null; + this.uri = null; + } +} +class MapElement extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "map", true); + this.equate = new XFAObjectArray(); + this.equateRange = new XFAObjectArray(); + } +} +class MediumInfo extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "mediumInfo", true); + this.map = null; + } +} +class config_Message extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "message", true); + this.msgId = null; + this.severity = null; + } +} +class Messaging extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "messaging", true); + this.message = new XFAObjectArray(); + } +} +class Mode extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "mode", ["append", "overwrite"]); + } +} +class ModifyAnnots extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "modifyAnnots"); + } +} +class MsgId extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "msgId", 1, n => n >= 1); + } +} +class NameAttr extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "nameAttr"); + } +} +class NeverEmbed extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "neverEmbed"); + } +} +class NumberOfCopies extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "numberOfCopies", null, n => n >= 2 && n <= 5); + } +} +class OpenAction extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "openAction", true); + this.destination = null; + } +} +class Output extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "output", true); + this.to = null; + this.type = null; + this.uri = null; + } +} +class OutputBin extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "outputBin"); + } +} +class OutputXSL extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "outputXSL", true); + this.uri = null; + } +} +class Overprint extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]); + } +} +class Packets extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "packets"); + } + [$finalize]() { + if (this[$content] === "*") { + return; + } + this[$content] = this[$content].trim().split(/\s+/).filter(x => ["config", "datasets", "template", "xfdf", "xslt"].includes(x)); + } +} +class PageOffset extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pageOffset"); + this.x = getInteger({ + data: attributes.x, + defaultValue: "useXDCSetting", + validate: n => true + }); + this.y = getInteger({ + data: attributes.y, + defaultValue: "useXDCSetting", + validate: n => true + }); + } +} +class PageRange extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pageRange"); + } + [$finalize]() { + const numbers = this[$content].trim().split(/\s+/).map(x => parseInt(x, 10)); + const ranges = []; + for (let i = 0, ii = numbers.length; i < ii; i += 2) { + ranges.push(numbers.slice(i, i + 2)); + } + this[$content] = ranges; + } +} +class Pagination extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]); + } +} +class PaginationOverride extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]); + } +} +class Part extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "part", 1, n => false); + } +} +class Pcl extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pcl", true); + this.name = attributes.name || ""; + this.batchOutput = null; + this.fontInfo = null; + this.jog = null; + this.mediumInfo = null; + this.outputBin = null; + this.pageOffset = null; + this.staple = null; + this.xdc = null; + } +} +class Pdf extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pdf", true); + this.name = attributes.name || ""; + this.adobeExtensionLevel = null; + this.batchOutput = null; + this.compression = null; + this.creator = null; + this.encryption = null; + this.fontInfo = null; + this.interactive = null; + this.linearized = null; + this.openAction = null; + this.pdfa = null; + this.producer = null; + this.renderPolicy = null; + this.scriptModel = null; + this.silentPrint = null; + this.submitFormat = null; + this.tagged = null; + this.version = null; + this.viewerPreferences = null; + this.xdc = null; + } +} +class Pdfa extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pdfa", true); + this.amd = null; + this.conformance = null; + this.includeXDPContent = null; + this.part = null; + } +} +class Permissions extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "permissions", true); + this.accessibleContent = null; + this.change = null; + this.contentCopy = null; + this.documentAssembly = null; + this.formFieldFilling = null; + this.modifyAnnots = null; + this.plaintextMetadata = null; + this.print = null; + this.printHighQuality = null; + } +} +class PickTrayByPDFSize extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "pickTrayByPDFSize"); + } +} +class config_Picture extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "picture"); + } +} +class PlaintextMetadata extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "plaintextMetadata"); + } +} +class Presence extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]); + } +} +class Present extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "present", true); + this.behaviorOverride = null; + this.cache = null; + this.common = null; + this.copies = null; + this.destination = null; + this.incrementalMerge = null; + this.layout = null; + this.output = null; + this.overprint = null; + this.pagination = null; + this.paginationOverride = null; + this.script = null; + this.validate = null; + this.xdp = null; + this.driver = new XFAObjectArray(); + this.labelPrinter = new XFAObjectArray(); + this.pcl = new XFAObjectArray(); + this.pdf = new XFAObjectArray(); + this.ps = new XFAObjectArray(); + this.submitUrl = new XFAObjectArray(); + this.webClient = new XFAObjectArray(); + this.zpl = new XFAObjectArray(); + } +} +class Print extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "print"); + } +} +class PrintHighQuality extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "printHighQuality"); + } +} +class PrintScaling extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]); + } +} +class PrinterName extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "printerName"); + } +} +class Producer extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "producer"); + } +} +class Ps extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ps", true); + this.name = attributes.name || ""; + this.batchOutput = null; + this.fontInfo = null; + this.jog = null; + this.mediumInfo = null; + this.outputBin = null; + this.staple = null; + this.xdc = null; + } +} +class Range extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "range"); + } + [$finalize]() { + this[$content] = this[$content].split(",", 2).map(range => range.split("-").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => { + if (range.length === 1) { + range.push(range[0]); + } + return range; + }); + } +} +class Record extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "record"); + } + [$finalize]() { + this[$content] = this[$content].trim(); + const n = parseInt(this[$content], 10); + if (!isNaN(n) && n >= 0) { + this[$content] = n; + } + } +} +class Relevant extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "relevant"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/); + } +} +class Rename extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "rename"); + } + [$finalize]() { + this[$content] = this[$content].trim(); + if (this[$content].toLowerCase().startsWith("xml") || new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u").test(this[$content])) { + warn("XFA - Rename: invalid XFA name"); + } + } +} +class RenderPolicy extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]); + } +} +class RunScripts extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]); + } +} +class config_Script extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "script", true); + this.currentPage = null; + this.exclude = null; + this.runScripts = null; + } +} +class ScriptModel extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]); + } +} +class Severity extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]); + } +} +class SilentPrint extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "silentPrint", true); + this.addSilentPrint = null; + this.printerName = null; + } +} +class Staple extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "staple"); + this.mode = getStringOption(attributes.mode, ["usePrinterSetting", "on", "off"]); + } +} +class StartNode extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "startNode"); + } +} +class StartPage extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "startPage", 0, n => true); + } +} +class SubmitFormat extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]); + } +} +class SubmitUrl extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "submitUrl"); + } +} +class SubsetBelow extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "subsetBelow", 100, n => n >= 0 && n <= 100); + } +} +class SuppressBanner extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "suppressBanner"); + } +} +class Tagged extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "tagged"); + } +} +class config_Template extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "template", true); + this.base = null; + this.relevant = null; + this.startPage = null; + this.uri = null; + this.xsl = null; + } +} +class Threshold extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]); + } +} +class To extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]); + } +} +class TemplateCache extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "templateCache"); + this.maxEntries = getInteger({ + data: attributes.maxEntries, + defaultValue: 5, + validate: n => n >= 0 + }); + } +} +class Trace extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "trace", true); + this.area = new XFAObjectArray(); + } +} +class Transform extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "transform", true); + this.groupParent = null; + this.ifEmpty = null; + this.nameAttr = null; + this.picture = null; + this.presence = null; + this.rename = null; + this.whitespace = null; + } +} +class Type extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]); + } +} +class Uri extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "uri"); + } +} +class config_Validate extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]); + } +} +class ValidateApprovalSignatures extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validateApprovalSignatures"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/).filter(x => ["docReady", "postSign"].includes(x)); + } +} +class ValidationMessaging extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]); + } +} +class Version extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]); + } +} +class VersionControl extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "VersionControl"); + this.outputBelow = getStringOption(attributes.outputBelow, ["warn", "error", "update"]); + this.sourceAbove = getStringOption(attributes.sourceAbove, ["warn", "error"]); + this.sourceBelow = getStringOption(attributes.sourceBelow, ["update", "maintain"]); + } +} +class ViewerPreferences extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "viewerPreferences", true); + this.ADBE_JSConsole = null; + this.ADBE_JSDebugger = null; + this.addViewerPreferences = null; + this.duplexOption = null; + this.enforce = null; + this.numberOfCopies = null; + this.pageRange = null; + this.pickTrayByPDFSize = null; + this.printScaling = null; + } +} +class WebClient extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "webClient", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.fontInfo = null; + this.xdc = null; + } +} +class Whitespace extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]); + } +} +class Window extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "window"); + } + [$finalize]() { + const pair = this[$content].split(",", 2).map(x => parseInt(x.trim(), 10)); + if (pair.some(x => isNaN(x))) { + this[$content] = [0, 0]; + return; + } + if (pair.length === 1) { + pair.push(pair[0]); + } + this[$content] = pair; + } +} +class Xdc extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xdc", true); + this.uri = new XFAObjectArray(); + this.xsl = new XFAObjectArray(); + } +} +class Xdp extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xdp", true); + this.packets = null; + } +} +class Xsl extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xsl", true); + this.debug = null; + this.uri = null; + } +} +class Zpl extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "zpl", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.batchOutput = null; + this.flipLabel = null; + this.fontInfo = null; + this.xdc = null; + } +} +class ConfigNamespace { + static [$buildXFAObject](name, attributes) { + if (ConfigNamespace.hasOwnProperty(name)) { + return ConfigNamespace[name](attributes); + } + return undefined; + } + static acrobat(attrs) { + return new Acrobat(attrs); + } + static acrobat7(attrs) { + return new Acrobat7(attrs); + } + static ADBE_JSConsole(attrs) { + return new ADBE_JSConsole(attrs); + } + static ADBE_JSDebugger(attrs) { + return new ADBE_JSDebugger(attrs); + } + static addSilentPrint(attrs) { + return new AddSilentPrint(attrs); + } + static addViewerPreferences(attrs) { + return new AddViewerPreferences(attrs); + } + static adjustData(attrs) { + return new AdjustData(attrs); + } + static adobeExtensionLevel(attrs) { + return new AdobeExtensionLevel(attrs); + } + static agent(attrs) { + return new Agent(attrs); + } + static alwaysEmbed(attrs) { + return new AlwaysEmbed(attrs); + } + static amd(attrs) { + return new Amd(attrs); + } + static area(attrs) { + return new config_Area(attrs); + } + static attributes(attrs) { + return new Attributes(attrs); + } + static autoSave(attrs) { + return new AutoSave(attrs); + } + static base(attrs) { + return new Base(attrs); + } + static batchOutput(attrs) { + return new BatchOutput(attrs); + } + static behaviorOverride(attrs) { + return new BehaviorOverride(attrs); + } + static cache(attrs) { + return new Cache(attrs); + } + static change(attrs) { + return new Change(attrs); + } + static common(attrs) { + return new Common(attrs); + } + static compress(attrs) { + return new Compress(attrs); + } + static compressLogicalStructure(attrs) { + return new CompressLogicalStructure(attrs); + } + static compressObjectStream(attrs) { + return new CompressObjectStream(attrs); + } + static compression(attrs) { + return new Compression(attrs); + } + static config(attrs) { + return new Config(attrs); + } + static conformance(attrs) { + return new Conformance(attrs); + } + static contentCopy(attrs) { + return new ContentCopy(attrs); + } + static copies(attrs) { + return new Copies(attrs); + } + static creator(attrs) { + return new Creator(attrs); + } + static currentPage(attrs) { + return new CurrentPage(attrs); + } + static data(attrs) { + return new Data(attrs); + } + static debug(attrs) { + return new Debug(attrs); + } + static defaultTypeface(attrs) { + return new DefaultTypeface(attrs); + } + static destination(attrs) { + return new Destination(attrs); + } + static documentAssembly(attrs) { + return new DocumentAssembly(attrs); + } + static driver(attrs) { + return new Driver(attrs); + } + static duplexOption(attrs) { + return new DuplexOption(attrs); + } + static dynamicRender(attrs) { + return new DynamicRender(attrs); + } + static embed(attrs) { + return new Embed(attrs); + } + static encrypt(attrs) { + return new config_Encrypt(attrs); + } + static encryption(attrs) { + return new config_Encryption(attrs); + } + static encryptionLevel(attrs) { + return new EncryptionLevel(attrs); + } + static enforce(attrs) { + return new Enforce(attrs); + } + static equate(attrs) { + return new Equate(attrs); + } + static equateRange(attrs) { + return new EquateRange(attrs); + } + static exclude(attrs) { + return new Exclude(attrs); + } + static excludeNS(attrs) { + return new ExcludeNS(attrs); + } + static flipLabel(attrs) { + return new FlipLabel(attrs); + } + static fontInfo(attrs) { + return new config_FontInfo(attrs); + } + static formFieldFilling(attrs) { + return new FormFieldFilling(attrs); + } + static groupParent(attrs) { + return new GroupParent(attrs); + } + static ifEmpty(attrs) { + return new IfEmpty(attrs); + } + static includeXDPContent(attrs) { + return new IncludeXDPContent(attrs); + } + static incrementalLoad(attrs) { + return new IncrementalLoad(attrs); + } + static incrementalMerge(attrs) { + return new IncrementalMerge(attrs); + } + static interactive(attrs) { + return new Interactive(attrs); + } + static jog(attrs) { + return new Jog(attrs); + } + static labelPrinter(attrs) { + return new LabelPrinter(attrs); + } + static layout(attrs) { + return new Layout(attrs); + } + static level(attrs) { + return new Level(attrs); + } + static linearized(attrs) { + return new Linearized(attrs); + } + static locale(attrs) { + return new Locale(attrs); + } + static localeSet(attrs) { + return new LocaleSet(attrs); + } + static log(attrs) { + return new Log(attrs); + } + static map(attrs) { + return new MapElement(attrs); + } + static mediumInfo(attrs) { + return new MediumInfo(attrs); + } + static message(attrs) { + return new config_Message(attrs); + } + static messaging(attrs) { + return new Messaging(attrs); + } + static mode(attrs) { + return new Mode(attrs); + } + static modifyAnnots(attrs) { + return new ModifyAnnots(attrs); + } + static msgId(attrs) { + return new MsgId(attrs); + } + static nameAttr(attrs) { + return new NameAttr(attrs); + } + static neverEmbed(attrs) { + return new NeverEmbed(attrs); + } + static numberOfCopies(attrs) { + return new NumberOfCopies(attrs); + } + static openAction(attrs) { + return new OpenAction(attrs); + } + static output(attrs) { + return new Output(attrs); + } + static outputBin(attrs) { + return new OutputBin(attrs); + } + static outputXSL(attrs) { + return new OutputXSL(attrs); + } + static overprint(attrs) { + return new Overprint(attrs); + } + static packets(attrs) { + return new Packets(attrs); + } + static pageOffset(attrs) { + return new PageOffset(attrs); + } + static pageRange(attrs) { + return new PageRange(attrs); + } + static pagination(attrs) { + return new Pagination(attrs); + } + static paginationOverride(attrs) { + return new PaginationOverride(attrs); + } + static part(attrs) { + return new Part(attrs); + } + static pcl(attrs) { + return new Pcl(attrs); + } + static pdf(attrs) { + return new Pdf(attrs); + } + static pdfa(attrs) { + return new Pdfa(attrs); + } + static permissions(attrs) { + return new Permissions(attrs); + } + static pickTrayByPDFSize(attrs) { + return new PickTrayByPDFSize(attrs); + } + static picture(attrs) { + return new config_Picture(attrs); + } + static plaintextMetadata(attrs) { + return new PlaintextMetadata(attrs); + } + static presence(attrs) { + return new Presence(attrs); + } + static present(attrs) { + return new Present(attrs); + } + static print(attrs) { + return new Print(attrs); + } + static printHighQuality(attrs) { + return new PrintHighQuality(attrs); + } + static printScaling(attrs) { + return new PrintScaling(attrs); + } + static printerName(attrs) { + return new PrinterName(attrs); + } + static producer(attrs) { + return new Producer(attrs); + } + static ps(attrs) { + return new Ps(attrs); + } + static range(attrs) { + return new Range(attrs); + } + static record(attrs) { + return new Record(attrs); + } + static relevant(attrs) { + return new Relevant(attrs); + } + static rename(attrs) { + return new Rename(attrs); + } + static renderPolicy(attrs) { + return new RenderPolicy(attrs); + } + static runScripts(attrs) { + return new RunScripts(attrs); + } + static script(attrs) { + return new config_Script(attrs); + } + static scriptModel(attrs) { + return new ScriptModel(attrs); + } + static severity(attrs) { + return new Severity(attrs); + } + static silentPrint(attrs) { + return new SilentPrint(attrs); + } + static staple(attrs) { + return new Staple(attrs); + } + static startNode(attrs) { + return new StartNode(attrs); + } + static startPage(attrs) { + return new StartPage(attrs); + } + static submitFormat(attrs) { + return new SubmitFormat(attrs); + } + static submitUrl(attrs) { + return new SubmitUrl(attrs); + } + static subsetBelow(attrs) { + return new SubsetBelow(attrs); + } + static suppressBanner(attrs) { + return new SuppressBanner(attrs); + } + static tagged(attrs) { + return new Tagged(attrs); + } + static template(attrs) { + return new config_Template(attrs); + } + static templateCache(attrs) { + return new TemplateCache(attrs); + } + static threshold(attrs) { + return new Threshold(attrs); + } + static to(attrs) { + return new To(attrs); + } + static trace(attrs) { + return new Trace(attrs); + } + static transform(attrs) { + return new Transform(attrs); + } + static type(attrs) { + return new Type(attrs); + } + static uri(attrs) { + return new Uri(attrs); + } + static validate(attrs) { + return new config_Validate(attrs); + } + static validateApprovalSignatures(attrs) { + return new ValidateApprovalSignatures(attrs); + } + static validationMessaging(attrs) { + return new ValidationMessaging(attrs); + } + static version(attrs) { + return new Version(attrs); + } + static versionControl(attrs) { + return new VersionControl(attrs); + } + static viewerPreferences(attrs) { + return new ViewerPreferences(attrs); + } + static webClient(attrs) { + return new WebClient(attrs); + } + static whitespace(attrs) { + return new Whitespace(attrs); + } + static window(attrs) { + return new Window(attrs); + } + static xdc(attrs) { + return new Xdc(attrs); + } + static xdp(attrs) { + return new Xdp(attrs); + } + static xsl(attrs) { + return new Xsl(attrs); + } + static zpl(attrs) { + return new Zpl(attrs); + } +} + +;// ./src/core/xfa/connection_set.js + + +const CONNECTION_SET_NS_ID = NamespaceIds.connectionSet.id; +class ConnectionSet extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "connectionSet", true); + this.wsdlConnection = new XFAObjectArray(); + this.xmlConnection = new XFAObjectArray(); + this.xsdConnection = new XFAObjectArray(); + } +} +class EffectiveInputPolicy extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "effectiveInputPolicy"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class EffectiveOutputPolicy extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class Operation extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "operation"); + this.id = attributes.id || ""; + this.input = attributes.input || ""; + this.name = attributes.name || ""; + this.output = attributes.output || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class RootElement extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "rootElement"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class SoapAction extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "soapAction"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class SoapAddress extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "soapAddress"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class connection_set_Uri extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "uri"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class WsdlAddress extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "wsdlAddress"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } +} +class WsdlConnection extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "wsdlConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.effectiveInputPolicy = null; + this.effectiveOutputPolicy = null; + this.operation = null; + this.soapAction = null; + this.soapAddress = null; + this.wsdlAddress = null; + } +} +class XmlConnection extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "xmlConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.uri = null; + } +} +class XsdConnection extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "xsdConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.rootElement = null; + this.uri = null; + } +} +class ConnectionSetNamespace { + static [$buildXFAObject](name, attributes) { + if (ConnectionSetNamespace.hasOwnProperty(name)) { + return ConnectionSetNamespace[name](attributes); + } + return undefined; + } + static connectionSet(attrs) { + return new ConnectionSet(attrs); + } + static effectiveInputPolicy(attrs) { + return new EffectiveInputPolicy(attrs); + } + static effectiveOutputPolicy(attrs) { + return new EffectiveOutputPolicy(attrs); + } + static operation(attrs) { + return new Operation(attrs); + } + static rootElement(attrs) { + return new RootElement(attrs); + } + static soapAction(attrs) { + return new SoapAction(attrs); + } + static soapAddress(attrs) { + return new SoapAddress(attrs); + } + static uri(attrs) { + return new connection_set_Uri(attrs); + } + static wsdlAddress(attrs) { + return new WsdlAddress(attrs); + } + static wsdlConnection(attrs) { + return new WsdlConnection(attrs); + } + static xmlConnection(attrs) { + return new XmlConnection(attrs); + } + static xsdConnection(attrs) { + return new XsdConnection(attrs); + } +} + +;// ./src/core/xfa/datasets.js + + + +const DATASETS_NS_ID = NamespaceIds.datasets.id; +class datasets_Data extends XmlObject { + constructor(attributes) { + super(DATASETS_NS_ID, "data", attributes); + } + [$isNsAgnostic]() { + return true; + } +} +class Datasets extends XFAObject { + constructor(attributes) { + super(DATASETS_NS_ID, "datasets", true); + this.data = null; + this.Signature = null; + } + [$onChild](child) { + const name = child[$nodeName]; + if (name === "data" && child[$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[$namespaceId] === NamespaceIds.signature.id) { + this[name] = child; + } + this[$appendChild](child); + } +} +class DatasetsNamespace { + static [$buildXFAObject](name, attributes) { + if (DatasetsNamespace.hasOwnProperty(name)) { + return DatasetsNamespace[name](attributes); + } + return undefined; + } + static datasets(attributes) { + return new Datasets(attributes); + } + static data(attributes) { + return new datasets_Data(attributes); + } +} + +;// ./src/core/xfa/locale_set.js + + + +const LOCALE_SET_NS_ID = NamespaceIds.localeSet.id; +class CalendarSymbols extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "calendarSymbols", true); + this.name = "gregorian"; + this.dayNames = new XFAObjectArray(2); + this.eraNames = null; + this.meridiemNames = null; + this.monthNames = new XFAObjectArray(2); + } +} +class CurrencySymbol extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "currencySymbol"); + this.name = getStringOption(attributes.name, ["symbol", "isoname", "decimal"]); + } +} +class CurrencySymbols extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "currencySymbols", true); + this.currencySymbol = new XFAObjectArray(3); + } +} +class DatePattern extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "datePattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } +} +class DatePatterns extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "datePatterns", true); + this.datePattern = new XFAObjectArray(4); + } +} +class DateTimeSymbols extends ContentObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "dateTimeSymbols"); + } +} +class Day extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "day"); + } +} +class DayNames extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "dayNames", true); + this.abbr = getInteger({ + data: attributes.abbr, + defaultValue: 0, + validate: x => x === 1 + }); + this.day = new XFAObjectArray(7); + } +} +class Era extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "era"); + } +} +class EraNames extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "eraNames", true); + this.era = new XFAObjectArray(2); + } +} +class locale_set_Locale extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "locale", true); + this.desc = attributes.desc || ""; + this.name = "isoname"; + this.calendarSymbols = null; + this.currencySymbols = null; + this.datePatterns = null; + this.dateTimeSymbols = null; + this.numberPatterns = null; + this.numberSymbols = null; + this.timePatterns = null; + this.typeFaces = null; + } +} +class locale_set_LocaleSet extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "localeSet", true); + this.locale = new XFAObjectArray(); + } +} +class Meridiem extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "meridiem"); + } +} +class MeridiemNames extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "meridiemNames", true); + this.meridiem = new XFAObjectArray(2); + } +} +class Month extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "month"); + } +} +class MonthNames extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "monthNames", true); + this.abbr = getInteger({ + data: attributes.abbr, + defaultValue: 0, + validate: x => x === 1 + }); + this.month = new XFAObjectArray(12); + } +} +class NumberPattern extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberPattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } +} +class NumberPatterns extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberPatterns", true); + this.numberPattern = new XFAObjectArray(4); + } +} +class NumberSymbol extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberSymbol"); + this.name = getStringOption(attributes.name, ["decimal", "grouping", "percent", "minus", "zero"]); + } +} +class NumberSymbols extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberSymbols", true); + this.numberSymbol = new XFAObjectArray(5); + } +} +class TimePattern extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "timePattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } +} +class TimePatterns extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "timePatterns", true); + this.timePattern = new XFAObjectArray(4); + } +} +class TypeFace extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "typeFace", true); + this.name = attributes.name | ""; + } +} +class TypeFaces extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "typeFaces", true); + this.typeFace = new XFAObjectArray(); + } +} +class LocaleSetNamespace { + static [$buildXFAObject](name, attributes) { + if (LocaleSetNamespace.hasOwnProperty(name)) { + return LocaleSetNamespace[name](attributes); + } + return undefined; + } + static calendarSymbols(attrs) { + return new CalendarSymbols(attrs); + } + static currencySymbol(attrs) { + return new CurrencySymbol(attrs); + } + static currencySymbols(attrs) { + return new CurrencySymbols(attrs); + } + static datePattern(attrs) { + return new DatePattern(attrs); + } + static datePatterns(attrs) { + return new DatePatterns(attrs); + } + static dateTimeSymbols(attrs) { + return new DateTimeSymbols(attrs); + } + static day(attrs) { + return new Day(attrs); + } + static dayNames(attrs) { + return new DayNames(attrs); + } + static era(attrs) { + return new Era(attrs); + } + static eraNames(attrs) { + return new EraNames(attrs); + } + static locale(attrs) { + return new locale_set_Locale(attrs); + } + static localeSet(attrs) { + return new locale_set_LocaleSet(attrs); + } + static meridiem(attrs) { + return new Meridiem(attrs); + } + static meridiemNames(attrs) { + return new MeridiemNames(attrs); + } + static month(attrs) { + return new Month(attrs); + } + static monthNames(attrs) { + return new MonthNames(attrs); + } + static numberPattern(attrs) { + return new NumberPattern(attrs); + } + static numberPatterns(attrs) { + return new NumberPatterns(attrs); + } + static numberSymbol(attrs) { + return new NumberSymbol(attrs); + } + static numberSymbols(attrs) { + return new NumberSymbols(attrs); + } + static timePattern(attrs) { + return new TimePattern(attrs); + } + static timePatterns(attrs) { + return new TimePatterns(attrs); + } + static typeFace(attrs) { + return new TypeFace(attrs); + } + static typeFaces(attrs) { + return new TypeFaces(attrs); + } +} + +;// ./src/core/xfa/signature.js + + +const SIGNATURE_NS_ID = NamespaceIds.signature.id; +class signature_Signature extends XFAObject { + constructor(attributes) { + super(SIGNATURE_NS_ID, "signature", true); + } +} +class SignatureNamespace { + static [$buildXFAObject](name, attributes) { + if (SignatureNamespace.hasOwnProperty(name)) { + return SignatureNamespace[name](attributes); + } + return undefined; + } + static signature(attributes) { + return new signature_Signature(attributes); + } +} + +;// ./src/core/xfa/stylesheet.js + + +const STYLESHEET_NS_ID = NamespaceIds.stylesheet.id; +class Stylesheet extends XFAObject { + constructor(attributes) { + super(STYLESHEET_NS_ID, "stylesheet", true); + } +} +class StylesheetNamespace { + static [$buildXFAObject](name, attributes) { + if (StylesheetNamespace.hasOwnProperty(name)) { + return StylesheetNamespace[name](attributes); + } + return undefined; + } + static stylesheet(attributes) { + return new Stylesheet(attributes); + } +} + +;// ./src/core/xfa/xdp.js + + + +const XDP_NS_ID = NamespaceIds.xdp.id; +class xdp_Xdp extends XFAObject { + constructor(attributes) { + super(XDP_NS_ID, "xdp", true); + this.uuid = attributes.uuid || ""; + this.timeStamp = attributes.timeStamp || ""; + this.config = null; + this.connectionSet = null; + this.datasets = null; + this.localeSet = null; + this.stylesheet = new XFAObjectArray(); + this.template = null; + } + [$onChildCheck](child) { + const ns = NamespaceIds[child[$nodeName]]; + return ns && child[$namespaceId] === ns.id; + } +} +class XdpNamespace { + static [$buildXFAObject](name, attributes) { + if (XdpNamespace.hasOwnProperty(name)) { + return XdpNamespace[name](attributes); + } + return undefined; + } + static xdp(attributes) { + return new xdp_Xdp(attributes); + } +} + +;// ./src/core/xfa/xhtml.js + + + + + +const XHTML_NS_ID = NamespaceIds.xhtml.id; +const $richText = Symbol(); +const VALID_STYLES = new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]); +const StyleMapping = new Map([["page-break-after", "breakAfter"], ["page-break-before", "breakBefore"], ["page-break-inside", "breakInside"], ["kerning-mode", value => value === "none" ? "none" : "normal"], ["xfa-font-horizontal-scale", value => `scaleX(${Math.max(0, parseInt(value) / 100).toFixed(2)})`], ["xfa-font-vertical-scale", value => `scaleY(${Math.max(0, parseInt(value) / 100).toFixed(2)})`], ["xfa-spacerun", ""], ["xfa-tab-stops", ""], ["font-size", (value, original) => { + value = original.fontSize = Math.abs(getMeasurement(value)); + return measureToString(0.99 * value); +}], ["letter-spacing", value => measureToString(getMeasurement(value))], ["line-height", value => measureToString(getMeasurement(value))], ["margin", value => measureToString(getMeasurement(value))], ["margin-bottom", value => measureToString(getMeasurement(value))], ["margin-left", value => measureToString(getMeasurement(value))], ["margin-right", value => measureToString(getMeasurement(value))], ["margin-top", value => measureToString(getMeasurement(value))], ["text-indent", value => measureToString(getMeasurement(value))], ["font-family", value => value], ["vertical-align", value => measureToString(getMeasurement(value))]]); +const spacesRegExp = /\s+/g; +const crlfRegExp = /[\r\n]+/g; +const crlfForRichTextRegExp = /\r\n?/g; +function mapStyle(styleStr, node, richText) { + const style = Object.create(null); + if (!styleStr) { + return style; + } + const original = Object.create(null); + for (const [key, value] of styleStr.split(";").map(s => s.split(":", 2))) { + const mapping = StyleMapping.get(key); + if (mapping === "") { + continue; + } + let newValue = value; + if (mapping) { + newValue = typeof mapping === "string" ? mapping : mapping(value, original); + } + if (key.endsWith("scale")) { + style.transform = style.transform ? `${style[key]} ${newValue}` : newValue; + } else { + style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] = newValue; + } + } + if (style.fontFamily) { + setFontFamily({ + typeface: style.fontFamily, + weight: style.fontWeight || "normal", + posture: style.fontStyle || "normal", + size: original.fontSize || 0 + }, node, node[$globalData].fontFinder, style); + } + if (richText && style.verticalAlign && style.verticalAlign !== "0px" && style.fontSize) { + const SUB_SUPER_SCRIPT_FACTOR = 0.583; + const VERTICAL_FACTOR = 0.333; + const fontSize = getMeasurement(style.fontSize); + style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR); + style.verticalAlign = measureToString(Math.sign(getMeasurement(style.verticalAlign)) * fontSize * VERTICAL_FACTOR); + } + if (richText && style.fontSize) { + style.fontSize = `calc(${style.fontSize} * var(--total-scale-factor))`; + } + fixTextIndent(style); + return style; +} +function checkStyle(node) { + if (!node.style) { + return ""; + } + return node.style.split(";").filter(s => !!s.trim()).map(s => s.split(":", 2).map(t => t.trim())).filter(([key, value]) => { + if (key === "font-family") { + node[$globalData].usedTypefaces.add(value); + } + return VALID_STYLES.has(key); + }).map(kv => kv.join(":")).join(";"); +} +const NoWhites = new Set(["body", "html"]); +class XhtmlObject extends XmlObject { + constructor(attributes, name) { + super(XHTML_NS_ID, name); + this[$richText] = false; + this.style = attributes.style || ""; + } + [$clean](builder) { + super[$clean](builder); + this.style = checkStyle(this); + } + [$acceptWhitespace]() { + return !NoWhites.has(this[$nodeName]); + } + [$onText](str, richText = false) { + if (!richText) { + str = str.replaceAll(crlfRegExp, ""); + if (!this.style.includes("xfa-spacerun:yes")) { + str = str.replaceAll(spacesRegExp, " "); + } + } else { + this[$richText] = true; + } + if (str) { + this[$content] += str; + } + } + [$pushGlyphs](measure, mustPop = true) { + const xfaFont = Object.create(null); + const margin = { + top: NaN, + bottom: NaN, + left: NaN, + right: NaN + }; + let lineHeight = null; + for (const [key, value] of this.style.split(";").map(s => s.split(":", 2))) { + switch (key) { + case "font-family": + xfaFont.typeface = stripQuotes(value); + break; + case "font-size": + xfaFont.size = getMeasurement(value); + break; + case "font-weight": + xfaFont.weight = value; + break; + case "font-style": + xfaFont.posture = value; + break; + case "letter-spacing": + xfaFont.letterSpacing = getMeasurement(value); + break; + case "margin": + const values = value.split(/ \t/).map(x => getMeasurement(x)); + switch (values.length) { + case 1: + margin.top = margin.bottom = margin.left = margin.right = values[0]; + break; + case 2: + margin.top = margin.bottom = values[0]; + margin.left = margin.right = values[1]; + break; + case 3: + margin.top = values[0]; + margin.bottom = values[2]; + margin.left = margin.right = values[1]; + break; + case 4: + margin.top = values[0]; + margin.left = values[1]; + margin.bottom = values[2]; + margin.right = values[3]; + break; + } + break; + case "margin-top": + margin.top = getMeasurement(value); + break; + case "margin-bottom": + margin.bottom = getMeasurement(value); + break; + case "margin-left": + margin.left = getMeasurement(value); + break; + case "margin-right": + margin.right = getMeasurement(value); + break; + case "line-height": + lineHeight = getMeasurement(value); + break; + } + } + measure.pushData(xfaFont, margin, lineHeight); + if (this[$content]) { + measure.addString(this[$content]); + } else { + for (const child of this[$getChildren]()) { + if (child[$nodeName] === "#text") { + measure.addString(child[$content]); + continue; + } + child[$pushGlyphs](measure); + } + } + if (mustPop) { + measure.popFont(); + } + } + [$toHTML](availableSpace) { + const children = []; + this[$extra] = { + children + }; + this[$childrenToHTML]({}); + if (children.length === 0 && !this[$content]) { + return HTMLResult.EMPTY; + } + let value; + if (this[$richText]) { + value = this[$content] ? this[$content].replaceAll(crlfForRichTextRegExp, "\n") : undefined; + } else { + value = this[$content] || undefined; + } + return HTMLResult.success({ + name: this[$nodeName], + attributes: { + href: this.href, + style: mapStyle(this.style, this, this[$richText]) + }, + children, + value + }); + } +} +class A extends XhtmlObject { + constructor(attributes) { + super(attributes, "a"); + this.href = fixURL(attributes.href) || ""; + } +} +class B extends XhtmlObject { + constructor(attributes) { + super(attributes, "b"); + } + [$pushGlyphs](measure) { + measure.pushFont({ + weight: "bold" + }); + super[$pushGlyphs](measure); + measure.popFont(); + } +} +class Body extends XhtmlObject { + constructor(attributes) { + super(attributes, "body"); + } + [$toHTML](availableSpace) { + const res = super[$toHTML](availableSpace); + const { + html + } = res; + if (!html) { + return HTMLResult.EMPTY; + } + html.name = "div"; + html.attributes.class = ["xfaRich"]; + return res; + } +} +class Br extends XhtmlObject { + constructor(attributes) { + super(attributes, "br"); + } + [$text]() { + return "\n"; + } + [$pushGlyphs](measure) { + measure.addString("\n"); + } + [$toHTML](availableSpace) { + return HTMLResult.success({ + name: "br" + }); + } +} +class Html extends XhtmlObject { + constructor(attributes) { + super(attributes, "html"); + } + [$toHTML](availableSpace) { + const children = []; + this[$extra] = { + children + }; + this[$childrenToHTML]({}); + if (children.length === 0) { + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: {} + }, + value: this[$content] || "" + }); + } + if (children.length === 1) { + const child = children[0]; + if (child.attributes?.class.includes("xfaRich")) { + return HTMLResult.success(child); + } + } + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: {} + }, + children + }); + } +} +class I extends XhtmlObject { + constructor(attributes) { + super(attributes, "i"); + } + [$pushGlyphs](measure) { + measure.pushFont({ + posture: "italic" + }); + super[$pushGlyphs](measure); + measure.popFont(); + } +} +class Li extends XhtmlObject { + constructor(attributes) { + super(attributes, "li"); + } +} +class Ol extends XhtmlObject { + constructor(attributes) { + super(attributes, "ol"); + } +} +class P extends XhtmlObject { + constructor(attributes) { + super(attributes, "p"); + } + [$pushGlyphs](measure) { + super[$pushGlyphs](measure, false); + measure.addString("\n"); + measure.addPara(); + measure.popFont(); + } + [$text]() { + const siblings = this[$getParent]()[$getChildren](); + if (siblings.at(-1) === this) { + return super[$text](); + } + return super[$text]() + "\n"; + } +} +class Span extends XhtmlObject { + constructor(attributes) { + super(attributes, "span"); + } +} +class Sub extends XhtmlObject { + constructor(attributes) { + super(attributes, "sub"); + } +} +class Sup extends XhtmlObject { + constructor(attributes) { + super(attributes, "sup"); + } +} +class Ul extends XhtmlObject { + constructor(attributes) { + super(attributes, "ul"); + } +} +class XhtmlNamespace { + static [$buildXFAObject](name, attributes) { + if (XhtmlNamespace.hasOwnProperty(name)) { + return XhtmlNamespace[name](attributes); + } + return undefined; + } + static a(attributes) { + return new A(attributes); + } + static b(attributes) { + return new B(attributes); + } + static body(attributes) { + return new Body(attributes); + } + static br(attributes) { + return new Br(attributes); + } + static html(attributes) { + return new Html(attributes); + } + static i(attributes) { + return new I(attributes); + } + static li(attributes) { + return new Li(attributes); + } + static ol(attributes) { + return new Ol(attributes); + } + static p(attributes) { + return new P(attributes); + } + static span(attributes) { + return new Span(attributes); + } + static sub(attributes) { + return new Sub(attributes); + } + static sup(attributes) { + return new Sup(attributes); + } + static ul(attributes) { + return new Ul(attributes); + } +} + +;// ./src/core/xfa/setup.js + + + + + + + + + +const NamespaceSetUp = { + config: ConfigNamespace, + connection: ConnectionSetNamespace, + datasets: DatasetsNamespace, + localeSet: LocaleSetNamespace, + signature: SignatureNamespace, + stylesheet: StylesheetNamespace, + template: TemplateNamespace, + xdp: XdpNamespace, + xhtml: XhtmlNamespace +}; + +;// ./src/core/xfa/unknown.js + + +class UnknownNamespace { + constructor(nsId) { + this.namespaceId = nsId; + } + [$buildXFAObject](name, attributes) { + return new XmlObject(this.namespaceId, name, attributes); + } +} + +;// ./src/core/xfa/builder.js + + + + + + + +class Root extends XFAObject { + constructor(ids) { + super(-1, "root", Object.create(null)); + this.element = null; + this[$ids] = ids; + } + [$onChild](child) { + this.element = child; + return true; + } + [$finalize]() { + super[$finalize](); + if (this.element.template instanceof Template) { + this[$ids].set($root, this.element); + this.element.template[$resolvePrototypes](this[$ids]); + this.element.template[$ids] = this[$ids]; + } + } +} +class Empty extends XFAObject { + constructor() { + super(-1, "", Object.create(null)); + } + [$onChild](_) { + return false; + } +} +class Builder { + constructor(rootNameSpace = null) { + this._namespaceStack = []; + this._nsAgnosticLevel = 0; + this._namespacePrefixes = new Map(); + this._namespaces = new Map(); + this._nextNsId = Math.max(...Object.values(NamespaceIds).map(({ + id + }) => id)); + this._currentNamespace = rootNameSpace || new UnknownNamespace(++this._nextNsId); + } + buildRoot(ids) { + return new Root(ids); + } + build({ + nsPrefix, + name, + attributes, + namespace, + prefixes + }) { + const hasNamespaceDef = namespace !== null; + if (hasNamespaceDef) { + this._namespaceStack.push(this._currentNamespace); + this._currentNamespace = this._searchNamespace(namespace); + } + if (prefixes) { + this._addNamespacePrefix(prefixes); + } + if (attributes.hasOwnProperty($nsAttributes)) { + const dataTemplate = NamespaceSetUp.datasets; + const nsAttrs = attributes[$nsAttributes]; + let xfaAttrs = null; + for (const [ns, attrs] of Object.entries(nsAttrs)) { + const nsToUse = this._getNamespaceToUse(ns); + if (nsToUse === dataTemplate) { + xfaAttrs = { + xfa: attrs + }; + break; + } + } + if (xfaAttrs) { + attributes[$nsAttributes] = xfaAttrs; + } else { + delete attributes[$nsAttributes]; + } + } + const namespaceToUse = this._getNamespaceToUse(nsPrefix); + const node = namespaceToUse?.[$buildXFAObject](name, attributes) || new Empty(); + if (node[$isNsAgnostic]()) { + this._nsAgnosticLevel++; + } + if (hasNamespaceDef || prefixes || node[$isNsAgnostic]()) { + node[$cleanup] = { + hasNamespace: hasNamespaceDef, + prefixes, + nsAgnostic: node[$isNsAgnostic]() + }; + } + return node; + } + isNsAgnostic() { + return this._nsAgnosticLevel > 0; + } + _searchNamespace(nsName) { + let ns = this._namespaces.get(nsName); + if (ns) { + return ns; + } + for (const [name, { + check + }] of Object.entries(NamespaceIds)) { + if (check(nsName)) { + ns = NamespaceSetUp[name]; + if (ns) { + this._namespaces.set(nsName, ns); + return ns; + } + break; + } + } + ns = new UnknownNamespace(++this._nextNsId); + this._namespaces.set(nsName, ns); + return ns; + } + _addNamespacePrefix(prefixes) { + for (const { + prefix, + value + } of prefixes) { + const namespace = this._searchNamespace(value); + let prefixStack = this._namespacePrefixes.get(prefix); + if (!prefixStack) { + prefixStack = []; + this._namespacePrefixes.set(prefix, prefixStack); + } + prefixStack.push(namespace); + } + } + _getNamespaceToUse(prefix) { + if (!prefix) { + return this._currentNamespace; + } + const prefixStack = this._namespacePrefixes.get(prefix); + if (prefixStack?.length > 0) { + return prefixStack.at(-1); + } + warn(`Unknown namespace prefix: ${prefix}.`); + return null; + } + clean(data) { + const { + hasNamespace, + prefixes, + nsAgnostic + } = data; + if (hasNamespace) { + this._currentNamespace = this._namespaceStack.pop(); + } + if (prefixes) { + prefixes.forEach(({ + prefix + }) => { + this._namespacePrefixes.get(prefix).pop(); + }); + } + if (nsAgnostic) { + this._nsAgnosticLevel--; + } + } +} + +;// ./src/core/xfa/parser.js + + + + +class XFAParser extends XMLParserBase { + constructor(rootNameSpace = null, richText = false) { + super(); + this._builder = new Builder(rootNameSpace); + this._stack = []; + this._globalData = { + usedTypefaces: new Set() + }; + this._ids = new Map(); + this._current = this._builder.buildRoot(this._ids); + this._errorCode = XMLParserErrorCode.NoError; + this._whiteRegex = /^\s+$/; + this._nbsps = /\xa0+/g; + this._richText = richText; + } + parse(data) { + this.parseXml(data); + if (this._errorCode !== XMLParserErrorCode.NoError) { + return undefined; + } + this._current[$finalize](); + return this._current.element; + } + onText(text) { + text = text.replace(this._nbsps, match => match.slice(1) + " "); + if (this._richText || this._current[$acceptWhitespace]()) { + this._current[$onText](text, this._richText); + return; + } + if (this._whiteRegex.test(text)) { + return; + } + this._current[$onText](text.trim()); + } + onCdata(text) { + this._current[$onText](text); + } + _mkAttributes(attributes, tagName) { + let namespace = null; + let prefixes = null; + const attributeObj = Object.create({}); + for (const { + name, + value + } of attributes) { + if (name === "xmlns") { + if (!namespace) { + namespace = value; + } else { + warn(`XFA - multiple namespace definition in <${tagName}>`); + } + } else if (name.startsWith("xmlns:")) { + const prefix = name.substring("xmlns:".length); + prefixes ??= []; + prefixes.push({ + prefix, + value + }); + } else { + const i = name.indexOf(":"); + if (i === -1) { + attributeObj[name] = value; + } else { + const nsAttrs = attributeObj[$nsAttributes] ??= Object.create(null); + const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)]; + const attrs = nsAttrs[ns] ||= Object.create(null); + attrs[attrName] = value; + } + } + } + return [namespace, prefixes, attributeObj]; + } + _getNameAndPrefix(name, nsAgnostic) { + const i = name.indexOf(":"); + if (i === -1) { + return [name, null]; + } + return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)]; + } + onBeginElement(tagName, attributes, isEmpty) { + const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName); + const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic()); + const node = this._builder.build({ + nsPrefix, + name, + attributes: attributesObj, + namespace, + prefixes + }); + node[$globalData] = this._globalData; + if (isEmpty) { + node[$finalize](); + if (this._current[$onChild](node)) { + node[$setId](this._ids); + } + node[$clean](this._builder); + return; + } + this._stack.push(this._current); + this._current = node; + } + onEndElement(name) { + const node = this._current; + if (node[$isCDATAXml]() && typeof node[$content] === "string") { + const parser = new XFAParser(); + parser._globalData = this._globalData; + const root = parser.parse(node[$content]); + node[$content] = null; + node[$onChild](root); + } + node[$finalize](); + this._current = this._stack.pop(); + if (this._current[$onChild](node)) { + node[$setId](this._ids); + } + node[$clean](this._builder); + } + onError(code) { + this._errorCode = code; + } +} + +;// ./src/core/xfa/factory.js + + + + + + + + +class XFAFactory { + constructor(data) { + try { + this.root = new XFAParser().parse(XFAFactory._createDocument(data)); + const binder = new Binder(this.root); + this.form = binder.bind(); + this.dataHandler = new DataHandler(this.root, binder.getData()); + this.form[$globalData].template = this.form; + } catch (e) { + warn(`XFA - an error occurred during parsing and binding: ${e}`); + } + } + isValid() { + return !!(this.root && this.form); + } + _createPagesHelper() { + const iterator = this.form[$toPages](); + return new Promise((resolve, reject) => { + const nextIteration = () => { + try { + const value = iterator.next(); + if (value.done) { + resolve(value.value); + } else { + setTimeout(nextIteration, 0); + } + } catch (e) { + reject(e); + } + }; + setTimeout(nextIteration, 0); + }); + } + async _createPages() { + try { + this.pages = await this._createPagesHelper(); + this.dims = this.pages.children.map(c => { + const { + width, + height + } = c.attributes.style; + return [0, 0, parseInt(width), parseInt(height)]; + }); + } catch (e) { + warn(`XFA - an error occurred during layout: ${e}`); + } + } + getBoundingBox(pageIndex) { + return this.dims[pageIndex]; + } + async getNumPages() { + if (!this.pages) { + await this._createPages(); + } + return this.dims.length; + } + setImages(images) { + this.form[$globalData].images = images; + } + setFonts(fonts) { + this.form[$globalData].fontFinder = new FontFinder(fonts); + const missingFonts = []; + for (let typeface of this.form[$globalData].usedTypefaces) { + typeface = stripQuotes(typeface); + const font = this.form[$globalData].fontFinder.find(typeface); + if (!font) { + missingFonts.push(typeface); + } + } + if (missingFonts.length > 0) { + return missingFonts; + } + return null; + } + appendFonts(fonts, reallyMissingFonts) { + this.form[$globalData].fontFinder.add(fonts, reallyMissingFonts); + } + async getPages() { + if (!this.pages) { + await this._createPages(); + } + const pages = this.pages; + this.pages = null; + return pages; + } + serializeData(storage) { + return this.dataHandler.serialize(storage); + } + static _createDocument(data) { + if (!data["/xdp:xdp"]) { + return data["xdp:xdp"]; + } + return Object.values(data).join(""); + } + static getRichTextAsHtml(rc) { + if (!rc || typeof rc !== "string") { + return null; + } + try { + let root = new XFAParser(XhtmlNamespace, true).parse(rc); + if (!["body", "xhtml"].includes(root[$nodeName])) { + const newRoot = XhtmlNamespace.body({}); + newRoot[$appendChild](root); + root = newRoot; + } + const result = root[$toHTML](); + if (!result.success) { + return null; + } + const { + html + } = result; + const { + attributes + } = html; + if (attributes) { + if (attributes.class) { + attributes.class = attributes.class.filter(attr => !attr.startsWith("xfa")); + } + attributes.dir = "auto"; + } + return { + html, + str: root[$text]() + }; + } catch (e) { + warn(`XFA - an error occurred during parsing of rich text: ${e}`); + } + return null; + } +} + +;// ./src/core/annotation.js + + + + + + + + + + + + + + + +class AnnotationFactory { + static createGlobals(pdfManager) { + return Promise.all([pdfManager.ensureCatalog("acroForm"), pdfManager.ensureDoc("xfaDatasets"), pdfManager.ensureCatalog("structTreeRoot"), pdfManager.ensureCatalog("baseUrl"), pdfManager.ensureCatalog("attachments"), pdfManager.ensureCatalog("globalColorSpaceCache")]).then(([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments, globalColorSpaceCache]) => ({ + pdfManager, + acroForm: acroForm instanceof Dict ? acroForm : Dict.empty, + xfaDatasets, + structTreeRoot, + baseUrl, + attachments, + globalColorSpaceCache + }), reason => { + warn(`createGlobals: "${reason}".`); + return null; + }); + } + static async create(xref, ref, annotationGlobals, idFactory, collectFields, orphanFields, collectByType, pageRef) { + const pageIndex = collectFields ? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager) : null; + return annotationGlobals.pdfManager.ensure(this, "_create", [xref, ref, annotationGlobals, idFactory, collectFields, orphanFields, collectByType, pageIndex, pageRef]); + } + static _create(xref, ref, annotationGlobals, idFactory, collectFields = false, orphanFields = null, collectByType = null, pageIndex = null, pageRef = null) { + const dict = xref.fetchIfRef(ref); + if (!(dict instanceof Dict)) { + return undefined; + } + let subtype = dict.get("Subtype"); + subtype = subtype instanceof Name ? subtype.name : null; + if (collectByType && !collectByType.has(AnnotationType[subtype.toUpperCase()])) { + return null; + } + const { + acroForm, + pdfManager + } = annotationGlobals; + const id = ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`; + const parameters = { + xref, + ref, + dict, + subtype, + id, + annotationGlobals, + collectFields, + orphanFields, + needAppearances: !collectFields && acroForm.get("NeedAppearances") === true, + pageIndex, + evaluatorOptions: pdfManager.evaluatorOptions, + pageRef + }; + switch (subtype) { + case "Link": + return new LinkAnnotation(parameters); + case "Text": + return new TextAnnotation(parameters); + case "Widget": + let fieldType = getInheritableProperty({ + dict, + key: "FT" + }); + fieldType = fieldType instanceof Name ? fieldType.name : null; + switch (fieldType) { + case "Tx": + return new TextWidgetAnnotation(parameters); + case "Btn": + return new ButtonWidgetAnnotation(parameters); + case "Ch": + return new ChoiceWidgetAnnotation(parameters); + case "Sig": + return new SignatureWidgetAnnotation(parameters); + } + warn(`Unimplemented widget field type "${fieldType}", ` + "falling back to base field type."); + return new WidgetAnnotation(parameters); + case "Popup": + return new PopupAnnotation(parameters); + case "FreeText": + return new FreeTextAnnotation(parameters); + case "Line": + return new LineAnnotation(parameters); + case "Square": + return new SquareAnnotation(parameters); + case "Circle": + return new CircleAnnotation(parameters); + case "PolyLine": + return new PolylineAnnotation(parameters); + case "Polygon": + return new PolygonAnnotation(parameters); + case "Caret": + return new CaretAnnotation(parameters); + case "Ink": + return new InkAnnotation(parameters); + case "Highlight": + return new HighlightAnnotation(parameters); + case "Underline": + return new UnderlineAnnotation(parameters); + case "Squiggly": + return new SquigglyAnnotation(parameters); + case "StrikeOut": + return new StrikeOutAnnotation(parameters); + case "Stamp": + return new StampAnnotation(parameters); + case "FileAttachment": + return new FileAttachmentAnnotation(parameters); + default: + if (!collectFields) { + if (!subtype) { + warn("Annotation is missing the required /Subtype."); + } else { + warn(`Unimplemented annotation type "${subtype}", ` + "falling back to base annotation."); + } + } + return new Annotation(parameters); + } + } + static async _getPageIndex(xref, ref, pdfManager) { + try { + const annotDict = await xref.fetchIfRefAsync(ref); + if (!(annotDict instanceof Dict)) { + return -1; + } + const pageRef = annotDict.getRaw("P"); + if (pageRef instanceof Ref) { + try { + const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [pageRef]); + return pageIndex; + } catch (ex) { + info(`_getPageIndex -- not a valid page reference: "${ex}".`); + } + } + if (annotDict.has("Kids")) { + return -1; + } + const numPages = await pdfManager.ensureDoc("numPages"); + for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { + const page = await pdfManager.getPage(pageIndex); + const annotations = await pdfManager.ensure(page, "annotations"); + for (const annotRef of annotations) { + if (annotRef instanceof Ref && isRefsEqual(annotRef, ref)) { + return pageIndex; + } + } + } + } catch (ex) { + warn(`_getPageIndex: "${ex}".`); + } + return -1; + } + static generateImages(annotations, xref, isOffscreenCanvasSupported) { + if (!isOffscreenCanvasSupported) { + warn("generateImages: OffscreenCanvas is not supported, cannot save or print some annotations with images."); + return null; + } + let imagePromises; + for (const { + bitmapId, + bitmap + } of annotations) { + if (!bitmap) { + continue; + } + imagePromises ||= new Map(); + imagePromises.set(bitmapId, StampAnnotation.createImage(bitmap, xref)); + } + return imagePromises; + } + static async saveNewAnnotations(evaluator, task, annotations, imagePromises, changes) { + const xref = evaluator.xref; + let baseFontRef; + const promises = []; + const { + isOffscreenCanvasSupported + } = evaluator.options; + for (const annotation of annotations) { + if (annotation.deleted) { + continue; + } + switch (annotation.annotationType) { + case AnnotationEditorType.FREETEXT: + if (!baseFontRef) { + const baseFont = new Dict(xref); + baseFont.setIfName("BaseFont", "Helvetica"); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type1"); + baseFont.setIfName("Encoding", "WinAnsiEncoding"); + baseFontRef = xref.getNewTemporaryRef(); + changes.put(baseFontRef, { + data: baseFont + }); + } + promises.push(FreeTextAnnotation.createNewAnnotation(xref, annotation, changes, { + evaluator, + task, + baseFontRef + })); + break; + case AnnotationEditorType.HIGHLIGHT: + if (annotation.quadPoints) { + promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, changes)); + } else { + promises.push(InkAnnotation.createNewAnnotation(xref, annotation, changes)); + } + break; + case AnnotationEditorType.INK: + promises.push(InkAnnotation.createNewAnnotation(xref, annotation, changes)); + break; + case AnnotationEditorType.STAMP: + const image = isOffscreenCanvasSupported ? await imagePromises?.get(annotation.bitmapId) : null; + if (image?.imageStream) { + const { + imageStream, + smaskStream + } = image; + if (smaskStream) { + const smaskRef = xref.getNewTemporaryRef(); + changes.put(smaskRef, { + data: smaskStream + }); + imageStream.dict.set("SMask", smaskRef); + } + const imageRef = image.imageRef = xref.getNewTemporaryRef(); + changes.put(imageRef, { + data: imageStream + }); + image.imageStream = image.smaskStream = null; + } + promises.push(StampAnnotation.createNewAnnotation(xref, annotation, changes, { + image + })); + break; + case AnnotationEditorType.SIGNATURE: + promises.push(StampAnnotation.createNewAnnotation(xref, annotation, changes, {})); + break; + } + } + return { + annotations: (await Promise.all(promises)).flat() + }; + } + static async printNewAnnotations(annotationGlobals, evaluator, task, annotations, imagePromises) { + if (!annotations) { + return null; + } + const { + options, + xref + } = evaluator; + const promises = []; + for (const annotation of annotations) { + if (annotation.deleted) { + continue; + } + switch (annotation.annotationType) { + case AnnotationEditorType.FREETEXT: + promises.push(FreeTextAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluator, + task, + evaluatorOptions: options + })); + break; + case AnnotationEditorType.HIGHLIGHT: + if (annotation.quadPoints) { + promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + } else { + promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + } + break; + case AnnotationEditorType.INK: + promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + break; + case AnnotationEditorType.STAMP: + const image = options.isOffscreenCanvasSupported ? await imagePromises?.get(annotation.bitmapId) : null; + if (image?.imageStream) { + const { + imageStream, + smaskStream + } = image; + if (smaskStream) { + imageStream.dict.set("SMask", smaskStream); + } + image.imageRef = new JpegStream(imageStream, imageStream.length); + image.imageStream = image.smaskStream = null; + } + promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + image, + evaluatorOptions: options + })); + break; + case AnnotationEditorType.SIGNATURE: + promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + break; + } + } + return Promise.all(promises); + } +} +function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) { + if (!Array.isArray(color)) { + return defaultColor; + } + const rgbColor = defaultColor || new Uint8ClampedArray(3); + switch (color.length) { + case 0: + return null; + case 1: + ColorSpaceUtils.gray.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + case 3: + ColorSpaceUtils.rgb.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + case 4: + ColorSpaceUtils.cmyk.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + default: + return defaultColor; + } +} +function getPdfColorArray(color, defaultValue = null) { + return color && Array.from(color, c => c / 255) || defaultValue; +} +function getQuadPoints(dict, rect) { + const quadPoints = dict.getArray("QuadPoints"); + if (!isNumberArray(quadPoints, null) || quadPoints.length === 0 || quadPoints.length % 8 > 0) { + return null; + } + const newQuadPoints = new Float32Array(quadPoints.length); + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + const [x1, y1, x2, y2, x3, y3, x4, y4] = quadPoints.slice(i, i + 8); + const minX = Math.min(x1, x2, x3, x4); + const maxX = Math.max(x1, x2, x3, x4); + const minY = Math.min(y1, y2, y3, y4); + const maxY = Math.max(y1, y2, y3, y4); + if (rect !== null && (minX < rect[0] || maxX > rect[2] || minY < rect[1] || maxY > rect[3])) { + return null; + } + newQuadPoints.set([minX, maxY, maxX, maxY, minX, minY, maxX, minY], i); + } + return newQuadPoints; +} +function getTransformMatrix(rect, bbox, matrix) { + const minMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + Util.axialAlignedBoundingBox(bbox, matrix, minMax); + const [minX, minY, maxX, maxY] = minMax; + if (minX === maxX || minY === maxY) { + return [1, 0, 0, 1, rect[0], rect[1]]; + } + const xRatio = (rect[2] - rect[0]) / (maxX - minX); + const yRatio = (rect[3] - rect[1]) / (maxY - minY); + return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio]; +} +class Annotation { + constructor(params) { + const { + dict, + xref, + annotationGlobals, + ref, + orphanFields + } = params; + const parentRef = orphanFields?.get(ref); + if (parentRef) { + dict.set("Parent", parentRef); + } + this.setTitle(dict.get("T")); + this.setContents(dict.get("Contents")); + this.setModificationDate(dict.get("M")); + this.setFlags(dict.get("F")); + this.setRectangle(dict.getArray("Rect")); + this.setColor(dict.getArray("C")); + this.setBorderStyle(dict); + this.setAppearance(dict); + this.setOptionalContent(dict); + const MK = dict.get("MK"); + this.setBorderAndBackgroundColors(MK); + this.setRotation(MK, dict); + this.ref = params.ref instanceof Ref ? params.ref : null; + this._streams = []; + if (this.appearance) { + this._streams.push(this.appearance); + } + const isLocked = !!(this.flags & AnnotationFlag.LOCKED); + const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS); + this.data = { + annotationFlags: this.flags, + borderStyle: this.borderStyle, + color: this.color, + backgroundColor: this.backgroundColor, + borderColor: this.borderColor, + rotation: this.rotation, + contentsObj: this._contents, + hasAppearance: !!this.appearance, + id: params.id, + modificationDate: this.modificationDate, + rect: this.rectangle, + subtype: params.subtype, + hasOwnCanvas: false, + noRotate: !!(this.flags & AnnotationFlag.NOROTATE), + noHTML: isLocked && isContentLocked, + isEditable: false, + structParent: -1 + }; + if (annotationGlobals.structTreeRoot) { + let structParent = dict.get("StructParent"); + this.data.structParent = structParent = Number.isInteger(structParent) && structParent >= 0 ? structParent : -1; + annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent); + } + if (params.collectFields) { + const kids = dict.get("Kids"); + if (Array.isArray(kids)) { + const kidIds = []; + for (const kid of kids) { + if (kid instanceof Ref) { + kidIds.push(kid.toString()); + } + } + if (kidIds.length !== 0) { + this.data.kidIds = kidIds; + } + } + this.data.actions = collectActions(xref, dict, AnnotationActionEventType); + this.data.fieldName = this._constructFieldName(dict); + this.data.pageIndex = params.pageIndex; + } + const it = dict.get("IT"); + if (it instanceof Name) { + this.data.it = it.name; + } + this._isOffscreenCanvasSupported = params.evaluatorOptions.isOffscreenCanvasSupported; + this._fallbackFontDict = null; + this._needAppearances = false; + } + _hasFlag(flags, flag) { + return !!(flags & flag); + } + _buildFlags(noView, noPrint) { + let { + flags + } = this; + if (noView === undefined) { + if (noPrint === undefined) { + return undefined; + } + if (noPrint) { + return flags & ~AnnotationFlag.PRINT; + } + return flags & ~AnnotationFlag.HIDDEN | AnnotationFlag.PRINT; + } + if (noView) { + flags |= AnnotationFlag.PRINT; + if (noPrint) { + return flags & ~AnnotationFlag.NOVIEW | AnnotationFlag.HIDDEN; + } + return flags & ~AnnotationFlag.HIDDEN | AnnotationFlag.NOVIEW; + } + flags &= ~(AnnotationFlag.HIDDEN | AnnotationFlag.NOVIEW); + if (noPrint) { + return flags & ~AnnotationFlag.PRINT; + } + return flags | AnnotationFlag.PRINT; + } + _isViewable(flags) { + return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.NOVIEW); + } + _isPrintable(flags) { + return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE); + } + mustBeViewed(annotationStorage, _renderForms) { + const noView = annotationStorage?.get(this.data.id)?.noView; + if (noView !== undefined) { + return !noView; + } + return this.viewable && !this._hasFlag(this.flags, AnnotationFlag.HIDDEN); + } + mustBePrinted(annotationStorage) { + const noPrint = annotationStorage?.get(this.data.id)?.noPrint; + if (noPrint !== undefined) { + return !noPrint; + } + return this.printable; + } + mustBeViewedWhenEditing(isEditing, modifiedIds = null) { + return isEditing ? !this.data.isEditable : !modifiedIds?.has(this.data.id); + } + get viewable() { + if (this.data.quadPoints === null) { + return false; + } + if (this.flags === 0) { + return true; + } + return this._isViewable(this.flags); + } + get printable() { + if (this.data.quadPoints === null) { + return false; + } + if (this.flags === 0) { + return false; + } + return this._isPrintable(this.flags); + } + _parseStringHelper(data) { + const str = typeof data === "string" ? stringToPDFString(data) : ""; + const dir = str && bidi(str).dir === "rtl" ? "rtl" : "ltr"; + return { + str, + dir + }; + } + setDefaultAppearance(params) { + const { + dict, + annotationGlobals + } = params; + const defaultAppearance = getInheritableProperty({ + dict, + key: "DA" + }) || annotationGlobals.acroForm.get("DA"); + this._defaultAppearance = typeof defaultAppearance === "string" ? defaultAppearance : ""; + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance); + } + setTitle(title) { + this._title = this._parseStringHelper(title); + } + setContents(contents) { + this._contents = this._parseStringHelper(contents); + } + setModificationDate(modificationDate) { + this.modificationDate = typeof modificationDate === "string" ? modificationDate : null; + } + setFlags(flags) { + this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0; + if (this.flags & AnnotationFlag.INVISIBLE && this.constructor.name !== "Annotation") { + this.flags ^= AnnotationFlag.INVISIBLE; + } + } + hasFlag(flag) { + return this._hasFlag(this.flags, flag); + } + setRectangle(rectangle) { + this.rectangle = lookupNormalRect(rectangle, [0, 0, 0, 0]); + } + setColor(color) { + this.color = getRgbColor(color); + } + setLineEndings(lineEndings) { + throw new Error("Not implemented: setLineEndings"); + } + setRotation(mk, dict) { + this.rotation = 0; + let angle = mk instanceof Dict ? mk.get("R") || 0 : dict.get("Rotate") || 0; + if (Number.isInteger(angle) && angle !== 0) { + angle %= 360; + if (angle < 0) { + angle += 360; + } + if (angle % 90 === 0) { + this.rotation = angle; + } + } + } + setBorderAndBackgroundColors(mk) { + if (mk instanceof Dict) { + this.borderColor = getRgbColor(mk.getArray("BC"), null); + this.backgroundColor = getRgbColor(mk.getArray("BG"), null); + } else { + this.borderColor = this.backgroundColor = null; + } + } + setBorderStyle(borderStyle) { + this.borderStyle = new AnnotationBorderStyle(); + if (!(borderStyle instanceof Dict)) { + return; + } + if (borderStyle.has("BS")) { + const dict = borderStyle.get("BS"); + if (dict instanceof Dict) { + const dictType = dict.get("Type"); + if (!dictType || isName(dictType, "Border")) { + this.borderStyle.setWidth(dict.get("W"), this.rectangle); + this.borderStyle.setStyle(dict.get("S")); + this.borderStyle.setDashArray(dict.getArray("D")); + } + } + } else if (borderStyle.has("Border")) { + const array = borderStyle.getArray("Border"); + if (Array.isArray(array) && array.length >= 3) { + this.borderStyle.setHorizontalCornerRadius(array[0]); + this.borderStyle.setVerticalCornerRadius(array[1]); + this.borderStyle.setWidth(array[2], this.rectangle); + if (array.length === 4) { + this.borderStyle.setDashArray(array[3], true); + } + } + } else { + this.borderStyle.setWidth(0); + } + } + setAppearance(dict) { + this.appearance = null; + const appearanceStates = dict.get("AP"); + if (!(appearanceStates instanceof Dict)) { + return; + } + const normalAppearanceState = appearanceStates.get("N"); + if (normalAppearanceState instanceof BaseStream) { + this.appearance = normalAppearanceState; + return; + } + if (!(normalAppearanceState instanceof Dict)) { + return; + } + const as = dict.get("AS"); + if (!(as instanceof Name) || !normalAppearanceState.has(as.name)) { + return; + } + const appearance = normalAppearanceState.get(as.name); + if (appearance instanceof BaseStream) { + this.appearance = appearance; + } + } + setOptionalContent(dict) { + this.oc = null; + const oc = dict.get("OC"); + if (oc instanceof Name) { + warn("setOptionalContent: Support for /Name-entry is not implemented."); + } else if (oc instanceof Dict) { + this.oc = oc; + } + } + async loadResources(keys, appearance) { + const resources = await appearance.dict.getAsync("Resources"); + if (resources) { + await ObjectLoader.load(resources, keys, resources.xref); + } + return resources; + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + const { + hasOwnCanvas, + id, + rect + } = this.data; + let appearance = this.appearance; + const isUsingOwnCanvas = !!(hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY); + if (isUsingOwnCanvas && (this.width === 0 || this.height === 0)) { + this.data.hasOwnCanvas = false; + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + if (!appearance) { + if (!isUsingOwnCanvas) { + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + appearance = new StringStream(""); + appearance.dict = new Dict(); + } + const appearanceDict = appearance.dict; + const resources = await this.loadResources(RESOURCES_KEYS_OPERATOR_LIST, appearance); + const bbox = lookupRect(appearanceDict.getArray("BBox"), [0, 0, 1, 1]); + const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), IDENTITY_MATRIX); + const transform = getTransformMatrix(rect, bbox, matrix); + const opList = new OperatorList(); + let optionalContent; + if (this.oc) { + optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); + } + if (optionalContent !== undefined) { + opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); + } + opList.addOp(OPS.beginAnnotation, [id, rect, transform, matrix, isUsingOwnCanvas]); + await evaluator.getOperatorList({ + stream: appearance, + task, + resources, + operatorList: opList, + fallbackFontDict: this._fallbackFontDict + }); + opList.addOp(OPS.endAnnotation, []); + if (optionalContent !== undefined) { + opList.addOp(OPS.endMarkedContent, []); + } + this.reset(); + return { + opList, + separateForm: false, + separateCanvas: isUsingOwnCanvas + }; + } + async save(evaluator, task, annotationStorage, changes) { + return null; + } + get overlaysTextContent() { + return false; + } + get hasTextContent() { + return false; + } + async extractTextContent(evaluator, task, viewBox) { + if (!this.appearance) { + return; + } + const resources = await this.loadResources(RESOURCES_KEYS_TEXT_CONTENT, this.appearance); + const text = []; + const buffer = []; + let firstPosition = null; + const sink = { + desiredSize: Math.Infinity, + ready: true, + enqueue(chunk, size) { + for (const item of chunk.items) { + if (item.str === undefined) { + continue; + } + firstPosition ||= item.transform.slice(-2); + buffer.push(item.str); + if (item.hasEOL) { + text.push(buffer.join("").trimEnd()); + buffer.length = 0; + } + } + } + }; + await evaluator.getTextContent({ + stream: this.appearance, + task, + resources, + includeMarkedContent: true, + keepWhiteSpace: true, + sink, + viewBox + }); + this.reset(); + if (buffer.length) { + text.push(buffer.join("").trimEnd()); + } + if (text.length > 1 || text[0]) { + const appearanceDict = this.appearance.dict; + const bbox = lookupRect(appearanceDict.getArray("BBox"), null); + const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), null); + this.data.textPosition = this._transformPoint(firstPosition, bbox, matrix); + this.data.textContent = text; + } + } + _transformPoint(coords, bbox, matrix) { + const { + rect + } = this.data; + bbox ||= [0, 0, 1, 1]; + matrix ||= [1, 0, 0, 1, 0, 0]; + const transform = getTransformMatrix(rect, bbox, matrix); + transform[4] -= rect[0]; + transform[5] -= rect[1]; + const p = coords.slice(); + Util.applyTransform(p, transform); + Util.applyTransform(p, matrix); + return p; + } + getFieldObject() { + if (this.data.kidIds) { + return { + id: this.data.id, + actions: this.data.actions, + name: this.data.fieldName, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + type: "", + kidIds: this.data.kidIds, + page: this.data.pageIndex, + rotation: this.rotation + }; + } + return null; + } + reset() { + for (const stream of this._streams) { + stream.reset(); + } + } + _constructFieldName(dict) { + if (!dict.has("T") && !dict.has("Parent")) { + warn("Unknown field name, falling back to empty field name."); + return ""; + } + if (!dict.has("Parent")) { + return stringToPDFString(dict.get("T")); + } + const fieldName = []; + if (dict.has("T")) { + fieldName.unshift(stringToPDFString(dict.get("T"))); + } + let loopDict = dict; + const visited = new RefSet(); + if (dict.objId) { + visited.put(dict.objId); + } + while (loopDict.has("Parent")) { + loopDict = loopDict.get("Parent"); + if (!(loopDict instanceof Dict) || loopDict.objId && visited.has(loopDict.objId)) { + break; + } + if (loopDict.objId) { + visited.put(loopDict.objId); + } + if (loopDict.has("T")) { + fieldName.unshift(stringToPDFString(loopDict.get("T"))); + } + } + return fieldName.join("."); + } + get width() { + return this.data.rect[2] - this.data.rect[0]; + } + get height() { + return this.data.rect[3] - this.data.rect[1]; + } +} +class AnnotationBorderStyle { + constructor() { + this.width = 1; + this.rawWidth = 1; + this.style = AnnotationBorderStyleType.SOLID; + this.dashArray = [3]; + this.horizontalCornerRadius = 0; + this.verticalCornerRadius = 0; + } + setWidth(width, rect = [0, 0, 0, 0]) { + if (width instanceof Name) { + this.width = 0; + return; + } + if (typeof width === "number") { + if (width > 0) { + this.rawWidth = width; + const maxWidth = (rect[2] - rect[0]) / 2; + const maxHeight = (rect[3] - rect[1]) / 2; + if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) { + warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`); + width = 1; + } + } + this.width = width; + } + } + setStyle(style) { + if (!(style instanceof Name)) { + return; + } + switch (style.name) { + case "S": + this.style = AnnotationBorderStyleType.SOLID; + break; + case "D": + this.style = AnnotationBorderStyleType.DASHED; + break; + case "B": + this.style = AnnotationBorderStyleType.BEVELED; + break; + case "I": + this.style = AnnotationBorderStyleType.INSET; + break; + case "U": + this.style = AnnotationBorderStyleType.UNDERLINE; + break; + default: + break; + } + } + setDashArray(dashArray, forceStyle = false) { + if (Array.isArray(dashArray)) { + let isValid = true; + let allZeros = true; + for (const element of dashArray) { + const validNumber = +element >= 0; + if (!validNumber) { + isValid = false; + break; + } else if (element > 0) { + allZeros = false; + } + } + if (dashArray.length === 0 || isValid && !allZeros) { + this.dashArray = dashArray; + if (forceStyle) { + this.setStyle(Name.get("D")); + } + } else { + this.width = 0; + } + } else if (dashArray) { + this.width = 0; + } + } + setHorizontalCornerRadius(radius) { + if (Number.isInteger(radius)) { + this.horizontalCornerRadius = radius; + } + } + setVerticalCornerRadius(radius) { + if (Number.isInteger(radius)) { + this.verticalCornerRadius = radius; + } + } +} +class MarkupAnnotation extends Annotation { + constructor(params) { + super(params); + const { + dict + } = params; + if (dict.has("IRT")) { + const rawIRT = dict.getRaw("IRT"); + this.data.inReplyTo = rawIRT instanceof Ref ? rawIRT.toString() : null; + const rt = dict.get("RT"); + this.data.replyType = rt instanceof Name ? rt.name : AnnotationReplyType.REPLY; + } + let popupRef = null; + if (this.data.replyType === AnnotationReplyType.GROUP) { + const parent = dict.get("IRT"); + this.setTitle(parent.get("T")); + this.data.titleObj = this._title; + this.setContents(parent.get("Contents")); + this.data.contentsObj = this._contents; + if (!parent.has("CreationDate")) { + this.data.creationDate = null; + } else { + this.setCreationDate(parent.get("CreationDate")); + this.data.creationDate = this.creationDate; + } + if (!parent.has("M")) { + this.data.modificationDate = null; + } else { + this.setModificationDate(parent.get("M")); + this.data.modificationDate = this.modificationDate; + } + popupRef = parent.getRaw("Popup"); + if (!parent.has("C")) { + this.data.color = null; + } else { + this.setColor(parent.getArray("C")); + this.data.color = this.color; + } + } else { + this.data.titleObj = this._title; + this.setCreationDate(dict.get("CreationDate")); + this.data.creationDate = this.creationDate; + popupRef = dict.getRaw("Popup"); + if (!dict.has("C")) { + this.data.color = null; + } + } + this.data.popupRef = popupRef instanceof Ref ? popupRef.toString() : null; + if (dict.has("RC")) { + this.data.richText = XFAFactory.getRichTextAsHtml(dict.get("RC")); + } + } + setCreationDate(creationDate) { + this.creationDate = typeof creationDate === "string" ? creationDate : null; + } + _setDefaultAppearance({ + xref, + extra, + strokeColor, + fillColor, + blendMode, + strokeAlpha, + fillAlpha, + pointsCallback + }) { + const bbox = this.data.rect = [Infinity, Infinity, -Infinity, -Infinity]; + const buffer = ["q"]; + if (extra) { + buffer.push(extra); + } + if (strokeColor) { + buffer.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`); + } + if (fillColor) { + buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`); + } + const pointsArray = this.data.quadPoints || Float32Array.from([this.rectangle[0], this.rectangle[3], this.rectangle[2], this.rectangle[3], this.rectangle[0], this.rectangle[1], this.rectangle[2], this.rectangle[1]]); + for (let i = 0, ii = pointsArray.length; i < ii; i += 8) { + const points = pointsCallback(buffer, pointsArray.subarray(i, i + 8)); + Util.rectBoundingBox(...points, bbox); + } + buffer.push("Q"); + const formDict = new Dict(xref); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.setIfName("Subtype", "Form"); + const appearanceStream = new StringStream(buffer.join(" ")); + appearanceStream.dict = appearanceStreamDict; + formDict.set("Fm0", appearanceStream); + const gsDict = new Dict(xref); + if (blendMode) { + gsDict.setIfName("BM", blendMode); + } + gsDict.setIfNumber("CA", strokeAlpha); + gsDict.setIfNumber("ca", fillAlpha); + const stateDict = new Dict(xref); + stateDict.set("GS0", gsDict); + const resources = new Dict(xref); + resources.set("ExtGState", stateDict); + resources.set("XObject", formDict); + const appearanceDict = new Dict(xref); + appearanceDict.set("Resources", resources); + appearanceDict.set("BBox", bbox); + this.appearance = new StringStream("/GS0 gs /Fm0 Do"); + this.appearance.dict = appearanceDict; + this._streams.push(this.appearance, appearanceStream); + } + static async createNewAnnotation(xref, annotation, changes, params) { + const annotationRef = annotation.ref ||= xref.getNewTemporaryRef(); + const ap = await this.createNewAppearanceStream(annotation, xref, params); + let annotationDict; + if (ap) { + const apRef = xref.getNewTemporaryRef(); + annotationDict = this.createNewDict(annotation, xref, { + apRef + }); + changes.put(apRef, { + data: ap + }); + } else { + annotationDict = this.createNewDict(annotation, xref, {}); + } + if (Number.isInteger(annotation.parentTreeId)) { + annotationDict.set("StructParent", annotation.parentTreeId); + } + changes.put(annotationRef, { + data: annotationDict + }); + const retRef = { + ref: annotationRef + }; + const { + popup + } = annotation; + if (popup) { + if (popup.deleted) { + annotationDict.delete("Popup"); + annotationDict.delete("Contents"); + annotationDict.delete("RC"); + return retRef; + } + const popupRef = popup.ref ||= xref.getNewTemporaryRef(); + popup.parent = annotationRef; + const popupDict = PopupAnnotation.createNewDict(popup, xref); + changes.put(popupRef, { + data: popupDict + }); + annotationDict.setIfDefined("Contents", stringToAsciiOrUTF16BE(popup.contents)); + annotationDict.set("Popup", popupRef); + return [retRef, { + ref: popupRef + }]; + } + return retRef; + } + static async createNewPrintAnnotation(annotationGlobals, xref, annotation, params) { + const ap = await this.createNewAppearanceStream(annotation, xref, params); + const annotationDict = this.createNewDict(annotation, xref, ap ? { + ap + } : {}); + const newAnnotation = new this.prototype.constructor({ + dict: annotationDict, + xref, + annotationGlobals, + evaluatorOptions: params.evaluatorOptions + }); + if (annotation.ref) { + newAnnotation.ref = newAnnotation.refToReplace = annotation.ref; + } + return newAnnotation; + } +} +class WidgetAnnotation extends Annotation { + constructor(params) { + super(params); + const { + dict, + xref, + annotationGlobals + } = params; + const data = this.data; + this._needAppearances = params.needAppearances; + data.annotationType = AnnotationType.WIDGET; + if (data.fieldName === undefined) { + data.fieldName = this._constructFieldName(dict); + } + if (data.actions === undefined) { + data.actions = collectActions(xref, dict, AnnotationActionEventType); + } + let fieldValue = getInheritableProperty({ + dict, + key: "V", + getArray: true + }); + data.fieldValue = this._decodeFormValue(fieldValue); + const defaultFieldValue = getInheritableProperty({ + dict, + key: "DV", + getArray: true + }); + data.defaultFieldValue = this._decodeFormValue(defaultFieldValue); + if (fieldValue === undefined && annotationGlobals.xfaDatasets) { + const path = this._title.str; + if (path) { + this._hasValueFromXFA = true; + data.fieldValue = fieldValue = annotationGlobals.xfaDatasets.getValue(path); + } + } + if (fieldValue === undefined && data.defaultFieldValue !== null) { + data.fieldValue = data.defaultFieldValue; + } + data.alternativeText = stringToPDFString(dict.get("TU") || ""); + this.setDefaultAppearance(params); + data.hasAppearance ||= this._needAppearances && data.fieldValue !== undefined && data.fieldValue !== null; + const fieldType = getInheritableProperty({ + dict, + key: "FT" + }); + data.fieldType = fieldType instanceof Name ? fieldType.name : null; + const localResources = getInheritableProperty({ + dict, + key: "DR" + }); + const acroFormResources = annotationGlobals.acroForm.get("DR"); + const appearanceResources = this.appearance?.dict.get("Resources"); + this._fieldResources = { + localResources, + acroFormResources, + appearanceResources, + mergedResources: Dict.merge({ + xref, + dictArray: [localResources, appearanceResources, acroFormResources], + mergeSubDicts: true + }) + }; + data.fieldFlags = getInheritableProperty({ + dict, + key: "Ff" + }); + if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) { + data.fieldFlags = 0; + } + data.password = this.hasFieldFlag(AnnotationFieldFlag.PASSWORD); + data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); + data.required = this.hasFieldFlag(AnnotationFieldFlag.REQUIRED); + data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN) || this._hasFlag(data.annotationFlags, AnnotationFlag.NOVIEW); + } + _decodeFormValue(formValue) { + if (Array.isArray(formValue)) { + return formValue.filter(item => typeof item === "string").map(item => stringToPDFString(item)); + } else if (formValue instanceof Name) { + return stringToPDFString(formValue.name); + } else if (typeof formValue === "string") { + return stringToPDFString(formValue); + } + return null; + } + hasFieldFlag(flag) { + return !!(this.data.fieldFlags & flag); + } + _isViewable(flags) { + return true; + } + mustBeViewed(annotationStorage, renderForms) { + if (renderForms) { + return this.viewable; + } + return super.mustBeViewed(annotationStorage, renderForms) && !this._hasFlag(this.flags, AnnotationFlag.NOVIEW); + } + getRotationMatrix(annotationStorage) { + let rotation = annotationStorage?.get(this.data.id)?.rotation; + if (rotation === undefined) { + rotation = this.rotation; + } + return rotation === 0 ? IDENTITY_MATRIX : getRotationMatrix(rotation, this.width, this.height); + } + getBorderAndBackgroundAppearances(annotationStorage) { + let rotation = annotationStorage?.get(this.data.id)?.rotation; + if (rotation === undefined) { + rotation = this.rotation; + } + if (!this.backgroundColor && !this.borderColor) { + return ""; + } + const rect = rotation === 0 || rotation === 180 ? `0 0 ${this.width} ${this.height} re` : `0 0 ${this.height} ${this.width} re`; + let str = ""; + if (this.backgroundColor) { + str = `${getPdfColor(this.backgroundColor, true)} ${rect} f `; + } + if (this.borderColor) { + const borderWidth = this.borderStyle.width || 1; + str += `${borderWidth} w ${getPdfColor(this.borderColor, false)} ${rect} S `; + } + return str; + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + if (intent & RenderingIntentFlag.ANNOTATIONS_FORMS && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) { + return { + opList: new OperatorList(), + separateForm: true, + separateCanvas: false + }; + } + if (!this._hasText) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + const content = await this._getAppearance(evaluator, task, intent, annotationStorage); + if (this.appearance && content === null) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + const opList = new OperatorList(); + if (!this._defaultAppearance || content === null) { + return { + opList, + separateForm: false, + separateCanvas: false + }; + } + const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY); + const matrix = [1, 0, 0, 1, 0, 0]; + const bbox = [0, 0, this.width, this.height]; + const transform = getTransformMatrix(this.data.rect, bbox, matrix); + let optionalContent; + if (this.oc) { + optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); + } + if (optionalContent !== undefined) { + opList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]); + } + opList.addOp(OPS.beginAnnotation, [this.data.id, this.data.rect, transform, this.getRotationMatrix(annotationStorage), isUsingOwnCanvas]); + const stream = new StringStream(content); + await evaluator.getOperatorList({ + stream, + task, + resources: this._fieldResources.mergedResources, + operatorList: opList + }); + opList.addOp(OPS.endAnnotation, []); + if (optionalContent !== undefined) { + opList.addOp(OPS.endMarkedContent, []); + } + return { + opList, + separateForm: false, + separateCanvas: isUsingOwnCanvas + }; + } + _getMKDict(rotation) { + const mk = new Dict(null); + if (rotation) { + mk.set("R", rotation); + } + mk.setIfArray("BC", getPdfColorArray(this.borderColor)); + mk.setIfArray("BG", getPdfColorArray(this.backgroundColor)); + return mk.size > 0 ? mk : null; + } + amendSavedDict(annotationStorage, dict) {} + setValue(dict, value, xref, changes) { + const { + dict: parentDict, + ref: parentRef + } = getParentToUpdate(dict, this.ref, xref); + if (!parentDict) { + dict.set("V", value); + } else if (!changes.has(parentRef)) { + const newParentDict = parentDict.clone(); + newParentDict.set("V", value); + changes.put(parentRef, { + data: newParentDict + }); + return newParentDict; + } + return null; + } + async save(evaluator, task, annotationStorage, changes) { + const storageEntry = annotationStorage?.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let value = storageEntry?.value, + rotation = storageEntry?.rotation; + if (value === this.data.fieldValue || value === undefined) { + if (!this._hasValueFromXFA && rotation === undefined && flags === undefined) { + return; + } + value ||= this.data.fieldValue; + } + if (rotation === undefined && !this._hasValueFromXFA && Array.isArray(value) && Array.isArray(this.data.fieldValue) && isArrayEqual(value, this.data.fieldValue) && flags === undefined) { + return; + } + if (rotation === undefined) { + rotation = this.rotation; + } + let appearance = null; + if (!this._needAppearances) { + appearance = await this._getAppearance(evaluator, task, RenderingIntentFlag.SAVE, annotationStorage); + if (appearance === null && flags === undefined) { + return; + } + } else {} + let needAppearances = false; + if (appearance?.needAppearances) { + needAppearances = true; + appearance = null; + } + const { + xref + } = evaluator; + const originalDict = xref.fetchIfRef(this.ref); + if (!(originalDict instanceof Dict)) { + return; + } + const dict = new Dict(xref); + for (const key of originalDict.getKeys()) { + if (key !== "AP") { + dict.set(key, originalDict.getRaw(key)); + } + } + if (flags !== undefined) { + dict.set("F", flags); + if (appearance === null && !needAppearances) { + const ap = originalDict.getRaw("AP"); + if (ap) { + dict.set("AP", ap); + } + } + } + const xfa = { + path: this.data.fieldName, + value + }; + const newParentDict = this.setValue(dict, Array.isArray(value) ? value.map(stringToAsciiOrUTF16BE) : stringToAsciiOrUTF16BE(value), xref, changes); + this.amendSavedDict(annotationStorage, newParentDict || dict); + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances + }); + if (appearance !== null) { + const newRef = xref.getNewTemporaryRef(); + const AP = new Dict(xref); + dict.set("AP", AP); + AP.set("N", newRef); + const resources = this._getSaveFieldResources(xref); + const appearanceStream = new StringStream(appearance); + const appearanceDict = appearanceStream.dict = new Dict(xref); + appearanceDict.setIfName("Subtype", "Form"); + appearanceDict.set("Resources", resources); + const bbox = rotation % 180 === 0 ? [0, 0, this.width, this.height] : [0, 0, this.height, this.width]; + appearanceDict.set("BBox", bbox); + const rotationMatrix = this.getRotationMatrix(annotationStorage); + if (rotationMatrix !== IDENTITY_MATRIX) { + appearanceDict.set("Matrix", rotationMatrix); + } + changes.put(newRef, { + data: appearanceStream, + xfa: null, + needAppearances: false + }); + } + dict.set("M", `D:${getModificationDate()}`); + } + async _getAppearance(evaluator, task, intent, annotationStorage) { + if (this.data.password) { + return null; + } + const storageEntry = annotationStorage?.get(this.data.id); + let value, rotation; + if (storageEntry) { + value = storageEntry.formattedValue || storageEntry.value; + rotation = storageEntry.rotation; + } + if (rotation === undefined && value === undefined && !this._needAppearances) { + if (!this._hasValueFromXFA || this.appearance) { + return null; + } + } + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + if (value === undefined) { + value = this.data.fieldValue; + if (!value) { + return `/Tx BMC q ${colors}Q EMC`; + } + } + if (Array.isArray(value) && value.length === 1) { + value = value[0]; + } + assert(typeof value === "string", "Expected `value` to be a string."); + value = value.trimEnd(); + if (this.data.combo) { + const option = this.data.options.find(({ + exportValue + }) => value === exportValue); + value = option?.displayValue || value; + } + if (value === "") { + return `/Tx BMC q ${colors}Q EMC`; + } + if (rotation === undefined) { + rotation = this.rotation; + } + let lineCount = -1; + let lines; + if (this.data.multiLine) { + lines = value.split(/\r\n?|\n/).map(line => line.normalize("NFC")); + lineCount = lines.length; + } else { + lines = [value.replace(/\r\n?|\n/, "").normalize("NFC")]; + } + const defaultPadding = 1; + const defaultHPadding = 2; + let { + width: totalWidth, + height: totalHeight + } = this; + if (rotation === 90 || rotation === 270) { + [totalWidth, totalHeight] = [totalHeight, totalWidth]; + } + if (!this._defaultAppearance) { + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); + } + let font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); + let defaultAppearance, fontSize, lineHeight; + const encodedLines = []; + let encodingError = false; + for (const line of lines) { + const encodedString = font.encodeString(line); + if (encodedString.length > 1) { + encodingError = true; + } + encodedLines.push(encodedString.join("")); + } + if (encodingError && intent & RenderingIntentFlag.SAVE) { + return { + needAppearances: true + }; + } + if (encodingError && this._isOffscreenCanvasSupported) { + const fontFamily = this.data.comb ? "monospace" : "sans-serif"; + const fakeUnicodeFont = new FakeUnicodeFont(evaluator.xref, fontFamily); + const resources = fakeUnicodeFont.createFontResources(lines.join("")); + const newFont = resources.getRaw("Font"); + if (this._fieldResources.mergedResources.has("Font")) { + const oldFont = this._fieldResources.mergedResources.get("Font"); + for (const key of newFont.getKeys()) { + oldFont.set(key, newFont.getRaw(key)); + } + } else { + this._fieldResources.mergedResources.set("Font", newFont); + } + const fontName = fakeUnicodeFont.fontName.name; + font = await WidgetAnnotation._getFontData(evaluator, task, { + fontName, + fontSize: 0 + }, resources); + for (let i = 0, ii = encodedLines.length; i < ii; i++) { + encodedLines[i] = stringToUTF16String(lines[i]); + } + const savedDefaultAppearance = Object.assign(Object.create(null), this.data.defaultAppearanceData); + this.data.defaultAppearanceData.fontSize = 0; + this.data.defaultAppearanceData.fontName = fontName; + [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); + this.data.defaultAppearanceData = savedDefaultAppearance; + } else { + if (!this._isOffscreenCanvasSupported) { + warn("_getAppearance: OffscreenCanvas is not supported, annotation may not render correctly."); + } + [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); + } + let descent = font.descent; + if (isNaN(descent)) { + descent = BASELINE_FACTOR * lineHeight; + } else { + descent = Math.max(BASELINE_FACTOR * lineHeight, Math.abs(descent) * fontSize); + } + const defaultVPadding = Math.min(Math.floor((totalHeight - fontSize) / 2), defaultPadding); + const alignment = this.data.textAlignment; + if (this.data.multiLine) { + return this._getMultilineAppearance(defaultAppearance, encodedLines, font, fontSize, totalWidth, totalHeight, alignment, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); + } + if (this.data.comb) { + return this._getCombAppearance(defaultAppearance, font, encodedLines[0], fontSize, totalWidth, totalHeight, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); + } + const bottomPadding = defaultVPadding + descent; + if (alignment === 0 || alignment > 2) { + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(defaultHPadding)} ${numberToString(bottomPadding)} Tm (${escapeString(encodedLines[0])}) Tj` + " ET Q EMC"; + } + const prevInfo = { + shift: 0 + }; + const renderedText = this._renderText(encodedLines[0], font, fontSize, totalWidth, alignment, prevInfo, defaultHPadding, bottomPadding); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC"; + } + static async _getFontData(evaluator, task, appearanceData, resources) { + const operatorList = new OperatorList(); + const initialState = { + font: null, + clone() { + return this; + } + }; + const { + fontName, + fontSize + } = appearanceData; + await evaluator.handleSetFont(resources, [fontName && Name.get(fontName), fontSize], null, operatorList, task, initialState, null); + return initialState.font; + } + _getTextWidth(text, font) { + return Math.sumPrecise(font.charsToGlyphs(text).map(g => g.width)) / 1000; + } + _computeFontSize(height, width, text, font, lineCount) { + let { + fontSize + } = this.data.defaultAppearanceData; + let lineHeight = (fontSize || 12) * LINE_FACTOR, + numberOfLines = Math.round(height / lineHeight); + if (!fontSize) { + const roundWithTwoDigits = x => Math.floor(x * 100) / 100; + if (lineCount === -1) { + const textWidth = this._getTextWidth(text, font); + fontSize = roundWithTwoDigits(Math.min(height / LINE_FACTOR, width / textWidth)); + numberOfLines = 1; + } else { + const lines = text.split(/\r\n?|\n/); + const cachedLines = []; + for (const line of lines) { + const encoded = font.encodeString(line).join(""); + const glyphs = font.charsToGlyphs(encoded); + const positions = font.getCharPositions(encoded); + cachedLines.push({ + line: encoded, + glyphs, + positions + }); + } + const isTooBig = fsize => { + let totalHeight = 0; + for (const cache of cachedLines) { + const chunks = this._splitLine(null, font, fsize, width, cache); + totalHeight += chunks.length * fsize; + if (totalHeight > height) { + return true; + } + } + return false; + }; + numberOfLines = Math.max(numberOfLines, lineCount); + while (true) { + lineHeight = height / numberOfLines; + fontSize = roundWithTwoDigits(lineHeight / LINE_FACTOR); + if (isTooBig(fontSize)) { + numberOfLines++; + continue; + } + break; + } + } + const { + fontName, + fontColor + } = this.data.defaultAppearanceData; + this._defaultAppearance = createDefaultAppearance({ + fontSize, + fontName, + fontColor + }); + } + return [this._defaultAppearance, fontSize, height / numberOfLines]; + } + _renderText(text, font, fontSize, totalWidth, alignment, prevInfo, hPadding, vPadding) { + let shift; + if (alignment === 1) { + const width = this._getTextWidth(text, font) * fontSize; + shift = (totalWidth - width) / 2; + } else if (alignment === 2) { + const width = this._getTextWidth(text, font) * fontSize; + shift = totalWidth - width - hPadding; + } else { + shift = hPadding; + } + const shiftStr = numberToString(shift - prevInfo.shift); + prevInfo.shift = shift; + vPadding = numberToString(vPadding); + return `${shiftStr} ${vPadding} Td (${escapeString(text)}) Tj`; + } + _getSaveFieldResources(xref) { + const { + localResources, + appearanceResources, + acroFormResources + } = this._fieldResources; + const fontName = this.data.defaultAppearanceData?.fontName; + if (!fontName) { + return localResources || Dict.empty; + } + for (const resources of [localResources, appearanceResources]) { + if (resources instanceof Dict) { + const localFont = resources.get("Font"); + if (localFont instanceof Dict && localFont.has(fontName)) { + return resources; + } + } + } + if (acroFormResources instanceof Dict) { + const acroFormFont = acroFormResources.get("Font"); + if (acroFormFont instanceof Dict && acroFormFont.has(fontName)) { + const subFontDict = new Dict(xref); + subFontDict.set(fontName, acroFormFont.getRaw(fontName)); + const subResourcesDict = new Dict(xref); + subResourcesDict.set("Font", subFontDict); + return Dict.merge({ + xref, + dictArray: [subResourcesDict, localResources], + mergeSubDicts: true + }); + } + } + return localResources || Dict.empty; + } + getFieldObject() { + return null; + } +} +class TextWidgetAnnotation extends WidgetAnnotation { + constructor(params) { + super(params); + const { + dict + } = params; + if (dict.has("PMD")) { + this.flags |= AnnotationFlag.HIDDEN; + this.data.hidden = true; + warn("Barcodes are not supported"); + } + this.data.hasOwnCanvas = this.data.readOnly && !this.data.noHTML; + this._hasText = true; + if (typeof this.data.fieldValue !== "string") { + this.data.fieldValue = ""; + } + let alignment = getInheritableProperty({ + dict, + key: "Q" + }); + if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) { + alignment = null; + } + this.data.textAlignment = alignment; + let maximumLength = getInheritableProperty({ + dict, + key: "MaxLen" + }); + if (!Number.isInteger(maximumLength) || maximumLength < 0) { + maximumLength = 0; + } + this.data.maxLen = maximumLength; + this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE); + this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.data.multiLine && !this.data.password && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== 0; + this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL); + const { + data: { + actions + } + } = this; + if (!actions) { + return; + } + const AFDateTime = /^AF(Date|Time)_(?:Keystroke|Format)(?:Ex)?\(['"]?([^'"]+)['"]?\);$/; + let canUseHTMLDateTime = false; + if (actions.Format?.length === 1 && actions.Keystroke?.length === 1 && AFDateTime.test(actions.Format[0]) && AFDateTime.test(actions.Keystroke[0]) || actions.Format?.length === 0 && actions.Keystroke?.length === 1 && AFDateTime.test(actions.Keystroke[0]) || actions.Keystroke?.length === 0 && actions.Format?.length === 1 && AFDateTime.test(actions.Format[0])) { + canUseHTMLDateTime = true; + } + const actionsToVisit = []; + if (actions.Format) { + actionsToVisit.push(...actions.Format); + } + if (actions.Keystroke) { + actionsToVisit.push(...actions.Keystroke); + } + if (canUseHTMLDateTime) { + delete actions.Keystroke; + actions.Format = actionsToVisit; + } + for (const formatAction of actionsToVisit) { + const m = formatAction.match(AFDateTime); + if (!m) { + continue; + } + const isDate = m[1] === "Date"; + let format = m[2]; + const num = parseInt(format, 10); + if (!isNaN(num) && Math.floor(Math.log10(num)) + 1 === m[2].length) { + format = (isDate ? DateFormats : TimeFormats)[num] ?? format; + } + this.data.datetimeFormat = format; + if (!canUseHTMLDateTime) { + break; + } + if (isDate) { + if (/HH|MM|ss|h/.test(format)) { + this.data.datetimeType = "datetime-local"; + this.data.timeStep = /ss/.test(format) ? 1 : 60; + } else { + this.data.datetimeType = "date"; + } + break; + } + this.data.datetimeType = "time"; + this.data.timeStep = /ss/.test(format) ? 1 : 60; + break; + } + } + get hasTextContent() { + return !!this.appearance && !this._needAppearances; + } + _getCombAppearance(defaultAppearance, font, text, fontSize, width, height, hPadding, vPadding, descent, lineHeight, annotationStorage) { + const combWidth = width / this.data.maxLen; + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + const buf = []; + const positions = font.getCharPositions(text); + for (const [start, end] of positions) { + buf.push(`(${escapeString(text.substring(start, end))}) Tj`); + } + const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString(vPadding + descent)} Tm ${renderedComb}` + " ET Q EMC"; + } + _getMultilineAppearance(defaultAppearance, lines, font, fontSize, width, height, alignment, hPadding, vPadding, descent, lineHeight, annotationStorage) { + const buf = []; + const totalWidth = width - 2 * hPadding; + const prevInfo = { + shift: 0 + }; + for (let i = 0, ii = lines.length; i < ii; i++) { + const line = lines[i]; + const chunks = this._splitLine(line, font, fontSize, totalWidth); + for (let j = 0, jj = chunks.length; j < jj; j++) { + const chunk = chunks[j]; + const vShift = i === 0 && j === 0 ? -vPadding - (lineHeight - descent) : -lineHeight; + buf.push(this._renderText(chunk, font, fontSize, width, alignment, prevInfo, hPadding, vShift)); + } + } + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + const renderedText = buf.join("\n"); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 ${numberToString(height)} Tm ${renderedText}` + " ET Q EMC"; + } + _splitLine(line, font, fontSize, width, cache = {}) { + line = cache.line || line; + const glyphs = cache.glyphs || font.charsToGlyphs(line); + if (glyphs.length <= 1) { + return [line]; + } + const positions = cache.positions || font.getCharPositions(line); + const scale = fontSize / 1000; + const chunks = []; + let lastSpacePosInStringStart = -1, + lastSpacePosInStringEnd = -1, + lastSpacePos = -1, + startChunk = 0, + currentWidth = 0; + for (let i = 0, ii = glyphs.length; i < ii; i++) { + const [start, end] = positions[i]; + const glyph = glyphs[i]; + const glyphWidth = glyph.width * scale; + if (glyph.unicode === " ") { + if (currentWidth + glyphWidth > width) { + chunks.push(line.substring(startChunk, start)); + startChunk = start; + currentWidth = glyphWidth; + lastSpacePosInStringStart = -1; + lastSpacePos = -1; + } else { + currentWidth += glyphWidth; + lastSpacePosInStringStart = start; + lastSpacePosInStringEnd = end; + lastSpacePos = i; + } + } else if (currentWidth + glyphWidth > width) { + if (lastSpacePosInStringStart !== -1) { + chunks.push(line.substring(startChunk, lastSpacePosInStringEnd)); + startChunk = lastSpacePosInStringEnd; + i = lastSpacePos + 1; + lastSpacePosInStringStart = -1; + currentWidth = 0; + } else { + chunks.push(line.substring(startChunk, start)); + startChunk = start; + currentWidth = glyphWidth; + } + } else { + currentWidth += glyphWidth; + } + } + if (startChunk < line.length) { + chunks.push(line.substring(startChunk, line.length)); + } + return chunks; + } + async extractTextContent(evaluator, task, viewBox) { + await super.extractTextContent(evaluator, task, viewBox); + const text = this.data.textContent; + if (!text) { + return; + } + const allText = text.join("\n"); + if (allText === this.data.fieldValue) { + return; + } + const regex = allText.replaceAll(/([.*+?^${}()|[\]\\])|(\s+)/g, (_m, p1) => p1 ? `\\${p1}` : "\\s+"); + if (new RegExp(`^\\s*${regex}\\s*$`).test(this.data.fieldValue)) { + this.data.textContent = this.data.fieldValue.split("\n"); + } + } + getFieldObject() { + return { + id: this.data.id, + value: this.data.fieldValue, + defaultValue: this.data.defaultFieldValue || "", + multiline: this.data.multiLine, + password: this.data.password, + charLimit: this.data.maxLen, + comb: this.data.comb, + editable: !this.data.readOnly, + hidden: this.data.hidden, + name: this.data.fieldName, + rect: this.data.rect, + actions: this.data.actions, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + datetimeFormat: this.data.datetimeFormat, + hasDatetimeHTML: !!this.data.datetimeType, + type: "text" + }; + } +} +class ButtonWidgetAnnotation extends WidgetAnnotation { + constructor(params) { + super(params); + this.checkedAppearance = null; + this.uncheckedAppearance = null; + const isRadio = this.hasFieldFlag(AnnotationFieldFlag.RADIO), + isPushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + this.data.checkBox = !isRadio && !isPushButton; + this.data.radioButton = isRadio && !isPushButton; + this.data.pushButton = isPushButton; + this.data.isTooltipOnly = false; + if (this.data.checkBox) { + this._processCheckBox(params); + } else if (this.data.radioButton) { + this._processRadioButton(params); + } else if (this.data.pushButton) { + this.data.hasOwnCanvas = true; + this.data.noHTML = false; + this._processPushButton(params); + } else { + warn("Invalid field flags for button widget annotation"); + } + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + if (this.data.pushButton) { + return super.getOperatorList(evaluator, task, intent, false, annotationStorage); + } + let value = null; + let rotation = null; + if (annotationStorage) { + const storageEntry = annotationStorage.get(this.data.id); + value = storageEntry ? storageEntry.value : null; + rotation = storageEntry ? storageEntry.rotation : null; + } + if (value === null && this.appearance) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + if (value === null || value === undefined) { + value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue; + } + const appearance = value ? this.checkedAppearance : this.uncheckedAppearance; + if (appearance) { + const savedAppearance = this.appearance; + const savedMatrix = lookupMatrix(appearance.dict.getArray("Matrix"), IDENTITY_MATRIX); + if (rotation) { + appearance.dict.set("Matrix", this.getRotationMatrix(annotationStorage)); + } + this.appearance = appearance; + const operatorList = super.getOperatorList(evaluator, task, intent, annotationStorage); + this.appearance = savedAppearance; + appearance.dict.set("Matrix", savedMatrix); + return operatorList; + } + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + async save(evaluator, task, annotationStorage, changes) { + if (this.data.checkBox) { + this._saveCheckbox(evaluator, task, annotationStorage, changes); + return; + } + if (this.data.radioButton) { + this._saveRadioButton(evaluator, task, annotationStorage, changes); + } + } + async _saveCheckbox(evaluator, task, annotationStorage, changes) { + if (!annotationStorage) { + return; + } + const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let rotation = storageEntry?.rotation, + value = storageEntry?.value; + if (rotation === undefined && flags === undefined) { + if (value === undefined) { + return; + } + const defaultValue = this.data.fieldValue === this.data.exportValue; + if (defaultValue === value) { + return; + } + } + let dict = evaluator.xref.fetchIfRef(this.ref); + if (!(dict instanceof Dict)) { + return; + } + dict = dict.clone(); + if (rotation === undefined) { + rotation = this.rotation; + } + if (value === undefined) { + value = this.data.fieldValue === this.data.exportValue; + } + const xfa = { + path: this.data.fieldName, + value: value ? this.data.exportValue : "" + }; + const name = Name.get(value ? this.data.exportValue : "Off"); + this.setValue(dict, name, evaluator.xref, changes); + dict.set("AS", name); + dict.set("M", `D:${getModificationDate()}`); + if (flags !== undefined) { + dict.set("F", flags); + } + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances: false + }); + } + async _saveRadioButton(evaluator, task, annotationStorage, changes) { + if (!annotationStorage) { + return; + } + const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let rotation = storageEntry?.rotation, + value = storageEntry?.value; + if (rotation === undefined && flags === undefined) { + if (value === undefined) { + return; + } + const defaultValue = this.data.fieldValue === this.data.buttonValue; + if (defaultValue === value) { + return; + } + } + let dict = evaluator.xref.fetchIfRef(this.ref); + if (!(dict instanceof Dict)) { + return; + } + dict = dict.clone(); + if (value === undefined) { + value = this.data.fieldValue === this.data.buttonValue; + } + if (rotation === undefined) { + rotation = this.rotation; + } + const xfa = { + path: this.data.fieldName, + value: value ? this.data.buttonValue : "" + }; + const name = Name.get(value ? this.data.buttonValue : "Off"); + if (value) { + this.setValue(dict, name, evaluator.xref, changes); + } + dict.set("AS", name); + dict.set("M", `D:${getModificationDate()}`); + if (flags !== undefined) { + dict.set("F", flags); + } + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances: false + }); + } + _getDefaultCheckedAppearance(params, type) { + const { + width, + height + } = this; + const bbox = [0, 0, width, height]; + const FONT_RATIO = 0.8; + const fontSize = Math.min(width, height) * FONT_RATIO; + let metrics, char; + if (type === "check") { + metrics = { + width: 0.755 * fontSize, + height: 0.705 * fontSize + }; + char = "\x33"; + } else if (type === "disc") { + metrics = { + width: 0.791 * fontSize, + height: 0.705 * fontSize + }; + char = "\x6C"; + } else { + unreachable(`_getDefaultCheckedAppearance - unsupported type: ${type}`); + } + const xShift = numberToString((width - metrics.width) / 2); + const yShift = numberToString((height - metrics.height) / 2); + const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`; + const appearanceStreamDict = new Dict(params.xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", bbox); + appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(params.xref); + const font = new Dict(params.xref); + font.set("PdfJsZaDb", this.fallbackFontDict); + resources.set("Font", font); + appearanceStreamDict.set("Resources", resources); + this.checkedAppearance = new StringStream(appearance); + this.checkedAppearance.dict = appearanceStreamDict; + this._streams.push(this.checkedAppearance); + } + _processCheckBox(params) { + const customAppearance = params.dict.get("AP"); + if (!(customAppearance instanceof Dict)) { + return; + } + const normalAppearance = customAppearance.get("N"); + if (!(normalAppearance instanceof Dict)) { + return; + } + const asValue = this._decodeFormValue(params.dict.get("AS")); + if (typeof asValue === "string") { + this.data.fieldValue = asValue; + } + const yes = this.data.fieldValue !== null && this.data.fieldValue !== "Off" ? this.data.fieldValue : "Yes"; + const exportValues = this._decodeFormValue(normalAppearance.getKeys()); + if (exportValues.length === 0) { + exportValues.push("Off", yes); + } else if (exportValues.length === 1) { + if (exportValues[0] === "Off") { + exportValues.push(yes); + } else { + exportValues.unshift("Off"); + } + } else if (exportValues.includes(yes)) { + exportValues.length = 0; + exportValues.push("Off", yes); + } else { + const otherYes = exportValues.find(v => v !== "Off"); + exportValues.length = 0; + exportValues.push("Off", otherYes); + } + if (!exportValues.includes(this.data.fieldValue)) { + this.data.fieldValue = "Off"; + } + this.data.exportValue = exportValues[1]; + const checkedAppearance = normalAppearance.get(this.data.exportValue); + this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; + const uncheckedAppearance = normalAppearance.get("Off"); + this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; + if (this.checkedAppearance) { + this._streams.push(this.checkedAppearance); + } else { + this._getDefaultCheckedAppearance(params, "check"); + } + if (this.uncheckedAppearance) { + this._streams.push(this.uncheckedAppearance); + } + this._fallbackFontDict = this.fallbackFontDict; + if (this.data.defaultFieldValue === null) { + this.data.defaultFieldValue = "Off"; + } + } + _processRadioButton(params) { + this.data.buttonValue = null; + const fieldParent = params.dict.get("Parent"); + if (fieldParent instanceof Dict) { + this.parent = params.dict.getRaw("Parent"); + const fieldParentValue = fieldParent.get("V"); + if (fieldParentValue instanceof Name) { + this.data.fieldValue = this._decodeFormValue(fieldParentValue); + } + } + const appearanceStates = params.dict.get("AP"); + if (!(appearanceStates instanceof Dict)) { + return; + } + const normalAppearance = appearanceStates.get("N"); + if (!(normalAppearance instanceof Dict)) { + return; + } + for (const key of normalAppearance.getKeys()) { + if (key !== "Off") { + this.data.buttonValue = this._decodeFormValue(key); + break; + } + } + const checkedAppearance = normalAppearance.get(this.data.buttonValue); + this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; + const uncheckedAppearance = normalAppearance.get("Off"); + this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; + if (this.checkedAppearance) { + this._streams.push(this.checkedAppearance); + } else { + this._getDefaultCheckedAppearance(params, "disc"); + } + if (this.uncheckedAppearance) { + this._streams.push(this.uncheckedAppearance); + } + this._fallbackFontDict = this.fallbackFontDict; + if (this.data.defaultFieldValue === null) { + this.data.defaultFieldValue = "Off"; + } + } + _processPushButton(params) { + const { + dict, + annotationGlobals + } = params; + if (!dict.has("A") && !dict.has("AA") && !this.data.alternativeText) { + warn("Push buttons without action dictionaries are not supported"); + return; + } + this.data.isTooltipOnly = !dict.has("A") && !dict.has("AA"); + Catalog.parseDestDictionary({ + destDict: dict, + resultObj: this.data, + docBaseUrl: annotationGlobals.baseUrl, + docAttachments: annotationGlobals.attachments + }); + } + getFieldObject() { + let type = "button"; + let exportValues; + if (this.data.checkBox) { + type = "checkbox"; + exportValues = this.data.exportValue; + } else if (this.data.radioButton) { + type = "radiobutton"; + exportValues = this.data.buttonValue; + } + return { + id: this.data.id, + value: this.data.fieldValue || "Off", + defaultValue: this.data.defaultFieldValue, + exportValues, + editable: !this.data.readOnly, + name: this.data.fieldName, + rect: this.data.rect, + hidden: this.data.hidden, + actions: this.data.actions, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + type + }; + } + get fallbackFontDict() { + const dict = new Dict(); + dict.setIfName("BaseFont", "ZapfDingbats"); + dict.setIfName("Type", "FallbackType"); + dict.setIfName("Subtype", "FallbackType"); + dict.setIfName("Encoding", "ZapfDingbatsEncoding"); + return shadow(this, "fallbackFontDict", dict); + } +} +class ChoiceWidgetAnnotation extends WidgetAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.indices = dict.getArray("I"); + this.hasIndices = Array.isArray(this.indices) && this.indices.length > 0; + this.data.options = []; + const options = getInheritableProperty({ + dict, + key: "Opt" + }); + if (Array.isArray(options)) { + for (let i = 0, ii = options.length; i < ii; i++) { + const option = xref.fetchIfRef(options[i]); + const isOptionArray = Array.isArray(option); + this.data.options[i] = { + exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option), + displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option) + }; + } + } + if (!this.hasIndices) { + if (typeof this.data.fieldValue === "string") { + this.data.fieldValue = [this.data.fieldValue]; + } else { + this.data.fieldValue ||= []; + } + } else { + this.data.fieldValue = []; + const ii = this.data.options.length; + for (const i of this.indices) { + if (Number.isInteger(i) && i >= 0 && i < ii) { + this.data.fieldValue.push(this.data.options[i].exportValue); + } + } + } + if (this.data.options.length === 0 && this.data.fieldValue.length > 0) { + this.data.options = this.data.fieldValue.map(value => ({ + exportValue: value, + displayValue: value + })); + } + this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); + this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); + this._hasText = true; + } + getFieldObject() { + const type = this.data.combo ? "combobox" : "listbox"; + const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null; + return { + id: this.data.id, + value, + defaultValue: this.data.defaultFieldValue, + editable: !this.data.readOnly, + name: this.data.fieldName, + rect: this.data.rect, + numItems: this.data.fieldValue.length, + multipleSelection: this.data.multiSelect, + hidden: this.data.hidden, + actions: this.data.actions, + items: this.data.options, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + type + }; + } + amendSavedDict(annotationStorage, dict) { + if (!this.hasIndices) { + return; + } + let values = annotationStorage?.get(this.data.id)?.value; + if (!Array.isArray(values)) { + values = [values]; + } + const indices = []; + const { + options + } = this.data; + for (let i = 0, j = 0, ii = options.length; i < ii; i++) { + if (options[i].exportValue === values[j]) { + indices.push(i); + j += 1; + } + } + dict.set("I", indices); + } + async _getAppearance(evaluator, task, intent, annotationStorage) { + if (this.data.combo) { + return super._getAppearance(evaluator, task, intent, annotationStorage); + } + let exportedValue, rotation; + const storageEntry = annotationStorage?.get(this.data.id); + if (storageEntry) { + rotation = storageEntry.rotation; + exportedValue = storageEntry.value; + } + if (rotation === undefined && exportedValue === undefined && !this._needAppearances) { + return null; + } + if (exportedValue === undefined) { + exportedValue = this.data.fieldValue; + } else if (!Array.isArray(exportedValue)) { + exportedValue = [exportedValue]; + } + const defaultPadding = 1; + const defaultHPadding = 2; + let { + width: totalWidth, + height: totalHeight + } = this; + if (rotation === 90 || rotation === 270) { + [totalWidth, totalHeight] = [totalHeight, totalWidth]; + } + const lineCount = this.data.options.length; + const valueIndices = []; + for (let i = 0; i < lineCount; i++) { + const { + exportValue + } = this.data.options[i]; + if (exportedValue.includes(exportValue)) { + valueIndices.push(i); + } + } + if (!this._defaultAppearance) { + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); + } + const font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); + let defaultAppearance; + let { + fontSize + } = this.data.defaultAppearanceData; + if (!fontSize) { + const lineHeight = (totalHeight - defaultPadding) / lineCount; + let lineWidth = -1; + let value; + for (const { + displayValue + } of this.data.options) { + const width = this._getTextWidth(displayValue, font); + if (width > lineWidth) { + lineWidth = width; + value = displayValue; + } + } + [defaultAppearance, fontSize] = this._computeFontSize(lineHeight, totalWidth - 2 * defaultHPadding, value, font, -1); + } else { + defaultAppearance = this._defaultAppearance; + } + const lineHeight = fontSize * LINE_FACTOR; + const vPadding = (lineHeight - fontSize) / 2; + const numberOfVisibleLines = Math.floor(totalHeight / lineHeight); + let firstIndex = 0; + if (valueIndices.length > 0) { + const minIndex = Math.min(...valueIndices); + const maxIndex = Math.max(...valueIndices); + firstIndex = Math.max(0, maxIndex - numberOfVisibleLines + 1); + if (firstIndex > minIndex) { + firstIndex = minIndex; + } + } + const end = Math.min(firstIndex + numberOfVisibleLines + 1, lineCount); + const buf = ["/Tx BMC q", `1 1 ${totalWidth} ${totalHeight} re W n`]; + if (valueIndices.length) { + buf.push("0.600006 0.756866 0.854904 rg"); + for (const index of valueIndices) { + if (firstIndex <= index && index < end) { + buf.push(`1 ${totalHeight - (index - firstIndex + 1) * lineHeight} ${totalWidth} ${lineHeight} re f`); + } + } + } + buf.push("BT", defaultAppearance, `1 0 0 1 0 ${totalHeight} Tm`); + const prevInfo = { + shift: 0 + }; + for (let i = firstIndex; i < end; i++) { + const { + displayValue + } = this.data.options[i]; + const vpadding = i === firstIndex ? vPadding : 0; + buf.push(this._renderText(displayValue, font, fontSize, totalWidth, 0, prevInfo, defaultHPadding, -lineHeight + vpadding)); + } + buf.push("ET Q EMC"); + return buf.join("\n"); + } +} +class SignatureWidgetAnnotation extends WidgetAnnotation { + constructor(params) { + super(params); + this.data.fieldValue = null; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = !this.data.hasOwnCanvas; + } + getFieldObject() { + return { + id: this.data.id, + value: null, + page: this.data.pageIndex, + type: "signature" + }; + } +} +class TextAnnotation extends MarkupAnnotation { + constructor(params) { + const DEFAULT_ICON_SIZE = 22; + super(params); + this.data.noRotate = true; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const { + dict + } = params; + this.data.annotationType = AnnotationType.TEXT; + if (this.data.hasAppearance) { + this.data.name = "NoIcon"; + } else { + this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; + this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; + this.data.name = dict.has("Name") ? dict.get("Name").name : "Note"; + } + if (dict.has("State")) { + this.data.state = dict.get("State") || null; + this.data.stateModel = dict.get("StateModel") || null; + } else { + this.data.state = null; + this.data.stateModel = null; + } + } +} +class LinkAnnotation extends Annotation { + constructor(params) { + super(params); + const { + dict, + annotationGlobals + } = params; + this.data.annotationType = AnnotationType.LINK; + this.data.noHTML = false; + const quadPoints = getQuadPoints(dict, this.rectangle); + if (quadPoints) { + this.data.quadPoints = quadPoints; + } + this.data.borderColor ||= this.data.color; + Catalog.parseDestDictionary({ + destDict: dict, + resultObj: this.data, + docBaseUrl: annotationGlobals.baseUrl, + docAttachments: annotationGlobals.attachments + }); + } + get overlaysTextContent() { + return true; + } +} +class PopupAnnotation extends Annotation { + constructor(params) { + super(params); + const { + dict + } = params; + this.data.annotationType = AnnotationType.POPUP; + this.data.noHTML = false; + if (this.width === 0 || this.height === 0) { + this.data.rect = null; + } + let parentItem = dict.get("Parent"); + if (!parentItem) { + warn("Popup annotation has a missing or invalid parent annotation."); + return; + } + this.data.parentRect = lookupNormalRect(parentItem.getArray("Rect"), null); + this.data.creationDate = parentItem.get("CreationDate") || ""; + const rt = parentItem.get("RT"); + if (isName(rt, AnnotationReplyType.GROUP)) { + parentItem = parentItem.get("IRT"); + } + if (!parentItem.has("M")) { + this.data.modificationDate = null; + } else { + this.setModificationDate(parentItem.get("M")); + this.data.modificationDate = this.modificationDate; + } + if (!parentItem.has("C")) { + this.data.color = null; + } else { + this.setColor(parentItem.getArray("C")); + this.data.color = this.color; + } + if (!this.viewable) { + const parentFlags = parentItem.get("F"); + if (this._isViewable(parentFlags)) { + this.setFlags(parentFlags); + } + } + this.setTitle(parentItem.get("T")); + this.data.titleObj = this._title; + this.setContents(parentItem.get("Contents")); + this.data.contentsObj = this._contents; + if (parentItem.has("RC")) { + this.data.richText = XFAFactory.getRichTextAsHtml(parentItem.get("RC")); + } + this.data.open = !!dict.get("Open"); + } + static createNewDict(annotation, xref, _params) { + const { + oldAnnotation, + rect, + parent + } = annotation; + const popup = oldAnnotation || new Dict(xref); + popup.setIfNotExists("Type", Name.get("Annot")); + popup.setIfNotExists("Subtype", Name.get("Popup")); + popup.setIfNotExists("Open", false); + popup.setIfArray("Rect", rect); + popup.set("Parent", parent); + return popup; + } + static async createNewAppearanceStream(annotation, xref, params) { + return null; + } +} +class FreeTextAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.hasOwnCanvas = this.data.noRotate; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + const { + annotationGlobals, + evaluatorOptions, + xref + } = params; + this.data.annotationType = AnnotationType.FREETEXT; + this.setDefaultAppearance(params); + this._hasAppearance = !!this.appearance; + if (this._hasAppearance) { + const { + fontColor, + fontSize + } = parseAppearanceStream(this.appearance, evaluatorOptions, xref, annotationGlobals.globalColorSpaceCache); + this.data.defaultAppearanceData.fontColor = fontColor; + this.data.defaultAppearanceData.fontSize = fontSize || 10; + } else { + this.data.defaultAppearanceData.fontSize ||= 10; + const { + fontColor, + fontSize + } = this.data.defaultAppearanceData; + if (this._contents.str) { + this.data.textContent = this._contents.str.split(/\r\n?|\n/).map(line => line.trimEnd()); + const { + coords, + bbox, + matrix + } = FakeUnicodeFont.getFirstPositionInfo(this.rectangle, this.rotation, fontSize); + this.data.textPosition = this._transformPoint(coords, bbox, matrix); + } + if (this._isOffscreenCanvasSupported) { + const strokeAlpha = params.dict.get("CA"); + const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif"); + this.appearance = fakeUnicodeFont.createAppearance(this._contents.str, this.rectangle, this.rotation, fontSize, fontColor, strokeAlpha); + this._streams.push(this.appearance); + } else { + warn("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly."); + } + } + } + get hasTextContent() { + return this._hasAppearance; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + color, + date, + fontSize, + oldAnnotation, + rect, + rotation, + user, + value + } = annotation; + const freetext = oldAnnotation || new Dict(xref); + freetext.setIfNotExists("Type", Name.get("Annot")); + freetext.setIfNotExists("Subtype", Name.get("FreeText")); + freetext.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date)}`); + if (oldAnnotation) { + freetext.delete("RC"); + } + freetext.setIfArray("Rect", rect); + const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`; + freetext.set("DA", da); + freetext.setIfDefined("Contents", stringToAsciiOrUTF16BE(value)); + freetext.setIfNotExists("F", 4); + freetext.setIfNotExists("Border", [0, 0, 0]); + freetext.setIfNumber("Rotate", rotation); + freetext.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + freetext.set("AP", n); + n.set("N", apRef || ap); + } + return freetext; + } + static async createNewAppearanceStream(annotation, xref, params) { + const { + baseFontRef, + evaluator, + task + } = params; + const { + color, + fontSize, + rect, + rotation, + value + } = annotation; + if (!color) { + return null; + } + const resources = new Dict(xref); + const font = new Dict(xref); + if (baseFontRef) { + font.set("Helv", baseFontRef); + } else { + const baseFont = new Dict(xref); + baseFont.setIfName("BaseFont", "Helvetica"); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type1"); + baseFont.setIfName("Encoding", "WinAnsiEncoding"); + font.set("Helv", baseFont); + } + resources.set("Font", font); + const helv = await WidgetAnnotation._getFontData(evaluator, task, { + fontName: "Helv", + fontSize + }, resources); + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + const lines = value.split("\n"); + const scale = fontSize / 1000; + let totalWidth = -Infinity; + const encodedLines = []; + for (let line of lines) { + const encoded = helv.encodeString(line); + if (encoded.length > 1) { + return null; + } + line = encoded.join(""); + encodedLines.push(line); + let lineWidth = 0; + const glyphs = helv.charsToGlyphs(line); + for (const glyph of glyphs) { + lineWidth += glyph.width * scale; + } + totalWidth = Math.max(totalWidth, lineWidth); + } + let hscale = 1; + if (totalWidth > w) { + hscale = w / totalWidth; + } + let vscale = 1; + const lineHeight = LINE_FACTOR * fontSize; + const lineAscent = (LINE_FACTOR - LINE_DESCENT_FACTOR) * fontSize; + const totalHeight = lineHeight * lines.length; + if (totalHeight > h) { + vscale = h / totalHeight; + } + const fscale = Math.min(hscale, vscale); + const newFontSize = fontSize * fscale; + let firstPoint, clipBox, matrix; + switch (rotation) { + case 0: + matrix = [1, 0, 0, 1]; + clipBox = [rect[0], rect[1], w, h]; + firstPoint = [rect[0], rect[3] - lineAscent]; + break; + case 90: + matrix = [0, 1, -1, 0]; + clipBox = [rect[1], -rect[2], w, h]; + firstPoint = [rect[1], -rect[0] - lineAscent]; + break; + case 180: + matrix = [-1, 0, 0, -1]; + clipBox = [-rect[2], -rect[3], w, h]; + firstPoint = [-rect[2], -rect[1] - lineAscent]; + break; + case 270: + matrix = [0, -1, 1, 0]; + clipBox = [-rect[3], rect[0], w, h]; + firstPoint = [-rect[3], rect[2] - lineAscent]; + break; + } + const buffer = ["q", `${matrix.join(" ")} 0 0 cm`, `${clipBox.join(" ")} re W n`, `BT`, `${getPdfColor(color, true)}`, `0 Tc /Helv ${numberToString(newFontSize)} Tf`]; + buffer.push(`${firstPoint.join(" ")} Td (${escapeString(encodedLines[0])}) Tj`); + const vShift = numberToString(lineHeight); + for (let i = 1, ii = encodedLines.length; i < ii; i++) { + const line = encodedLines[i]; + buffer.push(`0 -${vShift} Td (${escapeString(line)}) Tj`); + } + buffer.push("ET", "Q"); + const appearance = buffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Resources", resources); + appearanceStreamDict.set("Matrix", [1, 0, 0, 1, -rect[0], -rect[1]]); + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } +} +class LineAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.LINE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const lineCoordinates = lookupRect(dict.getArray("L"), [0, 0, 0, 0]); + this.data.lineCoordinates = Util.normalizeRect(lineCoordinates); + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + const borderWidth = this.borderStyle.width || 1, + borderAdjust = 2 * borderWidth; + const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust]; + if (!Util.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer, points) => { + buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, "S"); + return [points[0] - borderWidth, points[7] - borderWidth, points[2] + borderWidth, points[3] + borderWidth]; + } + }); + } + } +} +class SquareAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.SQUARE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + if (this.borderStyle.width === 0 && !fillColor) { + return; + } + this._setDefaultAppearance({ + xref, + extra: `${this.borderStyle.width} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer, points) => { + const x = points[4] + this.borderStyle.width / 2; + const y = points[5] + this.borderStyle.width / 2; + const width = points[6] - points[4] - this.borderStyle.width; + const height = points[3] - points[7] - this.borderStyle.width; + buffer.push(`${x} ${y} ${width} ${height} re`); + if (fillColor) { + buffer.push("B"); + } else { + buffer.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } +} +class CircleAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.CIRCLE; + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + if (this.borderStyle.width === 0 && !fillColor) { + return; + } + const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4)); + this._setDefaultAppearance({ + xref, + extra: `${this.borderStyle.width} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer, points) => { + const x0 = points[0] + this.borderStyle.width / 2; + const y0 = points[1] - this.borderStyle.width / 2; + const x1 = points[6] - this.borderStyle.width / 2; + const y1 = points[7] + this.borderStyle.width / 2; + const xMid = x0 + (x1 - x0) / 2; + const yMid = y0 + (y1 - y0) / 2; + const xOffset = (x1 - x0) / 2 * controlPointsDistance; + const yOffset = (y1 - y0) / 2 * controlPointsDistance; + buffer.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, "h"); + if (fillColor) { + buffer.push("B"); + } else { + buffer.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } +} +class PolylineAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.POLYLINE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + this.data.vertices = null; + const rawVertices = dict.getArray("Vertices"); + if (!isNumberArray(rawVertices, null)) { + return; + } + const vertices = this.data.vertices = Float32Array.from(rawVertices); + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + let fillColor = getRgbColor(dict.getArray("IC"), null); + if (fillColor) { + fillColor = getPdfColorArray(fillColor); + } + let operator; + if (fillColor) { + if (this.color) { + operator = fillColor.every((c, i) => c === strokeColor[i]) ? "f" : "B"; + } else { + operator = "f"; + } + } else { + operator = "S"; + } + const borderWidth = this.borderStyle.width || 1, + borderAdjust = 2 * borderWidth; + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + Util.rectBoundingBox(vertices[i] - borderAdjust, vertices[i + 1] - borderAdjust, vertices[i] + borderAdjust, vertices[i + 1] + borderAdjust, bbox); + } + if (!Util.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + strokeAlpha, + fillColor, + fillAlpha: fillColor ? strokeAlpha : null, + pointsCallback: (buffer, points) => { + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + buffer.push(`${vertices[i]} ${vertices[i + 1]} ${i === 0 ? "m" : "l"}`); + } + buffer.push(operator); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } +} +class PolygonAnnotation extends PolylineAnnotation { + constructor(params) { + super(params); + this.data.annotationType = AnnotationType.POLYGON; + } +} +class CaretAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.annotationType = AnnotationType.CARET; + } +} +class InkAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.INK; + this.data.inkLists = []; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + this.data.opacity = dict.get("CA") || 1; + const rawInkLists = dict.getArray("InkList"); + if (!Array.isArray(rawInkLists)) { + return; + } + for (let i = 0, ii = rawInkLists.length; i < ii; ++i) { + if (!Array.isArray(rawInkLists[i])) { + continue; + } + const inkList = new Float32Array(rawInkLists[i].length); + this.data.inkLists.push(inkList); + for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) { + const x = xref.fetchIfRef(rawInkLists[i][j]), + y = xref.fetchIfRef(rawInkLists[i][j + 1]); + if (typeof x === "number" && typeof y === "number") { + inkList[j] = x; + inkList[j + 1] = y; + } + } + } + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const borderWidth = this.borderStyle.width || 1, + borderAdjust = 2 * borderWidth; + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + for (const inkList of this.data.inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + Util.rectBoundingBox(inkList[i] - borderAdjust, inkList[i + 1] - borderAdjust, inkList[i] + borderAdjust, inkList[i + 1] + borderAdjust, bbox); + } + } + if (!Util.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + strokeAlpha, + pointsCallback: (buffer, points) => { + for (const inkList of this.data.inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + buffer.push(`${inkList[i]} ${inkList[i + 1]} ${i === 0 ? "m" : "l"}`); + } + buffer.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + oldAnnotation, + color, + date, + opacity, + paths, + outlines, + rect, + rotation, + thickness, + user + } = annotation; + const ink = oldAnnotation || new Dict(xref); + ink.setIfNotExists("Type", Name.get("Annot")); + ink.setIfNotExists("Subtype", Name.get("Ink")); + ink.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date)}`); + ink.setIfArray("Rect", rect); + ink.setIfArray("InkList", outlines?.points || paths?.points); + ink.setIfNotExists("F", 4); + ink.setIfNumber("Rotate", rotation); + ink.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (outlines) { + ink.setIfName("IT", "InkHighlight"); + } + if (thickness > 0) { + const bs = new Dict(xref); + ink.set("BS", bs); + bs.set("W", thickness); + } + ink.setIfArray("C", getPdfColorArray(color)); + ink.setIfNumber("CA", opacity); + if (ap || apRef) { + const n = new Dict(xref); + ink.set("AP", n); + n.set("N", apRef || ap); + } + return ink; + } + static async createNewAppearanceStream(annotation, xref, params) { + if (annotation.outlines) { + return this.createNewAppearanceStreamForHighlight(annotation, xref, params); + } + const { + color, + rect, + paths, + thickness, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, false)}`]; + if (opacity !== 1) { + appearanceBuffer.push("/R0 gs"); + } + for (const outline of paths.lines) { + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + if (isNaN(outline[i])) { + appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + if (outline.length === 6) { + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} l`); + } + } + appearanceBuffer.push("S"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + if (opacity !== 1) { + const resources = new Dict(xref); + const extGState = new Dict(xref); + const r0 = new Dict(xref); + r0.set("CA", opacity); + r0.setIfName("Type", "ExtGState"); + extGState.set("R0", r0); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + static async createNewAppearanceStreamForHighlight(annotation, xref, params) { + const { + color, + rect, + outlines: { + outline + }, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + if (isNaN(outline[i])) { + appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + appearanceBuffer.push("h f"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(xref); + const extGState = new Dict(xref); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + const r0 = new Dict(xref); + extGState.set("R0", r0); + r0.setIfName("BM", "Multiply"); + if (opacity !== 1) { + r0.set("ca", opacity); + r0.setIfName("Type", "ExtGState"); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } +} +class HighlightAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.HIGHLIGHT; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + this.data.opacity = dict.get("CA") || 1; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + const resources = this.appearance?.dict.get("Resources"); + if (!this.appearance || !resources?.has("ExtGState")) { + if (this.appearance) { + warn("HighlightAnnotation - ignoring built-in appearance stream."); + } + const fillColor = getPdfColorArray(this.color, [1, 1, 0]); + const fillAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + fillColor, + blendMode: "Multiply", + fillAlpha, + pointsCallback: (buffer, points) => { + buffer.push(`${points[0]} ${points[1]} m`, `${points[2]} ${points[3]} l`, `${points[6]} ${points[7]} l`, `${points[4]} ${points[5]} l`, "f"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + color, + date, + oldAnnotation, + opacity, + rect, + rotation, + user, + quadPoints + } = annotation; + const highlight = oldAnnotation || new Dict(xref); + highlight.setIfNotExists("Type", Name.get("Annot")); + highlight.setIfNotExists("Subtype", Name.get("Highlight")); + highlight.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date)}`); + highlight.setIfArray("Rect", rect); + highlight.setIfNotExists("F", 4); + highlight.setIfNotExists("Border", [0, 0, 0]); + highlight.setIfNumber("Rotate", rotation); + highlight.setIfArray("QuadPoints", quadPoints); + highlight.setIfArray("C", getPdfColorArray(color)); + highlight.setIfNumber("CA", opacity); + highlight.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + highlight.set("AP", n); + n.set("N", apRef || ap); + } + return highlight; + } + static async createNewAppearanceStream(annotation, xref, params) { + const { + color, + rect, + outlines, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; + const buffer = []; + for (const outline of outlines) { + buffer.length = 0; + buffer.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`); + for (let i = 2, ii = outline.length; i < ii; i += 2) { + buffer.push(`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`); + } + buffer.push("h"); + appearanceBuffer.push(buffer.join("\n")); + } + appearanceBuffer.push("f*"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(xref); + const extGState = new Dict(xref); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + const r0 = new Dict(xref); + extGState.set("R0", r0); + r0.setIfName("BM", "Multiply"); + if (opacity !== 1) { + r0.set("ca", opacity); + r0.setIfName("Type", "ExtGState"); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } +} +class UnderlineAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.UNDERLINE; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 0.571 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer, points) => { + buffer.push(`${points[4]} ${points[5] + 1.3} m`, `${points[6]} ${points[7] + 1.3} l`, "S"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } +} +class SquigglyAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.SQUIGGLY; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 1 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer, points) => { + const dy = (points[1] - points[5]) / 6; + let shift = dy; + let x = points[4]; + const y = points[5]; + const xEnd = points[6]; + buffer.push(`${x} ${y + shift} m`); + do { + x += 2; + shift = shift === 0 ? dy : 0; + buffer.push(`${x} ${y + shift} l`); + } while (x < xEnd); + buffer.push("S"); + return [points[4], y - 2 * dy, xEnd, y + 2 * dy]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } +} +class StrikeOutAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType.STRIKEOUT; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 1 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer, points) => { + buffer.push(`${(points[0] + points[4]) / 2} ` + `${(points[1] + points[5]) / 2} m`, `${(points[2] + points[6]) / 2} ` + `${(points[3] + points[7]) / 2} l`, "S"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } +} +class StampAnnotation extends MarkupAnnotation { + #savedHasOwnCanvas = null; + constructor(params) { + super(params); + this.data.annotationType = AnnotationType.STAMP; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + } + mustBeViewedWhenEditing(isEditing, modifiedIds = null) { + if (isEditing) { + if (!this.data.isEditable) { + return true; + } + this.#savedHasOwnCanvas ??= this.data.hasOwnCanvas; + this.data.hasOwnCanvas = true; + return true; + } + if (this.#savedHasOwnCanvas !== null) { + this.data.hasOwnCanvas = this.#savedHasOwnCanvas; + this.#savedHasOwnCanvas = null; + } + return !modifiedIds?.has(this.data.id); + } + static async createImage(bitmap, xref) { + const { + width, + height + } = bitmap; + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d", { + alpha: true + }); + ctx.drawImage(bitmap, 0, 0); + const data = ctx.getImageData(0, 0, width, height).data; + const buf32 = new Uint32Array(data.buffer); + const hasAlpha = buf32.some(FeatureTest.isLittleEndian ? x => x >>> 24 !== 0xff : x => (x & 0xff) !== 0xff); + if (hasAlpha) { + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, width, height); + ctx.drawImage(bitmap, 0, 0); + } + const jpegBufferPromise = canvas.convertToBlob({ + type: "image/jpeg", + quality: 1 + }).then(blob => blob.arrayBuffer()); + const xobjectName = Name.get("XObject"); + const imageName = Name.get("Image"); + const image = new Dict(xref); + image.set("Type", xobjectName); + image.set("Subtype", imageName); + image.set("BitsPerComponent", 8); + image.setIfName("ColorSpace", "DeviceRGB"); + image.setIfName("Filter", "DCTDecode"); + image.set("BBox", [0, 0, width, height]); + image.set("Width", width); + image.set("Height", height); + let smaskStream = null; + if (hasAlpha) { + const alphaBuffer = new Uint8Array(buf32.length); + if (FeatureTest.isLittleEndian) { + for (let i = 0, ii = buf32.length; i < ii; i++) { + alphaBuffer[i] = buf32[i] >>> 24; + } + } else { + for (let i = 0, ii = buf32.length; i < ii; i++) { + alphaBuffer[i] = buf32[i] & 0xff; + } + } + const smask = new Dict(xref); + smask.set("Type", xobjectName); + smask.set("Subtype", imageName); + smask.set("BitsPerComponent", 8); + smask.setIfName("ColorSpace", "DeviceGray"); + smask.set("Width", width); + smask.set("Height", height); + smaskStream = new Stream(alphaBuffer, 0, 0, smask); + } + const imageStream = new Stream(await jpegBufferPromise, 0, 0, image); + return { + imageStream, + smaskStream, + width, + height + }; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + date, + oldAnnotation, + rect, + rotation, + user + } = annotation; + const stamp = oldAnnotation || new Dict(xref); + stamp.setIfNotExists("Type", Name.get("Annot")); + stamp.setIfNotExists("Subtype", Name.get("Stamp")); + stamp.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date)}`); + stamp.setIfArray("Rect", rect); + stamp.setIfNotExists("F", 4); + stamp.setIfNotExists("Border", [0, 0, 0]); + stamp.setIfNumber("Rotate", rotation); + stamp.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + stamp.set("AP", n); + n.set("N", apRef || ap); + } + return stamp; + } + static async #createNewAppearanceStreamForDrawing(annotation, xref) { + const { + areContours, + color, + rect, + lines, + thickness + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, areContours)}`]; + for (const line of lines) { + appearanceBuffer.push(`${numberToString(line[4])} ${numberToString(line[5])} m`); + for (let i = 6, ii = line.length; i < ii; i += 6) { + if (isNaN(line[i])) { + appearanceBuffer.push(`${numberToString(line[i + 4])} ${numberToString(line[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = line.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + if (line.length === 6) { + appearanceBuffer.push(`${numberToString(line[4])} ${numberToString(line[5])} l`); + } + } + appearanceBuffer.push(areContours ? "F" : "S"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + static async createNewAppearanceStream(annotation, xref, params) { + if (annotation.oldAnnotation) { + return null; + } + if (annotation.isSignature) { + return this.#createNewAppearanceStreamForDrawing(annotation, xref); + } + const { + rotation + } = annotation; + const { + imageRef, + width, + height + } = params.image; + const resources = new Dict(xref); + const xobject = new Dict(xref); + resources.set("XObject", xobject); + xobject.set("Im0", imageRef); + const appearance = `q ${width} 0 0 ${height} 0 0 cm /Im0 Do Q`; + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", [0, 0, width, height]); + appearanceStreamDict.set("Resources", resources); + if (rotation) { + const matrix = getRotationMatrix(rotation, width, height); + appearanceStreamDict.set("Matrix", matrix); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } +} +class FileAttachmentAnnotation extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + const file = new FileSpec(dict.get("FS"), xref); + this.data.annotationType = AnnotationType.FILEATTACHMENT; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + this.data.file = file.serializable; + const name = dict.get("Name"); + this.data.name = name instanceof Name ? stringToPDFString(name.name) : "PushPin"; + const fillAlpha = dict.get("ca"); + this.data.fillAlpha = typeof fillAlpha === "number" && fillAlpha >= 0 && fillAlpha <= 1 ? fillAlpha : null; + } +} + +;// ./src/core/calculate_md5.js + +const PARAMS = { + get r() { + return shadow(this, "r", new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21])); + }, + get k() { + return shadow(this, "k", new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551])); + } +}; +function calculateMD5(data, offset, length) { + let h0 = 1732584193, + h1 = -271733879, + h2 = -1732584194, + h3 = 271733878; + const paddedLength = length + 72 & ~63; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + const n = paddedLength - 8; + if (i < n) { + i = n; + } + padded[i++] = length << 3 & 0xff; + padded[i++] = length >> 5 & 0xff; + padded[i++] = length >> 13 & 0xff; + padded[i++] = length >> 21 & 0xff; + padded[i++] = length >>> 29 & 0xff; + i += 3; + const w = new Int32Array(16); + const { + k, + r + } = PARAMS; + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j, i += 4) { + w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24; + } + let a = h0, + b = h1, + c = h2, + d = h3, + f, + g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = b & c | ~b & d; + g = j; + } else if (j < 32) { + f = d & b | ~d & c; + g = 5 * j + 1 & 15; + } else if (j < 48) { + f = b ^ c ^ d; + g = 3 * j + 5 & 15; + } else { + f = c ^ (b | ~d); + g = 7 * j & 15; + } + const tmp = d, + rotateArg = a + f + k[j] + w[g] | 0, + rotate = r[j]; + d = c; + c = b; + b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0; + a = tmp; + } + h0 = h0 + a | 0; + h1 = h1 + b | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + } + return new Uint8Array([h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24 & 0xFF, h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24 & 0xFF, h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24 & 0xFF, h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24 & 0xFF]); +} + +;// ./src/core/dataset_reader.js + + + +function decodeString(str) { + try { + return stringToUTF8String(str); + } catch (ex) { + warn(`UTF-8 decoding failed: "${ex}".`); + return str; + } +} +class DatasetXMLParser extends SimpleXMLParser { + constructor(options) { + super(options); + this.node = null; + } + onEndElement(name) { + const node = super.onEndElement(name); + if (node && name === "xfa:datasets") { + this.node = node; + throw new Error("Aborting DatasetXMLParser."); + } + } +} +class DatasetReader { + constructor(data) { + if (data.datasets) { + this.node = new SimpleXMLParser({ + hasAttributes: true + }).parseFromString(data.datasets).documentElement; + } else { + const parser = new DatasetXMLParser({ + hasAttributes: true + }); + try { + parser.parseFromString(data["xdp:xdp"]); + } catch {} + this.node = parser.node; + } + } + getValue(path) { + if (!this.node || !path) { + return ""; + } + const node = this.node.searchNode(parseXFAPath(path), 0); + if (!node) { + return ""; + } + const first = node.firstChild; + if (first?.nodeName === "value") { + return node.children.map(child => decodeString(child.textContent)); + } + return decodeString(node.textContent); + } +} + +;// ./src/core/intersector.js +class SingleIntersector { + #annotation; + minX = Infinity; + minY = Infinity; + maxX = -Infinity; + maxY = -Infinity; + #quadPoints = null; + #text = []; + #extraChars = []; + #lastIntersectingQuadIndex = -1; + #canTakeExtraChars = false; + constructor(annotation) { + this.#annotation = annotation; + const quadPoints = annotation.data.quadPoints; + if (!quadPoints) { + [this.minX, this.minY, this.maxX, this.maxY] = annotation.data.rect; + return; + } + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + this.minX = Math.min(this.minX, quadPoints[i]); + this.maxX = Math.max(this.maxX, quadPoints[i + 2]); + this.minY = Math.min(this.minY, quadPoints[i + 5]); + this.maxY = Math.max(this.maxY, quadPoints[i + 1]); + } + if (quadPoints.length > 8) { + this.#quadPoints = quadPoints; + } + } + #intersects(x, y) { + if (this.minX >= x || this.maxX <= x || this.minY >= y || this.maxY <= y) { + return false; + } + const quadPoints = this.#quadPoints; + if (!quadPoints) { + return true; + } + if (this.#lastIntersectingQuadIndex >= 0) { + const i = this.#lastIntersectingQuadIndex; + if (!(quadPoints[i] >= x || quadPoints[i + 2] <= x || quadPoints[i + 5] >= y || quadPoints[i + 1] <= y)) { + return true; + } + this.#lastIntersectingQuadIndex = -1; + } + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + if (!(quadPoints[i] >= x || quadPoints[i + 2] <= x || quadPoints[i + 5] >= y || quadPoints[i + 1] <= y)) { + this.#lastIntersectingQuadIndex = i; + return true; + } + } + return false; + } + addGlyph(x, y, glyph) { + if (!this.#intersects(x, y)) { + this.disableExtraChars(); + return false; + } + if (this.#extraChars.length > 0) { + this.#text.push(this.#extraChars.join("")); + this.#extraChars.length = 0; + } + this.#text.push(glyph); + this.#canTakeExtraChars = true; + return true; + } + addExtraChar(char) { + if (this.#canTakeExtraChars) { + this.#extraChars.push(char); + } + } + disableExtraChars() { + if (!this.#canTakeExtraChars) { + return; + } + this.#canTakeExtraChars = false; + this.#extraChars.length = 0; + } + setText() { + this.#annotation.data.overlaidText = this.#text.join(""); + } +} +const STEPS = 64; +class Intersector { + #intersectors = []; + #grid = []; + #minX; + #maxX; + #minY; + #maxY; + #invXRatio; + #invYRatio; + constructor(annotations) { + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + const intersectors = this.#intersectors; + for (const annotation of annotations) { + if (!annotation.data.quadPoints && !annotation.data.rect) { + continue; + } + const intersector = new SingleIntersector(annotation); + intersectors.push(intersector); + minX = Math.min(minX, intersector.minX); + minY = Math.min(minY, intersector.minY); + maxX = Math.max(maxX, intersector.maxX); + maxY = Math.max(maxY, intersector.maxY); + } + this.#minX = minX; + this.#minY = minY; + this.#maxX = maxX; + this.#maxY = maxY; + this.#invXRatio = (STEPS - 1) / (maxX - minX); + this.#invYRatio = (STEPS - 1) / (maxY - minY); + for (const intersector of intersectors) { + const iMin = this.#getGridIndex(intersector.minX, intersector.minY); + const iMax = this.#getGridIndex(intersector.maxX, intersector.maxY); + const w = (iMax - iMin) % STEPS; + const h = Math.floor((iMax - iMin) / STEPS); + for (let i = iMin; i <= iMin + h * STEPS; i += STEPS) { + for (let j = 0; j <= w; j++) { + let existing = this.#grid[i + j]; + if (!existing) { + this.#grid[i + j] = existing = []; + } + existing.push(intersector); + } + } + } + } + #getGridIndex(x, y) { + const i = Math.floor((x - this.#minX) * this.#invXRatio); + const j = Math.floor((y - this.#minY) * this.#invYRatio); + return i + j * STEPS; + } + addGlyph(transform, width, height, glyph) { + const x = transform[4] + width / 2; + const y = transform[5] + height / 2; + if (x < this.#minX || y < this.#minY || x > this.#maxX || y > this.#maxY) { + return; + } + const intersectors = this.#grid[this.#getGridIndex(x, y)]; + if (!intersectors) { + return; + } + for (const intersector of intersectors) { + intersector.addGlyph(x, y, glyph); + } + } + addExtraChar(char) { + for (const intersector of this.#intersectors) { + intersector.addExtraChar(char); + } + } + setText() { + for (const intersector of this.#intersectors) { + intersector.setText(); + } + } +} + +;// ./src/core/calculate_sha_other.js + +class Word64 { + constructor(highInteger, lowInteger) { + this.high = highInteger | 0; + this.low = lowInteger | 0; + } + and(word) { + this.high &= word.high; + this.low &= word.low; + } + xor(word) { + this.high ^= word.high; + this.low ^= word.low; + } + shiftRight(places) { + if (places >= 32) { + this.low = this.high >>> places - 32 | 0; + this.high = 0; + } else { + this.low = this.low >>> places | this.high << 32 - places; + this.high = this.high >>> places | 0; + } + } + rotateRight(places) { + let low, high; + if (places & 32) { + high = this.low; + low = this.high; + } else { + low = this.low; + high = this.high; + } + places &= 31; + this.low = low >>> places | high << 32 - places; + this.high = high >>> places | low << 32 - places; + } + not() { + this.high = ~this.high; + this.low = ~this.low; + } + add(word) { + const lowAdd = (this.low >>> 0) + (word.low >>> 0); + let highAdd = (this.high >>> 0) + (word.high >>> 0); + if (lowAdd > 0xffffffff) { + highAdd += 1; + } + this.low = lowAdd | 0; + this.high = highAdd | 0; + } + copyTo(bytes, offset) { + bytes[offset] = this.high >>> 24 & 0xff; + bytes[offset + 1] = this.high >> 16 & 0xff; + bytes[offset + 2] = this.high >> 8 & 0xff; + bytes[offset + 3] = this.high & 0xff; + bytes[offset + 4] = this.low >>> 24 & 0xff; + bytes[offset + 5] = this.low >> 16 & 0xff; + bytes[offset + 6] = this.low >> 8 & 0xff; + bytes[offset + 7] = this.low & 0xff; + } + assign(word) { + this.high = word.high; + this.low = word.low; + } +} +const calculate_sha_other_PARAMS = { + get k() { + return shadow(this, "k", [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)]); + } +}; +function ch(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.not(); + tmp.and(z); + result.xor(tmp); +} +function maj(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.and(z); + result.xor(tmp); + tmp.assign(y); + tmp.and(z); + result.xor(tmp); +} +function sigma(result, x, tmp) { + result.assign(x); + result.rotateRight(28); + tmp.assign(x); + tmp.rotateRight(34); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(39); + result.xor(tmp); +} +function sigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(14); + tmp.assign(x); + tmp.rotateRight(18); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(41); + result.xor(tmp); +} +function littleSigma(result, x, tmp) { + result.assign(x); + result.rotateRight(1); + tmp.assign(x); + tmp.rotateRight(8); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(7); + result.xor(tmp); +} +function littleSigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(19); + tmp.assign(x); + tmp.rotateRight(61); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(6); + result.xor(tmp); +} +function calculateSHA512(data, offset, length, mode384 = false) { + let h0, h1, h2, h3, h4, h5, h6, h7; + if (!mode384) { + h0 = new Word64(0x6a09e667, 0xf3bcc908); + h1 = new Word64(0xbb67ae85, 0x84caa73b); + h2 = new Word64(0x3c6ef372, 0xfe94f82b); + h3 = new Word64(0xa54ff53a, 0x5f1d36f1); + h4 = new Word64(0x510e527f, 0xade682d1); + h5 = new Word64(0x9b05688c, 0x2b3e6c1f); + h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); + h7 = new Word64(0x5be0cd19, 0x137e2179); + } else { + h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); + h1 = new Word64(0x629a292a, 0x367cd507); + h2 = new Word64(0x9159015a, 0x3070dd17); + h3 = new Word64(0x152fecd8, 0xf70e5939); + h4 = new Word64(0x67332667, 0xffc00b31); + h5 = new Word64(0x8eb44a87, 0x68581511); + h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); + h7 = new Word64(0x47b5481d, 0xbefa4fa4); + } + const paddedLength = Math.ceil((length + 17) / 128) * 128; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + const n = paddedLength - 16; + if (i < n) { + i = n; + } + i += 11; + padded[i++] = length >>> 29 & 0xff; + padded[i++] = length >> 21 & 0xff; + padded[i++] = length >> 13 & 0xff; + padded[i++] = length >> 5 & 0xff; + padded[i++] = length << 3 & 0xff; + const w = new Array(80); + for (i = 0; i < 80; i++) { + w[i] = new Word64(0, 0); + } + const { + k + } = calculate_sha_other_PARAMS; + let a = new Word64(0, 0), + b = new Word64(0, 0), + c = new Word64(0, 0); + let d = new Word64(0, 0), + e = new Word64(0, 0), + f = new Word64(0, 0); + let g = new Word64(0, 0), + h = new Word64(0, 0); + const t1 = new Word64(0, 0), + t2 = new Word64(0, 0); + const tmp1 = new Word64(0, 0), + tmp2 = new Word64(0, 0); + let tmp3; + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7]; + i += 8; + } + for (j = 16; j < 80; ++j) { + tmp3 = w[j]; + littleSigmaPrime(tmp3, w[j - 2], tmp2); + tmp3.add(w[j - 7]); + littleSigma(tmp1, w[j - 15], tmp2); + tmp3.add(tmp1); + tmp3.add(w[j - 16]); + } + a.assign(h0); + b.assign(h1); + c.assign(h2); + d.assign(h3); + e.assign(h4); + f.assign(h5); + g.assign(h6); + h.assign(h7); + for (j = 0; j < 80; ++j) { + t1.assign(h); + sigmaPrime(tmp1, e, tmp2); + t1.add(tmp1); + ch(tmp1, e, f, g, tmp2); + t1.add(tmp1); + t1.add(k[j]); + t1.add(w[j]); + sigma(t2, a, tmp2); + maj(tmp1, a, b, c, tmp2); + t2.add(tmp1); + tmp3 = h; + h = g; + g = f; + f = e; + d.add(t1); + e = d; + d = c; + c = b; + b = a; + tmp3.assign(t1); + tmp3.add(t2); + a = tmp3; + } + h0.add(a); + h1.add(b); + h2.add(c); + h3.add(d); + h4.add(e); + h5.add(f); + h6.add(g); + h7.add(h); + } + let result; + if (!mode384) { + result = new Uint8Array(64); + h0.copyTo(result, 0); + h1.copyTo(result, 8); + h2.copyTo(result, 16); + h3.copyTo(result, 24); + h4.copyTo(result, 32); + h5.copyTo(result, 40); + h6.copyTo(result, 48); + h7.copyTo(result, 56); + } else { + result = new Uint8Array(48); + h0.copyTo(result, 0); + h1.copyTo(result, 8); + h2.copyTo(result, 16); + h3.copyTo(result, 24); + h4.copyTo(result, 32); + h5.copyTo(result, 40); + } + return result; +} +function calculateSHA384(data, offset, length) { + return calculateSHA512(data, offset, length, true); +} + +;// ./src/core/calculate_sha256.js + +const calculate_sha256_PARAMS = { + get k() { + return shadow(this, "k", [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]); + } +}; +function rotr(x, n) { + return x >>> n | x << 32 - n; +} +function calculate_sha256_ch(x, y, z) { + return x & y ^ ~x & z; +} +function calculate_sha256_maj(x, y, z) { + return x & y ^ x & z ^ y & z; +} +function calculate_sha256_sigma(x) { + return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); +} +function calculate_sha256_sigmaPrime(x) { + return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); +} +function calculate_sha256_littleSigma(x) { + return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; +} +function calculate_sha256_littleSigmaPrime(x) { + return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; +} +function calculateSHA256(data, offset, length) { + let h0 = 0x6a09e667, + h1 = 0xbb67ae85, + h2 = 0x3c6ef372, + h3 = 0xa54ff53a, + h4 = 0x510e527f, + h5 = 0x9b05688c, + h6 = 0x1f83d9ab, + h7 = 0x5be0cd19; + const paddedLength = Math.ceil((length + 9) / 64) * 64; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + const n = paddedLength - 8; + if (i < n) { + i = n; + } + i += 3; + padded[i++] = length >>> 29 & 0xff; + padded[i++] = length >> 21 & 0xff; + padded[i++] = length >> 13 & 0xff; + padded[i++] = length >> 5 & 0xff; + padded[i++] = length << 3 & 0xff; + const w = new Uint32Array(64); + const { + k + } = calculate_sha256_PARAMS; + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + i += 4; + } + for (j = 16; j < 64; ++j) { + w[j] = calculate_sha256_littleSigmaPrime(w[j - 2]) + w[j - 7] + calculate_sha256_littleSigma(w[j - 15]) + w[j - 16] | 0; + } + let a = h0, + b = h1, + c = h2, + d = h3, + e = h4, + f = h5, + g = h6, + h = h7, + t1, + t2; + for (j = 0; j < 64; ++j) { + t1 = h + calculate_sha256_sigmaPrime(e) + calculate_sha256_ch(e, f, g) + k[j] + w[j]; + t2 = calculate_sha256_sigma(a) + calculate_sha256_maj(a, b, c); + h = g; + g = f; + f = e; + e = d + t1 | 0; + d = c; + c = b; + b = a; + a = t1 + t2 | 0; + } + h0 = h0 + a | 0; + h1 = h1 + b | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + h4 = h4 + e | 0; + h5 = h5 + f | 0; + h6 = h6 + g | 0; + h7 = h7 + h | 0; + } + return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]); +} + +;// ./src/core/decrypt_stream.js + +const chunkSize = 512; +class DecryptStream extends DecodeStream { + constructor(str, maybeLength, decrypt) { + super(maybeLength); + this.stream = str; + this.dict = str.dict; + this.decrypt = decrypt; + this.nextChunk = null; + this.initialized = false; + } + readBlock() { + let chunk; + if (this.initialized) { + chunk = this.nextChunk; + } else { + chunk = this.stream.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk?.length) { + this.eof = true; + return; + } + this.nextChunk = this.stream.getBytes(chunkSize); + const hasMoreData = this.nextChunk?.length > 0; + const decrypt = this.decrypt; + chunk = decrypt(chunk, !hasMoreData); + const bufferLength = this.bufferLength, + newLength = bufferLength + chunk.length, + buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + } + getOriginalStream() { + return this; + } +} + +;// ./src/core/crypto.js + + + + + + +class ARCFourCipher { + constructor(key) { + this.a = 0; + this.b = 0; + const s = new Uint8Array(256); + const keyLength = key.length; + for (let i = 0; i < 256; ++i) { + s[i] = i; + } + for (let i = 0, j = 0; i < 256; ++i) { + const tmp = s[i]; + j = j + tmp + key[i % keyLength] & 0xff; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + encryptBlock(data) { + let a = this.a, + b = this.b; + const s = this.s; + const n = data.length; + const output = new Uint8Array(n); + for (let i = 0; i < n; ++i) { + a = a + 1 & 0xff; + const tmp = s[a]; + b = b + tmp & 0xff; + const tmp2 = s[b]; + s[a] = tmp2; + s[b] = tmp; + output[i] = data[i] ^ s[tmp + tmp2 & 0xff]; + } + this.a = a; + this.b = b; + return output; + } + decryptBlock(data) { + return this.encryptBlock(data); + } + encrypt(data) { + return this.encryptBlock(data); + } +} +class NullCipher { + decryptBlock(data) { + return data; + } + encrypt(data) { + return data; + } +} +class AESBaseCipher { + _s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]); + _inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]); + _mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + _mixCol = new Uint8Array(256).map((_, i) => i < 128 ? i << 1 : i << 1 ^ 0x1b); + constructor() { + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + _expandKey(cipherKey) { + unreachable("Cannot call `_expandKey` on the base class"); + } + _decrypt(input, key) { + let t, u, v; + const state = new Uint8Array(16); + state.set(input); + for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) { + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (let j = 0; j < 16; ++j) { + state[j] = this._inv_s[state[j]]; + } + for (let j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (let j = 0; j < 16; j += 4) { + const s0 = this._mix[state[j]]; + const s1 = this._mix[state[j + 1]]; + const s2 = this._mix[state[j + 2]]; + const s3 = this._mix[state[j + 3]]; + t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8; + state[j] = t >>> 24 & 0xff; + state[j + 1] = t >> 16 & 0xff; + state[j + 2] = t >> 8 & 0xff; + state[j + 3] = t & 0xff; + } + } + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (let j = 0; j < 16; ++j) { + state[j] = this._inv_s[state[j]]; + state[j] ^= key[j]; + } + return state; + } + _encrypt(input, key) { + const s = this._s; + let t, u, v; + const state = new Uint8Array(16); + state.set(input); + for (let j = 0; j < 16; ++j) { + state[j] ^= key[j]; + } + for (let i = 1; i < this._cyclesOfRepetition; i++) { + for (let j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (let j = 0; j < 16; j += 4) { + const s0 = state[j]; + const s1 = state[j + 1]; + const s2 = state[j + 2]; + const s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j] ^= t ^ this._mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ this._mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ this._mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ this._mixCol[s3 ^ s0]; + } + for (let j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + for (let j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + _decryptBlock2(data, finalize) { + const sourceLength = data.length; + let buffer = this.buffer, + bufferLength = this.bufferPosition; + const result = []; + let iv = this.iv; + for (let i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + const plain = this._decrypt(buffer, this._key); + for (let j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array(0); + } + let outputLength = 16 * result.length; + if (finalize) { + const lastBlock = result.at(-1); + let psLen = lastBlock[15]; + if (psLen <= 16) { + for (let i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + const output = new Uint8Array(outputLength); + for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + decryptBlock(data, finalize, iv = null) { + const sourceLength = data.length; + const buffer = this.buffer; + let bufferLength = this.bufferPosition; + if (iv) { + this.iv = iv; + } else { + for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + this.bufferLength = bufferLength; + return new Uint8Array(0); + } + this.iv = buffer; + data = data.subarray(16); + } + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + this.decryptBlock = this._decryptBlock2; + return this.decryptBlock(data, finalize); + } + encrypt(data, iv) { + const sourceLength = data.length; + let buffer = this.buffer, + bufferLength = this.bufferPosition; + const result = []; + iv ||= new Uint8Array(16); + for (let i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (let j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + const cipher = this._encrypt(buffer, this._key); + iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array(0); + } + const outputLength = 16 * result.length; + const output = new Uint8Array(outputLength); + for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } +} +class AES128Cipher extends AESBaseCipher { + _rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]); + constructor(key) { + super(); + this._cyclesOfRepetition = 10; + this._keySize = 160; + this._key = this._expandKey(key); + } + _expandKey(cipherKey) { + const b = 176; + const s = this._s; + const rcon = this._rcon; + const result = new Uint8Array(b); + result.set(cipherKey); + for (let j = 16, i = 1; j < b; ++i) { + let t1 = result[j - 3]; + let t2 = result[j - 2]; + let t3 = result[j - 1]; + let t4 = result[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 ^= rcon[i]; + for (let n = 0; n < 4; ++n) { + result[j] = t1 ^= result[j - 16]; + j++; + result[j] = t2 ^= result[j - 16]; + j++; + result[j] = t3 ^= result[j - 16]; + j++; + result[j] = t4 ^= result[j - 16]; + j++; + } + } + return result; + } +} +class AES256Cipher extends AESBaseCipher { + constructor(key) { + super(); + this._cyclesOfRepetition = 14; + this._keySize = 224; + this._key = this._expandKey(key); + } + _expandKey(cipherKey) { + const b = 240; + const s = this._s; + const result = new Uint8Array(b); + result.set(cipherKey); + let r = 1; + let t1, t2, t3, t4; + for (let j = 32, i = 1; j < b; ++i) { + if (j % 32 === 16) { + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + } else if (j % 32 === 0) { + t1 = result[j - 3]; + t2 = result[j - 2]; + t3 = result[j - 1]; + t4 = result[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 ^= r; + if ((r <<= 1) >= 256) { + r = (r ^ 0x1b) & 0xff; + } + } + for (let n = 0; n < 4; ++n) { + result[j] = t1 ^= result[j - 32]; + j++; + result[j] = t2 ^= result[j - 32]; + j++; + result[j] = t3 ^= result[j - 32]; + j++; + result[j] = t4 ^= result[j - 32]; + j++; + } + } + return result; + } +} +class PDFBase { + _hash(password, input, userBytes) { + unreachable("Abstract method `_hash` called"); + } + checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { + const hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + const result = this._hash(password, hashData, userBytes); + return isArrayEqual(result, ownerPassword); + } + checkUserPassword(password, userValidationSalt, userPassword) { + const hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + const result = this._hash(password, hashData, []); + return isArrayEqual(result, userPassword); + } + getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { + const hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + const key = this._hash(password, hashData, userBytes); + const cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); + } + getUserKey(password, userKeySalt, userEncryption) { + const hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + const key = this._hash(password, hashData, []); + const cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); + } +} +class PDF17 extends PDFBase { + _hash(password, input, userBytes) { + return calculateSHA256(input, 0, input.length); + } +} +class PDF20 extends PDFBase { + _hash(password, input, userBytes) { + let k = calculateSHA256(input, 0, input.length).subarray(0, 32); + let e = [0]; + let i = 0; + while (i < 64 || e.at(-1) > i - 32) { + const combinedLength = password.length + k.length + userBytes.length, + combinedArray = new Uint8Array(combinedLength); + let writeOffset = 0; + combinedArray.set(password, writeOffset); + writeOffset += password.length; + combinedArray.set(k, writeOffset); + writeOffset += k.length; + combinedArray.set(userBytes, writeOffset); + const k1 = new Uint8Array(combinedLength * 64); + for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) { + k1.set(combinedArray, pos); + } + const cipher = new AES128Cipher(k.subarray(0, 16)); + e = cipher.encrypt(k1, k.subarray(16, 32)); + const remainder = Math.sumPrecise(e.slice(0, 16)) % 3; + if (remainder === 0) { + k = calculateSHA256(e, 0, e.length); + } else if (remainder === 1) { + k = calculateSHA384(e, 0, e.length); + } else if (remainder === 2) { + k = calculateSHA512(e, 0, e.length); + } + i++; + } + return k.subarray(0, 32); + } +} +class CipherTransform { + constructor(stringCipherConstructor, streamCipherConstructor) { + this.StringCipherConstructor = stringCipherConstructor; + this.StreamCipherConstructor = streamCipherConstructor; + } + createStream(stream, length) { + const cipher = new this.StreamCipherConstructor(); + return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) { + return cipher.decryptBlock(data, finalize); + }); + } + decryptString(s) { + const cipher = new this.StringCipherConstructor(); + let data = stringToBytes(s); + data = cipher.decryptBlock(data, true); + return bytesToString(data); + } + encryptString(s) { + const cipher = new this.StringCipherConstructor(); + if (cipher instanceof AESBaseCipher) { + const strLen = s.length; + const pad = 16 - strLen % 16; + s += String.fromCharCode(pad).repeat(pad); + const iv = new Uint8Array(16); + crypto.getRandomValues(iv); + let data = stringToBytes(s); + data = cipher.encrypt(data, iv); + const buf = new Uint8Array(16 + data.length); + buf.set(iv); + buf.set(data, 16); + return bytesToString(buf); + } + let data = stringToBytes(s); + data = cipher.encrypt(data); + return bytesToString(data); + } +} +class CipherTransformFactory { + static get _defaultPasswordBytes() { + return shadow(this, "_defaultPasswordBytes", new Uint8Array([0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a])); + } + #createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) { + if (password) { + const passwordLength = Math.min(127, password.length); + password = password.subarray(0, passwordLength); + } else { + password = []; + } + const pdfAlgorithm = revision === 6 ? new PDF20() : new PDF17(); + if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) { + return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); + } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) { + return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption); + } + return null; + } + #prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { + const hashDataSize = 40 + ownerPassword.length + fileId.length; + const hashData = new Uint8Array(hashDataSize); + let i = 0, + j, + n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + } + j = 0; + while (i < 32) { + hashData[i++] = CipherTransformFactory._defaultPasswordBytes[j++]; + } + hashData.set(ownerPassword, i); + i += ownerPassword.length; + hashData[i++] = flags & 0xff; + hashData[i++] = flags >> 8 & 0xff; + hashData[i++] = flags >> 16 & 0xff; + hashData[i++] = flags >>> 24 & 0xff; + hashData.set(fileId, i); + i += fileId.length; + if (revision >= 4 && !encryptMetadata) { + hashData.fill(0xff, i, i + 4); + i += 4; + } + let hash = calculateMD5(hashData, 0, i); + const keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, keyLengthInBytes); + } + } + const encryptionKey = hash.subarray(0, keyLengthInBytes); + let cipher, checkData; + if (revision >= 3) { + i = 0; + hashData.set(CipherTransformFactory._defaultPasswordBytes, i); + i += 32; + hashData.set(fileId, i); + i += fileId.length; + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + const derivedKey = new Uint8Array(n); + for (j = 1; j <= 19; ++j) { + for (let k = 0; k < n; ++k) { + derivedKey[k] = encryptionKey[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(CipherTransformFactory._defaultPasswordBytes); + } + return checkData.every((data, k) => userPassword[k] === data) ? encryptionKey : null; + } + #decodeUserPassword(password, ownerPassword, revision, keyLength) { + const hashData = new Uint8Array(32); + let i = 0; + const n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + let j = 0; + while (i < 32) { + hashData[i++] = CipherTransformFactory._defaultPasswordBytes[j++]; + } + let hash = calculateMD5(hashData, 0, i); + const keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, hash.length); + } + } + let cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + const derivedKey = new Uint8Array(keyLengthInBytes); + for (j = 19; j >= 0; j--) { + for (let k = 0; k < keyLengthInBytes; ++k) { + derivedKey[k] = hash[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + #buildObjectKey(num, gen, encryptionKey, isAes = false) { + const n = encryptionKey.length; + const key = new Uint8Array(n + 9); + key.set(encryptionKey); + let i = n; + key[i++] = num & 0xff; + key[i++] = num >> 8 & 0xff; + key[i++] = num >> 16 & 0xff; + key[i++] = gen & 0xff; + key[i++] = gen >> 8 & 0xff; + if (isAes) { + key[i++] = 0x73; + key[i++] = 0x41; + key[i++] = 0x6c; + key[i++] = 0x54; + } + const hash = calculateMD5(key, 0, i); + return hash.subarray(0, Math.min(n + 5, 16)); + } + #buildCipherConstructor(cf, name, num, gen, key) { + if (!(name instanceof Name)) { + throw new FormatError("Invalid crypt filter name."); + } + const self = this; + const cryptFilter = cf.get(name.name); + const cfm = cryptFilter?.get("CFM"); + if (!cfm || cfm.name === "None") { + return function () { + return new NullCipher(); + }; + } + if (cfm.name === "V2") { + return function () { + return new ARCFourCipher(self.#buildObjectKey(num, gen, key, false)); + }; + } + if (cfm.name === "AESV2") { + return function () { + return new AES128Cipher(self.#buildObjectKey(num, gen, key, true)); + }; + } + if (cfm.name === "AESV3") { + return function () { + return new AES256Cipher(key); + }; + } + throw new FormatError("Unknown crypto method"); + } + constructor(dict, fileId, password) { + const filter = dict.get("Filter"); + if (!isName(filter, "Standard")) { + throw new FormatError("unknown encryption method"); + } + this.filterName = filter.name; + this.dict = dict; + const algorithm = dict.get("V"); + if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) { + throw new FormatError("unsupported encryption algorithm"); + } + this.algorithm = algorithm; + let keyLength = dict.get("Length"); + if (!keyLength) { + if (algorithm <= 3) { + keyLength = 40; + } else { + const cfDict = dict.get("CF"); + const streamCryptoName = dict.get("StmF"); + if (cfDict instanceof Dict && streamCryptoName instanceof Name) { + cfDict.suppressEncryption = true; + const handlerDict = cfDict.get(streamCryptoName.name); + keyLength = handlerDict?.get("Length") || 128; + if (keyLength < 40) { + keyLength <<= 3; + } + } + } + } + if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) { + throw new FormatError("invalid key length"); + } + const ownerBytes = stringToBytes(dict.get("O")), + userBytes = stringToBytes(dict.get("U")); + const ownerPassword = ownerBytes.subarray(0, 32); + const userPassword = userBytes.subarray(0, 32); + const flags = dict.get("P"); + const revision = dict.get("R"); + const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get("EncryptMetadata") !== false; + this.encryptMetadata = encryptMetadata; + const fileIdBytes = stringToBytes(fileId); + let passwordBytes; + if (password) { + if (revision === 6) { + try { + password = utf8StringToString(password); + } catch { + warn("CipherTransformFactory: Unable to convert UTF8 encoded password."); + } + } + passwordBytes = stringToBytes(password); + } + let encryptionKey; + if (algorithm !== 5) { + encryptionKey = this.#prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } else { + const ownerValidationSalt = ownerBytes.subarray(32, 40); + const ownerKeySalt = ownerBytes.subarray(40, 48); + const uBytes = userBytes.subarray(0, 48); + const userValidationSalt = userBytes.subarray(32, 40); + const userKeySalt = userBytes.subarray(40, 48); + const ownerEncryption = stringToBytes(dict.get("OE")); + const userEncryption = stringToBytes(dict.get("UE")); + const perms = stringToBytes(dict.get("Perms")); + encryptionKey = this.#createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms); + } + if (!encryptionKey) { + if (!password) { + throw new PasswordException("No password given", PasswordResponses.NEED_PASSWORD); + } + const decodedPassword = this.#decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength); + encryptionKey = this.#prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } + if (!encryptionKey) { + throw new PasswordException("Incorrect Password", PasswordResponses.INCORRECT_PASSWORD); + } + if (algorithm === 4 && encryptionKey.length < 16) { + this.encryptionKey = new Uint8Array(16); + this.encryptionKey.set(encryptionKey); + } else { + this.encryptionKey = encryptionKey; + } + if (algorithm >= 4) { + const cf = dict.get("CF"); + if (cf instanceof Dict) { + cf.suppressEncryption = true; + } + this.cf = cf; + this.stmf = dict.get("StmF") || Name.get("Identity"); + this.strf = dict.get("StrF") || Name.get("Identity"); + this.eff = dict.get("EFF") || this.stmf; + } + } + createCipherTransform(num, gen) { + if (this.algorithm === 4 || this.algorithm === 5) { + return new CipherTransform(this.#buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey), this.#buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey)); + } + const key = this.#buildObjectKey(num, gen, this.encryptionKey, false); + const cipherConstructor = function () { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } +} + +;// ./src/core/xref.js + + + + + + +class XRef { + constructor(stream, pdfManager) { + this.stream = stream; + this.pdfManager = pdfManager; + this.entries = []; + this._xrefStms = new Set(); + this._cacheMap = new Map(); + this._pendingRefs = new RefSet(); + this._newPersistentRefNum = null; + this._newTemporaryRefNum = null; + this._persistentRefsCache = null; + } + getNewPersistentRef(obj) { + if (this._newPersistentRefNum === null) { + this._newPersistentRefNum = this.entries.length || 1; + } + const num = this._newPersistentRefNum++; + this._cacheMap.set(num, obj); + return Ref.get(num, 0); + } + getNewTemporaryRef() { + if (this._newTemporaryRefNum === null) { + this._newTemporaryRefNum = this.entries.length || 1; + if (this._newPersistentRefNum) { + this._persistentRefsCache = new Map(); + for (let i = this._newTemporaryRefNum; i < this._newPersistentRefNum; i++) { + this._persistentRefsCache.set(i, this._cacheMap.get(i)); + this._cacheMap.delete(i); + } + } + } + return Ref.get(this._newTemporaryRefNum++, 0); + } + resetNewTemporaryRef() { + this._newTemporaryRefNum = null; + if (this._persistentRefsCache) { + for (const [num, obj] of this._persistentRefsCache) { + this._cacheMap.set(num, obj); + } + } + this._persistentRefsCache = null; + } + setStartXRef(startXRef) { + this.startXRefQueue = [startXRef]; + } + parse(recoveryMode = false) { + let trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn("Indexing all PDF objects"); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + let encrypt; + try { + encrypt = trailerDict.get("Encrypt"); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`); + } + if (encrypt instanceof Dict) { + const ids = trailerDict.get("ID"); + const fileId = ids?.length ? ids[0] : ""; + encrypt.suppressEncryption = true; + this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password); + } + let root; + try { + root = trailerDict.get("Root"); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`XRef.parse - Invalid "Root" reference: "${ex}".`); + } + if (root instanceof Dict) { + try { + const pages = root.get("Pages"); + if (pages instanceof Dict) { + this.root = root; + return; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`XRef.parse - Invalid "Pages" reference: "${ex}".`); + } + } + if (!recoveryMode) { + throw new XRefParseException(); + } + throw new InvalidPDFException("Invalid Root reference."); + } + processXRefTable(parser) { + if (!("tableState" in this)) { + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + const obj = this.readXRefTable(parser); + if (!isCmd(obj, "trailer")) { + throw new FormatError("Invalid XRef table: could not find trailer dictionary"); + } + let dict = parser.getObj(); + if (!(dict instanceof Dict) && dict.dict) { + dict = dict.dict; + } + if (!(dict instanceof Dict)) { + throw new FormatError("Invalid XRef table: could not parse trailer dictionary"); + } + delete this.tableState; + return dict; + } + readXRefTable(parser) { + const stream = parser.lexer.stream; + const tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + let obj; + while (true) { + if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) { + if (isCmd(obj = parser.getObj(), "trailer")) { + break; + } + tableState.firstEntryNum = obj; + tableState.entryCount = parser.getObj(); + } + let first = tableState.firstEntryNum; + const count = tableState.entryCount; + if (!Number.isInteger(first) || !Number.isInteger(count)) { + throw new FormatError("Invalid XRef table: wrong types in subsection header"); + } + for (let i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + const entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + const type = parser.getObj(); + if (type instanceof Cmd) { + switch (type.cmd) { + case "f": + entry.free = true; + break; + case "n": + entry.uncompressed = true; + break; + } + } + if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) { + throw new FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`); + } + if (i === 0 && entry.free && first === 1) { + first = 0; + } + if (!this.entries[i + first]) { + this.entries[i + first] = entry; + } + } + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + if (this.entries[0] && !this.entries[0].free) { + throw new FormatError("Invalid XRef table: unexpected first object"); + } + return obj; + } + processXRefStream(stream) { + if (!("streamState" in this)) { + const { + dict, + pos + } = stream; + const byteWidths = dict.get("W"); + const range = dict.get("Index") || [0, dict.get("Size")]; + this.streamState = { + entryRanges: range, + byteWidths, + entryNum: 0, + streamPos: pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + return stream.dict; + } + readXRefStream(stream) { + const streamState = this.streamState; + stream.pos = streamState.streamPos; + const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths; + const entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + const [first, n] = entryRanges; + if (!Number.isInteger(first) || !Number.isInteger(n)) { + throw new FormatError(`Invalid XRef range fields: ${first}, ${n}`); + } + if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) { + throw new FormatError(`Invalid XRef entry fields length: ${first}, ${n}`); + } + for (let i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + let type = 0, + offset = 0, + generation = 0; + for (let j = 0; j < typeFieldWidth; ++j) { + const typeByte = stream.getByte(); + if (typeByte === -1) { + throw new FormatError("Invalid XRef byteWidths 'type'."); + } + type = type << 8 | typeByte; + } + if (typeFieldWidth === 0) { + type = 1; + } + for (let j = 0; j < offsetFieldWidth; ++j) { + const offsetByte = stream.getByte(); + if (offsetByte === -1) { + throw new FormatError("Invalid XRef byteWidths 'offset'."); + } + offset = offset << 8 | offsetByte; + } + for (let j = 0; j < generationFieldWidth; ++j) { + const generationByte = stream.getByte(); + if (generationByte === -1) { + throw new FormatError("Invalid XRef byteWidths 'generation'."); + } + generation = generation << 8 | generationByte; + } + const entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + throw new FormatError(`Invalid XRef entry type: ${type}`); + } + if (!this.entries[first + i]) { + this.entries[first + i] = entry; + } + } + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + } + indexObjects() { + const TAB = 0x9, + LF = 0xa, + CR = 0xd, + SPACE = 0x20; + const PERCENT = 0x25, + LT = 0x3c; + function readToken(data, offset) { + let token = "", + ch = data[offset]; + while (ch !== LF && ch !== CR && ch !== LT) { + if (++offset >= data.length) { + break; + } + token += String.fromCharCode(ch); + ch = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + const length = what.length, + dataLength = data.length; + let skipped = 0; + while (offset < dataLength) { + let i = 0; + while (i < length && data[offset + i] === what[i]) { + ++i; + } + if (i >= length) { + break; + } + offset++; + skipped++; + } + return skipped; + } + const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer\s*<<)\b/g; + const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g; + const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/; + const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); + const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]); + const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); + this.entries.length = 0; + this._cacheMap.clear(); + const stream = this.stream; + stream.pos = 0; + const buffer = stream.getBytes(), + bufferStr = bytesToString(buffer), + length = buffer.length; + let position = stream.start; + const trailers = [], + xrefStms = []; + while (position < length) { + let ch = buffer[position]; + if (ch === TAB || ch === LF || ch === CR || ch === SPACE) { + ++position; + continue; + } + if (ch === PERCENT) { + do { + ++position; + if (position >= length) { + break; + } + ch = buffer[position]; + } while (ch !== LF && ch !== CR); + continue; + } + const token = readToken(buffer, position); + let m; + if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) { + position += skipUntil(buffer, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else if (m = objRegExp.exec(token)) { + const num = m[1] | 0, + gen = m[2] | 0; + const startPos = position + token.length; + let contentLength, + updateEntries = false; + if (!this.entries[num]) { + updateEntries = true; + } else if (this.entries[num].gen === gen) { + try { + const parser = new Parser({ + lexer: new Lexer(stream.makeSubStream(startPos)) + }); + parser.getObj(); + updateEntries = true; + } catch (ex) { + if (ex instanceof ParserEOFException) { + warn(`indexObjects -- checking object (${token}): "${ex}".`); + } else { + updateEntries = true; + } + } + } + if (updateEntries) { + this.entries[num] = { + offset: position - stream.start, + gen, + uncompressed: true + }; + } + gEndobjRegExp.lastIndex = startPos; + const match = gEndobjRegExp.exec(bufferStr); + if (match) { + const endPos = gEndobjRegExp.lastIndex + 1; + contentLength = endPos - position; + if (match[1] !== "endobj") { + warn(`indexObjects: Found "${match[1]}" inside of another "obj", ` + 'caused by missing "endobj" -- trying to recover.'); + contentLength -= match[1].length + 1; + } + } else { + contentLength = length - position; + } + const content = buffer.subarray(position, position + contentLength); + const xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) { + xrefStms.push(position - stream.start); + this._xrefStms.add(position - stream.start); + } + position += contentLength; + } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) { + trailers.push(position); + const startPos = position + token.length; + let contentLength; + gStartxrefRegExp.lastIndex = startPos; + const match = gStartxrefRegExp.exec(bufferStr); + if (match) { + const endPos = gStartxrefRegExp.lastIndex + 1; + contentLength = endPos - position; + if (match[1] !== "startxref") { + warn(`indexObjects: Found "${match[1]}" after "trailer", ` + 'caused by missing "startxref" -- trying to recover.'); + contentLength -= match[1].length + 1; + } + } else { + contentLength = length - position; + } + position += contentLength; + } else { + position += token.length + 1; + } + } + for (const xrefStm of xrefStms) { + this.startXRefQueue.push(xrefStm); + this.readXRef(true); + } + const trailerDicts = []; + let isEncrypted = false; + for (const trailer of trailers) { + stream.pos = trailer; + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true, + recoveryMode: true + }); + const obj = parser.getObj(); + if (!isCmd(obj, "trailer")) { + continue; + } + const dict = parser.getObj(); + if (!(dict instanceof Dict)) { + continue; + } + trailerDicts.push(dict); + if (dict.has("Encrypt")) { + isEncrypted = true; + } + } + let trailerDict, trailerError; + for (const dict of [...trailerDicts, "genFallback", ...trailerDicts]) { + if (dict === "genFallback") { + if (!trailerError) { + break; + } + this._generationFallback = true; + continue; + } + let validPagesDict = false; + try { + const rootDict = dict.get("Root"); + if (!(rootDict instanceof Dict)) { + continue; + } + const pagesDict = rootDict.get("Pages"); + if (!(pagesDict instanceof Dict)) { + continue; + } + const pagesCount = pagesDict.get("Count"); + if (Number.isInteger(pagesCount)) { + validPagesDict = true; + } + } catch (ex) { + trailerError = ex; + continue; + } + if (validPagesDict && (!isEncrypted || dict.has("Encrypt")) && dict.has("ID")) { + return dict; + } + trailerDict = dict; + } + if (trailerDict) { + return trailerDict; + } + if (this.topDict) { + return this.topDict; + } + if (!trailerDicts.length) { + for (const num in this.entries) { + if (!Object.hasOwn(this.entries, num)) { + continue; + } + const entry = this.entries[num]; + const ref = Ref.get(parseInt(num), entry.gen); + let obj; + try { + obj = this.fetch(ref); + } catch { + continue; + } + if (obj instanceof BaseStream) { + obj = obj.dict; + } + if (obj instanceof Dict && obj.has("Root")) { + return obj; + } + } + } + throw new InvalidPDFException("Invalid PDF structure."); + } + readXRef(recoveryMode = false) { + const stream = this.stream; + const startXRefParsedCache = new Set(); + while (this.startXRefQueue.length) { + try { + const startXRef = this.startXRefQueue[0]; + if (startXRefParsedCache.has(startXRef)) { + warn("readXRef - skipping XRef table since it was already parsed."); + this.startXRefQueue.shift(); + continue; + } + startXRefParsedCache.add(startXRef); + stream.pos = startXRef + stream.start; + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + let obj = parser.getObj(); + let dict; + if (isCmd(obj, "xref")) { + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + obj = dict.get("XRefStm"); + if (Number.isInteger(obj) && !this._xrefStms.has(obj)) { + this._xrefStms.add(obj); + this.startXRefQueue.push(obj); + } + } else if (Number.isInteger(obj)) { + if (!Number.isInteger(parser.getObj()) || !isCmd(parser.getObj(), "obj") || !((obj = parser.getObj()) instanceof BaseStream)) { + throw new FormatError("Invalid XRef stream"); + } + dict = this.processXRefStream(obj); + if (!this.topDict) { + this.topDict = dict; + } + if (!dict) { + throw new FormatError("Failed to read XRef stream"); + } + } else { + throw new FormatError("Invalid XRef stream header"); + } + obj = dict.get("Prev"); + if (Number.isInteger(obj)) { + this.startXRefQueue.push(obj); + } else if (obj instanceof Ref) { + this.startXRefQueue.push(obj.num); + } + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info("(while reading XRef): " + e); + } + this.startXRefQueue.shift(); + } + if (this.topDict) { + return this.topDict; + } + if (recoveryMode) { + return undefined; + } + throw new XRefParseException(); + } + getEntry(i) { + const xrefEntry = this.entries[i]; + if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { + return xrefEntry; + } + return null; + } + fetchIfRef(obj, suppressEncryption = false) { + if (obj instanceof Ref) { + return this.fetch(obj, suppressEncryption); + } + return obj; + } + fetch(ref, suppressEncryption = false) { + if (!(ref instanceof Ref)) { + throw new Error("ref object is not a reference"); + } + const num = ref.num; + const cacheEntry = this._cacheMap.get(num); + if (cacheEntry !== undefined) { + if (cacheEntry instanceof Dict && !cacheEntry.objId) { + cacheEntry.objId = ref.toString(); + } + return cacheEntry; + } + let xrefEntry = this.getEntry(num); + if (xrefEntry === null) { + return xrefEntry; + } + if (this._pendingRefs.has(ref)) { + this._pendingRefs.remove(ref); + warn(`Ignoring circular reference: ${ref}.`); + return CIRCULAR_REF; + } + this._pendingRefs.put(ref); + try { + xrefEntry = xrefEntry.uncompressed ? this.fetchUncompressed(ref, xrefEntry, suppressEncryption) : this.fetchCompressed(ref, xrefEntry, suppressEncryption); + this._pendingRefs.remove(ref); + } catch (ex) { + this._pendingRefs.remove(ref); + throw ex; + } + if (xrefEntry instanceof Dict) { + xrefEntry.objId = ref.toString(); + } else if (xrefEntry instanceof BaseStream) { + xrefEntry.dict.objId = ref.toString(); + } + return xrefEntry; + } + fetchUncompressed(ref, xrefEntry, suppressEncryption = false) { + const gen = ref.gen; + let num = ref.num; + if (xrefEntry.gen !== gen) { + const msg = `Inconsistent generation in XRef: ${ref}`; + if (this._generationFallback && xrefEntry.gen < gen) { + warn(msg); + return this.fetchUncompressed(Ref.get(num, xrefEntry.gen), xrefEntry, suppressEncryption); + } + throw new XRefEntryException(msg); + } + const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start); + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + const obj1 = parser.getObj(); + const obj2 = parser.getObj(); + const obj3 = parser.getObj(); + if (obj1 !== num || obj2 !== gen || !(obj3 instanceof Cmd)) { + throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); + } + if (obj3.cmd !== "obj") { + if (obj3.cmd.startsWith("obj")) { + num = parseInt(obj3.cmd.substring(3), 10); + if (!Number.isNaN(num)) { + return num; + } + } + throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); + } + xrefEntry = this.encrypt && !suppressEncryption ? parser.getObj(this.encrypt.createCipherTransform(num, gen)) : parser.getObj(); + if (!(xrefEntry instanceof BaseStream)) { + this._cacheMap.set(num, xrefEntry); + } + return xrefEntry; + } + fetchCompressed(ref, xrefEntry, suppressEncryption = false) { + const tableOffset = xrefEntry.offset; + const stream = this.fetch(Ref.get(tableOffset, 0)); + if (!(stream instanceof BaseStream)) { + throw new FormatError("bad ObjStm stream"); + } + const first = stream.dict.get("First"); + const n = stream.dict.get("N"); + if (!Number.isInteger(first) || !Number.isInteger(n)) { + throw new FormatError("invalid first and n parameters for ObjStm stream"); + } + let parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + const nums = new Array(n); + const offsets = new Array(n); + for (let i = 0; i < n; ++i) { + const num = parser.getObj(); + if (!Number.isInteger(num)) { + throw new FormatError(`invalid object number in the ObjStm stream: ${num}`); + } + const offset = parser.getObj(); + if (!Number.isInteger(offset)) { + throw new FormatError(`invalid object offset in the ObjStm stream: ${offset}`); + } + nums[i] = num; + const entry = this.getEntry(num); + if (entry?.offset === tableOffset && entry.gen !== i) { + entry.gen = i; + } + offsets[i] = offset; + } + const start = (stream.start || 0) + first; + const entries = new Array(n); + for (let i = 0; i < n; ++i) { + const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined; + if (length < 0) { + throw new FormatError("Invalid offset in the ObjStm stream."); + } + parser = new Parser({ + lexer: new Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)), + xref: this, + allowStreams: true + }); + const obj = parser.getObj(); + entries[i] = obj; + if (obj instanceof BaseStream) { + continue; + } + const num = nums[i], + entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this._cacheMap.set(num, obj); + } + } + xrefEntry = entries[xrefEntry.gen]; + if (xrefEntry === undefined) { + throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`); + } + return xrefEntry; + } + async fetchIfRefAsync(obj, suppressEncryption) { + if (obj instanceof Ref) { + return this.fetchAsync(obj, suppressEncryption); + } + return obj; + } + async fetchAsync(ref, suppressEncryption) { + try { + return this.fetch(ref, suppressEncryption); + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + throw ex; + } + await this.pdfManager.requestRange(ex.begin, ex.end); + return this.fetchAsync(ref, suppressEncryption); + } + } + getCatalogObj() { + return this.root; + } +} + +;// ./src/core/document.js + + + + + + + + + + + + + + + + + + + + +const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; +class Page { + #areAnnotationsCached = false; + #resourcesPromise = null; + constructor({ + pdfManager, + xref, + pageIndex, + pageDict, + ref, + globalIdFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + globalColorSpaceCache, + globalImageCache, + systemFontCache, + nonBlendModesSet, + xfaFactory + }) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.standardFontDataCache = standardFontDataCache; + this.globalColorSpaceCache = globalColorSpaceCache; + this.globalImageCache = globalImageCache; + this.systemFontCache = systemFontCache; + this.nonBlendModesSet = nonBlendModesSet; + this.evaluatorOptions = pdfManager.evaluatorOptions; + this.xfaFactory = xfaFactory; + const idCounters = { + obj: 0 + }; + this._localIdFactory = class extends globalIdFactory { + static createObjId() { + return `p${pageIndex}_${++idCounters.obj}`; + } + static getPageObjId() { + return `p${ref.toString()}`; + } + }; + } + #createPartialEvaluator(handler) { + return new PartialEvaluator({ + xref: this.xref, + handler, + pageIndex: this.pageIndex, + idFactory: this._localIdFactory, + fontCache: this.fontCache, + builtInCMapCache: this.builtInCMapCache, + standardFontDataCache: this.standardFontDataCache, + globalColorSpaceCache: this.globalColorSpaceCache, + globalImageCache: this.globalImageCache, + systemFontCache: this.systemFontCache, + options: this.evaluatorOptions + }); + } + #getInheritableProperty(key, getArray = false) { + const value = getInheritableProperty({ + dict: this.pageDict, + key, + getArray, + stopWhenFound: false + }); + if (!Array.isArray(value)) { + return value; + } + if (value.length === 1 || !(value[0] instanceof Dict)) { + return value[0]; + } + return Dict.merge({ + xref: this.xref, + dictArray: value + }); + } + get content() { + return this.pageDict.getArray("Contents"); + } + get resources() { + const resources = this.#getInheritableProperty("Resources"); + return shadow(this, "resources", resources instanceof Dict ? resources : Dict.empty); + } + getBoundingBox(name) { + if (this.xfaData) { + return this.xfaData.bbox; + } + const box = lookupNormalRect(this.#getInheritableProperty(name, true), null); + if (box) { + if (box[2] - box[0] > 0 && box[3] - box[1] > 0) { + return box; + } + warn(`Empty, or invalid, /${name} entry.`); + } + return null; + } + get mediaBox() { + return shadow(this, "mediaBox", this.getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX); + } + get cropBox() { + return shadow(this, "cropBox", this.getBoundingBox("CropBox") || this.mediaBox); + } + get userUnit() { + const obj = this.pageDict.get("UserUnit"); + return shadow(this, "userUnit", typeof obj === "number" && obj > 0 ? obj : 1.0); + } + get view() { + const { + cropBox, + mediaBox + } = this; + if (cropBox !== mediaBox && !isArrayEqual(cropBox, mediaBox)) { + const box = Util.intersect(cropBox, mediaBox); + if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) { + return shadow(this, "view", box); + } + warn("Empty /CropBox and /MediaBox intersection."); + } + return shadow(this, "view", mediaBox); + } + get rotate() { + let rotate = this.#getInheritableProperty("Rotate") || 0; + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate %= 360; + } else if (rotate < 0) { + rotate = (rotate % 360 + 360) % 360; + } + return shadow(this, "rotate", rotate); + } + #onSubStreamError(reason, objId) { + if (this.evaluatorOptions.ignoreErrors) { + warn(`getContentStream - ignoring sub-stream (${objId}): "${reason}".`); + return; + } + throw reason; + } + async getContentStream() { + const content = await this.pdfManager.ensure(this, "content"); + if (content instanceof BaseStream) { + return content; + } + if (Array.isArray(content)) { + return new StreamsSequenceStream(content, this.#onSubStreamError.bind(this)); + } + return new NullStream(); + } + get xfaData() { + return shadow(this, "xfaData", this.xfaFactory ? { + bbox: this.xfaFactory.getBoundingBox(this.pageIndex) + } : null); + } + async #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) { + const promises = []; + for (const annotation of annotations) { + if (annotation.id) { + const ref = Ref.fromString(annotation.id); + if (!ref) { + warn(`A non-linked annotation cannot be modified: ${annotation.id}`); + continue; + } + if (annotation.deleted) { + deletedAnnotations.put(ref, ref); + if (annotation.popupRef) { + const popupRef = Ref.fromString(annotation.popupRef); + if (popupRef) { + deletedAnnotations.put(popupRef, popupRef); + } + } + continue; + } + if (annotation.popup?.deleted) { + const popupRef = Ref.fromString(annotation.popupRef); + if (popupRef) { + deletedAnnotations.put(popupRef, popupRef); + } + } + existingAnnotations?.put(ref); + annotation.ref = ref; + promises.push(this.xref.fetchAsync(ref).then(obj => { + if (obj instanceof Dict) { + annotation.oldAnnotation = obj.clone(); + } + }, () => { + warn(`Cannot fetch \`oldAnnotation\` for: ${ref}.`); + })); + delete annotation.id; + } + } + await Promise.all(promises); + } + async saveNewAnnotations(handler, task, annotations, imagePromises, changes) { + if (this.xfaFactory) { + throw new Error("XFA: Cannot save new annotations."); + } + const partialEvaluator = this.#createPartialEvaluator(handler); + const deletedAnnotations = new RefSetCache(); + const existingAnnotations = new RefSet(); + await this.#replaceIdByRef(annotations, deletedAnnotations, existingAnnotations); + const pageDict = this.pageDict; + const annotationsArray = this.annotations.filter(a => !(a instanceof Ref && deletedAnnotations.has(a))); + const newData = await AnnotationFactory.saveNewAnnotations(partialEvaluator, task, annotations, imagePromises, changes); + for (const { + ref + } of newData.annotations) { + if (ref instanceof Ref && !existingAnnotations.has(ref)) { + annotationsArray.push(ref); + } + } + const dict = pageDict.clone(); + dict.set("Annots", annotationsArray); + changes.put(this.ref, { + data: dict + }); + for (const deletedRef of deletedAnnotations) { + changes.put(deletedRef, { + data: null + }); + } + } + async save(handler, task, annotationStorage, changes) { + const partialEvaluator = this.#createPartialEvaluator(handler); + const annotations = await this._parsedAnnotations; + const promises = []; + for (const annotation of annotations) { + promises.push(annotation.save(partialEvaluator, task, annotationStorage, changes).catch(function (reason) { + warn("save - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); + return null; + })); + } + return Promise.all(promises); + } + async loadResources(keys) { + await (this.#resourcesPromise ??= this.pdfManager.ensure(this, "resources")); + await ObjectLoader.load(this.resources, keys, this.xref); + } + async #getMergedResources(streamDict, keys) { + const localResources = streamDict?.get("Resources"); + if (!(localResources instanceof Dict && localResources.size)) { + return this.resources; + } + await ObjectLoader.load(localResources, keys, this.xref); + return Dict.merge({ + xref: this.xref, + dictArray: [localResources, this.resources], + mergeSubDicts: true + }); + } + async getOperatorList({ + handler, + sink, + task, + intent, + cacheKey, + annotationStorage = null, + modifiedIds = null + }) { + const contentStreamPromise = this.getContentStream(); + const resourcesPromise = this.loadResources(RESOURCES_KEYS_OPERATOR_LIST); + const partialEvaluator = this.#createPartialEvaluator(handler); + const newAnnotsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null; + const newAnnots = newAnnotsByPage?.get(this.pageIndex); + let newAnnotationsPromise = Promise.resolve(null); + let deletedAnnotations = null; + if (newAnnots) { + const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals"); + let imagePromises; + const missingBitmaps = new Set(); + for (const { + bitmapId, + bitmap + } of newAnnots) { + if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) { + missingBitmaps.add(bitmapId); + } + } + const { + isOffscreenCanvasSupported + } = this.evaluatorOptions; + if (missingBitmaps.size > 0) { + const annotationWithBitmaps = newAnnots.slice(); + for (const [key, annotation] of annotationStorage) { + if (!key.startsWith(AnnotationEditorPrefix)) { + continue; + } + if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) { + annotationWithBitmaps.push(annotation); + } + } + imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported); + } else { + imagePromises = AnnotationFactory.generateImages(newAnnots, this.xref, isOffscreenCanvasSupported); + } + deletedAnnotations = new RefSet(); + newAnnotationsPromise = Promise.all([annotationGlobalsPromise, this.#replaceIdByRef(newAnnots, deletedAnnotations, null)]).then(([annotationGlobals]) => { + if (!annotationGlobals) { + return null; + } + return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnots, imagePromises); + }); + } + const pageListPromise = Promise.all([contentStreamPromise, resourcesPromise]).then(async ([contentStream]) => { + const resources = await this.#getMergedResources(contentStream.dict, RESOURCES_KEYS_OPERATOR_LIST); + const opList = new OperatorList(intent, sink); + handler.send("StartRenderPage", { + transparency: partialEvaluator.hasBlendModes(resources, this.nonBlendModesSet), + pageIndex: this.pageIndex, + cacheKey + }); + await partialEvaluator.getOperatorList({ + stream: contentStream, + task, + resources, + operatorList: opList + }); + return opList; + }); + let [pageOpList, annotations, newAnnotations] = await Promise.all([pageListPromise, this._parsedAnnotations, newAnnotationsPromise]); + if (newAnnotations) { + annotations = annotations.filter(a => !(a.ref && deletedAnnotations.has(a.ref))); + for (let i = 0, ii = newAnnotations.length; i < ii; i++) { + const newAnnotation = newAnnotations[i]; + if (newAnnotation.refToReplace) { + const j = annotations.findIndex(a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace)); + if (j >= 0) { + annotations.splice(j, 1, newAnnotation); + newAnnotations.splice(i--, 1); + ii--; + } + } + } + annotations = annotations.concat(newAnnotations); + } + if (annotations.length === 0 || intent & RenderingIntentFlag.ANNOTATIONS_DISABLE) { + pageOpList.flush(true); + return { + length: pageOpList.totalLength + }; + } + const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS), + isEditing = !!(intent & RenderingIntentFlag.IS_EDITING), + intentAny = !!(intent & RenderingIntentFlag.ANY), + intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), + intentPrint = !!(intent & RenderingIntentFlag.PRINT); + const opListPromises = []; + for (const annotation of annotations) { + if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) && annotation.mustBeViewedWhenEditing(isEditing, modifiedIds) || intentPrint && annotation.mustBePrinted(annotationStorage)) { + opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, annotationStorage).catch(function (reason) { + warn("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); + return { + opList: null, + separateForm: false, + separateCanvas: false + }; + })); + } + } + const opLists = await Promise.all(opListPromises); + let form = false, + canvas = false; + for (const { + opList, + separateForm, + separateCanvas + } of opLists) { + pageOpList.addOpList(opList); + form ||= separateForm; + canvas ||= separateCanvas; + } + pageOpList.flush(true, { + form, + canvas + }); + return { + length: pageOpList.totalLength + }; + } + async extractTextContent({ + handler, + task, + includeMarkedContent, + disableNormalization, + sink, + intersector = null + }) { + const contentStreamPromise = this.getContentStream(); + const resourcesPromise = this.loadResources(RESOURCES_KEYS_TEXT_CONTENT); + const langPromise = this.pdfManager.ensureCatalog("lang"); + const [contentStream,, lang] = await Promise.all([contentStreamPromise, resourcesPromise, langPromise]); + const resources = await this.#getMergedResources(contentStream.dict, RESOURCES_KEYS_TEXT_CONTENT); + const partialEvaluator = this.#createPartialEvaluator(handler); + return partialEvaluator.getTextContent({ + stream: contentStream, + task, + resources, + includeMarkedContent, + disableNormalization, + sink, + viewBox: this.view, + lang, + intersector + }); + } + async getStructTree() { + const structTreeRoot = await this.pdfManager.ensureCatalog("structTreeRoot"); + if (!structTreeRoot) { + return null; + } + await this._parsedAnnotations; + try { + const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [structTreeRoot]); + const data = await this.pdfManager.ensure(structTree, "serializable"); + return data; + } catch (ex) { + warn(`getStructTree: "${ex}".`); + return null; + } + } + _parseStructTree(structTreeRoot) { + const tree = new StructTreePage(structTreeRoot, this.pageDict); + tree.parse(this.ref); + return tree; + } + async getAnnotationsData(handler, task, intent) { + const annotations = await this._parsedAnnotations; + if (annotations.length === 0) { + return annotations; + } + const annotationsData = [], + textContentPromises = []; + let partialEvaluator; + const intentAny = !!(intent & RenderingIntentFlag.ANY), + intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), + intentPrint = !!(intent & RenderingIntentFlag.PRINT); + const highlightedAnnotations = []; + for (const annotation of annotations) { + const isVisible = intentAny || intentDisplay && annotation.viewable; + if (isVisible || intentPrint && annotation.printable) { + annotationsData.push(annotation.data); + } + if (annotation.hasTextContent && isVisible) { + partialEvaluator ??= this.#createPartialEvaluator(handler); + textContentPromises.push(annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]).catch(function (reason) { + warn(`getAnnotationsData - ignoring textContent during "${task.name}" task: "${reason}".`); + })); + } else if (annotation.overlaysTextContent && isVisible) { + highlightedAnnotations.push(annotation); + } + } + if (highlightedAnnotations.length > 0) { + const intersector = new Intersector(highlightedAnnotations); + textContentPromises.push(this.extractTextContent({ + handler, + task, + includeMarkedContent: false, + disableNormalization: false, + sink: null, + viewBox: this.view, + lang: null, + intersector + }).then(() => { + intersector.setText(); + })); + } + await Promise.all(textContentPromises); + return annotationsData; + } + get annotations() { + const annots = this.#getInheritableProperty("Annots"); + return shadow(this, "annotations", Array.isArray(annots) ? annots : []); + } + get _parsedAnnotations() { + const promise = this.pdfManager.ensure(this, "annotations").then(async annots => { + if (annots.length === 0) { + return annots; + } + const [annotationGlobals, fieldObjects] = await Promise.all([this.pdfManager.ensureDoc("annotationGlobals"), this.pdfManager.ensureDoc("fieldObjects")]); + if (!annotationGlobals) { + return []; + } + const orphanFields = fieldObjects?.orphanFields; + const annotationPromises = []; + for (const annotationRef of annots) { + annotationPromises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, orphanFields, null, this.ref).catch(function (reason) { + warn(`_parsedAnnotations: "${reason}".`); + return null; + })); + } + const sortedAnnotations = []; + let popupAnnotations, widgetAnnotations; + for (const annotation of await Promise.all(annotationPromises)) { + if (!annotation) { + continue; + } + if (annotation instanceof WidgetAnnotation) { + (widgetAnnotations ||= []).push(annotation); + continue; + } + if (annotation instanceof PopupAnnotation) { + (popupAnnotations ||= []).push(annotation); + continue; + } + sortedAnnotations.push(annotation); + } + if (widgetAnnotations) { + sortedAnnotations.push(...widgetAnnotations); + } + if (popupAnnotations) { + sortedAnnotations.push(...popupAnnotations); + } + return sortedAnnotations; + }); + this.#areAnnotationsCached = true; + return shadow(this, "_parsedAnnotations", promise); + } + get jsActions() { + const actions = collectActions(this.xref, this.pageDict, PageActionEventType); + return shadow(this, "jsActions", actions); + } + async collectAnnotationsByType(handler, task, types, promises, annotationGlobals) { + const { + pageIndex + } = this; + if (this.#areAnnotationsCached) { + const cachedAnnotations = await this._parsedAnnotations; + for (const { + data + } of cachedAnnotations) { + if (!types || types.has(data.annotationType)) { + data.pageIndex = pageIndex; + promises.push(Promise.resolve(data)); + } + } + return; + } + const annots = await this.pdfManager.ensure(this, "annotations"); + for (const annotationRef of annots) { + promises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, null, types, this.ref).then(async annotation => { + if (!annotation) { + return null; + } + annotation.data.pageIndex = pageIndex; + if (annotation.hasTextContent && annotation.viewable) { + const partialEvaluator = this.#createPartialEvaluator(handler); + await annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]); + } + return annotation.data; + }).catch(function (reason) { + warn(`collectAnnotationsByType: "${reason}".`); + return null; + })); + } + } +} +const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]); +const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]); +const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]); +function find(stream, signature, limit = 1024, backwards = false) { + const signatureLength = signature.length; + const scanBytes = stream.peekBytes(limit); + const scanLength = scanBytes.length - signatureLength; + if (scanLength <= 0) { + return false; + } + if (backwards) { + const signatureEnd = signatureLength - 1; + let pos = scanBytes.length - 1; + while (pos >= signatureEnd) { + let j = 0; + while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) { + j++; + } + if (j >= signatureLength) { + stream.pos += pos - signatureEnd; + return true; + } + pos--; + } + } else { + let pos = 0; + while (pos <= scanLength) { + let j = 0; + while (j < signatureLength && scanBytes[pos + j] === signature[j]) { + j++; + } + if (j >= signatureLength) { + stream.pos += pos; + return true; + } + pos++; + } + } + return false; +} +class PDFDocument { + #pagePromises = new Map(); + #version = null; + constructor(pdfManager, stream) { + if (stream.length <= 0) { + throw new InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes."); + } + this.pdfManager = pdfManager; + this.stream = stream; + this.xref = new XRef(stream, pdfManager); + const idCounters = { + font: 0 + }; + this._globalIdFactory = class { + static getDocId() { + return `g_${pdfManager.docId}`; + } + static createFontId() { + return `f${++idCounters.font}`; + } + static createObjId() { + unreachable("Abstract method `createObjId` called."); + } + static getPageObjId() { + unreachable("Abstract method `getPageObjId` called."); + } + }; + } + parse(recoveryMode) { + this.xref.parse(recoveryMode); + this.catalog = new Catalog(this.pdfManager, this.xref); + } + get linearization() { + let linearization = null; + try { + linearization = Linearization.create(this.stream); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info(err); + } + return shadow(this, "linearization", linearization); + } + get startXRef() { + const stream = this.stream; + let startXRef = 0; + if (this.linearization) { + stream.reset(); + if (find(stream, ENDOBJ_SIGNATURE)) { + stream.skip(6); + let ch = stream.peekByte(); + while (isWhiteSpace(ch)) { + stream.pos++; + ch = stream.peekByte(); + } + startXRef = stream.pos - stream.start; + } + } else { + const step = 1024; + const startXRefLength = STARTXREF_SIGNATURE.length; + let found = false, + pos = stream.end; + while (!found && pos > 0) { + pos -= step - startXRefLength; + if (pos < 0) { + pos = 0; + } + stream.pos = pos; + found = find(stream, STARTXREF_SIGNATURE, step, true); + } + if (found) { + stream.skip(9); + let ch; + do { + ch = stream.getByte(); + } while (isWhiteSpace(ch)); + let str = ""; + while (ch >= 0x20 && ch <= 0x39) { + str += String.fromCharCode(ch); + ch = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) { + startXRef = 0; + } + } + } + return shadow(this, "startXRef", startXRef); + } + checkHeader() { + const stream = this.stream; + stream.reset(); + if (!find(stream, PDF_HEADER_SIGNATURE)) { + return; + } + stream.moveStart(); + stream.skip(PDF_HEADER_SIGNATURE.length); + let version = "", + ch; + while ((ch = stream.getByte()) > 0x20 && version.length < 7) { + version += String.fromCharCode(ch); + } + if (PDF_VERSION_REGEXP.test(version)) { + this.#version = version; + } else { + warn(`Invalid PDF header version: ${version}`); + } + } + parseStartXRef() { + this.xref.setStartXRef(this.startXRef); + } + get numPages() { + let num = 0; + if (this.catalog.hasActualNumPages) { + num = this.catalog.numPages; + } else if (this.xfaFactory) { + num = this.xfaFactory.getNumPages(); + } else if (this.linearization) { + num = this.linearization.numPages; + } else { + num = this.catalog.numPages; + } + return shadow(this, "numPages", num); + } + #hasOnlyDocumentSignatures(fields, recursionDepth = 0) { + const RECURSION_LIMIT = 10; + if (!Array.isArray(fields)) { + return false; + } + return fields.every(field => { + field = this.xref.fetchIfRef(field); + if (!(field instanceof Dict)) { + return false; + } + if (field.has("Kids")) { + if (++recursionDepth > RECURSION_LIMIT) { + warn("#hasOnlyDocumentSignatures: maximum recursion depth reached"); + return false; + } + return this.#hasOnlyDocumentSignatures(field.get("Kids"), recursionDepth); + } + const isSignature = isName(field.get("FT"), "Sig"); + const rectangle = field.get("Rect"); + const isInvisible = Array.isArray(rectangle) && rectangle.every(value => value === 0); + return isSignature && isInvisible; + }); + } + get _xfaStreams() { + const { + acroForm + } = this.catalog; + if (!acroForm) { + return null; + } + const xfa = acroForm.get("XFA"); + const entries = new Map(["xdp:xdp", "template", "datasets", "config", "connectionSet", "localeSet", "stylesheet", "/xdp:xdp"].map(e => [e, null])); + if (xfa instanceof BaseStream && !xfa.isEmpty) { + entries.set("xdp:xdp", xfa); + return entries; + } + if (!Array.isArray(xfa) || xfa.length === 0) { + return null; + } + for (let i = 0, ii = xfa.length; i < ii; i += 2) { + let name; + if (i === 0) { + name = "xdp:xdp"; + } else if (i === ii - 2) { + name = "/xdp:xdp"; + } else { + name = xfa[i]; + } + if (!entries.has(name)) { + continue; + } + const data = this.xref.fetchIfRef(xfa[i + 1]); + if (!(data instanceof BaseStream) || data.isEmpty) { + continue; + } + entries.set(name, data); + } + return entries; + } + get xfaDatasets() { + const streams = this._xfaStreams; + if (!streams) { + return shadow(this, "xfaDatasets", null); + } + for (const key of ["datasets", "xdp:xdp"]) { + const stream = streams.get(key); + if (!stream) { + continue; + } + try { + const str = stringToUTF8String(stream.getString()); + const data = { + [key]: str + }; + return shadow(this, "xfaDatasets", new DatasetReader(data)); + } catch { + warn("XFA - Invalid utf-8 string."); + break; + } + } + return shadow(this, "xfaDatasets", null); + } + get xfaData() { + const streams = this._xfaStreams; + if (!streams) { + return null; + } + const data = Object.create(null); + for (const [key, stream] of streams) { + if (!stream) { + continue; + } + try { + data[key] = stringToUTF8String(stream.getString()); + } catch { + warn("XFA - Invalid utf-8 string."); + return null; + } + } + return data; + } + get xfaFactory() { + let data; + if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) { + data = this.xfaData; + } + return shadow(this, "xfaFactory", data ? new XFAFactory(data) : null); + } + get isPureXfa() { + return this.xfaFactory ? this.xfaFactory.isValid() : false; + } + get htmlForXfa() { + return this.xfaFactory ? this.xfaFactory.getPages() : null; + } + async #loadXfaImages() { + const xfaImages = await this.pdfManager.ensureCatalog("xfaImages"); + if (!xfaImages) { + return; + } + this.xfaFactory.setImages(xfaImages); + } + async #loadXfaFonts(handler, task) { + const acroForm = await this.pdfManager.ensureCatalog("acroForm"); + if (!acroForm) { + return; + } + const resources = await acroForm.getAsync("DR"); + if (!(resources instanceof Dict)) { + return; + } + await ObjectLoader.load(resources, ["Font"], this.xref); + const fontRes = resources.get("Font"); + if (!(fontRes instanceof Dict)) { + return; + } + const options = Object.assign(Object.create(null), this.pdfManager.evaluatorOptions, { + useSystemFonts: false + }); + const { + builtInCMapCache, + fontCache, + standardFontDataCache + } = this.catalog; + const partialEvaluator = new PartialEvaluator({ + xref: this.xref, + handler, + pageIndex: -1, + idFactory: this._globalIdFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + options + }); + const operatorList = new OperatorList(); + const pdfFonts = []; + const initialState = { + get font() { + return pdfFonts.at(-1); + }, + set font(font) { + pdfFonts.push(font); + }, + clone() { + return this; + } + }; + const parseFont = (fontName, fallbackFontDict, cssFontInfo) => partialEvaluator.handleSetFont(resources, [Name.get(fontName), 1], null, operatorList, task, initialState, fallbackFontDict, cssFontInfo).catch(reason => { + warn(`loadXfaFonts: "${reason}".`); + return null; + }); + const promises = []; + for (const [fontName, font] of fontRes) { + const descriptor = font.get("FontDescriptor"); + if (!(descriptor instanceof Dict)) { + continue; + } + let fontFamily = descriptor.get("FontFamily"); + fontFamily = fontFamily.replaceAll(/[ ]+(\d)/g, "$1"); + const fontWeight = descriptor.get("FontWeight"); + const italicAngle = -descriptor.get("ItalicAngle"); + const cssFontInfo = { + fontFamily, + fontWeight, + italicAngle + }; + if (!validateCSSFont(cssFontInfo)) { + continue; + } + promises.push(parseFont(fontName, null, cssFontInfo)); + } + await Promise.all(promises); + const missingFonts = this.xfaFactory.setFonts(pdfFonts); + if (!missingFonts) { + return; + } + options.ignoreErrors = true; + promises.length = 0; + pdfFonts.length = 0; + const reallyMissingFonts = new Set(); + for (const missing of missingFonts) { + if (!getXfaFontName(`${missing}-Regular`)) { + reallyMissingFonts.add(missing); + } + } + if (reallyMissingFonts.size) { + missingFonts.push("PdfJS-Fallback"); + } + for (const missing of missingFonts) { + if (reallyMissingFonts.has(missing)) { + continue; + } + for (const fontInfo of [{ + name: "Regular", + fontWeight: 400, + italicAngle: 0 + }, { + name: "Bold", + fontWeight: 700, + italicAngle: 0 + }, { + name: "Italic", + fontWeight: 400, + italicAngle: 12 + }, { + name: "BoldItalic", + fontWeight: 700, + italicAngle: 12 + }]) { + const name = `${missing}-${fontInfo.name}`; + promises.push(parseFont(name, getXfaFontDict(name), { + fontFamily: missing, + fontWeight: fontInfo.fontWeight, + italicAngle: fontInfo.italicAngle + })); + } + } + await Promise.all(promises); + this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts); + } + loadXfaResources(handler, task) { + return Promise.all([this.#loadXfaFonts(handler, task).catch(() => {}), this.#loadXfaImages()]); + } + serializeXfaData(annotationStorage) { + return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null; + } + get version() { + return this.catalog.version || this.#version; + } + get formInfo() { + const formInfo = { + hasFields: false, + hasAcroForm: false, + hasXfa: false, + hasSignatures: false + }; + const { + acroForm + } = this.catalog; + if (!acroForm) { + return shadow(this, "formInfo", formInfo); + } + try { + const fields = acroForm.get("Fields"); + const hasFields = Array.isArray(fields) && fields.length > 0; + formInfo.hasFields = hasFields; + const xfa = acroForm.get("XFA"); + formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || xfa instanceof BaseStream && !xfa.isEmpty; + const sigFlags = acroForm.get("SigFlags"); + const hasSignatures = !!(sigFlags & 0x1); + const hasOnlyDocumentSignatures = hasSignatures && this.#hasOnlyDocumentSignatures(fields); + formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures; + formInfo.hasSignatures = hasSignatures; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn(`Cannot fetch form information: "${ex}".`); + } + return shadow(this, "formInfo", formInfo); + } + get documentInfo() { + const { + catalog, + formInfo, + xref + } = this; + const docInfo = { + PDFFormatVersion: this.version, + Language: catalog.lang, + EncryptFilterName: xref.encrypt?.filterName ?? null, + IsLinearized: !!this.linearization, + IsAcroFormPresent: formInfo.hasAcroForm, + IsXFAPresent: formInfo.hasXfa, + IsCollectionPresent: !!catalog.collection, + IsSignaturesPresent: formInfo.hasSignatures + }; + let infoDict; + try { + infoDict = xref.trailer.get("Info"); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info("The document information dictionary is invalid."); + } + if (!(infoDict instanceof Dict)) { + return shadow(this, "documentInfo", docInfo); + } + for (const [key, value] of infoDict) { + switch (key) { + case "Title": + case "Author": + case "Subject": + case "Keywords": + case "Creator": + case "Producer": + case "CreationDate": + case "ModDate": + if (typeof value === "string") { + docInfo[key] = stringToPDFString(value); + continue; + } + break; + case "Trapped": + if (value instanceof Name) { + docInfo[key] = value; + continue; + } + break; + default: + let customValue; + switch (typeof value) { + case "string": + customValue = stringToPDFString(value); + break; + case "number": + case "boolean": + customValue = value; + break; + default: + if (value instanceof Name) { + customValue = value; + } + break; + } + if (customValue === undefined) { + warn(`Bad value, for custom key "${key}", in Info: ${value}.`); + continue; + } + docInfo.Custom ??= Object.create(null); + docInfo.Custom[key] = customValue; + continue; + } + warn(`Bad value, for key "${key}", in Info: ${value}.`); + } + return shadow(this, "documentInfo", docInfo); + } + get fingerprints() { + const FINGERPRINT_FIRST_BYTES = 1024; + const EMPTY_FINGERPRINT = "\x00".repeat(16); + function validate(data) { + return typeof data === "string" && data.length === 16 && data !== EMPTY_FINGERPRINT; + } + const id = this.xref.trailer.get("ID"); + let hashOriginal, hashModified; + if (Array.isArray(id) && validate(id[0])) { + hashOriginal = stringToBytes(id[0]); + if (id[1] !== id[0] && validate(id[1])) { + hashModified = stringToBytes(id[1]); + } + } else { + hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + } + return shadow(this, "fingerprints", [toHexUtil(hashOriginal), hashModified ? toHexUtil(hashModified) : null]); + } + async #getLinearizationPage(pageIndex) { + const { + catalog, + linearization, + xref + } = this; + const ref = Ref.get(linearization.objectNumberFirst, 0); + try { + const obj = await xref.fetchAsync(ref); + if (obj instanceof Dict) { + let type = obj.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !obj.has("Type") && !obj.has("Kids") && obj.has("Contents")) { + if (!catalog.pageKidsCountCache.has(ref)) { + catalog.pageKidsCountCache.put(ref, 1); + } + if (!catalog.pageIndexCache.has(ref)) { + catalog.pageIndexCache.put(ref, 0); + } + return [obj, ref]; + } + } + throw new FormatError("The Linearization dictionary doesn't point to a valid Page dictionary."); + } catch (reason) { + warn(`_getLinearizationPage: "${reason.message}".`); + return catalog.getPageDict(pageIndex); + } + } + getPage(pageIndex) { + const cachedPromise = this.#pagePromises.get(pageIndex); + if (cachedPromise) { + return cachedPromise; + } + const { + catalog, + linearization, + xfaFactory + } = this; + let promise; + if (xfaFactory) { + promise = Promise.resolve([Dict.empty, null]); + } else if (linearization?.pageFirst === pageIndex) { + promise = this.#getLinearizationPage(pageIndex); + } else { + promise = catalog.getPageDict(pageIndex); + } + promise = promise.then(([pageDict, ref]) => new Page({ + pdfManager: this.pdfManager, + xref: this.xref, + pageIndex, + pageDict, + ref, + globalIdFactory: this._globalIdFactory, + fontCache: catalog.fontCache, + builtInCMapCache: catalog.builtInCMapCache, + standardFontDataCache: catalog.standardFontDataCache, + globalColorSpaceCache: catalog.globalColorSpaceCache, + globalImageCache: catalog.globalImageCache, + systemFontCache: catalog.systemFontCache, + nonBlendModesSet: catalog.nonBlendModesSet, + xfaFactory + })); + this.#pagePromises.set(pageIndex, promise); + return promise; + } + async checkFirstPage(recoveryMode = false) { + if (recoveryMode) { + return; + } + try { + await this.getPage(0); + } catch (reason) { + if (reason instanceof XRefEntryException) { + this.#pagePromises.delete(0); + await this.cleanup(); + throw new XRefParseException(); + } + } + } + async checkLastPage(recoveryMode = false) { + const { + catalog, + pdfManager + } = this; + catalog.setActualNumPages(); + let numPages; + try { + await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]); + if (this.xfaFactory) { + return; + } else if (this.linearization) { + numPages = this.linearization.numPages; + } else { + numPages = catalog.numPages; + } + if (!Number.isInteger(numPages)) { + throw new FormatError("Page count is not an integer."); + } else if (numPages <= 1) { + return; + } + await this.getPage(numPages - 1); + } catch (reason) { + this.#pagePromises.delete(numPages - 1); + await this.cleanup(); + if (reason instanceof XRefEntryException && !recoveryMode) { + throw new XRefParseException(); + } + warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`); + let pagesTree; + try { + pagesTree = await catalog.getAllPageDicts(recoveryMode); + } catch (reasonAll) { + if (reasonAll instanceof XRefEntryException && !recoveryMode) { + throw new XRefParseException(); + } + catalog.setActualNumPages(1); + return; + } + for (const [pageIndex, [pageDict, ref]] of pagesTree) { + let promise; + if (pageDict instanceof Error) { + promise = Promise.reject(pageDict); + promise.catch(() => {}); + } else { + promise = Promise.resolve(new Page({ + pdfManager, + xref: this.xref, + pageIndex, + pageDict, + ref, + globalIdFactory: this._globalIdFactory, + fontCache: catalog.fontCache, + builtInCMapCache: catalog.builtInCMapCache, + standardFontDataCache: catalog.standardFontDataCache, + globalColorSpaceCache: this.globalColorSpaceCache, + globalImageCache: catalog.globalImageCache, + systemFontCache: catalog.systemFontCache, + nonBlendModesSet: catalog.nonBlendModesSet, + xfaFactory: null + })); + } + this.#pagePromises.set(pageIndex, promise); + } + catalog.setActualNumPages(pagesTree.size); + } + } + async fontFallback(id, handler) { + const { + catalog, + pdfManager + } = this; + for (const translatedFont of await Promise.all(catalog.fontCache)) { + if (translatedFont.loadedName === id) { + translatedFont.fallback(handler, pdfManager.evaluatorOptions); + return; + } + } + } + async cleanup(manuallyTriggered = false) { + return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches(); + } + async #collectFieldObjects(name, parentRef, fieldRef, promises, annotationGlobals, visitedRefs, orphanFields) { + const { + xref + } = this; + if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) { + return; + } + visitedRefs.put(fieldRef); + const field = await xref.fetchAsync(fieldRef); + if (!(field instanceof Dict)) { + return; + } + let subtype = await field.getAsync("Subtype"); + subtype = subtype instanceof Name ? subtype.name : null; + switch (subtype) { + case "Link": + return; + } + if (field.has("T")) { + const partName = stringToPDFString(await field.getAsync("T")); + name = name === "" ? partName : `${name}.${partName}`; + } else { + let obj = field; + while (true) { + obj = obj.getRaw("Parent") || parentRef; + if (obj instanceof Ref) { + if (visitedRefs.has(obj)) { + break; + } + obj = await xref.fetchAsync(obj); + } + if (!(obj instanceof Dict)) { + break; + } + if (obj.has("T")) { + const partName = stringToPDFString(await obj.getAsync("T")); + name = name === "" ? partName : `${name}.${partName}`; + break; + } + } + } + if (parentRef && !field.has("Parent") && isName(field.get("Subtype"), "Widget")) { + orphanFields.put(fieldRef, parentRef); + } + if (!promises.has(name)) { + promises.set(name, []); + } + promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, orphanFields, null, null).then(annotation => annotation?.getFieldObject()).catch(function (reason) { + warn(`#collectFieldObjects: "${reason}".`); + return null; + })); + if (!field.has("Kids")) { + return; + } + const kids = await field.getAsync("Kids"); + if (Array.isArray(kids)) { + for (const kid of kids) { + await this.#collectFieldObjects(name, fieldRef, kid, promises, annotationGlobals, visitedRefs, orphanFields); + } + } + } + get fieldObjects() { + const promise = this.pdfManager.ensureDoc("formInfo").then(async formInfo => { + if (!formInfo.hasFields) { + return null; + } + const annotationGlobals = await this.annotationGlobals; + if (!annotationGlobals) { + return null; + } + const { + acroForm + } = annotationGlobals; + const visitedRefs = new RefSet(); + const allFields = Object.create(null); + const fieldPromises = new Map(); + const orphanFields = new RefSetCache(); + for (const fieldRef of acroForm.get("Fields")) { + await this.#collectFieldObjects("", null, fieldRef, fieldPromises, annotationGlobals, visitedRefs, orphanFields); + } + const allPromises = []; + for (const [name, promises] of fieldPromises) { + allPromises.push(Promise.all(promises).then(fields => { + fields = fields.filter(field => !!field); + if (fields.length > 0) { + allFields[name] = fields; + } + })); + } + await Promise.all(allPromises); + return { + allFields: objectSize(allFields) > 0 ? allFields : null, + orphanFields + }; + }); + return shadow(this, "fieldObjects", promise); + } + get hasJSActions() { + const promise = this.pdfManager.ensureDoc("_parseHasJSActions"); + return shadow(this, "hasJSActions", promise); + } + async _parseHasJSActions() { + const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]); + if (catalogJsActions) { + return true; + } + if (fieldObjects?.allFields) { + return Object.values(fieldObjects.allFields).some(fieldObject => fieldObject.some(object => object.actions !== null)); + } + return false; + } + get calculationOrderIds() { + const calculationOrder = this.catalog.acroForm?.get("CO"); + if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) { + return shadow(this, "calculationOrderIds", null); + } + const ids = []; + for (const id of calculationOrder) { + if (id instanceof Ref) { + ids.push(id.toString()); + } + } + return shadow(this, "calculationOrderIds", ids.length ? ids : null); + } + get annotationGlobals() { + return shadow(this, "annotationGlobals", AnnotationFactory.createGlobals(this.pdfManager)); + } +} + +;// ./src/core/pdf_manager.js + + + + + + + + + + +function parseDocBaseUrl(url) { + if (url) { + const absoluteUrl = createValidAbsoluteUrl(url); + if (absoluteUrl) { + return absoluteUrl.href; + } + warn(`Invalid absolute docBaseUrl: "${url}".`); + } + return null; +} +class BasePdfManager { + constructor({ + docBaseUrl, + docId, + enableXfa, + evaluatorOptions, + handler, + password + }) { + this._docBaseUrl = parseDocBaseUrl(docBaseUrl); + this._docId = docId; + this._password = password; + this.enableXfa = enableXfa; + evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest.isOffscreenCanvasSupported; + evaluatorOptions.isImageDecoderSupported &&= FeatureTest.isImageDecoderSupported; + this.evaluatorOptions = Object.freeze(evaluatorOptions); + ImageResizer.setOptions(evaluatorOptions); + JpegStream.setOptions(evaluatorOptions); + OperatorList.setOptions(evaluatorOptions); + const options = { + ...evaluatorOptions, + handler + }; + JpxImage.setOptions(options); + IccColorSpace.setOptions(options); + CmykICCBasedCS.setOptions(options); + } + get docId() { + return this._docId; + } + get password() { + return this._password; + } + get docBaseUrl() { + return this._docBaseUrl; + } + ensureDoc(prop, args) { + return this.ensure(this.pdfDocument, prop, args); + } + ensureXRef(prop, args) { + return this.ensure(this.pdfDocument.xref, prop, args); + } + ensureCatalog(prop, args) { + return this.ensure(this.pdfDocument.catalog, prop, args); + } + getPage(pageIndex) { + return this.pdfDocument.getPage(pageIndex); + } + fontFallback(id, handler) { + return this.pdfDocument.fontFallback(id, handler); + } + cleanup(manuallyTriggered = false) { + return this.pdfDocument.cleanup(manuallyTriggered); + } + async ensure(obj, prop, args) { + unreachable("Abstract method `ensure` called"); + } + requestRange(begin, end) { + unreachable("Abstract method `requestRange` called"); + } + requestLoadedStream(noFetch = false) { + unreachable("Abstract method `requestLoadedStream` called"); + } + sendProgressiveData(chunk) { + unreachable("Abstract method `sendProgressiveData` called"); + } + updatePassword(password) { + this._password = password; + } + terminate(reason) { + unreachable("Abstract method `terminate` called"); + } +} +class LocalPdfManager extends BasePdfManager { + constructor(args) { + super(args); + const stream = new Stream(args.source); + this.pdfDocument = new PDFDocument(this, stream); + this._loadedStreamPromise = Promise.resolve(stream); + } + async ensure(obj, prop, args) { + const value = obj[prop]; + if (typeof value === "function") { + return value.apply(obj, args); + } + return value; + } + requestRange(begin, end) { + return Promise.resolve(); + } + requestLoadedStream(noFetch = false) { + return this._loadedStreamPromise; + } + terminate(reason) {} +} +class NetworkPdfManager extends BasePdfManager { + constructor(args) { + super(args); + this.streamManager = new ChunkedStreamManager(args.source, { + msgHandler: args.handler, + length: args.length, + disableAutoFetch: args.disableAutoFetch, + rangeChunkSize: args.rangeChunkSize + }); + this.pdfDocument = new PDFDocument(this, this.streamManager.getStream()); + } + async ensure(obj, prop, args) { + try { + const value = obj[prop]; + if (typeof value === "function") { + return value.apply(obj, args); + } + return value; + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + throw ex; + } + await this.requestRange(ex.begin, ex.end); + return this.ensure(obj, prop, args); + } + } + requestRange(begin, end) { + return this.streamManager.requestRange(begin, end); + } + requestLoadedStream(noFetch = false) { + return this.streamManager.requestAllChunks(noFetch); + } + sendProgressiveData(chunk) { + this.streamManager.onReceiveData({ + chunk + }); + } + terminate(reason) { + this.streamManager.abort(reason); + } +} + +;// ./src/shared/message_handler.js + +const CallbackKind = { + DATA: 1, + ERROR: 2 +}; +const StreamKind = { + CANCEL: 1, + CANCEL_COMPLETE: 2, + CLOSE: 3, + ENQUEUE: 4, + ERROR: 5, + PULL: 6, + PULL_COMPLETE: 7, + START_COMPLETE: 8 +}; +function onFn() {} +function wrapReason(ex) { + if (ex instanceof AbortException || ex instanceof InvalidPDFException || ex instanceof PasswordException || ex instanceof ResponseException || ex instanceof UnknownErrorException) { + return ex; + } + if (!(ex instanceof Error || typeof ex === "object" && ex !== null)) { + unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); + } + switch (ex.name) { + case "AbortException": + return new AbortException(ex.message); + case "InvalidPDFException": + return new InvalidPDFException(ex.message); + case "PasswordException": + return new PasswordException(ex.message, ex.code); + case "ResponseException": + return new ResponseException(ex.message, ex.status, ex.missing); + case "UnknownErrorException": + return new UnknownErrorException(ex.message, ex.details); + } + return new UnknownErrorException(ex.message, ex.toString()); +} +class MessageHandler { + #messageAC = new AbortController(); + constructor(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackId = 1; + this.streamId = 1; + this.streamSinks = Object.create(null); + this.streamControllers = Object.create(null); + this.callbackCapabilities = Object.create(null); + this.actionHandler = Object.create(null); + comObj.addEventListener("message", this.#onMessage.bind(this), { + signal: this.#messageAC.signal + }); + } + #onMessage({ + data + }) { + if (data.targetName !== this.sourceName) { + return; + } + if (data.stream) { + this.#processStreamMessage(data); + return; + } + if (data.callback) { + const callbackId = data.callbackId; + const capability = this.callbackCapabilities[callbackId]; + if (!capability) { + throw new Error(`Cannot resolve callback ${callbackId}`); + } + delete this.callbackCapabilities[callbackId]; + if (data.callback === CallbackKind.DATA) { + capability.resolve(data.data); + } else if (data.callback === CallbackKind.ERROR) { + capability.reject(wrapReason(data.reason)); + } else { + throw new Error("Unexpected callback case"); + } + return; + } + const action = this.actionHandler[data.action]; + if (!action) { + throw new Error(`Unknown action from worker: ${data.action}`); + } + if (data.callbackId) { + const sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + Promise.try(action, data.data).then(function (result) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.DATA, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.ERROR, + callbackId: data.callbackId, + reason: wrapReason(reason) + }); + }); + return; + } + if (data.streamId) { + this.#createStreamSink(data); + return; + } + action(data.data); + } + on(actionName, handler) { + const ah = this.actionHandler; + if (ah[actionName]) { + throw new Error(`There is already an actionName called "${actionName}"`); + } + ah[actionName] = handler; + } + send(actionName, data, transfers) { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data + }, transfers); + } + sendWithPromise(actionName, data, transfers) { + const callbackId = this.callbackId++; + const capability = Promise.withResolvers(); + this.callbackCapabilities[callbackId] = capability; + try { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + callbackId, + data + }, transfers); + } catch (ex) { + capability.reject(ex); + } + return capability.promise; + } + sendWithStream(actionName, data, queueingStrategy, transfers) { + const streamId = this.streamId++, + sourceName = this.sourceName, + targetName = this.targetName, + comObj = this.comObj; + return new ReadableStream({ + start: controller => { + const startCapability = Promise.withResolvers(); + this.streamControllers[streamId] = { + controller, + startCall: startCapability, + pullCall: null, + cancelCall: null, + isClosed: false + }; + comObj.postMessage({ + sourceName, + targetName, + action: actionName, + streamId, + data, + desiredSize: controller.desiredSize + }, transfers); + return startCapability.promise; + }, + pull: controller => { + const pullCapability = Promise.withResolvers(); + this.streamControllers[streamId].pullCall = pullCapability; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL, + streamId, + desiredSize: controller.desiredSize + }); + return pullCapability.promise; + }, + cancel: reason => { + assert(reason instanceof Error, "cancel must have a valid reason"); + const cancelCapability = Promise.withResolvers(); + this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL, + streamId, + reason: wrapReason(reason) + }); + return cancelCapability.promise; + } + }, queueingStrategy); + } + #createStreamSink(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const self = this, + action = this.actionHandler[data.action]; + const streamSink = { + enqueue(chunk, size = 1, transfers) { + if (this.isCancelled) { + return; + } + const lastDesiredSize = this.desiredSize; + this.desiredSize -= size; + if (lastDesiredSize > 0 && this.desiredSize <= 0) { + this.sinkCapability = Promise.withResolvers(); + this.ready = this.sinkCapability.promise; + } + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ENQUEUE, + streamId, + chunk + }, transfers); + }, + close() { + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CLOSE, + streamId + }); + delete self.streamSinks[streamId]; + }, + error(reason) { + assert(reason instanceof Error, "error must have a valid reason"); + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ERROR, + streamId, + reason: wrapReason(reason) + }); + }, + sinkCapability: Promise.withResolvers(), + onPull: null, + onCancel: null, + isCancelled: false, + desiredSize: data.desiredSize, + ready: null + }; + streamSink.sinkCapability.resolve(); + streamSink.ready = streamSink.sinkCapability.promise; + this.streamSinks[streamId] = streamSink; + Promise.try(action, data.data, streamSink).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + } + #processStreamMessage(data) { + const streamId = data.streamId, + sourceName = this.sourceName, + targetName = data.sourceName, + comObj = this.comObj; + const streamController = this.streamControllers[streamId], + streamSink = this.streamSinks[streamId]; + switch (data.stream) { + case StreamKind.START_COMPLETE: + if (data.success) { + streamController.startCall.resolve(); + } else { + streamController.startCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL_COMPLETE: + if (data.success) { + streamController.pullCall.resolve(); + } else { + streamController.pullCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL: + if (!streamSink) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + break; + } + if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { + streamSink.sinkCapability.resolve(); + } + streamSink.desiredSize = data.desiredSize; + Promise.try(streamSink.onPull || onFn).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + break; + case StreamKind.ENQUEUE: + assert(streamController, "enqueue should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.controller.enqueue(data.chunk); + break; + case StreamKind.CLOSE: + assert(streamController, "close should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.isClosed = true; + streamController.controller.close(); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.ERROR: + assert(streamController, "error should have stream controller"); + streamController.controller.error(wrapReason(data.reason)); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL_COMPLETE: + if (data.success) { + streamController.cancelCall.resolve(); + } else { + streamController.cancelCall.reject(wrapReason(data.reason)); + } + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL: + if (!streamSink) { + break; + } + const dataReason = wrapReason(data.reason); + Promise.try(streamSink.onCancel || onFn, dataReason).then(function () { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + success: true + }); + }, function (reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + streamSink.sinkCapability.reject(dataReason); + streamSink.isCancelled = true; + delete this.streamSinks[streamId]; + break; + default: + throw new Error("Unexpected stream case"); + } + } + async #deleteStreamController(streamController, streamId) { + await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]); + delete this.streamControllers[streamId]; + } + destroy() { + this.#messageAC?.abort(); + this.#messageAC = null; + } +} + +;// ./src/core/writer.js + + + + + + + +async function writeObject(ref, obj, buffer, { + encrypt = null, + encryptRef = null +}) { + const transform = encrypt && encryptRef !== ref ? encrypt.createCipherTransform(ref.num, ref.gen) : null; + buffer.push(`${ref.num} ${ref.gen} obj\n`); + await writeValue(obj, buffer, transform); + buffer.push("\nendobj\n"); +} +async function writeDict(dict, buffer, transform) { + buffer.push("<<"); + for (const [key, rawObj] of dict.getRawEntries()) { + buffer.push(` /${escapePDFName(key)} `); + await writeValue(rawObj, buffer, transform); + } + buffer.push(">>"); +} +async function writeStream(stream, buffer, transform) { + stream = stream.getOriginalStream(); + stream.reset(); + let bytes = stream.getBytes(); + const { + dict + } = stream; + const [filter, params] = await Promise.all([dict.getAsync("Filter"), dict.getAsync("DecodeParms")]); + const filterZero = Array.isArray(filter) ? await dict.xref.fetchIfRefAsync(filter[0]) : filter; + const isFilterZeroFlateDecode = isName(filterZero, "FlateDecode"); + const MIN_LENGTH_FOR_COMPRESSING = 256; + if (bytes.length >= MIN_LENGTH_FOR_COMPRESSING && !isFilterZeroFlateDecode) { + try { + const cs = new CompressionStream("deflate"); + const writer = cs.writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => {}); + const buf = await new Response(cs.readable).arrayBuffer(); + bytes = new Uint8Array(buf); + let newFilter, newParams; + if (!filter) { + newFilter = Name.get("FlateDecode"); + } else if (!isFilterZeroFlateDecode) { + newFilter = Array.isArray(filter) ? [Name.get("FlateDecode"), ...filter] : [Name.get("FlateDecode"), filter]; + if (params) { + newParams = Array.isArray(params) ? [null, ...params] : [null, params]; + } + } + if (newFilter) { + dict.set("Filter", newFilter); + } + if (newParams) { + dict.set("DecodeParms", newParams); + } + } catch (ex) { + info(`writeStream - cannot compress data: "${ex}".`); + } + } + let string = bytesToString(bytes); + if (transform) { + string = transform.encryptString(string); + } + dict.set("Length", string.length); + await writeDict(dict, buffer, transform); + buffer.push(" stream\n", string, "\nendstream"); +} +async function writeArray(array, buffer, transform) { + buffer.push("["); + for (let i = 0, ii = array.length; i < ii; i++) { + await writeValue(array[i], buffer, transform); + if (i < ii - 1) { + buffer.push(" "); + } + } + buffer.push("]"); +} +async function writeValue(value, buffer, transform) { + if (value instanceof Name) { + buffer.push(`/${escapePDFName(value.name)}`); + } else if (value instanceof Ref) { + buffer.push(`${value.num} ${value.gen} R`); + } else if (Array.isArray(value) || ArrayBuffer.isView(value)) { + await writeArray(value, buffer, transform); + } else if (typeof value === "string") { + if (transform) { + value = transform.encryptString(value); + } + buffer.push(`(${escapeString(value)})`); + } else if (typeof value === "number") { + buffer.push(value.toString()); + } else if (typeof value === "boolean") { + buffer.push(value.toString()); + } else if (value instanceof Dict) { + await writeDict(value, buffer, transform); + } else if (value instanceof BaseStream) { + await writeStream(value, buffer, transform); + } else if (value === null) { + buffer.push("null"); + } else { + warn(`Unhandled value in writer: ${typeof value}, please file a bug.`); + } +} +function writeInt(number, size, offset, buffer) { + for (let i = size + offset - 1; i > offset - 1; i--) { + buffer[i] = number & 0xff; + number >>= 8; + } + return offset + size; +} +function writeString(string, offset, buffer) { + const ii = string.length; + for (let i = 0; i < ii; i++) { + buffer[offset + i] = string.charCodeAt(i) & 0xff; + } + return offset + ii; +} +function computeMD5(filesize, xrefInfo) { + const time = Math.floor(Date.now() / 1000); + const filename = xrefInfo.filename || ""; + const md5Buffer = [time.toString(), filename, filesize.toString(), ...xrefInfo.infoMap.values()]; + const md5BufferLen = Math.sumPrecise(md5Buffer.map(str => str.length)); + const array = new Uint8Array(md5BufferLen); + let offset = 0; + for (const str of md5Buffer) { + offset = writeString(str, offset, array); + } + return bytesToString(calculateMD5(array, 0, array.length)); +} +function writeXFADataForAcroform(str, changes) { + const xml = new SimpleXMLParser({ + hasAttributes: true + }).parseFromString(str); + for (const { + xfa + } of changes) { + if (!xfa) { + continue; + } + const { + path, + value + } = xfa; + if (!path) { + continue; + } + const nodePath = parseXFAPath(path); + let node = xml.documentElement.searchNode(nodePath, 0); + if (!node && nodePath.length > 1) { + node = xml.documentElement.searchNode([nodePath.at(-1)], 0); + } + if (node) { + node.childNodes = Array.isArray(value) ? value.map(val => new SimpleDOMNode("value", val)) : [new SimpleDOMNode("#text", value)]; + } else { + warn(`Node not found for path: ${path}`); + } + } + const buffer = []; + xml.documentElement.dump(buffer); + return buffer.join(""); +} +async function updateAcroform({ + xref, + acroForm, + acroFormRef, + hasXfa, + hasXfaDatasetsEntry, + xfaDatasetsRef, + needAppearances, + changes +}) { + if (hasXfa && !hasXfaDatasetsEntry && !xfaDatasetsRef) { + warn("XFA - Cannot save it"); + } + if (!needAppearances && (!hasXfa || !xfaDatasetsRef || hasXfaDatasetsEntry)) { + return; + } + const dict = acroForm.clone(); + if (hasXfa && !hasXfaDatasetsEntry) { + const newXfa = acroForm.get("XFA").slice(); + newXfa.splice(2, 0, "datasets"); + newXfa.splice(3, 0, xfaDatasetsRef); + dict.set("XFA", newXfa); + } + if (needAppearances) { + dict.set("NeedAppearances", true); + } + changes.put(acroFormRef, { + data: dict + }); +} +function updateXFA({ + xfaData, + xfaDatasetsRef, + changes, + xref +}) { + if (xfaData === null) { + const datasets = xref.fetchIfRef(xfaDatasetsRef); + xfaData = writeXFADataForAcroform(datasets.getString(), changes); + } + const xfaDataStream = new StringStream(xfaData); + xfaDataStream.dict = new Dict(xref); + xfaDataStream.dict.setIfName("Type", "EmbeddedFile"); + changes.put(xfaDatasetsRef, { + data: xfaDataStream + }); +} +async function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer) { + buffer.push("xref\n"); + const indexes = getIndexes(newRefs); + let indexesPosition = 0; + for (const { + ref, + data + } of newRefs) { + if (ref.num === indexes[indexesPosition]) { + buffer.push(`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]}\n`); + indexesPosition += 2; + } + if (data !== null) { + buffer.push(`${baseOffset.toString().padStart(10, "0")} ${Math.min(ref.gen, 0xffff).toString().padStart(5, "0")} n\r\n`); + baseOffset += data.length; + } else { + buffer.push(`0000000000 ${Math.min(ref.gen + 1, 0xffff).toString().padStart(5, "0")} f\r\n`); + } + } + computeIDs(baseOffset, xrefInfo, newXref); + buffer.push("trailer\n"); + await writeDict(newXref, buffer, null); + buffer.push("\nstartxref\n", baseOffset.toString(), "\n%%EOF\n"); +} +function getIndexes(newRefs) { + const indexes = []; + for (const { + ref + } of newRefs) { + if (ref.num === indexes.at(-2) + indexes.at(-1)) { + indexes[indexes.length - 1] += 1; + } else { + indexes.push(ref.num, 1); + } + } + return indexes; +} +async function getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) { + const xrefTableData = []; + let maxOffset = 0; + let maxGen = 0; + for (const { + ref, + data, + objStreamRef, + index + } of newRefs) { + let gen; + maxOffset = Math.max(maxOffset, baseOffset); + if (objStreamRef) { + gen = index; + xrefTableData.push([2, objStreamRef.num, gen]); + } else if (data !== null) { + gen = Math.min(ref.gen, 0xffff); + xrefTableData.push([1, baseOffset, gen]); + baseOffset += data.length; + } else { + gen = Math.min(ref.gen + 1, 0xffff); + xrefTableData.push([0, 0, gen]); + } + maxGen = Math.max(maxGen, gen); + } + newXref.set("Index", getIndexes(newRefs)); + const offsetSize = getSizeInBytes(maxOffset); + const maxGenSize = getSizeInBytes(maxGen); + const sizes = [1, offsetSize, maxGenSize]; + newXref.set("W", sizes); + computeIDs(baseOffset, xrefInfo, newXref); + const structSize = Math.sumPrecise(sizes); + const data = new Uint8Array(structSize * xrefTableData.length); + const stream = new Stream(data); + stream.dict = newXref; + let offset = 0; + for (const [type, objOffset, gen] of xrefTableData) { + offset = writeInt(type, sizes[0], offset, data); + offset = writeInt(objOffset, sizes[1], offset, data); + offset = writeInt(gen, sizes[2], offset, data); + } + await writeObject(xrefInfo.newRef, stream, buffer, {}); + buffer.push("startxref\n", baseOffset.toString(), "\n%%EOF\n"); +} +function computeIDs(baseOffset, xrefInfo, newXref) { + if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) { + const md5 = computeMD5(baseOffset, xrefInfo); + newXref.set("ID", [xrefInfo.fileIds[0] || md5, md5]); + } +} +function getTrailerDict(xrefInfo, changes, useXrefStream) { + const newXref = new Dict(null); + newXref.setIfDefined("Prev", xrefInfo?.startXRef); + const refForXrefTable = xrefInfo.newRef; + if (useXrefStream) { + changes.put(refForXrefTable, { + data: "" + }); + newXref.set("Size", refForXrefTable.num + 1); + newXref.setIfName("Type", "XRef"); + } else { + newXref.set("Size", refForXrefTable.num); + } + newXref.setIfDefined("Root", xrefInfo?.rootRef); + newXref.setIfDefined("Info", xrefInfo?.infoRef); + newXref.setIfDefined("Encrypt", xrefInfo?.encryptRef); + return newXref; +} +async function writeChanges(changes, xref, buffer = []) { + const newRefs = []; + for (const [ref, { + data, + objStreamRef, + index + }] of changes.items()) { + if (objStreamRef) { + newRefs.push({ + ref, + data, + objStreamRef, + index + }); + continue; + } + if (data === null || typeof data === "string") { + newRefs.push({ + ref, + data + }); + continue; + } + await writeObject(ref, data, buffer, xref); + newRefs.push({ + ref, + data: buffer.join("") + }); + buffer.length = 0; + } + return newRefs.sort((a, b) => a.ref.num - b.ref.num); +} +async function incrementalUpdate({ + originalData, + xrefInfo, + changes, + xref = null, + hasXfa = false, + xfaDatasetsRef = null, + hasXfaDatasetsEntry = false, + needAppearances, + acroFormRef = null, + acroForm = null, + xfaData = null, + useXrefStream = false +}) { + await updateAcroform({ + xref, + acroForm, + acroFormRef, + hasXfa, + hasXfaDatasetsEntry, + xfaDatasetsRef, + needAppearances, + changes + }); + if (hasXfa) { + updateXFA({ + xfaData, + xfaDatasetsRef, + changes, + xref + }); + } + const newXref = getTrailerDict(xrefInfo, changes, useXrefStream); + const buffer = []; + const newRefs = await writeChanges(changes, xref, buffer); + let baseOffset = originalData.length; + const lastByte = originalData.at(-1); + if (lastByte !== 0x0a && lastByte !== 0x0d) { + buffer.push("\n"); + baseOffset += 1; + } + for (const { + data + } of newRefs) { + if (data !== null) { + buffer.push(data); + } + } + await (useXrefStream ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer)); + const totalLength = originalData.length + Math.sumPrecise(buffer.map(str => str.length)); + const array = new Uint8Array(totalLength); + array.set(originalData); + let offset = originalData.length; + for (const str of buffer) { + offset = writeString(str, offset, array); + } + return array; +} + +;// ./src/core/editor/pdf_editor.js + + + + + + + +const MAX_LEAVES_PER_PAGES_NODE = 16; +const MAX_IN_NAME_TREE_NODE = 64; +class PageData { + constructor(page, documentData) { + this.page = page; + this.documentData = documentData; + this.annotations = null; + this.pointingNamedDestinations = null; + documentData.pagesMap.put(page.ref, this); + } +} +class DocumentData { + constructor(document) { + this.document = document; + this.destinations = null; + this.pageLabels = null; + this.pagesMap = new RefSetCache(); + this.oldRefMapping = new RefSetCache(); + this.dedupNamedDestinations = new Map(); + this.usedNamedDestinations = new Set(); + this.postponedRefCopies = new RefSetCache(); + this.usedStructParents = new Set(); + this.oldStructParentMapping = new Map(); + this.structTreeRoot = null; + this.parentTree = null; + this.idTree = null; + this.roleMap = null; + this.classMap = null; + this.namespaces = null; + this.structTreeAF = null; + this.structTreePronunciationLexicon = []; + } +} +class XRefWrapper { + constructor(entries) { + this.entries = entries; + } + fetch(ref) { + return ref instanceof Ref ? this.entries[ref.num] : ref; + } +} +class PDFEditor { + constructor({ + useObjectStreams = true, + title = "", + author = "" + } = {}) { + this.hasSingleFile = false; + this.currentDocument = null; + this.oldPages = []; + this.newPages = []; + this.xref = [null]; + this.xrefWrapper = new XRefWrapper(this.xref); + this.newRefCount = 1; + [this.rootRef, this.rootDict] = this.newDict; + [this.infoRef, this.infoDict] = this.newDict; + [this.pagesRef, this.pagesDict] = this.newDict; + this.namesDict = null; + this.useObjectStreams = useObjectStreams; + this.objStreamRefs = useObjectStreams ? new Set() : null; + this.version = "1.7"; + this.title = title; + this.author = author; + this.pageLabels = null; + this.namedDestinations = new Map(); + this.parentTree = new Map(); + this.structTreeKids = []; + this.idTree = new Map(); + this.classMap = new Dict(); + this.roleMap = new Dict(); + this.namespaces = new Map(); + this.structTreeAF = []; + this.structTreePronunciationLexicon = []; + } + get newRef() { + const ref = Ref.get(this.newRefCount++, 0); + return ref; + } + get newDict() { + const ref = this.newRef; + const dict = this.xref[ref.num] = new Dict(); + return [ref, dict]; + } + async #cloneObject(obj, xref) { + const ref = this.newRef; + this.xref[ref.num] = await this.#collectDependencies(obj, true, xref); + return ref; + } + cloneDict(dict) { + const newDict = dict.clone(); + newDict.xref = this.xrefWrapper; + return newDict; + } + async #collectDependencies(obj, mustClone, xref) { + if (obj instanceof Ref) { + const { + currentDocument: { + oldRefMapping + } + } = this; + let newRef = oldRefMapping.get(obj); + if (newRef) { + return newRef; + } + const oldRef = obj; + obj = await xref.fetchAsync(oldRef); + if (typeof obj === "number") { + return obj; + } + newRef = this.newRef; + oldRefMapping.put(oldRef, newRef); + this.xref[newRef.num] = await this.#collectDependencies(obj, true, xref); + return newRef; + } + const promises = []; + const { + currentDocument: { + postponedRefCopies + } + } = this; + if (Array.isArray(obj)) { + if (mustClone) { + obj = obj.slice(); + } + for (let i = 0, ii = obj.length; i < ii; i++) { + const postponedActions = postponedRefCopies.get(obj[i]); + if (postponedActions) { + postponedActions.push(ref => obj[i] = ref); + continue; + } + promises.push(this.#collectDependencies(obj[i], true, xref).then(newObj => obj[i] = newObj)); + } + await Promise.all(promises); + return obj; + } + let dict; + if (obj instanceof BaseStream) { + ({ + dict + } = obj = obj.getOriginalStream().clone()); + dict.xref = this.xrefWrapper; + } else if (obj instanceof Dict) { + if (mustClone) { + obj = obj.clone(); + obj.xref = this.xrefWrapper; + } + dict = obj; + } + if (dict) { + for (const [key, rawObj] of dict.getRawEntries()) { + const postponedActions = postponedRefCopies.get(rawObj); + if (postponedActions) { + postponedActions.push(ref => dict.set(key, ref)); + continue; + } + promises.push(this.#collectDependencies(rawObj, true, xref).then(newObj => dict.set(key, newObj))); + } + await Promise.all(promises); + } + return obj; + } + async #cloneStructTreeNode(parentStructRef, node, xref, removedStructElements, dedupIDs, dedupClasses, dedupRoles, visited = new RefSet()) { + const { + currentDocument: { + pagesMap, + oldRefMapping + } + } = this; + const pg = node.getRaw("Pg"); + if (pg instanceof Ref && !pagesMap.has(pg)) { + return null; + } + let kids; + const k = kids = node.getRaw("K"); + if (k instanceof Ref) { + if (visited.has(k)) { + return null; + } + kids = await xref.fetchAsync(k); + if (!Array.isArray(kids)) { + kids = [k]; + } + } + kids = Array.isArray(kids) ? kids : [kids]; + const newKids = []; + const structElemIndices = []; + for (let kid of kids) { + const kidRef = kid instanceof Ref ? kid : null; + if (kidRef) { + if (visited.has(kidRef)) { + continue; + } + visited.put(kidRef); + kid = await xref.fetchAsync(kidRef); + } + if (typeof kid === "number") { + newKids.push(kid); + continue; + } + if (!(kid instanceof Dict)) { + continue; + } + const pgRef = kid.getRaw("Pg"); + if (pgRef instanceof Ref && !pagesMap.has(pgRef)) { + continue; + } + const type = kid.get("Type"); + if (!type || isName(type, "StructElem")) { + let setAsSpan = false; + if (kidRef && removedStructElements.has(kidRef)) { + if (!isName(kid.get("S"), "Link")) { + continue; + } + setAsSpan = true; + } + const newKidRef = await this.#cloneStructTreeNode(kidRef, kid, xref, removedStructElements, dedupIDs, dedupClasses, dedupRoles, visited); + if (newKidRef) { + structElemIndices.push(newKids.length); + newKids.push(newKidRef); + if (kidRef) { + oldRefMapping.put(kidRef, newKidRef); + } + if (setAsSpan) { + this.xref[newKidRef.num].setIfName("S", "Span"); + } + } + continue; + } + if (isName(type, "OBJR")) { + if (!kidRef) { + continue; + } + const newKidRef = oldRefMapping.get(kidRef); + if (!newKidRef) { + continue; + } + const newKid = this.xref[newKidRef.num]; + const objRef = newKid.getRaw("Obj"); + if (objRef instanceof Ref) { + const obj = this.xref[objRef.num]; + if (obj instanceof Dict && !obj.has("StructParent") && parentStructRef) { + const structParent = this.parentTree.size; + this.parentTree.set(structParent, [oldRefMapping, parentStructRef]); + obj.set("StructParent", structParent); + } + } + newKids.push(newKidRef); + continue; + } + if (isName(type, "MCR")) { + const newKid = await this.#collectDependencies(kidRef || kid, true, xref); + newKids.push(newKid); + continue; + } + if (kidRef) { + const newKidRef = await this.#collectDependencies(kidRef, true, xref); + newKids.push(newKidRef); + } + } + if (kids.length !== 0 && newKids.length === 0) { + return null; + } + const newNodeRef = this.newRef; + const newNode = this.xref[newNodeRef.num] = this.cloneDict(node); + newNode.delete("ID"); + newNode.delete("C"); + newNode.delete("K"); + newNode.delete("P"); + newNode.delete("S"); + await this.#collectDependencies(newNode, false, xref); + const classNames = node.get("C"); + if (classNames instanceof Name) { + const newClassName = dedupClasses.get(classNames.name); + if (newClassName) { + newNode.set("C", Name.get(newClassName)); + } else { + newNode.set("C", classNames); + } + } else if (Array.isArray(classNames)) { + const newClassNames = []; + for (const className of classNames) { + if (className instanceof Name) { + const newClassName = dedupClasses.get(className.name); + if (newClassName) { + newClassNames.push(Name.get(newClassName)); + } else { + newClassNames.push(className); + } + } + } + newNode.set("C", newClassNames); + } + const roleName = node.get("S"); + if (roleName instanceof Name) { + const newRoleName = dedupRoles.get(roleName.name); + if (newRoleName) { + newNode.set("S", Name.get(newRoleName)); + } else { + newNode.set("S", roleName); + } + } + const id = node.get("ID"); + if (typeof id === "string") { + const stringId = stringToPDFString(id, false); + const newId = dedupIDs.get(stringId); + if (newId) { + newNode.set("ID", stringToAsciiOrUTF16BE(newId)); + } else { + newNode.set("ID", id); + } + } + let attributes = newNode.get("A"); + if (attributes) { + if (!Array.isArray(attributes)) { + attributes = [attributes]; + } + for (let attr of attributes) { + attr = this.xrefWrapper.fetch(attr); + if (isName(attr.get("O"), "Table") && attr.has("Headers")) { + const headers = this.xrefWrapper.fetch(attr.getRaw("Headers")); + if (Array.isArray(headers)) { + for (let i = 0, ii = headers.length; i < ii; i++) { + const newId = dedupIDs.get(stringToPDFString(headers[i], false)); + if (newId) { + headers[i] = newId; + } + } + } + } + } + } + for (const index of structElemIndices) { + const structElemRef = newKids[index]; + const structElem = this.xref[structElemRef.num]; + structElem.set("P", newNodeRef); + } + if (newKids.length === 1) { + newNode.set("K", newKids[0]); + } else if (newKids.length > 1) { + newNode.set("K", newKids); + } + return newNodeRef; + } + async extractPages(pageInfos) { + const promises = []; + let newIndex = 0; + this.hasSingleFile = pageInfos.length === 1; + const allDocumentData = []; + for (const { + document, + includePages, + excludePages + } of pageInfos) { + if (!document) { + continue; + } + const documentData = new DocumentData(document); + allDocumentData.push(documentData); + promises.push(this.#collectDocumentData(documentData)); + let keptIndices, keptRanges, deletedIndices, deletedRanges; + for (const page of includePages || []) { + if (Array.isArray(page)) { + (keptRanges ||= []).push(page); + } else { + (keptIndices ||= new Set()).add(page); + } + } + for (const page of excludePages || []) { + if (Array.isArray(page)) { + (deletedRanges ||= []).push(page); + } else { + (deletedIndices ||= new Set()).add(page); + } + } + for (let i = 0, ii = document.numPages; i < ii; i++) { + if (deletedIndices?.has(i)) { + continue; + } + if (deletedRanges) { + let isDeleted = false; + for (const [start, end] of deletedRanges) { + if (i >= start && i <= end) { + isDeleted = true; + break; + } + } + if (isDeleted) { + continue; + } + } + let takePage = false; + if (keptIndices) { + takePage = keptIndices.has(i); + } + if (!takePage && keptRanges) { + for (const [start, end] of keptRanges) { + if (i >= start && i <= end) { + takePage = true; + break; + } + } + } + if (!takePage && !keptIndices && !keptRanges) { + takePage = true; + } + if (!takePage) { + continue; + } + const newPageIndex = newIndex++; + promises.push(document.getPage(i).then(page => { + this.oldPages[newPageIndex] = new PageData(page, documentData); + })); + } + } + await Promise.all(promises); + promises.length = 0; + this.#collectValidDestinations(allDocumentData); + this.#collectPageLabels(); + for (const page of this.oldPages) { + promises.push(this.#postCollectPageData(page)); + } + await Promise.all(promises); + this.#findDuplicateNamedDestinations(); + this.#setPostponedRefCopies(allDocumentData); + for (let i = 0, ii = this.oldPages.length; i < ii; i++) { + this.newPages[i] = await this.#makePageCopy(i, null); + } + this.#fixPostponedRefCopies(allDocumentData); + await this.#mergeStructTrees(allDocumentData); + return this.writePDF(); + } + async #collectDocumentData(documentData) { + const { + document: { + pdfManager, + xref + } + } = documentData; + await Promise.all([pdfManager.ensureCatalog("destinations").then(destinations => documentData.destinations = destinations), pdfManager.ensureCatalog("rawPageLabels").then(pageLabels => documentData.pageLabels = pageLabels), pdfManager.ensureCatalog("structTreeRoot").then(structTreeRoot => documentData.structTreeRoot = structTreeRoot)]); + const structTreeRoot = documentData.structTreeRoot; + if (structTreeRoot) { + const rootDict = structTreeRoot.dict; + const parentTree = rootDict.get("ParentTree"); + if (parentTree) { + const numberTree = new NumberTree(parentTree, xref); + documentData.parentTree = numberTree.getAll(true); + } + const idTree = rootDict.get("IDTree"); + if (idTree) { + const nameTree = new NameTree(idTree, xref); + documentData.idTree = nameTree.getAll(true); + } + documentData.roleMap = rootDict.get("RoleMap") || null; + documentData.classMap = rootDict.get("ClassMap") || null; + let namespaces = rootDict.get("Namespaces") || null; + if (namespaces && !Array.isArray(namespaces)) { + namespaces = [namespaces]; + } + documentData.namespaces = namespaces; + documentData.structTreeAF = rootDict.get("AF") || null; + documentData.structTreePronunciationLexicon = rootDict.get("PronunciationLexicon") || null; + } + } + async #postCollectPageData(pageData) { + const { + page: { + xref, + annotations + }, + documentData: { + pagesMap, + destinations, + usedNamedDestinations + } + } = pageData; + if (!annotations) { + return; + } + const promises = []; + let newAnnotations = []; + let newIndex = 0; + for (const annotationRef of annotations) { + const newAnnotationIndex = newIndex++; + promises.push(xref.fetchIfRefAsync(annotationRef).then(async annotationDict => { + if (!isName(annotationDict.get("Subtype"), "Link")) { + newAnnotations[newAnnotationIndex] = annotationRef; + return; + } + const action = annotationDict.get("A"); + const dest = action instanceof Dict ? action.get("D") : annotationDict.get("Dest"); + if (!dest || Array.isArray(dest) && (!(dest[0] instanceof Ref) || pagesMap.has(dest[0]))) { + newAnnotations[newAnnotationIndex] = annotationRef; + } else if (typeof dest === "string") { + const destString = stringToPDFString(dest, true); + if (destinations.has(destString)) { + newAnnotations[newAnnotationIndex] = annotationRef; + usedNamedDestinations.add(destString); + } + } + })); + } + await Promise.all(promises); + newAnnotations = newAnnotations.filter(annot => !!annot); + pageData.annotations = newAnnotations.length > 0 ? newAnnotations : null; + } + #setPostponedRefCopies(allDocumentData) { + for (const { + postponedRefCopies, + pagesMap + } of allDocumentData) { + for (const oldPageRef of pagesMap.keys()) { + postponedRefCopies.put(oldPageRef, []); + } + } + } + #fixPostponedRefCopies(allDocumentData) { + for (const { + postponedRefCopies, + oldRefMapping + } of allDocumentData) { + for (const [oldRef, actions] of postponedRefCopies.items()) { + const newRef = oldRefMapping.get(oldRef); + for (const action of actions) { + action(newRef); + } + } + postponedRefCopies.clear(); + } + } + #visitObject(obj, callback, visited = new RefSet()) { + if (obj instanceof Ref) { + if (!visited.has(obj)) { + visited.put(obj); + this.#visitObject(this.xref[obj.num], callback, visited); + } + return; + } + if (Array.isArray(obj)) { + for (const item of obj) { + this.#visitObject(item, callback, visited); + } + return; + } + let dict; + if (obj instanceof BaseStream) { + ({ + dict + } = obj); + } else if (obj instanceof Dict) { + dict = obj; + } + if (dict) { + callback(dict); + for (const value of dict.getRawValues()) { + this.#visitObject(value, callback, visited); + } + } + } + async #mergeStructTrees(allDocumentData) { + let newStructParentId = 0; + const { + parentTree: newParentTree + } = this; + for (let i = 0, ii = this.newPages.length; i < ii; i++) { + const { + documentData: { + parentTree, + oldRefMapping, + oldStructParentMapping, + usedStructParents, + document: { + xref + } + } + } = this.oldPages[i]; + if (!parentTree) { + continue; + } + const pageRef = this.newPages[i]; + const pageDict = this.xref[pageRef.num]; + this.#visitObject(pageDict, dict => { + const structParent = dict.get("StructParent") ?? dict.get("StructParents"); + if (typeof structParent !== "number") { + return; + } + usedStructParents.add(structParent); + let parent = parentTree.get(structParent); + const parentRef = parent instanceof Ref ? parent : null; + if (parentRef) { + const array = xref.fetch(parentRef); + if (Array.isArray(array)) { + parent = array; + } + } + if (Array.isArray(parent) && parent.every(ref => ref === null)) { + parent = null; + } + if (!parent) { + if (dict.has("StructParent")) { + dict.delete("StructParent"); + } else { + dict.delete("StructParents"); + } + return; + } + let newStructParent = oldStructParentMapping.get(structParent); + if (newStructParent === undefined) { + newStructParent = newStructParentId++; + oldStructParentMapping.set(structParent, newStructParent); + newParentTree.set(newStructParent, [oldRefMapping, parent]); + } + if (dict.has("StructParent")) { + dict.set("StructParent", newStructParent); + } else { + dict.set("StructParents", newStructParent); + } + }); + } + const { + structTreeKids, + idTree: newIdTree, + classMap: newClassMap, + roleMap: newRoleMap, + namespaces: newNamespaces, + structTreeAF: newStructTreeAF, + structTreePronunciationLexicon: newStructTreePronunciationLexicon + } = this; + for (const documentData of allDocumentData) { + const { + document: { + xref + }, + oldRefMapping, + parentTree, + usedStructParents, + structTreeRoot, + idTree, + classMap, + roleMap, + namespaces, + structTreeAF, + structTreePronunciationLexicon + } = documentData; + if (!structTreeRoot) { + continue; + } + this.currentDocument = documentData; + const removedStructElements = new RefSet(); + for (const [key, value] of parentTree || []) { + if (!usedStructParents.has(key) && value instanceof Ref) { + removedStructElements.put(value); + } + } + const dedupIDs = new Map(); + for (const [id, nodeRef] of idTree || []) { + let _id = id; + if (newIdTree.has(id)) { + for (let i = 1;; i++) { + const newId = `${id}_${i}`; + if (!newIdTree.has(newId)) { + dedupIDs.set(id, newId); + _id = newId; + break; + } + } + } + newIdTree.set(_id, nodeRef); + } + const dedupClasses = new Map(); + if (classMap?.size > 0) { + for (let [className, classDict] of classMap) { + classDict = await this.#collectDependencies(classDict, true, xref); + if (newClassMap.has(className)) { + for (let i = 1;; i++) { + const newClassName = `${className}_${i}`; + if (!newClassMap.has(newClassName)) { + dedupClasses.set(className, newClassName); + className = newClassName; + break; + } + } + } + newClassMap.set(className, classDict); + } + } + const dedupRoles = new Map(); + if (roleMap?.size > 0) { + for (const [roleName, mappedName] of roleMap) { + const newMappedName = newRoleMap.get(roleName); + if (!newMappedName) { + newRoleMap.set(roleName, mappedName); + continue; + } + if (newMappedName === mappedName) { + continue; + } + for (let i = 1;; i++) { + const newRoleName = `${roleName}_${i}`; + if (!newRoleMap.has(newRoleName)) { + dedupRoles.set(roleName, newRoleName); + newRoleMap.set(newRoleName, mappedName); + break; + } + } + } + } + if (namespaces?.length > 0) { + for (const namespaceRef of namespaces) { + const namespace = await xref.fetchIfRefAsync(namespaceRef); + let ns = namespace.get("NS"); + if (!ns || newNamespaces.has(ns)) { + continue; + } + ns = stringToPDFString(ns, false); + const newNamespace = await this.#collectDependencies(namespace, true, xref); + newNamespaces.set(ns, newNamespace); + } + } + if (structTreeAF) { + for (const afRef of structTreeAF) { + newStructTreeAF.push(await this.#collectDependencies(afRef, true, xref)); + } + } + if (structTreePronunciationLexicon) { + for (const lexiconRef of structTreePronunciationLexicon) { + newStructTreePronunciationLexicon.push(await this.#collectDependencies(lexiconRef, true, xref)); + } + } + let kids = structTreeRoot.dict.get("K"); + if (!kids) { + continue; + } + kids = Array.isArray(kids) ? kids : [kids]; + for (let kid of kids) { + const kidRef = kid instanceof Ref ? kid : null; + if (kidRef && removedStructElements.has(kidRef)) { + continue; + } + kid = await xref.fetchIfRefAsync(kid); + const newKidRef = await this.#cloneStructTreeNode(kidRef, kid, xref, removedStructElements, dedupIDs, dedupClasses, dedupRoles); + if (newKidRef) { + structTreeKids.push(newKidRef); + } + } + for (const [id, nodeRef] of idTree || []) { + const newNodeRef = oldRefMapping.get(nodeRef); + const newId = dedupIDs.get(id) || id; + if (newNodeRef) { + newIdTree.set(newId, newNodeRef); + } else { + newIdTree.delete(newId); + } + } + } + for (const [key, [oldRefMapping, parent]] of newParentTree) { + if (!parent) { + newParentTree.delete(key); + continue; + } + if (!Array.isArray(parent)) { + const newParent = oldRefMapping.get(parent); + if (newParent === undefined) { + newParentTree.delete(key); + } else { + newParentTree.set(key, newParent); + } + continue; + } + const newParents = parent.map(ref => ref instanceof Ref && oldRefMapping.get(ref) || null); + if (newParents.length === 0 || newParents.every(ref => ref === null)) { + newParentTree.delete(key); + continue; + } + newParentTree.set(key, newParents); + } + this.currentDocument = null; + } + #collectValidDestinations(allDocumentData) { + for (const documentData of allDocumentData) { + if (!documentData.destinations) { + continue; + } + const { + destinations, + pagesMap + } = documentData; + const newDestinations = documentData.destinations = new Map(); + for (const [key, dest] of Object.entries(destinations)) { + const pageRef = dest[0]; + const pageData = pagesMap.get(pageRef); + if (!pageData) { + continue; + } + (pageData.pointingNamedDestinations ||= new Set()).add(key); + newDestinations.set(key, dest); + } + } + } + #findDuplicateNamedDestinations() { + const { + namedDestinations + } = this; + for (let i = 0, ii = this.oldPages.length; i < ii; i++) { + const page = this.oldPages[i]; + const { + documentData: { + destinations, + dedupNamedDestinations, + usedNamedDestinations + } + } = page; + let { + pointingNamedDestinations + } = page; + if (!pointingNamedDestinations) { + continue; + } + page.pointingNamedDestinations = pointingNamedDestinations = pointingNamedDestinations.intersection(usedNamedDestinations); + for (const pointingDest of pointingNamedDestinations) { + if (!usedNamedDestinations.has(pointingDest)) { + continue; + } + const dest = destinations.get(pointingDest).slice(); + if (!namedDestinations.has(pointingDest)) { + namedDestinations.set(pointingDest, dest); + continue; + } + const newName = `${pointingDest}_p${i + 1}`; + dedupNamedDestinations.set(pointingDest, newName); + namedDestinations.set(newName, dest); + } + } + } + #fixNamedDestinations(annotations, dedupNamedDestinations) { + if (dedupNamedDestinations.size === 0) { + return; + } + const fixDestination = (dict, key, dest) => { + if (typeof dest === "string") { + dict.set(key, dedupNamedDestinations.get(stringToPDFString(dest, true)) || dest); + } + }; + for (const annotRef of annotations) { + const annotDict = this.xref[annotRef.num]; + if (!isName(annotDict.get("Subtype"), "Link")) { + continue; + } + const action = annotDict.get("A"); + if (action instanceof Dict && action.has("D")) { + const dest = action.get("D"); + fixDestination(action, "D", dest); + continue; + } + const dest = annotDict.get("Dest"); + fixDestination(annotDict, "Dest", dest); + } + } + async #collectPageLabels() { + if (!this.hasSingleFile) { + return; + } + const { + documentData: { + document, + pageLabels + } + } = this.oldPages[0]; + if (!pageLabels) { + return; + } + const numPages = document.numPages; + const oldPageLabels = []; + const oldPageIndices = new Set(this.oldPages.map(({ + page: { + pageIndex + } + }) => pageIndex)); + let currentLabel = null; + let stFirstIndex = -1; + for (let i = 0; i < numPages; i++) { + const newLabel = pageLabels.get(i); + if (newLabel) { + currentLabel = newLabel; + stFirstIndex = currentLabel.has("St") ? i : -1; + } + if (!oldPageIndices.has(i)) { + continue; + } + if (stFirstIndex !== -1) { + const st = currentLabel.get("St"); + currentLabel = this.cloneDict(currentLabel); + currentLabel.set("St", st + (i - stFirstIndex)); + stFirstIndex = -1; + } + oldPageLabels.push(currentLabel); + } + currentLabel = oldPageLabels[0]; + let currentIndex = 0; + const newPageLabels = this.pageLabels = [[0, currentLabel]]; + for (let i = 0, ii = oldPageLabels.length; i < ii; i++) { + const label = oldPageLabels[i]; + if (label === currentLabel) { + continue; + } + currentIndex = i; + currentLabel = label; + newPageLabels.push([currentIndex, currentLabel]); + } + } + async #makePageCopy(pageIndex) { + const { + page, + documentData, + annotations, + pointingNamedDestinations + } = this.oldPages[pageIndex]; + this.currentDocument = documentData; + const { + dedupNamedDestinations, + oldRefMapping + } = documentData; + const { + xref, + rotate, + mediaBox, + resources, + ref: oldPageRef + } = page; + const pageRef = this.newRef; + const pageDict = this.xref[pageRef.num] = this.cloneDict(page.pageDict); + oldRefMapping.put(oldPageRef, pageRef); + if (pointingNamedDestinations) { + for (const pointingDest of pointingNamedDestinations) { + const name = dedupNamedDestinations.get(pointingDest) || pointingDest; + const dest = this.namedDestinations.get(name); + dest[0] = pageRef; + } + } + for (const key of ["Rotate", "MediaBox", "CropBox", "BleedBox", "TrimBox", "ArtBox", "Resources", "Annots", "Parent", "UserUnit"]) { + pageDict.delete(key); + } + const lastRef = this.newRefCount; + await this.#collectDependencies(pageDict, false, xref); + pageDict.set("Rotate", rotate); + pageDict.set("MediaBox", mediaBox); + for (const boxName of ["CropBox", "BleedBox", "TrimBox", "ArtBox"]) { + const box = page.getBoundingBox(boxName); + if (box?.some((value, index) => value !== mediaBox[index])) { + pageDict.set(boxName, box); + } + } + const userUnit = page.userUnit; + if (userUnit !== 1) { + pageDict.set("UserUnit", userUnit); + } + pageDict.setIfDict("Resources", await this.#collectDependencies(resources, true, xref)); + if (annotations) { + const newAnnotations = await this.#collectDependencies(annotations, true, xref); + this.#fixNamedDestinations(newAnnotations, dedupNamedDestinations); + pageDict.setIfArray("Annots", newAnnotations); + } + if (this.useObjectStreams) { + const newLastRef = this.newRefCount; + const pageObjectRefs = []; + for (let i = lastRef; i < newLastRef; i++) { + const obj = this.xref[i]; + if (obj instanceof BaseStream) { + continue; + } + pageObjectRefs.push(Ref.get(i, 0)); + } + for (let i = 0; i < pageObjectRefs.length; i += 0xffff) { + const objStreamRef = this.newRef; + this.objStreamRefs.add(objStreamRef.num); + this.xref[objStreamRef.num] = pageObjectRefs.slice(i, i + 0xffff); + } + } + this.currentDocument = null; + return pageRef; + } + #makePageTree() { + const { + newPages: pages, + rootDict, + pagesRef, + pagesDict + } = this; + rootDict.set("Pages", pagesRef); + pagesDict.setIfName("Type", "Pages"); + pagesDict.set("Count", pages.length); + const maxLeaves = MAX_LEAVES_PER_PAGES_NODE <= 1 ? pages.length : MAX_LEAVES_PER_PAGES_NODE; + const stack = [{ + dict: pagesDict, + kids: pages, + parentRef: pagesRef + }]; + while (stack.length > 0) { + const { + dict, + kids, + parentRef + } = stack.pop(); + if (kids.length <= maxLeaves) { + dict.set("Kids", kids); + for (const ref of kids) { + this.xref[ref.num].set("Parent", parentRef); + } + continue; + } + const chunkSize = Math.max(maxLeaves, Math.ceil(kids.length / maxLeaves)); + const kidsChunks = []; + for (let i = 0; i < kids.length; i += chunkSize) { + kidsChunks.push(kids.slice(i, i + chunkSize)); + } + const kidsRefs = []; + dict.set("Kids", kidsRefs); + for (const chunk of kidsChunks) { + const [kidRef, kidDict] = this.newDict; + kidsRefs.push(kidRef); + kidDict.setIfName("Type", "Pages"); + kidDict.set("Parent", parentRef); + kidDict.set("Count", chunk.length); + stack.push({ + dict: kidDict, + kids: chunk, + parentRef: kidRef + }); + } + } + } + #makeNameNumTree(map, areNames) { + const allEntries = map.sort(areNames ? ([keyA], [keyB]) => keyA.localeCompare(keyB) : ([keyA], [keyB]) => keyA - keyB); + const maxLeaves = MAX_IN_NAME_TREE_NODE <= 1 ? allEntries.length : MAX_IN_NAME_TREE_NODE; + const [treeRef, treeDict] = this.newDict; + const stack = [{ + dict: treeDict, + entries: allEntries + }]; + const valueType = areNames ? "Names" : "Nums"; + while (stack.length > 0) { + const { + dict, + entries + } = stack.pop(); + if (entries.length <= maxLeaves) { + dict.set("Limits", [entries[0][0], entries.at(-1)[0]]); + dict.set(valueType, entries.flat()); + continue; + } + const entriesChunks = []; + const chunkSize = Math.max(maxLeaves, Math.ceil(entries.length / maxLeaves)); + for (let i = 0; i < entries.length; i += chunkSize) { + entriesChunks.push(entries.slice(i, i + chunkSize)); + } + const entriesRefs = []; + dict.set("Kids", entriesRefs); + for (const chunk of entriesChunks) { + const [entriesRef, entriesDict] = this.newDict; + entriesRefs.push(entriesRef); + entriesDict.set("Limits", [chunk[0][0], chunk.at(-1)[0]]); + stack.push({ + dict: entriesDict, + entries: chunk + }); + } + } + return treeRef; + } + #makePageLabelsTree() { + const { + pageLabels + } = this; + if (!pageLabels || pageLabels.length === 0) { + return; + } + const { + rootDict + } = this; + const pageLabelsRef = this.#makeNameNumTree(this.pageLabels, false); + rootDict.set("PageLabels", pageLabelsRef); + } + #makeDestinationsTree() { + const { + namedDestinations + } = this; + if (namedDestinations.size === 0) { + return; + } + if (!this.namesDict) { + [this.namesRef, this.namesDict] = this.newDict; + this.rootDict.set("Names", this.namesRef); + } + this.namesDict.set("Dests", this.#makeNameNumTree(Array.from(namedDestinations.entries()), true)); + } + #makeStructTree() { + const { + structTreeKids + } = this; + if (!structTreeKids || structTreeKids.length === 0) { + return; + } + const { + rootDict + } = this; + const structTreeRef = this.newRef; + const structTree = this.xref[structTreeRef.num] = new Dict(); + structTree.setIfName("Type", "StructTreeRoot"); + structTree.setIfArray("K", structTreeKids); + for (const kidRef of structTreeKids) { + const kid = this.xref[kidRef.num]; + const type = kid.get("Type"); + if (!type || isName(type, "StructElem")) { + kid.set("P", structTreeRef); + } + } + if (this.parentTree.size > 0) { + const parentTreeRef = this.#makeNameNumTree(Array.from(this.parentTree.entries()), false); + const parentTree = this.xref[parentTreeRef.num]; + parentTree.setIfName("Type", "ParentTree"); + structTree.set("ParentTree", parentTreeRef); + structTree.set("ParentTreeNextKey", this.parentTree.size); + } + if (this.idTree.size > 0) { + const idTreeRef = this.#makeNameNumTree(Array.from(this.idTree.entries()), true); + const idTree = this.xref[idTreeRef.num]; + idTree.setIfName("Type", "IDTree"); + structTree.set("IDTree", idTreeRef); + } + if (this.classMap.size > 0) { + const classMapRef = this.newRef; + this.xref[classMapRef.num] = this.classMap; + structTree.set("ClassMap", classMapRef); + } + if (this.roleMap.size > 0) { + const roleMapRef = this.newRef; + this.xref[roleMapRef.num] = this.roleMap; + structTree.set("RoleMap", roleMapRef); + } + if (this.namespaces.size > 0) { + const namespacesRef = this.newRef; + this.xref[namespacesRef.num] = Array.from(this.namespaces.values()); + structTree.set("Namespaces", namespacesRef); + } + if (this.structTreeAF.length > 0) { + const structTreeAFRef = this.newRef; + this.xref[structTreeAFRef.num] = this.structTreeAF; + structTree.set("AF", structTreeAFRef); + } + if (this.structTreePronunciationLexicon.length > 0) { + const structTreePronunciationLexiconRef = this.newRef; + this.xref[structTreePronunciationLexiconRef.num] = this.structTreePronunciationLexicon; + structTree.set("PronunciationLexicon", structTreePronunciationLexiconRef); + } + rootDict.set("StructTreeRoot", structTreeRef); + } + async #makeRoot() { + const { + rootDict + } = this; + rootDict.setIfName("Type", "Catalog"); + rootDict.setIfName("Version", this.version); + this.#makePageTree(); + this.#makePageLabelsTree(); + this.#makeDestinationsTree(); + this.#makeStructTree(); + } + #makeInfo() { + const infoMap = new Map(); + if (this.hasSingleFile) { + const { + xref: { + trailer + } + } = this.oldPages[0].documentData.document; + const oldInfoDict = trailer.get("Info"); + for (const [key, value] of oldInfoDict || []) { + if (typeof value === "string") { + infoMap.set(key, stringToPDFString(value)); + } + } + } + infoMap.delete("ModDate"); + infoMap.set("CreationDate", getModificationDate()); + infoMap.set("Creator", "PDF.js"); + infoMap.set("Producer", "Firefox"); + if (this.author) { + infoMap.set("Author", this.author); + } + if (this.title) { + infoMap.set("Title", this.title); + } + for (const [key, value] of infoMap) { + this.infoDict.set(key, stringToAsciiOrUTF16BE(value)); + } + return infoMap; + } + async #makeEncrypt() { + if (!this.hasSingleFile) { + return [null, null, null]; + } + const { + documentData + } = this.oldPages[0]; + const { + document: { + xref: { + trailer, + encrypt + } + } + } = documentData; + if (!trailer.has("Encrypt")) { + return [null, null, null]; + } + const encryptDict = trailer.get("Encrypt"); + if (!(encryptDict instanceof Dict)) { + return [null, null, null]; + } + this.currentDocument = documentData; + const result = [await this.#cloneObject(encryptDict, trailer.xref), encrypt, trailer.get("ID")]; + this.currentDocument = null; + return result; + } + async #createChanges() { + const changes = new RefSetCache(); + changes.put(Ref.get(0, 0xffff), { + data: null + }); + for (let i = 1, ii = this.xref.length; i < ii; i++) { + if (this.objStreamRefs?.has(i)) { + await this.#createObjectStream(Ref.get(i, 0), this.xref[i], changes); + } else { + changes.put(Ref.get(i, 0), { + data: this.xref[i] + }); + } + } + return [changes, this.newRef]; + } + async #createObjectStream(objStreamRef, objRefs, changes) { + const streamBuffer = [""]; + const objOffsets = []; + let offset = 0; + const buffer = []; + for (let i = 0, ii = objRefs.length; i < ii; i++) { + const objRef = objRefs[i]; + changes.put(objRef, { + data: null, + objStreamRef, + index: i + }); + objOffsets.push(`${objRef.num} ${offset}`); + const data = this.xref[objRef.num]; + await writeValue(data, buffer, null); + const obj = buffer.join(""); + buffer.length = 0; + streamBuffer.push(obj); + offset += obj.length + 1; + } + streamBuffer[0] = objOffsets.join("\n"); + const objStream = new StringStream(streamBuffer.join("\n")); + const objStreamDict = objStream.dict = new Dict(); + objStreamDict.setIfName("Type", "ObjStm"); + objStreamDict.set("N", objRefs.length); + objStreamDict.set("First", streamBuffer[0].length + 1); + changes.put(objStreamRef, { + data: objStream + }); + } + async writePDF() { + await this.#makeRoot(); + const infoMap = this.#makeInfo(); + const [encryptRef, encrypt, fileIds] = await this.#makeEncrypt(); + const [changes, xrefTableRef] = await this.#createChanges(); + const header = [...`%PDF-${this.version}\n%`.split("").map(c => c.charCodeAt(0)), 0xfa, 0xde, 0xfa, 0xce]; + return incrementalUpdate({ + originalData: new Uint8Array(header), + changes, + xrefInfo: { + startXRef: null, + rootRef: this.rootRef, + infoRef: this.infoRef, + encryptRef, + newRef: xrefTableRef, + fileIds: fileIds || [null, null], + infoMap + }, + useXrefStream: this.useObjectStreams, + xref: { + encrypt, + encryptRef + } + }); + } +} + +;// ./src/core/worker_stream.js + +class PDFWorkerStream { + constructor(msgHandler) { + this._msgHandler = msgHandler; + this._contentLength = null; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + getFullReader() { + assert(!this._fullRequestReader, "PDFWorkerStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler); + return this._fullRequestReader; + } + getRangeReader(begin, end) { + const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler); + this._rangeRequestReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } +} +class PDFWorkerStreamReader { + constructor(msgHandler) { + this._msgHandler = msgHandler; + this.onProgress = null; + this._contentLength = null; + this._isRangeSupported = false; + this._isStreamingSupported = false; + const readableStream = this._msgHandler.sendWithStream("GetReader"); + this._reader = readableStream.getReader(); + this._headersReady = this._msgHandler.sendWithPromise("ReaderHeadersReady").then(data => { + this._isStreamingSupported = data.isStreamingSupported; + this._isRangeSupported = data.isRangeSupported; + this._contentLength = data.contentLength; + }); + } + get headersReady() { + return this._headersReady; + } + get contentLength() { + return this._contentLength; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + get isRangeSupported() { + return this._isRangeSupported; + } + async read() { + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value: undefined, + done: true + }; + } + return { + value: value.buffer, + done: false + }; + } + cancel(reason) { + this._reader.cancel(reason); + } +} +class PDFWorkerStreamRangeReader { + constructor(begin, end, msgHandler) { + this._msgHandler = msgHandler; + this.onProgress = null; + const readableStream = this._msgHandler.sendWithStream("GetRangeReader", { + begin, + end + }); + this._reader = readableStream.getReader(); + } + get isStreamingSupported() { + return false; + } + async read() { + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value: undefined, + done: true + }; + } + return { + value: value.buffer, + done: false + }; + } + cancel(reason) { + this._reader.cancel(reason); + } +} + +;// ./src/core/worker.js + + + + + + + + + + + +class WorkerTask { + constructor(name) { + this.name = name; + this.terminated = false; + this._capability = Promise.withResolvers(); + } + get finished() { + return this._capability.promise; + } + finish() { + this._capability.resolve(); + } + terminate() { + this.terminated = true; + } + ensureNotTerminated() { + if (this.terminated) { + throw new Error("Worker task was terminated"); + } + } +} +class WorkerMessageHandler { + static { + if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" && typeof self.postMessage === "function" && "onmessage" in self) { + this.initializeFromPort(self); + } + } + static setup(handler, port) { + let testMessageProcessed = false; + handler.on("test", data => { + if (testMessageProcessed) { + return; + } + testMessageProcessed = true; + handler.send("test", data instanceof Uint8Array); + }); + handler.on("configure", data => { + setVerbosityLevel(data.verbosity); + }); + handler.on("GetDocRequest", data => this.createDocumentHandler(data, port)); + } + static createDocumentHandler(docParams, port) { + let pdfManager; + let terminated = false; + let cancelXHRs = null; + const WorkerTasks = new Set(); + const verbosity = getVerbosityLevel(); + const { + docId, + apiVersion + } = docParams; + const workerVersion = "5.4.445"; + if (apiVersion !== workerVersion) { + throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); + } + const workerHandlerName = docId + "_worker"; + let handler = new MessageHandler(workerHandlerName, docId, port); + function ensureNotTerminated() { + if (terminated) { + throw new Error("Worker was terminated"); + } + } + function startWorkerTask(task) { + WorkerTasks.add(task); + } + function finishWorkerTask(task) { + task.finish(); + WorkerTasks.delete(task); + } + async function loadDocument(recoveryMode) { + await pdfManager.ensureDoc("checkHeader"); + await pdfManager.ensureDoc("parseStartXRef"); + await pdfManager.ensureDoc("parse", [recoveryMode]); + await pdfManager.ensureDoc("checkFirstPage", [recoveryMode]); + await pdfManager.ensureDoc("checkLastPage", [recoveryMode]); + const isPureXfa = await pdfManager.ensureDoc("isPureXfa"); + if (isPureXfa) { + const task = new WorkerTask("loadXfaResources"); + startWorkerTask(task); + await pdfManager.ensureDoc("loadXfaResources", [handler, task]); + finishWorkerTask(task); + } + const [numPages, fingerprints] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprints")]); + const htmlForXfa = isPureXfa ? await pdfManager.ensureDoc("htmlForXfa") : null; + return { + numPages, + fingerprints, + htmlForXfa + }; + } + async function getPdfManager({ + data, + password, + disableAutoFetch, + rangeChunkSize, + length, + docBaseUrl, + enableXfa, + evaluatorOptions + }) { + const pdfManagerArgs = { + source: null, + disableAutoFetch, + docBaseUrl, + docId, + enableXfa, + evaluatorOptions, + handler, + length, + password, + rangeChunkSize + }; + if (data) { + pdfManagerArgs.source = data; + return new LocalPdfManager(pdfManagerArgs); + } + const pdfStream = new PDFWorkerStream(handler), + fullRequest = pdfStream.getFullReader(); + const pdfManagerCapability = Promise.withResolvers(); + let newPdfManager, + cachedChunks = [], + loaded = 0; + fullRequest.headersReady.then(function () { + if (!fullRequest.isRangeSupported) { + return; + } + pdfManagerArgs.source = pdfStream; + pdfManagerArgs.length = fullRequest.contentLength; + pdfManagerArgs.disableAutoFetch ||= fullRequest.isStreamingSupported; + newPdfManager = new NetworkPdfManager(pdfManagerArgs); + for (const chunk of cachedChunks) { + newPdfManager.sendProgressiveData(chunk); + } + cachedChunks = []; + pdfManagerCapability.resolve(newPdfManager); + cancelXHRs = null; + }).catch(function (reason) { + pdfManagerCapability.reject(reason); + cancelXHRs = null; + }); + new Promise(function (resolve, reject) { + const readChunk = function ({ + value, + done + }) { + try { + ensureNotTerminated(); + if (done) { + if (!newPdfManager) { + const pdfFile = arrayBuffersToBytes(cachedChunks); + cachedChunks = []; + if (length && pdfFile.length !== length) { + warn("reported HTTP length is different from actual"); + } + pdfManagerArgs.source = pdfFile; + newPdfManager = new LocalPdfManager(pdfManagerArgs); + pdfManagerCapability.resolve(newPdfManager); + } + cancelXHRs = null; + return; + } + loaded += value.byteLength; + if (!fullRequest.isStreamingSupported) { + handler.send("DocProgress", { + loaded, + total: Math.max(loaded, fullRequest.contentLength || 0) + }); + } + if (newPdfManager) { + newPdfManager.sendProgressiveData(value); + } else { + cachedChunks.push(value); + } + fullRequest.read().then(readChunk, reject); + } catch (e) { + reject(e); + } + }; + fullRequest.read().then(readChunk, reject); + }).catch(function (e) { + pdfManagerCapability.reject(e); + cancelXHRs = null; + }); + cancelXHRs = reason => { + pdfStream.cancelAllRequests(reason); + }; + return pdfManagerCapability.promise; + } + function setupDoc(data) { + function onSuccess(doc) { + ensureNotTerminated(); + handler.send("GetDoc", { + pdfInfo: doc + }); + } + function onFailure(ex) { + ensureNotTerminated(); + if (ex instanceof PasswordException) { + const task = new WorkerTask(`PasswordException: response ${ex.code}`); + startWorkerTask(task); + handler.sendWithPromise("PasswordRequest", ex).then(function ({ + password + }) { + finishWorkerTask(task); + pdfManager.updatePassword(password); + pdfManagerReady(); + }).catch(function () { + finishWorkerTask(task); + handler.send("DocException", ex); + }); + } else { + handler.send("DocException", wrapReason(ex)); + } + } + function pdfManagerReady() { + ensureNotTerminated(); + loadDocument(false).then(onSuccess, function (reason) { + ensureNotTerminated(); + if (!(reason instanceof XRefParseException)) { + onFailure(reason); + return; + } + pdfManager.requestLoadedStream().then(function () { + ensureNotTerminated(); + loadDocument(true).then(onSuccess, onFailure); + }); + }); + } + ensureNotTerminated(); + getPdfManager(data).then(function (newPdfManager) { + if (terminated) { + newPdfManager.terminate(new AbortException("Worker was terminated.")); + throw new Error("Worker was terminated"); + } + pdfManager = newPdfManager; + pdfManager.requestLoadedStream(true).then(stream => { + handler.send("DataLoaded", { + length: stream.bytes.byteLength + }); + }); + }).then(pdfManagerReady, onFailure); + } + handler.on("GetPage", function (data) { + return pdfManager.getPage(data.pageIndex).then(function (page) { + return Promise.all([pdfManager.ensure(page, "rotate"), pdfManager.ensure(page, "ref"), pdfManager.ensure(page, "userUnit"), pdfManager.ensure(page, "view")]).then(function ([rotate, ref, userUnit, view]) { + return { + rotate, + ref, + refStr: ref?.toString() ?? null, + userUnit, + view + }; + }); + }); + }); + handler.on("GetPageIndex", function (data) { + const pageRef = Ref.get(data.num, data.gen); + return pdfManager.ensureCatalog("getPageIndex", [pageRef]); + }); + handler.on("GetDestinations", function (data) { + return pdfManager.ensureCatalog("destinations"); + }); + handler.on("GetDestination", function (data) { + return pdfManager.ensureCatalog("getDestination", [data.id]); + }); + handler.on("GetPageLabels", function (data) { + return pdfManager.ensureCatalog("pageLabels"); + }); + handler.on("GetPageLayout", function (data) { + return pdfManager.ensureCatalog("pageLayout"); + }); + handler.on("GetPageMode", function (data) { + return pdfManager.ensureCatalog("pageMode"); + }); + handler.on("GetViewerPreferences", function (data) { + return pdfManager.ensureCatalog("viewerPreferences"); + }); + handler.on("GetOpenAction", function (data) { + return pdfManager.ensureCatalog("openAction"); + }); + handler.on("GetAttachments", function (data) { + return pdfManager.ensureCatalog("attachments"); + }); + handler.on("GetDocJSActions", function (data) { + return pdfManager.ensureCatalog("jsActions"); + }); + handler.on("GetPageJSActions", function ({ + pageIndex + }) { + return pdfManager.getPage(pageIndex).then(page => pdfManager.ensure(page, "jsActions")); + }); + handler.on("GetAnnotationsByType", async function ({ + types, + pageIndexesToSkip + }) { + const [numPages, annotationGlobals] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("annotationGlobals")]); + if (!annotationGlobals) { + return null; + } + const pagePromises = []; + const annotationPromises = []; + let task = null; + try { + for (let i = 0, ii = numPages; i < ii; i++) { + if (pageIndexesToSkip?.has(i)) { + continue; + } + if (!task) { + task = new WorkerTask("GetAnnotationsByType"); + startWorkerTask(task); + } + pagePromises.push(pdfManager.getPage(i).then(async page => { + if (!page) { + return []; + } + return page.collectAnnotationsByType(handler, task, types, annotationPromises, annotationGlobals) || []; + })); + } + await Promise.all(pagePromises); + const annotations = await Promise.all(annotationPromises); + return annotations.filter(a => !!a); + } finally { + if (task) { + finishWorkerTask(task); + } + } + }); + handler.on("GetOutline", function (data) { + return pdfManager.ensureCatalog("documentOutline"); + }); + handler.on("GetOptionalContentConfig", function (data) { + return pdfManager.ensureCatalog("optionalContentConfig"); + }); + handler.on("GetPermissions", function (data) { + return pdfManager.ensureCatalog("permissions"); + }); + handler.on("GetMetadata", function (data) { + return Promise.all([pdfManager.ensureDoc("documentInfo"), pdfManager.ensureCatalog("metadata"), pdfManager.ensureCatalog("hasStructTree")]); + }); + handler.on("GetMarkInfo", function (data) { + return pdfManager.ensureCatalog("markInfo"); + }); + handler.on("GetData", function (data) { + return pdfManager.requestLoadedStream().then(stream => stream.bytes); + }); + handler.on("GetAnnotations", function ({ + pageIndex, + intent + }) { + return pdfManager.getPage(pageIndex).then(function (page) { + const task = new WorkerTask(`GetAnnotations: page ${pageIndex}`); + startWorkerTask(task); + return page.getAnnotationsData(handler, task, intent).then(data => { + finishWorkerTask(task); + return data; + }, reason => { + finishWorkerTask(task); + throw reason; + }); + }); + }); + handler.on("GetFieldObjects", function (data) { + return pdfManager.ensureDoc("fieldObjects").then(fieldObjects => fieldObjects?.allFields || null); + }); + handler.on("HasJSActions", function (data) { + return pdfManager.ensureDoc("hasJSActions"); + }); + handler.on("GetCalculationOrderIds", function (data) { + return pdfManager.ensureDoc("calculationOrderIds"); + }); + handler.on("ExtractPages", async function ({ + pageInfos + }) { + if (!pageInfos) { + warn("extractPages: nothing to extract."); + return null; + } + if (!Array.isArray(pageInfos)) { + pageInfos = [pageInfos]; + } + let newDocumentId = 0; + for (const pageInfo of pageInfos) { + if (pageInfo.document === null) { + pageInfo.document = pdfManager.pdfDocument; + } else if (ArrayBuffer.isView(pageInfo.document)) { + const manager = new LocalPdfManager({ + source: pageInfo.document, + docId: `${docId}_extractPages_${newDocumentId++}`, + handler, + password: pageInfo.password ?? null, + evaluatorOptions: Object.assign({}, pdfManager.evaluatorOptions) + }); + let recoveryMode = false; + let isValid = true; + while (true) { + try { + await manager.requestLoadedStream(); + await manager.ensureDoc("checkHeader"); + await manager.ensureDoc("parseStartXRef"); + await manager.ensureDoc("parse", [recoveryMode]); + break; + } catch (e) { + if (e instanceof XRefParseException) { + if (recoveryMode === false) { + recoveryMode = true; + continue; + } else { + isValid = false; + warn("extractPages: XRefParseException."); + } + } else if (e instanceof PasswordException) { + const task = new WorkerTask(`PasswordException: response ${e.code}`); + startWorkerTask(task); + try { + const { + password + } = await handler.sendWithPromise("PasswordRequest", e); + manager.updatePassword(password); + } catch { + isValid = false; + warn("extractPages: invalid password."); + } finally { + finishWorkerTask(task); + } + } else { + isValid = false; + warn("extractPages: invalid document."); + } + if (!isValid) { + break; + } + } + } + if (!isValid) { + pageInfo.document = null; + } + const isPureXfa = await manager.ensureDoc("isPureXfa"); + if (isPureXfa) { + pageInfo.document = null; + warn("extractPages does not support pure XFA documents."); + } else { + pageInfo.document = manager.pdfDocument; + } + } else { + warn("extractPages: invalid document."); + } + } + try { + const pdfEditor = new PDFEditor(); + const buffer = await pdfEditor.extractPages(pageInfos); + return buffer; + } catch (reason) { + console.error(reason); + return null; + } + }); + handler.on("SaveDocument", async function ({ + isPureXfa, + numPages, + annotationStorage, + filename + }) { + const globalPromises = [pdfManager.requestLoadedStream(), pdfManager.ensureCatalog("acroForm"), pdfManager.ensureCatalog("acroFormRef"), pdfManager.ensureDoc("startXRef"), pdfManager.ensureDoc("xref"), pdfManager.ensureCatalog("structTreeRoot")]; + const changes = new RefSetCache(); + const promises = []; + const newAnnotationsByPage = !isPureXfa ? getNewAnnotationsMap(annotationStorage) : null; + const [stream, acroForm, acroFormRef, startXRef, xref, _structTreeRoot] = await Promise.all(globalPromises); + const catalogRef = xref.trailer.getRaw("Root") || null; + let structTreeRoot; + if (newAnnotationsByPage) { + if (!_structTreeRoot) { + if (await StructTreeRoot.canCreateStructureTree({ + catalogRef, + pdfManager, + newAnnotationsByPage + })) { + structTreeRoot = null; + } + } else if (await _structTreeRoot.canUpdateStructTree({ + pdfManager, + newAnnotationsByPage + })) { + structTreeRoot = _structTreeRoot; + } + const imagePromises = AnnotationFactory.generateImages(annotationStorage.values(), xref, pdfManager.evaluatorOptions.isOffscreenCanvasSupported); + const newAnnotationPromises = structTreeRoot === undefined ? promises : []; + for (const [pageIndex, annotations] of newAnnotationsByPage) { + newAnnotationPromises.push(pdfManager.getPage(pageIndex).then(page => { + const task = new WorkerTask(`Save (editor): page ${pageIndex}`); + startWorkerTask(task); + return page.saveNewAnnotations(handler, task, annotations, imagePromises, changes).finally(function () { + finishWorkerTask(task); + }); + })); + } + if (structTreeRoot === null) { + promises.push(Promise.all(newAnnotationPromises).then(async () => { + await StructTreeRoot.createStructureTree({ + newAnnotationsByPage, + xref, + catalogRef, + pdfManager, + changes + }); + })); + } else if (structTreeRoot) { + promises.push(Promise.all(newAnnotationPromises).then(async () => { + await structTreeRoot.updateStructureTree({ + newAnnotationsByPage, + pdfManager, + changes + }); + })); + } + } + if (isPureXfa) { + promises.push(pdfManager.ensureDoc("serializeXfaData", [annotationStorage])); + } else { + for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { + promises.push(pdfManager.getPage(pageIndex).then(function (page) { + const task = new WorkerTask(`Save: page ${pageIndex}`); + startWorkerTask(task); + return page.save(handler, task, annotationStorage, changes).finally(function () { + finishWorkerTask(task); + }); + })); + } + } + const refs = await Promise.all(promises); + let xfaData = null; + if (isPureXfa) { + xfaData = refs[0]; + if (!xfaData) { + return stream.bytes; + } + } else if (changes.size === 0) { + return stream.bytes; + } + const needAppearances = acroFormRef && acroForm instanceof Dict && changes.values().some(ref => ref.needAppearances); + const xfa = acroForm instanceof Dict && acroForm.get("XFA") || null; + let xfaDatasetsRef = null; + let hasXfaDatasetsEntry = false; + if (Array.isArray(xfa)) { + for (let i = 0, ii = xfa.length; i < ii; i += 2) { + if (xfa[i] === "datasets") { + xfaDatasetsRef = xfa[i + 1]; + hasXfaDatasetsEntry = true; + } + } + if (xfaDatasetsRef === null) { + xfaDatasetsRef = xref.getNewTemporaryRef(); + } + } else if (xfa) { + warn("Unsupported XFA type."); + } + let newXrefInfo = Object.create(null); + if (xref.trailer) { + const infoMap = new Map(); + const xrefInfo = xref.trailer.get("Info") || null; + if (xrefInfo instanceof Dict) { + for (const [key, value] of xrefInfo) { + if (typeof value === "string") { + infoMap.set(key, stringToPDFString(value)); + } + } + } + newXrefInfo = { + rootRef: catalogRef, + encryptRef: xref.trailer.getRaw("Encrypt") || null, + newRef: xref.getNewTemporaryRef(), + infoRef: xref.trailer.getRaw("Info") || null, + infoMap, + fileIds: xref.trailer.get("ID") || null, + startXRef, + filename + }; + } + return incrementalUpdate({ + originalData: stream.bytes, + xrefInfo: newXrefInfo, + changes, + xref, + hasXfa: !!xfa, + xfaDatasetsRef, + hasXfaDatasetsEntry, + needAppearances, + acroFormRef, + acroForm, + xfaData, + useXrefStream: isDict(xref.topDict, "XRef") + }).finally(() => { + xref.resetNewTemporaryRef(); + }); + }); + handler.on("GetOperatorList", function (data, sink) { + const pageIndex = data.pageIndex; + pdfManager.getPage(pageIndex).then(function (page) { + const task = new WorkerTask(`GetOperatorList: page ${pageIndex}`); + startWorkerTask(task); + const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0; + page.getOperatorList({ + handler, + sink, + task, + intent: data.intent, + cacheKey: data.cacheKey, + annotationStorage: data.annotationStorage, + modifiedIds: data.modifiedIds + }).then(function (operatorListInfo) { + finishWorkerTask(task); + if (start) { + info(`page=${pageIndex + 1} - getOperatorList: time=` + `${Date.now() - start}ms, len=${operatorListInfo.length}`); + } + sink.close(); + }, function (reason) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + sink.error(reason); + }); + }); + }); + handler.on("GetTextContent", function (data, sink) { + const { + pageIndex, + includeMarkedContent, + disableNormalization + } = data; + pdfManager.getPage(pageIndex).then(function (page) { + const task = new WorkerTask("GetTextContent: page " + pageIndex); + startWorkerTask(task); + const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0; + page.extractTextContent({ + handler, + task, + sink, + includeMarkedContent, + disableNormalization + }).then(function () { + finishWorkerTask(task); + if (start) { + info(`page=${pageIndex + 1} - getTextContent: time=` + `${Date.now() - start}ms`); + } + sink.close(); + }, function (reason) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + sink.error(reason); + }); + }); + }); + handler.on("GetStructTree", function (data) { + return pdfManager.getPage(data.pageIndex).then(page => pdfManager.ensure(page, "getStructTree")); + }); + handler.on("FontFallback", function (data) { + return pdfManager.fontFallback(data.id, handler); + }); + handler.on("Cleanup", function (data) { + return pdfManager.cleanup(true); + }); + handler.on("Terminate", function (data) { + terminated = true; + const waitOn = []; + if (pdfManager) { + pdfManager.terminate(new AbortException("Worker was terminated.")); + const cleanupPromise = pdfManager.cleanup(); + waitOn.push(cleanupPromise); + pdfManager = null; + } else { + clearGlobalCaches(); + } + cancelXHRs?.(new AbortException("Worker was terminated.")); + for (const task of WorkerTasks) { + waitOn.push(task.finished); + task.terminate(); + } + return Promise.all(waitOn).then(function () { + handler.destroy(); + handler = null; + }); + }); + handler.on("Ready", function (data) { + setupDoc(docParams); + docParams = null; + }); + return workerHandlerName; + } + static initializeFromPort(port) { + const handler = new MessageHandler("worker", "main", port); + this.setup(handler, port); + handler.send("ready", null); + } +} + +;// ./src/pdf.worker.js + +globalThis.pdfjsWorker = { + WorkerMessageHandler: WorkerMessageHandler +}; + +export { WorkerMessageHandler }; diff --git a/popup.txt b/popup.txt new file mode 100644 index 0000000..676b4c6 --- /dev/null +++ b/popup.txt @@ -0,0 +1,299 @@ + + +function createButton(label = 'BUTTON', onClick) { + const button = document.createElement('button'); + button.textContent = label; + button.addEventListener('click', onClick); + return button; +} + + +function createNewPopup(_title, _contentElements) { + const popup = new PopupBox(_title, _contentElements); + popup.setAttribute('title', _title); + let dlgBody = popup.dialog.querySelector('.dialog-content'); + let dlgFooter = popup.dialog.querySelector('.dialog-footer'); + document.body.appendChild(popup); + return popup; +} + + +class PopupBox extends HTMLElement { + constructor(title = 'Popup', contentElements = [], menuOptions = []) { + super(); + this.attachShadow({ mode: 'open' }); + this.args = { + title: title, + content: contentElements, + menuOptions: menuOptions, + }; + this.content = this.args.content.length > 0 ? {...this.args.content} : {...Array.from(this.shadowRoot.children)}; + this.dialog = this.createDialogStructure(title, contentElements); + this.shadowRoot.append(this.createStyles(), this.dialog); + this.setMenuOptions(menuOptions); + this.#updateDialogContent(); + this.show(); + this.dialog.addEventListener('click', (event) => { + if (event.target != this.dialog && !this.shadowRoot.contains(event.target)) { + event.preventDefault(); + this.hide(); + } + + }); + } + // Attach styles and dialog content to the shadow DOM } + static get observedAttributes() { + return ['title', 'content']; + } + attributeChangedCallback(name, oldValue, newValue) { + if (name === 'title') { + this.dialog.querySelector('.dialog-header').textContent = newValue; + } else if (name === 'content') { + this.#updateDialogContent(); + } + } + + static updateDialogContent() { + const _this = document.querySelector('popup-box'); + _this.updateDialogContent(); + } + + #updateDialogContent() { + this.shadowRoot.querySelector('#dialog-content').innerHTML = ''; + this.shadowRoot.querySelector('#dialog-content').append((Array.from(this.content)).flatMap(content => { + if (content instanceof HTMLElement) { + return content; + } else if (typeof content === 'string') { + const div = document.createElement('div'); + div.innerHTML = content; + return div.children; + } else if (Array.isArray(content)) { + return content; + } else { + return []; + } + })); + } + + addContents(contentElements) { + this.content = Array.from(contentElements); + this.#updateDialogContent(); + } + + createStyles() { + const style = document.createElement('style'); + style.textContent = ` + :host { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + resize: both; + @touch-action: none; + + } + .dialog { + background: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + max-width: 80%; + max-height: 80vh; + overflow: auto; + } + .dialog-header { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + font-size: 1.2rem; + color: black; + background-color: #f5f5f5; + padding: 8px; + } + .dialog-content { + margin-bottom: 20px; + } + .dialog-footer { + border-top: 1px solid #eee; + padding-top: 10px; + text-align: right; + } + button { + padding: 8px 16px; + border: none; + border-radius: 4px; + background: #007bff; + color: white; + cursor: pointer; + } + button:hover { + background: #0056b3; + } + `; + return style; + } + + createDialogStructure(title, contentElements) { + const dialog = document.createElement('div'); + dialog.classList.add('dialog'); + dialog.innerHTML = ` + +
      + +

      ${title}

      +
      + + + + +
      +
      + + +
      ${[...Array.from(contentElements)]?.forEach(element => element.outerHTML)?.join('')} + + +
      + + `; + + dialog.querySelector('.dlg-close-btn').addEventListener('click', () => this.hide()); + dialog.addEventListener('click', (e) => { + if (e.target === this) this.hide(); + }); + + // Close on escape key + window.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && this.isConnected) this.hide(); + }); + + this.dialog = dialog; + return dialog; + } + + show() { + document.body.appendChild(this); + document.body.style.overflow = 'hidden'; + } + + hide() { + if (this.isConnected) { + document.body.removeChild(this); + document.body.style.overflow = 'auto'; + } + } + + connectedCallback() { + this.setContent(this.args.content); + } + + setMenuOptions(options = [], index = 0) { + this.options = options; + if (!Array.isArray(options)) { + console.error('Menu options must be an array.'); + return; + } + if (options.length > 0) { + let i = 0; + const defaultOption = { + label: options[i].lable || 'File', + onClick: () => { + const menu = this.shadowRoot.querySelector('#dialog-menubar'); + const menuOptions = menu.querySelectorAll('.menu-option'); + if (menu.childElementCount > 0) { + menuOptions.forEach(option => { + option.classList.remove('active'); + }); + } + else { + menuOptions.forEach(option => { + option.classList.add('active'); + }); + } + menuOptions.forEach(option => { + option.style.display = option.style.display === 'block' ? 'none' : 'block'; + }); + menu.childElementCount > 0 ? menu.style.display = 'inline' : menu.style.display = 'inline-flex'; + } + }; + this.options.push(defaultOption); + } + const menuBar = this.shadowRoot.querySelector('#dialog-menubar'); + menuBar.innerHTML = ''; + this.options.forEach(option => { + const optsdiv = document.createElement('div'); + const button = document.createElement('button'); + optsdiv.appendChild(button); + optsdiv.classList.add('menu-option'); + button.setAttribute('data-index', index); + button.textContent = option.label; + button.addEventListener('click', option.onClick); + menuBar.appendChild(optsdiv); + }); + } + + // Method to update content + setContent(content) { + const contentDiv = this.shadowRoot.querySelector('#dialog-content'); + contentDiv.innerHTML = ''; + if (typeof content === 'string') { + contentDiv.innerHTML = content; + } else if (Array.isArray(content)) { + contentDiv.innerHTML = content.map(el => el.outerHTML).join(''); + } else if (content instanceof Element) { + contentDiv.appendChild(content); + } + } + + // Method to update title + setTitle(title) { + this.shadowRoot.querySelector('#dialog-title').textContent = title; + } + + // Method to update footer + setFooter(footer) { + const footerDiv = this.shadowRoot.querySelector('.dialog-footer'); + footerDiv.innerHTML = ''; + if (typeof footer === 'string') { + footerDiv.innerHTML = footer; + footerDiv.style.textAlign = 'center'; + } + else if (footer instanceof Element) { + footerDiv.appendChild(footer); + } + else { + footerDiv.innerHTML = footer; + footerDiv.style.textAlign = 'center'; + } + footerDiv.style.fontSize = '12px'; + footerDiv.style.color = 'white'; + footerDiv.style.fontWeight = 'bold'; + footerDiv.style.fontFamily = 'Arial, sans-serif'; + footerDiv.style.fontStyle = 'italic'; + footerDiv.style.fontVariant = 'small-caps'; + footerDiv.style.textShadow = '2px 2px 4px rgba(0, 0, 0, 0.5)'; + footerDiv.style.textDecoration = 'underline'; + footerDiv.style.textDecorationColor = 'white'; + footerDiv.style.textDecorationStyle = 'double'; + footerDiv.style.textDecorationThickness = '2px'; + footerDiv.style.textDecorationLine = 'underline'; + footerDiv.style.textDecorationSkipInk = 'none'; + footerDiv.style.textDecorationSkip = 'none'; + } +} + +customElements.define('popup-box', PopupBox); diff --git a/react/reactdomclient.js b/react/reactdomclient.js new file mode 100644 index 0000000..02e6e22 --- /dev/null +++ b/react/reactdomclient.js @@ -0,0 +1,38 @@ +'use strict'; + +function checkDCE() { + /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ + if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' || + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function' + ) { + return; + } + if (process.env.NODE_ENV !== 'production') { + // This branch is unreachable because this function is only called + // in production, but the condition is true only in development. + // Therefore if the branch is still here, dead code elimination wasn't + // properly applied. + // Don't change the message. React DevTools relies on it. Also make sure + // this message doesn't occur elsewhere in this function, or it will cause + // a false positive. + throw new Error('^_^'); + } + try { + // Verify that the code above has been dead code eliminated (DCE'd). + __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE); + } catch (err) { + // DevTools shouldn't crash React, no matter what. + // We should still report in case we break this code. + console.error(err); + } +} + +if (process.env.NODE_ENV === 'production') { + // DCE check should happen before ReactDOM bundle executes so that + // DevTools can report bad minification during injection. + checkDCE(); + module.exports = require('./cjs/react-dom-client.production.js'); +} else { + module.exports = require('./cjs/react-dom-client.development.js'); +} diff --git a/socketworker/_class_extract_field_descriptor.js b/socketworker/_class_extract_field_descriptor.js new file mode 100644 index 0000000..44ca9e7 --- /dev/null +++ b/socketworker/_class_extract_field_descriptor.js @@ -0,0 +1,6 @@ +function _class_extract_field_descriptor(receiver, privateMap, action) { + if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance"); + + return privateMap.get(receiver); +} +export { _class_extract_field_descriptor as _ }; diff --git a/socketworker/_class_private_field_get.js b/socketworker/_class_private_field_get.js new file mode 100644 index 0000000..078d320 --- /dev/null +++ b/socketworker/_class_private_field_get.js @@ -0,0 +1,8 @@ +import { _ as _class_apply_descriptor_get } from "./_class_apply_descriptor_get.js"; +import { _ as _class_extract_field_descriptor } from "./_class_extract_field_descriptor.js"; + +function _class_private_field_get(receiver, privateMap) { + var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get"); + return _class_apply_descriptor_get(receiver, descriptor); +} +export { _class_private_field_get as _ }; diff --git a/socketworker/_class_private_field_init.js b/socketworker/_class_private_field_init.js new file mode 100644 index 0000000..3daa81a --- /dev/null +++ b/socketworker/_class_private_field_init.js @@ -0,0 +1,7 @@ +import { _ as _check_private_redeclaration } from "./_check_private_redeclaration.js"; + +function _class_private_field_init(obj, privateMap, value) { + _check_private_redeclaration(obj, privateMap); + privateMap.set(obj, value); +} +export { _class_private_field_init as _ }; diff --git a/socketworker/alive-session.js b/socketworker/alive-session.js new file mode 100644 index 0000000..6aa9c34 --- /dev/null +++ b/socketworker/alive-session.js @@ -0,0 +1,289 @@ +import { AlivePresence, getPresenceKey, isPresenceChannel } from './presence.js'; +import { IDLE_METADATA_KEY, PresenceMetadataSet } from './presence-metadata.js'; +import { StableSocket } from '@github/stable-socket'; +import { SubscriptionSet } from './subscription-set.js'; +import { eachSlice } from './iterables.js'; +import { retry } from './eventloop-tasks.js'; +var SocketDisconnectReasons; +(function (SocketDisconnectReasons) { + SocketDisconnectReasons["Deploy"] = "Alive Redeploy"; + SocketDisconnectReasons["Reconnect"] = "Alive Reconnect"; +})(SocketDisconnectReasons || (SocketDisconnectReasons = {})); +function generatePresenceId() { + return `${Math.round(Math.random() * (Math.pow(2, 31) - 1))}_${Math.round(Date.now() / 1000)}`; +} +function getUserIdFromSocketUrl(url) { + const match = url.match(/\/u\/(\d+)\/ws/); + return match ? +match[1] : 0; +} +export class AliveSession { + constructor(url, getUrl, inSharedWorker, notify, maxReconnectBackoff = 600000, options = {}) { + this.url = url; + this.getUrl = getUrl; + this.inSharedWorker = inSharedWorker; + this.notify = notify; + this.maxReconnectBackoff = maxReconnectBackoff; + this.options = options; + this.subscriptions = new SubscriptionSet(); + this.state = 'online'; + this.retrying = null; + this.connectionCount = 0; + this.presence = new AlivePresence(); + this.presenceMetadata = new PresenceMetadataSet(); + this.intentionallyDisconnected = false; + this.lastCameOnline = 0; + this.userId = getUserIdFromSocketUrl(url); + this.presenceId = generatePresenceId(); + this.presenceKey = getPresenceKey(this.userId, this.presenceId); + this.socket = this.connect(); + } + subscribe(subscriptions) { + const added = this.subscriptions.add(...subscriptions); + this.sendSubscribe(added); + for (const subscription of subscriptions) { + const channel = subscription.topic.name; + if (!isPresenceChannel(channel)) { + continue; + } + this.notifyCachedPresence(subscription.subscriber, channel); + } + } + unsubscribe(subscriptions) { + const removed = this.subscriptions.delete(...subscriptions); + this.sendUnsubscribe(removed); + } + unsubscribeAll(...subscribers) { + const removed = this.subscriptions.drain(...subscribers); + this.sendUnsubscribe(removed); + const updatedPresenceChannels = this.presenceMetadata.removeSubscribers(subscribers); + this.sendPresenceMetadataUpdate(updatedPresenceChannels); + } + requestPresence(subscriber, channels) { + for (const channel of channels) { + this.notifyCachedPresence(subscriber, channel); + } + } + notifyCachedPresence(subscriber, channel) { + const presenceItems = this.presence.getChannelItems(channel); + if (presenceItems.length === 0) { + return; + } + this.notifyPresenceChannel(channel, presenceItems); + } + updatePresenceMetadata(metadataUpdates) { + const updatedChannels = new Set(); + for (const update of metadataUpdates) { + this.presenceMetadata.setMetadata(update); + updatedChannels.add(update.channelName); + } + this.sendPresenceMetadataUpdate(updatedChannels); + } + sendPresenceMetadataUpdate(channelNames) { + if (!channelNames.size) { + return; + } + const topics = []; + for (const channelName of channelNames) { + const topic = this.subscriptions.topic(channelName); + if (topic) { + topics.push(topic); + } + } + this.sendSubscribe(topics); + } + online() { + var _a; + this.lastCameOnline = Date.now(); + this.state = 'online'; + (_a = this.retrying) === null || _a === void 0 ? void 0 : _a.abort(); + this.socket.open(); + } + offline() { + var _a; + this.state = 'offline'; + (_a = this.retrying) === null || _a === void 0 ? void 0 : _a.abort(); + this.socket.close(); + } + shutdown() { + if (this.inSharedWorker) { + self.close(); + } + } + get reconnectWindow() { + const wasRecentlyOffline = Date.now() - this.lastCameOnline < 60 * 1000; + if (this.connectionCount === 0 || this.intentionallyDisconnected || wasRecentlyOffline) { + return 0; + } + return 10 * 1000; + } + socketDidOpen() { + this.intentionallyDisconnected = false; + this.connectionCount++; + this.socket.url = this.getUrlWithPresenceId(); + this.sendSubscribe(this.subscriptions.topics()); + } + socketDidClose(socket, code, reason) { + if (this.redeployEarlyReconnectTimeout !== undefined) { + clearTimeout(this.redeployEarlyReconnectTimeout); + } + if (reason === "Alive Reconnect") { + this.intentionallyDisconnected = true; + } + else if (reason === "Alive Redeploy") { + this.intentionallyDisconnected = true; + const reconnectDelayMinutes = 3 + Math.random() * 22; + const reconnectDelay = reconnectDelayMinutes * 60 * 1000; + this.redeployEarlyReconnectTimeout = setTimeout(() => { + this.intentionallyDisconnected = true; + this.socket.close(1000, 'Alive Redeploy Early Client Reconnect'); + }, reconnectDelay); + } + } + socketDidFinish() { + if (this.state === 'offline') + return; + this.reconnect(); + } + socketDidReceiveMessage(_, message) { + const payload = JSON.parse(message); + switch (payload.e) { + case 'ack': { + this.handleAck(payload); + break; + } + case 'msg': { + this.handleMessage(payload); + break; + } + } + } + handleAck(ack) { + for (const topic of this.subscriptions.topics()) { + topic.offset = ack.off; + } + } + handleMessage(msg) { + const channel = msg.ch; + const topic = this.subscriptions.topic(channel); + if (!topic) + return; + topic.offset = msg.off; + if ('e' in msg.data) { + const presenceItems = this.presence.handleMessage(channel, msg.data); + this.notifyPresenceChannel(channel, presenceItems); + return; + } + if (!msg.data.wait) + msg.data.wait = 0; + this.notify(this.subscriptions.subscribers(channel), { + channel, + type: 'message', + data: msg.data + }); + } + notifyPresenceChannel(channel, presenceItems) { + var _a, _b; + const userPresenceById = new Map(); + for (const presenceItem of presenceItems) { + const { userId, metadata, presenceKey } = presenceItem; + const userPresence = userPresenceById.get(userId) || { userId, isOwnUser: userId === this.userId, metadata: [] }; + if (presenceKey === this.presenceKey) { + continue; + } + for (const data of metadata) { + if (IDLE_METADATA_KEY in data) { + if (userPresence.isIdle !== false) { + userPresence.isIdle = Boolean(data[IDLE_METADATA_KEY]); + } + continue; + } + userPresence.metadata.push(data); + } + userPresenceById.set(userId, userPresence); + } + for (const subscriber of this.subscriptions.subscribers(channel)) { + const userId = this.userId; + const otherUsers = Array.from(userPresenceById.values()).filter(user => user.userId !== userId); + const ownUserRemoteMetadata = (_b = (_a = userPresenceById.get(this.userId)) === null || _a === void 0 ? void 0 : _a.metadata) !== null && _b !== void 0 ? _b : []; + const ownUserLocalMetadata = this.presenceMetadata.getChannelMetadata(channel, { + subscriber, + markAllAsLocal: !this.inSharedWorker + }); + this.notify([subscriber], { + channel, + type: 'presence', + data: [ + { + userId, + isOwnUser: true, + metadata: [...ownUserRemoteMetadata, ...ownUserLocalMetadata] + }, + ...otherUsers + ] + }); + } + } + async reconnect() { + if (this.retrying) + return; + try { + this.retrying = new AbortController(); + const url = await retry(this.getUrl, Infinity, this.maxReconnectBackoff, this.retrying.signal); + if (url) { + this.url = url; + this.socket = this.connect(); + } + else { + this.shutdown(); + } + } + catch (e) { + if (e.name !== 'AbortError') + throw e; + } + finally { + this.retrying = null; + } + } + getUrlWithPresenceId() { + const liveUrl = new URL(this.url, self.location.origin); + liveUrl.searchParams.set('shared', this.inSharedWorker.toString()); + liveUrl.searchParams.set('p', `${this.presenceId}.${this.connectionCount}`); + return liveUrl.toString(); + } + connect() { + const socket = new StableSocket(this.getUrlWithPresenceId(), this, this.options.socketPolicy || { + timeout: 4000, + attempts: 16, + maxDelay: 512000 + }); + socket.open(); + return socket; + } + sendSubscribe(topics) { + const entries = Array.from(topics); + for (const slice of eachSlice(entries, 25)) { + const subscribe = {}; + for (const topic of slice) { + if (isPresenceChannel(topic.name)) { + subscribe[topic.signed] = JSON.stringify(this.presenceMetadata.getChannelMetadata(topic.name)); + } + else { + subscribe[topic.signed] = topic.offset; + } + } + this.socket.send(JSON.stringify({ subscribe })); + } + } + sendUnsubscribe(topics) { + const signed = Array.from(topics, t => t.signed); + for (const slice of eachSlice(signed, 25)) { + this.socket.send(JSON.stringify({ unsubscribe: slice })); + } + for (const topic of topics) { + if (isPresenceChannel(topic.name)) { + this.presence.clearChannel(topic.name); + } + } + } +} diff --git a/socketworker/compat b/socketworker/compat new file mode 100644 index 0000000..1a88faa --- /dev/null +++ b/socketworker/compat @@ -0,0 +1,45 @@ +(() => { + if (typeof __webpack_require__ !== 'undefined') { + var oldGetScript = __webpack_require__.u; + var oldLoadScript = __webpack_require__.e; + var queryMap = {}; + var countMap = {}; + var getRetryDelay = function () { + return 0; + }; + __webpack_require__.u = function (chunkId) { + var result = oldGetScript(chunkId); + return ( + result + + (queryMap.hasOwnProperty(chunkId) ? '?' + queryMap[chunkId] : '') + ); + }; + __webpack_require__.e = function (chunkId) { + var result = oldLoadScript(chunkId); + return result.catch(function (error) { + var retries = countMap.hasOwnProperty(chunkId) ? countMap[chunkId] : 3; + if (retries < 1) { + var realSrc = oldGetScript(chunkId); + error.message = + 'Loading chunk ' + + chunkId + + ' failed after 3 retries.\n(' + + realSrc + + ')'; + error.request = realSrc; + throw error; + } + return new Promise(function (resolve) { + var retryAttempt = 3 - retries + 1; + setTimeout(function () { + var retryAttemptString = '&retry-attempt=' + retryAttempt; + var cacheBust = 'cache-bust=true' + retryAttemptString; + queryMap[chunkId] = cacheBust; + countMap[chunkId] = retries - 1; + resolve(__webpack_require__.e(chunkId)); + }, getRetryDelay(retryAttempt)); + }); + }); + }; + } +})(); diff --git a/socketworker/eventloop-tasks.js b/socketworker/eventloop-tasks.js new file mode 100644 index 0000000..13199a1 --- /dev/null +++ b/socketworker/eventloop-tasks.js @@ -0,0 +1,49 @@ +function whenAborted(signal) { + return new Promise((resolve, reject) => { + const error = new Error('aborted'); + error.name = 'AbortError'; + if (signal.aborted) { + reject(error); + } + else { + signal.addEventListener('abort', () => reject(error)); + } + }); +} +export async function wait(ms, signal) { + let id; + const done = new Promise(resolve => { + id = self.setTimeout(resolve, ms); + }); + if (!signal) + return done; + try { + await Promise.race([done, whenAborted(signal)]); + } + catch (e) { + self.clearTimeout(id); + throw e; + } +} +function rand(max) { + return Math.floor(Math.random() * Math.floor(max)); +} +export async function retry(fn, attempts, maxDelay = Infinity, signal) { + const aborted = signal ? whenAborted(signal) : null; + for (let i = 0; i < attempts; i++) { + try { + const op = aborted ? Promise.race([fn(), aborted]) : fn(); + return await op; + } + catch (e) { + if (e.name === 'AbortError') + throw e; + if (i === attempts - 1) + throw e; + const ms = Math.pow(2, i) * 1000; + const vary = rand(ms * 0.1); + await wait(Math.min(maxDelay, ms + vary), signal); + } + } + throw new Error('retry failed'); +} diff --git a/socketworker/multimapindex.js b/socketworker/multimapindex.js new file mode 100644 index 0000000..9fb6db7 --- /dev/null +++ b/socketworker/multimapindex.js @@ -0,0 +1,64 @@ +export default class MultiMap { + constructor(iterable) { + this.map = new Map(); + if (iterable) { + for (const [k, v] of iterable) { + this.set(k, v); + } + } + } + get(key) { + const values = this.map.get(key); + return values ? values : new Set(); + } + set(key, value) { + let values = this.map.get(key); + if (!values) { + values = new Set(); + this.map.set(key, values); + } + values.add(value); + return this; + } + has(key) { + return this.map.has(key); + } + delete(key, value) { + const values = this.map.get(key); + if (!values) + return false; + if (!value) + return this.map.delete(key); + const deleted = values.delete(value); + if (!values.size) + this.map.delete(key); + return deleted; + } + drain(value) { + const empty = []; + for (const key of this.keys()) { + if (this.delete(key, value) && !this.has(key)) { + empty.push(key); + } + } + return empty; + } + keys() { + return this.map.keys(); + } + values() { + return this.map.values(); + } + entries() { + return this.map.entries(); + } + [Symbol.iterator]() { + return this.entries(); + } + clear() { + this.map.clear(); + } + get size() { + return this.map.size; + } +} diff --git a/socketworker/presence-metadata.js b/socketworker/presence-metadata.js new file mode 100644 index 0000000..3f9ff46 --- /dev/null +++ b/socketworker/presence-metadata.js @@ -0,0 +1,81 @@ +export const IDLE_METADATA_KEY = '_i'; +function markMetadataAsLocal(metadata) { + return Object.assign(Object.assign({}, metadata), { isLocal: true }); +} +class PresenceMetadataForChannel { + constructor() { + this.subscriberMetadata = new Map(); + } + setMetadata(subscriber, value) { + this.subscriberMetadata.set(subscriber, value); + } + removeSubscribers(subscribers) { + let found = false; + for (const subscriber of subscribers) { + found = this.subscriberMetadata.delete(subscriber) || found; + } + return found; + } + getMetadata(localizationOptions) { + if (!localizationOptions) { + const allMetadata = []; + let idle; + for (const subscriberMetadata of this.subscriberMetadata.values()) { + for (const metadata of subscriberMetadata) { + if (IDLE_METADATA_KEY in metadata) { + const subscriberIsIdle = Boolean(metadata[IDLE_METADATA_KEY]); + idle = idle === undefined ? subscriberIsIdle : subscriberIsIdle && idle; + } + else { + allMetadata.push(metadata); + } + } + } + if (idle !== undefined) { + allMetadata.push({ [IDLE_METADATA_KEY]: idle ? 1 : 0 }); + } + return allMetadata; + } + const metadata = []; + const { subscriber, markAllAsLocal } = localizationOptions; + for (const [fromSubscriber, subscriberMetadata] of this.subscriberMetadata) { + const shouldLocalizeMetadata = markAllAsLocal || fromSubscriber === subscriber; + const metadataToAdd = shouldLocalizeMetadata ? subscriberMetadata.map(markMetadataAsLocal) : subscriberMetadata; + metadata.push(...metadataToAdd); + } + return metadata; + } + hasSubscribers() { + return this.subscriberMetadata.size > 0; + } +} +export class PresenceMetadataSet { + constructor() { + this.metadataByChannel = new Map(); + } + setMetadata({ subscriber, channelName, metadata }) { + let channelMetadata = this.metadataByChannel.get(channelName); + if (!channelMetadata) { + channelMetadata = new PresenceMetadataForChannel(); + this.metadataByChannel.set(channelName, channelMetadata); + } + channelMetadata.setMetadata(subscriber, metadata); + } + removeSubscribers(subscribers) { + const channelsWithSubscribers = new Set(); + for (const [channelName, channelMetadata] of this.metadataByChannel) { + const channelHadSubscriber = channelMetadata.removeSubscribers(subscribers); + if (channelHadSubscriber) { + channelsWithSubscribers.add(channelName); + } + if (!channelMetadata.hasSubscribers()) { + this.metadataByChannel.delete(channelName); + } + } + return channelsWithSubscribers; + } + getChannelMetadata(channelName, localizationOptions) { + const channelMetadata = this.metadataByChannel.get(channelName); + return (channelMetadata === null || channelMetadata === void 0 ? void 0 : channelMetadata.getMetadata(localizationOptions)) || []; + } +} diff --git a/socketworker/presence.js b/socketworker/presence.js new file mode 100644 index 0000000..5bdb087 --- /dev/null +++ b/socketworker/presence.js @@ -0,0 +1,78 @@ +export function getPresenceKey(userId, presenceId) { + return `${userId}:${presenceId}`; +} +export function decompressItem(data) { + const [presenceId, connectionCount] = data.p.split('.'); + return { + userId: data.u, + presenceKey: getPresenceKey(data.u, presenceId), + connectionCount: Number(connectionCount), + metadata: data.m || [] + }; +} +const presenceChannelPrefix = 'presence-'; +export function isPresenceChannel(channelName) { + return channelName.startsWith(presenceChannelPrefix); +} +class PresenceChannel { + constructor() { + this.presenceItems = new Map(); + } + shouldUsePresenceItem(item) { + const existingItem = this.presenceItems.get(item.presenceKey); + return !existingItem || existingItem.connectionCount <= item.connectionCount; + } + addPresenceItem(item) { + if (!this.shouldUsePresenceItem(item)) { + return; + } + this.presenceItems.set(item.presenceKey, item); + } + removePresenceItem(item) { + if (!this.shouldUsePresenceItem(item)) { + return; + } + this.presenceItems.delete(item.presenceKey); + } + replacePresenceItems(items) { + this.presenceItems.clear(); + for (const item of items) { + this.addPresenceItem(item); + } + } + getPresenceItems() { + return Array.from(this.presenceItems.values()); + } +} +export class AlivePresence { + constructor() { + this.presenceChannels = new Map(); + } + getPresenceChannel(channelName) { + const channel = this.presenceChannels.get(channelName) || new PresenceChannel(); + this.presenceChannels.set(channelName, channel); + return channel; + } + handleMessage(channelName, data) { + const channel = this.getPresenceChannel(channelName); + switch (data.e) { + case 'pf': + channel.replacePresenceItems(data.d.map(decompressItem)); + break; + case 'pa': + channel.addPresenceItem(decompressItem(data.d)); + break; + case 'pr': + channel.removePresenceItem(decompressItem(data.d)); + break; + } + return this.getChannelItems(channelName); + } + getChannelItems(channelName) { + const channel = this.getPresenceChannel(channelName); + return channel.getPresenceItems(); + } + clearChannel(channelName) { + this.presenceChannels.delete(channelName); + } +} diff --git a/socketworker/session.ts b/socketworker/session.ts new file mode 100644 index 0000000..5ed7537 --- /dev/null +++ b/socketworker/session.ts @@ -0,0 +1,45 @@ +import {AliveSession as BaseAliveSession} from '@github/alive-client' +import type {AliveSessionOptions, Notifier} from '@github/alive-client' +export class AliveSession extends BaseAliveSession { + #refreshUrl: string + constructor(url: string, refreshUrl: string, shared: boolean, notify: Notifier, options: AliveSessionOptions) { + super(url, () => this.#getUrlFromRefreshUrl(), shared, notify, undefined, options) + this.#refreshUrl = refreshUrl + } + + #getUrlFromRefreshUrl() { + return fetchRefreshUrl(this.#refreshUrl) + } +} + +type PostUrl = {url?: string; token?: string} +async function fetchRefreshUrl(url: string): Promise { + const data = await fetchJSON(url) + return data && data.url && data.token ? post(data.url, data.token) : null +} + +async function fetchJSON(url: string): Promise { + const response = await fetch(url, {headers: {Accept: 'application/json'}}) + if (response.ok) { + return response.json() + } else if (response.status === 404) { + return null + } else { + throw new Error('fetch error') + } +} + +async function post(url: string, csrf: string): Promise { + const response = await fetch(url, { + method: 'POST', + mode: 'same-origin', + headers: { + 'Scoped-CSRF-Token': csrf, + }, + }) + if (response.ok) { + return response.text() + } else { + throw new Error('fetch error') + } +} diff --git a/socketworker/socket-worker-15d0549033ee.js b/socketworker/socket-worker-15d0549033ee.js new file mode 100644 index 0000000..bbb0fbd --- /dev/null +++ b/socketworker/socket-worker-15d0549033ee.js @@ -0,0 +1,3 @@ +(()=>{"use strict";let e;if("undefined"!=typeof __webpack_require__){var t=__webpack_require__.u,s=__webpack_require__.e,n={},r={};__webpack_require__.u=function(e){return t(e)+(n.hasOwnProperty(e)?"?"+n[e]:"")},__webpack_require__.e=function(e){return s(e).catch(function(s){var i=r.hasOwnProperty(e)?r[e]:3;if(i<1){var a=t(e);throw s.message="Loading chunk "+e+` failed after 3 retries. +(`+a+")",s.request=a,s}return new Promise(function(t){var s=3-i+1;setTimeout(function(){n[e]="cache-bust=true&retry-attempt="+s,r[e]=i-1,t(__webpack_require__.e(e))},0)})})}}function i(e,t,s){if(!t.has(e))throw TypeError("attempted to "+s+" private field on non-instance");return t.get(e)}function a(e,t){if(t.has(e))throw TypeError("Cannot initialize the same private elements twice on an object")}function o(e){var t;let[s,n]=e.p.split(".");return{userId:e.u,presenceKey:(t=e.u,`${t}:${s}`),connectionCount:Number(n),metadata:e.m||[]}}function c(e){return e.startsWith("presence-")}let PresenceChannel=class PresenceChannel{constructor(){this.presenceItems=new Map}shouldUsePresenceItem(e){let t=this.presenceItems.get(e.presenceKey);return!t||t.connectionCount<=e.connectionCount}addPresenceItem(e){this.shouldUsePresenceItem(e)&&this.presenceItems.set(e.presenceKey,e)}removePresenceItem(e){this.shouldUsePresenceItem(e)&&this.presenceItems.delete(e.presenceKey)}replacePresenceItems(e){for(let t of(this.presenceItems.clear(),e))this.addPresenceItem(t)}getPresenceItems(){return Array.from(this.presenceItems.values())}};let AlivePresence=class AlivePresence{constructor(){this.presenceChannels=new Map}getPresenceChannel(e){let t=this.presenceChannels.get(e)||new PresenceChannel;return this.presenceChannels.set(e,t),t}handleMessage(e,t){let s=this.getPresenceChannel(e);switch(t.e){case"pf":s.replacePresenceItems(t.d.map(o));break;case"pa":s.addPresenceItem(o(t.d));break;case"pr":s.removePresenceItem(o(t.d))}return this.getChannelItems(e)}getChannelItems(e){return this.getPresenceChannel(e).getPresenceItems()}clearChannel(e){this.presenceChannels.delete(e)}};function l(e){return Object.assign(Object.assign({},e),{isLocal:!0})}let PresenceMetadataForChannel=class PresenceMetadataForChannel{constructor(){this.subscriberMetadata=new Map}setMetadata(e,t){this.subscriberMetadata.set(e,t)}removeSubscribers(e){let t=!1;for(let s of e)t=this.subscriberMetadata.delete(s)||t;return t}getMetadata(e){if(!e){let e,t=[];for(let s of this.subscriberMetadata.values())for(let n of s)if("_i"in n){let t=!!n._i;e=void 0===e?t:t&&e}else t.push(n);return void 0!==e&&t.push({_i:+!!e}),t}let t=[],{subscriber:s,markAllAsLocal:n}=e;for(let[e,r]of this.subscriberMetadata){let i=n||e===s?r.map(l):r;t.push(...i)}return t}hasSubscribers(){return this.subscriberMetadata.size>0}};let PresenceMetadataSet=class PresenceMetadataSet{constructor(){this.metadataByChannel=new Map}setMetadata({subscriber:e,channelName:t,metadata:s}){let n=this.metadataByChannel.get(t);n||(n=new PresenceMetadataForChannel,this.metadataByChannel.set(t,n)),n.setMetadata(e,s)}removeSubscribers(e){let t=new Set;for(let[s,n]of this.metadataByChannel)n.removeSubscribers(e)&&t.add(s),n.hasSubscribers()||this.metadataByChannel.delete(s);return t}getChannelMetadata(e,t){let s=this.metadataByChannel.get(e);return(null==s?void 0:s.getMetadata(t))||[]}};async function h(e,t){let s,n=new Promise((t,n)=>{s=self.setTimeout(()=>n(Error("timeout")),e)});if(!t)return n;try{await Promise.race([n,f(t)])}catch(e){throw self.clearTimeout(s),e}}async function u(e,t){let s,n=new Promise(t=>{s=self.setTimeout(t,e)});if(!t)return n;try{await Promise.race([n,f(t)])}catch(e){throw self.clearTimeout(s),e}}async function d(e,t,s=1/0,n){let r=n?f(n):null;for(let i=0;i{let n=Error("aborted");n.name="AbortError",e.aborted?s(n):e.addEventListener("abort",()=>s(n))})}async function p(e,t,s){var n;let r=new WebSocket(e),i=(n=r,new Promise((e,t)=>{n.readyState===WebSocket.OPEN?e(n):(n.onerror=()=>{n.onerror=null,n.onopen=null,t(Error("connect failed"))},n.onopen=()=>{n.onerror=null,n.onopen=null,e(n)})}));try{return await Promise.race([i,h(t,s)]),r}catch(e){throw m(i),e}}async function m(e){try{(await e).close()}catch(e){}}let StableSocket=class StableSocket{constructor(e,t,s){this.socket=null,this.opening=null,this.url=e,this.delegate=t,this.policy=s}async open(){if(this.opening||this.socket)return;this.opening=new AbortController;let e=Object.assign(Object.assign({},this.policy),{signal:this.opening.signal});try{var t;this.socket=await (t=this.url,d(()=>p(t,e.timeout,e.signal),e.attempts,e.maxDelay,e.signal))}catch(e){this.delegate.socketDidFinish(this);return}finally{this.opening=null}this.socket.onclose=e=>{var t;this.socket=null,this.delegate.socketDidClose(this,e.code,e.reason),(this.delegate.socketShouldRetry?this.delegate.socketShouldRetry(this,e.code):(t=e.code)!==b&&t!==g)?setTimeout(()=>this.open(),Math.random()*(100+(this.delegate.reconnectWindow||50)-100)+100):this.delegate.socketDidFinish(this)},this.socket.onmessage=e=>{this.delegate.socketDidReceiveMessage(this,e.data)},this.delegate.socketDidOpen(this)}close(e,t){this.opening?(this.opening.abort(),this.opening=null):this.socket&&(this.socket.onclose=null,this.socket.close(e,t),this.socket=null,this.delegate.socketDidClose(this,e,t),this.delegate.socketDidFinish(this))}send(e){this.socket&&this.socket.send(e)}isOpen(){return!!this.socket}};let b=1008,g=1011;let MultiMap=class MultiMap{constructor(e){if(this.map=new Map,e)for(const[t,s]of e)this.set(t,s)}get(e){return this.map.get(e)||new Set}set(e,t){let s=this.map.get(e);return s||(s=new Set,this.map.set(e,s)),s.add(t),this}has(e){return this.map.has(e)}delete(e,t){let s=this.map.get(e);if(!s)return!1;if(!t)return this.map.delete(e);let n=s.delete(t);return s.size||this.map.delete(e),n}drain(e){let t=[];for(let s of this.keys())this.delete(s,e)&&!this.has(s)&&t.push(s);return t}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}[Symbol.iterator](){return this.entries()}clear(){this.map.clear()}get size(){return this.map.size}};let SubscriptionSet=class SubscriptionSet{constructor(){this.subscriptions=new MultiMap,this.signatures=new Map}add(...e){let t=[];for(let{subscriber:s,topic:n}of e)this.subscriptions.has(n.name)||(t.push(n),this.signatures.set(n.name,n)),this.subscriptions.set(n.name,s);return t}delete(...e){let t=[];for(let{subscriber:s,topic:n}of e)this.subscriptions.delete(n.name,s)&&!this.subscriptions.has(n.name)&&(t.push(n),this.signatures.delete(n.name));return t}drain(...e){let t=[];for(let s of e)for(let e of this.subscriptions.drain(s)){let s=this.signatures.get(e);this.signatures.delete(e),t.push(s)}return t}topics(){return this.signatures.values()}topic(e){return this.signatures.get(e)||null}subscribers(e){return this.subscriptions.get(e).values()}};function*y(e,t){for(let s=0;s{let n=Error("aborted");n.name="AbortError",e.aborted?s(n):e.addEventListener("abort",()=>s(n))})}async function k(e,t){let s,n=new Promise(t=>{s=self.setTimeout(t,e)});if(!t)return n;try{await Promise.race([n,w(t)])}catch(e){throw self.clearTimeout(s),e}}async function M(e,t,s=1/0,n){let r=n?w(n):null;for(let i=0;i{this.intentionallyDisconnected=!0,this.socket.close(1e3,"Alive Redeploy Early Client Reconnect")},60*e*1e3)}}socketDidFinish(){"offline"!==this.state&&this.reconnect()}socketDidReceiveMessage(e,t){let s=JSON.parse(t);switch(s.e){case"ack":this.handleAck(s);break;case"msg":this.handleMessage(s)}}handleAck(e){for(let t of this.subscriptions.topics())t.offset=e.off}handleMessage(e){let t=e.ch,s=this.subscriptions.topic(t);if(s){if(s.offset=e.off,"e"in e.data){let s=this.presence.handleMessage(t,e.data);this.notifyPresenceChannel(t,s);return}e.data.wait||(e.data.wait=0),this.notify(this.subscriptions.subscribers(t),{channel:t,type:"message",data:e.data})}}notifyPresenceChannel(e,t){var s,n;let r=new Map;for(let e of t){let{userId:t,metadata:s,presenceKey:n}=e,i=r.get(t)||{userId:t,isOwnUser:t===this.userId,metadata:[]};if(n!==this.presenceKey){for(let e of s){if("_i"in e){!1!==i.isIdle&&(i.isIdle=!!e._i);continue}i.metadata.push(e)}r.set(t,i)}}for(let t of this.subscriptions.subscribers(e)){let i=this.userId,a=Array.from(r.values()).filter(e=>e.userId!==i),o=null!=(n=null==(s=r.get(this.userId))?void 0:s.metadata)?n:[],c=this.presenceMetadata.getChannelMetadata(e,{subscriber:t,markAllAsLocal:!this.inSharedWorker});this.notify([t],{channel:e,type:"presence",data:[{userId:i,isOwnUser:!0,metadata:[...o,...c]},...a]})}}async reconnect(){if(!this.retrying)try{this.retrying=new AbortController;let e=await M(this.getUrl,1/0,this.maxReconnectBackoff,this.retrying.signal);e?(this.url=e,this.socket=this.connect()):this.shutdown()}catch(e){if("AbortError"!==e.name)throw e}finally{this.retrying=null}}getUrlWithPresenceId(){let e=new URL(this.url,self.location.origin);return e.searchParams.set("shared",this.inSharedWorker.toString()),e.searchParams.set("p",`${this.presenceId}.${this.connectionCount}`),e.toString()}connect(){let e=new StableSocket(this.getUrlWithPresenceId(),this,this.options.socketPolicy||{timeout:4e3,attempts:16,maxDelay:512e3});return e.open(),e}sendSubscribe(e){for(let t of y(Array.from(e),25)){let e={};for(let s of t)c(s.name)?e[s.signed]=JSON.stringify(this.presenceMetadata.getChannelMetadata(s.name)):e[s.signed]=s.offset;this.socket.send(JSON.stringify({subscribe:e}))}}sendUnsubscribe(e){for(let t of y(Array.from(e,e=>e.signed),25))this.socket.send(JSON.stringify({unsubscribe:t}));for(let t of e)c(t.name)&&this.presence.clearChannel(t.name)}};var P,v,C=new WeakMap,S=new WeakSet;let AliveSession=class AliveSession extends alive_session_AliveSession{constructor(e,t,s,n,r){super(e,()=>(function(e,t,s){if(!t.has(e))throw TypeError("attempted to get private field on non-instance");return s})(this,S,_).call(this),s,n,void 0,r),function(e,t){a(e,t),t.add(e)}(this,S),function(e,t,s){a(e,t),t.set(e,s)}(this,C,{writable:!0,value:void 0}),function(e,t,s){var n=i(e,t,"set");if(n.set)n.set.call(e,s);else{if(!n.writable)throw TypeError("attempted to set read only private field");n.value=s}}(this,C,t)}};function _(){var e;return I((e=i(this,C,"get"),e.get?e.get.call(this):e.value))}async function I(e){let t=await A(e);return t&&t.url&&t.token?E(t.url,t.token):null}async function A(e){let t=await fetch(e,{headers:{Accept:"application/json"}});if(t.ok)return t.json();if(404===t.status)return null;throw Error("fetch error")}async function E(e,t){let s=await fetch(e,{method:"POST",mode:"same-origin",headers:{"Scoped-CSRF-Token":t}});if(s.ok)return s.text();throw Error("fetch error")}function D(e,t){for(let s of e)s.postMessage(t)}let O=(e=null,function(t){let s=t.target,n=t.data;n.connect&&!e?e=new AliveSession(n.connect.url,n.connect.refreshUrl,!0,D,n.connect.options):e&&function(e,t,s){let n=e=>({subscriber:t,topic:e});if(s.subscribe&&e.subscribe(s.subscribe.map(n)),s.unsubscribe&&e.unsubscribe(s.unsubscribe.map(n)),s.requestPresence&&e.requestPresence(t,s.requestPresence),s.updatePresenceMetadata){for(let e of s.updatePresenceMetadata)e.subscriber=t;e.updatePresenceMetadata(s.updatePresenceMetadata)}null!=s.online&&(s.online?e.online():e.offline()),s.hangup&&e.unsubscribeAll(t)}(e,s,n)});if(self.onconnect=e=>{let t=e.ports[0];t&&(t.onmessage=O)},"function"==typeof BroadcastChannel){let e=new BroadcastChannel("shared-worker-error");self.addEventListener("error",t=>{let{error:{name:s,message:n,stack:r}}=t;e.postMessage({error:{name:s,message:n,stack:r}})})}})(); +//# sourceMappingURL=socket-worker-eacb6da07a42.js.map \ No newline at end of file diff --git a/socketworker/socket-worker.ts b/socketworker/socket-worker.ts new file mode 100644 index 0000000..dbf83d6 --- /dev/null +++ b/socketworker/socket-worker.ts @@ -0,0 +1,93 @@ +import type {AliveEvent, AliveSessionOptions, MetadataUpdate, Topic} from '@github/alive-client' +import {AliveSession} from '@github-ui/alive/session' + +declare const self: SharedWorkerGlobalScope + +type Command = { + connect?: {url: string; refreshUrl: string; options: AliveSessionOptions} + subscribe?: Topic[] + unsubscribe?: Topic[] + requestPresence?: string[] + updatePresenceMetadata?: Array> + hangup?: boolean + online?: boolean +} + +function notify(subscribers: Iterable, event: AliveEvent) { + for (const port of subscribers) { + port.postMessage(event) + } +} + +function fromPort(session: AliveSession, port: MessagePort, data: Command) { + const toSub = (topic: Topic) => ({subscriber: port, topic}) + + if (data.subscribe) { + session.subscribe(data.subscribe.map(toSub)) + } + + if (data.unsubscribe) { + session.unsubscribe(data.unsubscribe.map(toSub)) + } + + if (data.requestPresence) { + session.requestPresence(port, data.requestPresence) + } + + if (data.updatePresenceMetadata) { + for (const update of data.updatePresenceMetadata) { + // Set the subscriber for the update + // This is used to track where the metadata originated + update.subscriber = port + } + session.updatePresenceMetadata(data.updatePresenceMetadata) + } + + if (data.online != null) { + if (data.online) { + session.online() + } else { + session.offline() + } + } + + if (data.hangup) { + session.unsubscribeAll(port) + } +} + +function withSocket(): (event: MessageEvent) => void { + let session: AliveSession | null = null + return function (event: MessageEvent) { + const port = event.target as MessagePort + const data = event.data as Command + if (data.connect && !session) { + session = new AliveSession(data.connect.url, data.connect.refreshUrl, true, notify, data.connect.options) + } else if (session) { + fromPort(session, port, data) + } + } +} + +const process = withSocket() + +self.onconnect = (event: MessageEvent) => { + const port = event.ports[0] + if (port) { + port.onmessage = process + } +} + +if (typeof BroadcastChannel === 'function') { + // Broadcast errors to all tabs. The tabs will then forward the error Sentry. + const errorChannel = new BroadcastChannel('shared-worker-error') + self.addEventListener('error', event => { + const { + error: {name, message, stack}, + } = event + + errorChannel.postMessage({ + error: {name, message, stack}, + }) + }) +} diff --git a/socketworker/stablesocketindex.js b/socketworker/stablesocketindex.js new file mode 100644 index 0000000..c4cbe2c --- /dev/null +++ b/socketworker/stablesocketindex.js @@ -0,0 +1,231 @@ +async function timeout(ms, signal) { + let id; + const done = new Promise((resolve, reject) => { + id = self.setTimeout(() => reject(new Error('timeout')), ms); + }); + if (!signal) + return done; + try { + await Promise.race([done, whenAborted(signal)]); + } + catch (e) { + self.clearTimeout(id); + throw e; + } +} +async function wait(ms, signal) { + let id; + const done = new Promise(resolve => { + id = self.setTimeout(resolve, ms); + }); + if (!signal) + return done; + try { + await Promise.race([done, whenAborted(signal)]); + } + catch (e) { + self.clearTimeout(id); + throw e; + } +} +async function retry(fn, attempts, maxDelay = Infinity, signal) { + const aborted = signal ? whenAborted(signal) : null; + for (let i = 0; i < attempts; i++) { + try { + const op = aborted ? Promise.race([fn(), aborted]) : fn(); + return await op; + } + catch (e) { + if (e.name === 'AbortError') + throw e; + if (i === attempts - 1) + throw e; + const ms = Math.pow(2, i) * 1000; + const vary = rand(ms * 0.1); + await wait(Math.min(maxDelay, ms + vary), signal); + } + } + throw new Error('retry failed'); +} +function whenAborted(signal) { + return new Promise((resolve, reject) => { + const error = new Error('aborted'); + error.name = 'AbortError'; + if (signal.aborted) { + reject(error); + } + else { + signal.addEventListener('abort', () => reject(error)); + } + }); +} +function rand(max) { + return Math.floor(Math.random() * Math.floor(max)); +} + +async function connect(url, ms, signal) { + const socket = new WebSocket(url); + const opened = whenOpen(socket); + try { + await Promise.race([opened, timeout(ms, signal)]); + return socket; + } + catch (e) { + shutdown(opened); + throw e; + } +} +async function shutdown(opened) { + try { + const socket = await opened; + socket.close(); + } + catch (_a) { + } +} +function connectWithRetry(url, policy) { + const fn = () => connect(url, policy.timeout, policy.signal); + return retry(fn, policy.attempts, policy.maxDelay, policy.signal); +} +function whenOpen(socket) { + return new Promise((resolve, reject) => { + if (socket.readyState === WebSocket.OPEN) { + resolve(socket); + } + else { + socket.onerror = () => { + socket.onerror = null; + socket.onopen = null; + reject(new Error('connect failed')); + }; + socket.onopen = () => { + socket.onerror = null; + socket.onopen = null; + resolve(socket); + }; + } + }); +} + +class StableSocket { + constructor(url, delegate, policy) { + this.socket = null; + this.opening = null; + this.url = url; + this.delegate = delegate; + this.policy = policy; + } + async open() { + if (this.opening || this.socket) + return; + this.opening = new AbortController(); + const policy = Object.assign(Object.assign({}, this.policy), { signal: this.opening.signal }); + try { + this.socket = await connectWithRetry(this.url, policy); + } + catch (_a) { + this.delegate.socketDidFinish(this); + return; + } + finally { + this.opening = null; + } + this.socket.onclose = (event) => { + this.socket = null; + this.delegate.socketDidClose(this, event.code, event.reason); + const fatal = this.delegate.socketShouldRetry + ? !this.delegate.socketShouldRetry(this, event.code) + : isFatal(event.code); + if (fatal) { + this.delegate.socketDidFinish(this); + } + else { + setTimeout(() => this.open(), rand$1(100, 100 + (this.delegate.reconnectWindow || 50))); + } + }; + this.socket.onmessage = (event) => { + this.delegate.socketDidReceiveMessage(this, event.data); + }; + this.delegate.socketDidOpen(this); + } + close(code, reason) { + if (this.opening) { + this.opening.abort(); + this.opening = null; + } + else if (this.socket) { + this.socket.onclose = null; + this.socket.close(code, reason); + this.socket = null; + this.delegate.socketDidClose(this, code, reason); + this.delegate.socketDidFinish(this); + } + } + send(data) { + if (this.socket) { + this.socket.send(data); + } + } + isOpen() { + return !!this.socket; + } +} +function rand$1(min, max) { + return Math.random() * (max - min) + min; +} +function isFatal(code) { + return code === POLICY_VIOLATION || code === INTERNAL_ERROR; +} +const POLICY_VIOLATION = 1008; +const INTERNAL_ERROR = 1011; + +class BufferedSocket { + constructor(socket) { + this.buf = []; + this.socket = socket; + this.delegate = socket.delegate; + socket.delegate = this; + } + open() { + return this.socket.open(); + } + close(code, reason) { + this.socket.close(code, reason); + } + send(data) { + if (this.socket.isOpen()) { + this.flush(); + this.socket.send(data); + } + else { + this.buf.push(data); + } + } + isOpen() { + return this.socket.isOpen(); + } + flush() { + for (const data of this.buf) { + this.socket.send(data); + } + this.buf.length = 0; + } + socketDidOpen(socket) { + this.flush(); + this.delegate.socketDidOpen(socket); + } + socketDidClose(socket, code, reason) { + this.delegate.socketDidClose(socket, code, reason); + } + socketDidFinish(socket) { + this.delegate.socketDidFinish(socket); + } + socketDidReceiveMessage(socket, message) { + this.delegate.socketDidReceiveMessage(socket, message); + } + socketShouldRetry(socket, code) { + return this.delegate.socketShouldRetry ? this.delegate.socketShouldRetry(socket, code) : !isFatal(code); + } +} + +export { BufferedSocket, StableSocket, connect, connectWithRetry }; diff --git a/socketworker/subscription-set.js b/socketworker/subscription-set.js new file mode 100644 index 0000000..f2fe0c3 --- /dev/null +++ b/socketworker/subscription-set.js @@ -0,0 +1,49 @@ +import MultiMap from '@github/multimap'; +export class SubscriptionSet { + constructor() { + this.subscriptions = new MultiMap(); + this.signatures = new Map(); + } + add(...subscriptions) { + const added = []; + for (const { subscriber, topic } of subscriptions) { + if (!this.subscriptions.has(topic.name)) { + added.push(topic); + this.signatures.set(topic.name, topic); + } + this.subscriptions.set(topic.name, subscriber); + } + return added; + } + delete(...subscriptions) { + const removed = []; + for (const { subscriber, topic } of subscriptions) { + const deleted = this.subscriptions.delete(topic.name, subscriber); + if (deleted && !this.subscriptions.has(topic.name)) { + removed.push(topic); + this.signatures.delete(topic.name); + } + } + return removed; + } + drain(...subscribers) { + const removed = []; + for (const subscriber of subscribers) { + for (const name of this.subscriptions.drain(subscriber)) { + const topic = this.signatures.get(name); + this.signatures.delete(name); + removed.push(topic); + } + } + return removed; + } + topics() { + return this.signatures.values(); + } + topic(name) { + return this.signatures.get(name) || null; + } + subscribers(topic) { + return this.subscriptions.get(topic).values(); + } +} diff --git a/suiteux..js b/suiteux..js new file mode 100644 index 0000000..2035dda --- /dev/null +++ b/suiteux..js @@ -0,0 +1,69 @@ +var shellPerformance=window.performance,HighResolutionTimingSupported=!!shellPerformance&&"function"==typeof shellPerformance.mark;HighResolutionTimingSupported&&shellPerformance.mark("shell_core_start"),function(){var e,t,n,o,r,i={57556:function(e,t,n){"use strict";var o;n.d(t,{f:function(){return o}}),function(e){e.depth0="0 0 0 0 transparent",e.depth4="0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",e.depth8="0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",e.depth16="0 6.4px 14.4px 0 rgba(0, 0, 0, 0.132), 0 1.2px 3.6px 0 rgba(0, 0, 0, 0.108)",e.depth64="0 25.6px 57.6px 0 rgba(0, 0, 0, 0.22), 0 4.8px 14.4px 0 rgba(0, 0, 0, 0.18)"}(o||(o={}))},71250:function(e,t,n){"use strict";var o;n.d(t,{d:function(){return o}}),function(e){e.USGOV_DOD="https://pf.events.data.microsoft.com/OneCollector/1.0/",e.USGOV_DOJ="https://tb.events.data.microsoft.com/OneCollector/1.0/",e.PUBLIC="https://browser.events.data.microsoft.com/OneCollector/1.0/",e.CUSTOMER_CONTENT="",e.EUDB="https://eu-office.events.data.microsoft.com/OneCollector/1.0/"}(o||(o={}))},32104:function(e){e.exports="data:font/woff;charset=utf-8;base64,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"},37875:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".EsS594twlMdbEJOPJo6UDg\\=\\={position:absolute;z-index:1000000;background-color:#fff;width:320px;min-width:320px;max-width:320px;box-sizing:border-box;outline:none;overflow-y:auto;visibility:visible;pointer-events:auto;border:1px solid #f4f4f4;border-radius:2px;box-shadow:0 8px 16px 0 rgba(0,0,0,.1);animation-duration:.15s;animation-name:contextMenu-slideIn;animation-timing-function:cubic-bezier(0,0,0,1);transform-origin:top;display:block;min-width:180px!important;outline-width:0;outline-color:invert}.u10sUHK1gkyWPJAvhySBrw\\=\\={margin:0;padding:0;list-style:none}.o365cs-base .gL7YLFs55DBFHGm0aAlvaw\\=\\={width:100%;height:100%;padding-right:40px;overflow-y:auto;overflow-x:hidden;box-sizing:content-box;position:relative}@keyframes contextMenu-slideIn{0%{opacity:0;transform:scaleY(.93)}to{opacity:1;transform:scaleY(1)}}",""]),t.locals={contextMenu:"EsS594twlMdbEJOPJo6UDg==",defaultList:"u10sUHK1gkyWPJAvhySBrw==",innerScroll:"gL7YLFs55DBFHGm0aAlvaw=="}},79928:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\={font-size:14px;display:block;box-sizing:border-box;margin:1px;padding:6px;text-align:left;height:32px;line-height:normal;animation-name:contextMenuItem-slideIn;animation-timing-function:linear;transition:background-color 83ms linear;border-style:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;align-content:center}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover{outline:none;transition:background-color .167s linear}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:focus{background-color:#e0dfdd}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:focus:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:focus:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:focus:focus{outline:1px dotted;outline:1px auto -webkit-focus-ring-color;outline-style:auto}@media (forced-colors:active),screen and (-ms-high-contrast:active){.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none}}@media (forced-colors:active)and (prefers-color-scheme:dark),screen and (-ms-high-contrast:white-on-black){.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none;color:#fff}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:hover,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:hover,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:hover{color:#000;background-color:#1aebff}}@media (forced-colors:active)and (prefers-color-scheme:light),screen and (-ms-high-contrast:black-on-white){.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none;color:#000}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:active:hover,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus:hover,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:hover:hover{color:#fff;background-color:#37006e}}@media(hover:none),(pointer:coarse){.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus,.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:focus-visible{border:2px solid highlight;padding:4px}}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:nth-child(2){animation-duration:.05s}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:nth-child(3){animation-duration:67ms}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=:nth-child(n+4){animation-duration:83ms}.o365cs-base .qLbnXrrpb1JPt\\+x0quZ\\+QQ\\=\\=>label{font-weight:400;margin:0;padding:0;font-size:14px;line-height:normal;color:currentColor!important}.o365cs-base .qqcB4nWgri26vFLL0yHLHw\\=\\={transition:color 83ms linear;display:inline-block;vertical-align:middle;padding-right:6px;padding-bottom:2px;width:20px;height:20px}@keyframes contextMenuItem-slideIn{0%{opacity:0}to{opacity:1}}",""]),t.locals={contextMenuItem:"qLbnXrrpb1JPt+x0quZ+QQ==",imgIcon:"qqcB4nWgri26vFLL0yHLHw=="}},18587:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".o365cs-base .rSDngy50C4hLvjN77R3dbA\\=\\={height:100%}",""]),t.locals={entrypointContainer:"rSDngy50C4hLvjN77R3dbA=="}},48643:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".eGE08z8aIfAkGe8BvkfeSw\\=\\={position:absolute;z-index:1000000;background-color:#fff;width:320px;min-width:320px;max-width:320px;box-sizing:border-box;outline:none;overflow-y:auto;visibility:visible;pointer-events:auto}.JPdZa9r8EHVwO2nsUxqScA\\=\\={z-index:1000001;position:fixed}",""]),t.locals={popup:"eGE08z8aIfAkGe8BvkfeSw==",react15Css:"JPdZa9r8EHVwO2nsUxqScA=="}},82819:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\={display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;border:1px solid hsla(0,0%,100%,0);box-shadow:0 1px 2px 0 rgba(0,0,0,.1);box-sizing:border-box;width:276px;padding-left:0;align-items:flex-start;margin:0 0 17px 16px}html[dir=rtl] .o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\={margin-left:0;margin-right:16px}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=:hover{-webkit-box-shadow:0 8px 16px 0 rgba(0,0,0,.1);box-shadow:0 8px 16px 0 rgba(0,0,0,.1)}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>button{min-width:30px;width:30px;height:36px;padding-left:10px;padding-right:10px;background-color:transparent;border:none;align-items:flex-start}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>input::-ms-clear{display:none}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>input::-webkit-search-cancel-button,.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>input::-webkit-search-decoration,.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>input::-webkit-search-results-button,.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=>input::-webkit-search-results-decoration{-webkit-appearance:none;display:none}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\= .j6BvNpCF90XiKxu0F7sZzw\\=\\={width:250px;height:32px;background:transparent;align-items:flex-start;border:none;display:block;font:13px SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;text-overflow:ellipsis;padding-left:5px;outline:none;margin:.1em}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\= .j6BvNpCF90XiKxu0F7sZzw\\=\\=:-internal-autofill-selected{background-color:transparent!important}.o365cs-base .oxbF2LyKwVB\\/a5\\+4gTMkFg\\=\\=:focus{cursor:text}.o365cs-base .nHk7LESAfIWtWyD9f7IM9g\\=\\={margin:0 0 5px 16px}',""]),t.locals={SearchControl:"oxbF2LyKwVB/a5+4gTMkFg==",inputBox:"j6BvNpCF90XiKxu0F7sZzw==",SearchControlZoomMargin:"nHk7LESAfIWtWyD9f7IM9g=="}},4377:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,"html[dir=rtl] ._7PGqXIlT8jItdB8fOBmFkg\\=\\={transform:scaleX(-1);-moz-transform:scaleX(-1);-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1)}",""]),t.locals={iconFontRTL:"_7PGqXIlT8jItdB8fOBmFkg=="}},59663:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.o365cs-base .TlAdlUrWd0Z6\\/TteKJSQig\\=\\={position:absolute}.o365cs-base .TlAdlUrWd0Z6\\/TteKJSQig\\=\\= ._1ZqUEbZKjUMrjQWoZseg6g\\=\\={font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;font-size:10px;position:absolute;width:16px;height:16px;line-height:15px;border-radius:1em;box-sizing:border-box;text-align:center;left:0}@media(-ms-high-contrast:active),(forced-colors:active){.o365cs-base .TlAdlUrWd0Z6\\/TteKJSQig\\=\\= ._1ZqUEbZKjUMrjQWoZseg6g\\=\\={-ms-high-contrast-adjust:none;forced-color-adjust:none;background-color:Highlight!important;color:highlightText!important}}.o365cs-base .TlAdlUrWd0Z6\\/TteKJSQig\\=\\= ._56EuyMD2soE1\\/gKXBY0q9g\\=\\={top:7px;width:8px;height:8px;border:1px solid #fff;border-radius:4px}.o365cs-base .TlAdlUrWd0Z6\\/TteKJSQig\\=\\= .\\+OLPNIF6B5kKoA97J3vVpw\\=\\={border-color:#000}',""]),t.locals={unseenitems:"TlAdlUrWd0Z6/TteKJSQig==",unseenCount:"_1ZqUEbZKjUMrjQWoZseg6g==",emptyBadge:"_56EuyMD2soE1/gKXBY0q9g==",emptyBadgeDarkMode:"+OLPNIF6B5kKoA97J3vVpw=="}},73966:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar{width:8px}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button,.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-corner,.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-track{background-color:transparent}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button{background-repeat:no-repeat;cursor:pointer}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button:vertical{background-position:50%;width:18px;height:18px}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button:vertical:increment{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAUUlEQVQ4T6XLMQ6AMAwEwfz/bXRIfOeQCxckK8iKYgqvfCPJLxgNjAZGA6OB0VjCcV55M/8/jkbDMv+VJbSdccHYvsYFo4HRwGhgNDAaGPdl3LNlBnofQ4+bAAAAAElFTkSuQmCC)}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button:vertical:increment:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAUklEQVQ4T6XLsQ2AMAwF0ey/A1swAnt95MIFyQlyoniFT/4jyS8YDYwGRgOjgdFYwnFeeTP/P45GwzL/lSW0nXHB2L7GBaOB0cBoYDQwGhj3Zdx8sf7rjOGQqwAAAABJRU5ErkJggg==)}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button:vertical:decrement{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAVUlEQVQ4T6XMMQoAIQxEUe9/NrsFrzOSIqDxgzu7xSv8ZGySfsHowOjA6MDowOjAmPozFGpfYQw5vn2CsY5TvQtHoOGq3m+PLzA6MDowOjA6ML6nNgFW+wZ6kTk6FAAAAABJRU5ErkJggg==)}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-button:vertical:decrement:hover{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAVklEQVQ4T6XMwQ3AIAwEQfrvgS5SAn0d8sMSmJXIJY95sPLRJP2C0YHRgdGB0YHRgTH1ZyjUvsIYcnz7BGMdp3oXjkDDVb3fHl9gdGB0YHRgdGB8T20CB+X+675uLU0AAAAASUVORK5CYII=)}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-thumb{border-radius:9px;border:3px solid transparent;background-color:#ccd3d6}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-thumb:vertical{min-height:50px}.o365cs-base .XNCq\\+l4QufHtwDhOGdcrEA\\=\\=::-webkit-scrollbar-thumb:hover{background-color:#9db4c4}.o365cs-base .oDjNsKgU0LouSL2Cszjoaw\\=\\={display:flex;font-family:SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif!important;font-weight:600;background:transparent!important;border:0;padding:0;min-width:0;height:auto;text-decoration:none!important;cursor:pointer}.o365cs-base .oDjNsKgU0LouSL2Cszjoaw\\=\\=>span{padding-bottom:2px;transition:border-bottom-color 83ms linear}.o365cs-base .oDjNsKgU0LouSL2Cszjoaw\\=\\=:hover>span{border-bottom:1px solid;padding-bottom:1px}',""]),t.locals={scrollbar:"XNCq+l4QufHtwDhOGdcrEA==",fluentLink:"oDjNsKgU0LouSL2Cszjoaw=="}},41306:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.NszUgtzDfx0t1PQrucmvnA\\=\\={display:block}.c6QE6q0imyqZPiHyLPm9YA\\=\\={font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif}.uGAx4CbRh\\+jEaMdf4Etv7w\\=\\={font-family:SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;font-weight:600}.vmO5rYvtVrmsybm3QJFJUw\\=\\={font-family:SegoeUI-Light-final,Segoe UI Light,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif}.Q8qHkqThZ3HCwPmk\\+m2bFQ\\=\\={font-family:SegoeUI-SemiLight-final,Segoe UI Semilight,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif}.iDm2WTqpMgwzbBSSRlbuog\\=\\={font-family:Arial,SegoeUI-Regular-final,Segoe UI,Segoe,Tahoma,Helvetica,sans-serif}',""]),t.locals={displayBlock:"NszUgtzDfx0t1PQrucmvnA==",segoeRegular:"c6QE6q0imyqZPiHyLPm9YA==",segoeSemibold:"uGAx4CbRh+jEaMdf4Etv7w==",segoeLight:"vmO5rYvtVrmsybm3QJFJUw==",segoeSemiLight:"Q8qHkqThZ3HCwPmk+m2bFQ==",arialRegular:"iDm2WTqpMgwzbBSSRlbuog=="}},35843:function(e,t,n){t=e.exports=n(63585)(!1);var o=n(80268)(n(32104));t.push([e.id,"@font-face{font-family:ShellFabricMDL2Icons;src:url("+o+');font-weight:400;font-style:normal}.o365cs-base .ms-Icon--Settings:before{content:""}.o365cs-base .ms-Icon--Ringer:before{content:"îª"}.o365cs-base .ms-Icon--Help:before{content:""}.o365cs-base .ms-Icon--BookingsDoDLogo:before,.o365cs-base .ms-Icon--BusinessCentralLogo:before,.o365cs-base .ms-Icon--ClipchampLogo:before,.o365cs-base .ms-Icon--CloudPCLogo:before,.o365cs-base .ms-Icon--CopilotLogo:before,.o365cs-base .ms-Icon--DefenderLogo:before,.o365cs-base .ms-Icon--DesignerLogo:before,.o365cs-base .ms-Icon--EditorLogo:before,.o365cs-base .ms-Icon--FamilySafetyLogo:before,.o365cs-base .ms-Icon--LearningActivitiesLogo:before,.o365cs-base .ms-Icon--LighthouseLogo:before,.o365cs-base .ms-Icon--LoopLogo:before,.o365cs-base .ms-Icon--M365CopilotNewLogo:before,.o365cs-base .ms-Icon--MeshLogo:before,.o365cs-base .ms-Icon--Microsoft365Logo:before,.o365cs-base .ms-Icon--MicrosoftReflectLogo:before,.o365cs-base .ms-Icon--MoreAppsDarkLogo:before,.o365cs-base .ms-Icon--MoreAppsLogo:before,.o365cs-base .ms-Icon--PowerPagesLogo:before,.o365cs-base .ms-Icon--PrivacyLogo:before,.o365cs-base .ms-Icon--PurviewLogo:before,.o365cs-base .ms-Icon--ReadingCoachLogo:before,.o365cs-base .ms-Icon--RewardsLogo:before,.o365cs-base .ms-Icon--VivaAmplifyLogo:before,.o365cs-base .ms-Icon--VivaConnectionsLogo:before,.o365cs-base .ms-Icon--VivaEngageLogo:before,.o365cs-base .ms-Icon--VivaGlintLogo:before,.o365cs-base .ms-Icon--VivaGoalsLogo:before,.o365cs-base .ms-Icon--VivaHomeLogo:before,.o365cs-base .ms-Icon--VivaInsightsLogo:before,.o365cs-base .ms-Icon--VivaLearningLogo:before,.o365cs-base .ms-Icon--VivaPulseLogo:before,.o365cs-base .ms-Icon--VivaTopicsLogo:before,.o365cs-base .ms-Icon--WaffleOffice365:before{content:"ï“ "}.o365cs-base .ms-Icon--Search:before{content:""}.o365cs-base .ms-Icon--Contact:before{content:"î»"}.o365cs-base .ms-Icon--CustomerVoiceLogo:before{content:"î“·"}.o365cs-base .ms-Icon--ListsLogo:before{content:"î“™"}.o365cs-base .ms-Icon--AddIn:before{content:"ïµ"}.o365cs-base .ms-Icon--AdminALogo:before{content:""}.o365cs-base .ms-Icon--AdminPLogo:before{content:"îµ±"}.o365cs-base .ms-Icon--AnalyticsLogo:before{content:""}.o365cs-base .ms-Icon--AlarmClock:before{content:""}.o365cs-base .ms-Icon--Back:before{content:""}.o365cs-base .ms-Icon--BingLogo:before{content:"î­«"}.o365cs-base .ms-Icon--BookingsLogo:before{content:"î·‡"}.o365cs-base .ms-Icon--BusinessCenterLogo:before{content:"ï’²"}.o365cs-base .ms-Icon--Calendar:before{content:""}.o365cs-base .ms-Icon--Camera:before{content:""}.o365cs-base .ms-Icon--CaretSolidDown:before{content:""}.o365cs-base .ms-Icon--Chart:before{content:""}.o365cs-base .ms-Icon--ChatCircleArrow:before{content:"ï‡"}.o365cs-base .ms-Icon--ChatCircleCheck:before{content:"î½½"}.o365cs-base .ms-Icon--ChatCircleClock:before{content:"î½¾"}.o365cs-base .ms-Icon--ChatCircleMinus:before{content:""}.o365cs-base .ms-Icon--CheckMark:before{content:""}.o365cs-base .ms-Icon--ChevronDownMed:before{content:""}.o365cs-base .ms-Icon--ChevronLeft:before{content:"î«"}.o365cs-base .ms-Icon--ChevronRight:before{content:"î¬"}.o365cs-base .ms-Icon--ChevronUpMed:before{content:""}.o365cs-base .ms-Icon--ChromeClose:before{content:""}.o365cs-base .ms-Icon--CircleFill:before{content:""}.o365cs-base .ms-Icon--ClassNotebookLogo32:before{content:"ï’†"}.o365cs-base .ms-Icon--ClassroomLogo:before{content:"î½µ"}.o365cs-base .ms-Icon--Clear:before{content:""}.o365cs-base .ms-Icon--Delete:before{content:"î"}.o365cs-base .ms-Icon--Diamond:before{content:"î´‚"}.o365cs-base .ms-Icon--DocsLogoInverse:before{content:"î·‹"}.o365cs-base .ms-Icon--Download:before{content:""}.o365cs-base .ms-Icon--DynamicSMBLogo:before{content:"î·"}.o365cs-base .ms-Icon--Dynamics365Logo:before{content:"î·Œ"}.o365cs-base .ms-Icon--Emoji2:before{content:"î®"}.o365cs-base .ms-Icon--ExcelLogo:before{content:""}.o365cs-base .ms-Icon--Event:before{content:"î²£"}.o365cs-base .ms-Icon--EventToDoLogo:before{content:"ï¡©"}.o365cs-base .ms-Icon--FeatureFlagsLogo:before{content:"îŸ"}.o365cs-base .ms-Icon--FolderHorizontal:before{content:"ï„«"}.o365cs-base .ms-Icon--FileASPX:before{content:"ï‹©"}.o365cs-base .ms-Icon--Forward:before{content:""}.o365cs-base .ms-Icon--FullCircleMask:before{content:""}.o365cs-base .ms-Icon--GallatinLogo:before{content:"ï’–"}.o365cs-base .ms-Icon--GlobalNavButton:before{content:""}.o365cs-base .ms-Icon--Globe:before{content:"î´"}.o365cs-base .ms-Icon--HelpMirrored:before{content:"î©‘"}.o365cs-base .ms-Icon--History:before{content:"î œ"}.o365cs-base .ms-Icon--Info:before{content:""}.o365cs-base .ms-Icon--KaizalaLogo:before{content:"ï’’"}.o365cs-base .ms-Icon--Lightbulb:before{content:""}.o365cs-base .ms-Icon--MSNLogo:before{content:"î­¬"}.o365cs-base .ms-Icon--Mail:before{content:""}.o365cs-base .ms-Icon--MicrosoftFlowLogo:before{content:"ï’±"}.o365cs-base .ms-Icon--MicrosoftStaffhubLogo:before{content:"ï„°"}.o365cs-base .ms-Icon--More:before{content:""}.o365cs-base .ms-Icon--MoreVertical:before{content:""}.o365cs-base .ms-Icon--M365InvoicingLogo:before{content:"ïŸ"}.o365cs-base .ms-Icon--NavigateExternalInline:before{content:"ïŸ"}.o365cs-base .ms-Icon--News:before{content:""}.o365cs-base .ms-Icon--NonprofitLogo32:before{content:"ï’•"}.o365cs-base .ms-Icon--OfficeAddinsLogo:before{content:""}.o365cs-base .ms-Icon--OfficeChat:before{content:"ïœ"}.o365cs-base .ms-Icon--OfficeChatSolid:before{content:"ïœ"}.o365cs-base .ms-Icon--OfficeFormsLogo:before{content:"ï´"}.o365cs-base .ms-Icon--OfficeLogo:before{content:"î­®"}.o365cs-base .ms-Icon--OfficeVideoLogo:before{content:""}.o365cs-base .ms-Icon--OneDrive:before{content:"î¥"}.o365cs-base .ms-Icon--OneNoteLogo:before{content:""}.o365cs-base .ms-Icon--OutlookLogo:before{content:""}.o365cs-base .ms-Icon--Page:before{content:""}.o365cs-base .ms-Icon--ParatureLogo:before{content:"îµ»"}.o365cs-base .ms-Icon--People:before{content:""}.o365cs-base .ms-Icon--Phone:before{content:""}.o365cs-base .ms-Icon--Pinned:before{content:"î¡€"}.o365cs-base .ms-Icon--PlannerLogo:before{content:"î·‘"}.o365cs-base .ms-Icon--PopExpand:before{content:"î’š"}.o365cs-base .ms-Icon--PowerAppsLogo:before{content:"ï‚‘"}.o365cs-base .ms-Icon--PowerBILogo:before{content:""}.o365cs-base .ms-Icon--PowerPointLogo:before{content:""}.o365cs-base .ms-Icon--ProjectLogo32:before{content:""}.o365cs-base .ms-Icon--ProtectionCenterLogo32:before{content:"ï’”"}.o365cs-base .ms-Icon--QuickNote:before{content:""}.o365cs-base .ms-Icon--SecurityLogo:before{content:"î¶…"}.o365cs-base .ms-Icon--SharepointLogo:before{content:""}.o365cs-base .ms-Icon--SkypeForBusinessLogo:before{content:""}.o365cs-base .ms-Icon--SkypeLogo:before{content:"î­¯"}.o365cs-base .ms-Icon--SocialListeningLogo:before{content:"îµ¼"}.o365cs-base .ms-Icon--StaffNotebookLogo32:before{content:"ï’Œ"}.o365cs-base .ms-Icon--StoreLogo:before{content:""}.o365cs-base .ms-Icon--StreamLogo:before{content:""}.o365cs-base .ms-Icon--SwayLogo32:before{content:"ï’‚"}.o365cs-base .ms-Icon--TaskLogo:before{content:"ï’“"}.o365cs-base .ms-Icon--TeamsLogo:before{content:""}.o365cs-base .ms-Icon--ToDoLogoInverse:before{content:"ï’¼"}.o365cs-base .ms-Icon--ToDoLogoOutline:before{content:"ï›"}.o365cs-base .ms-Icon--ToggleBorder:before{content:"î°’"}.o365cs-base .ms-Icon--ToggleThumb:before{content:"î°”"}.o365cs-base .ms-Icon--UnknownSolid:before{content:"ï‹¡"}.o365cs-base .ms-Icon--Unpin:before{content:"îº"}.o365cs-base .ms-Icon--Video:before{content:""}.o365cs-base .ms-Icon--VisioLogo:before{content:""}.o365cs-base .ms-Icon--Warning:before{content:""}.o365cs-base .ms-Icon--WhiteboardLogo:before{content:"ï™´"}.o365cs-base .ms-Icon--WordLogo:before{content:""}.o365cs-base .ms-Icon--YammerLogo:before{content:"î´™"}',""])},72189:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".o365cs-base ._8kgf\\/hwnaG6yDp7ROaUTXQ\\=\\={height:100%}.o365cs-base .al\\+TT2aHbwgQ07YKgWsrZw\\=\\={width:100%}.o365cs-base .v02KEC8zreNUdRsgFKjILA\\=\\={float:left}.o365cs-base ._8oKR2YgB\\/Xftf\\+UcYXBF8w\\=\\={float:right}.o365cs-base .VzNFGH0cG\\+njOb21wXfhhA\\=\\={display:table}.o365cs-base .vcfp76jyih\\+ENVqQ\\/8DFnw\\=\\={display:table-cell;vertical-align:top}.o365cs-base .JalJSTN5KL5K7CcIcQkzbA\\=\\={display:table-cell;vertical-align:bottom}.o365cs-base .DjQ3\\+qKHwG9bQOOkLpHAlw\\=\\={display:table-cell;vertical-align:middle}.o365cs-base .Eke7MaGTyd6e99459bb4rg\\=\\={display:none}.o365cs-base .TgJAsY26sVHapvCKU8XENA\\=\\={position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0}",""]),t.locals={maxHeight:"_8kgf/hwnaG6yDp7ROaUTXQ==",maxWidth:"al+TT2aHbwgQ07YKgWsrZw==",floatLeft:"v02KEC8zreNUdRsgFKjILA==",floatRight:"_8oKR2YgB/Xftf+UcYXBF8w==",table:"VzNFGH0cG+njOb21wXfhhA==",tableCellTop:"vcfp76jyih+ENVqQ/8DFnw==",tableCellBottom:"JalJSTN5KL5K7CcIcQkzbA==",tableCellMiddle:"DjQ3+qKHwG9bQOOkLpHAlw==",hidden:"Eke7MaGTyd6e99459bb4rg==",visuallyHidden:"TgJAsY26sVHapvCKU8XENA=="}},86258:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,".LOH65mHND5UuJ9b5MOPIyg\\=\\={height:calc(100vh - 115px)}.EjkBtpEVGYQK1q\\/td6mhdg\\=\\={height:calc(100vh - 113px)}.sbU\\+9csU7o21SILr6MJmgw\\=\\={height:calc(100vh - 73px)}",""]),t.locals={flexPaneContentContainer:"LOH65mHND5UuJ9b5MOPIyg==",flexPaneContentContainerForThinHeader:"EjkBtpEVGYQK1q/td6mhdg==",flexPaneContentContainerForShyHeader:"sbU+9csU7o21SILr6MJmgw=="}},16832:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.TaSuqlyJ5MSqTQbXTeS3tQ\\=\\={font-family:ShellFabricMDL2IconsLite,ShellFabricMDL2Icons;line-height:1}.TaSuqlyJ5MSqTQbXTeS3tQ\\=\\= .o365cs-base [class*=" ms-Icon--"]:before,.TaSuqlyJ5MSqTQbXTeS3tQ\\=\\= .o365cs-base [class^=ms-Icon--]:before{font-family:inherit}.HKHsnwPD9asgCY\\/1RHVuQw\\=\\=,.I4nj8afMLjWpJ2UOud88zg\\=\\={height:100%}',""]),t.locals={customHeaderButton:"TaSuqlyJ5MSqTQbXTeS3tQ==",customHeaderButtonsContainer:"HKHsnwPD9asgCY/1RHVuQw==",customHeaderButtonWrapper:"I4nj8afMLjWpJ2UOud88zg=="}},76193:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,"._9i5RwVv0f00JLPQL7I\\+Y8Q\\=\\={width:360px;height:calc(100vh - 50px);overflow:hidden;position:fixed;z-index:1000000;top:50px;right:0;pointer-events:none}.X6jmOJbtPxrdLcpMF7gbRg\\=\\= iframe{height:1000px!important;overflow:hidden;position:absolute}.mdn3zwUjEpxe5XhvWdUUVg\\=\\={height:calc(100vh - 48px);top:48px}.f3ZNvJ3t0PnWAgoWv5LY2g\\=\\={height:calc(100vh - 8px);top:8px}@-moz-document url-prefix(){.XlKf\\+hNIUsKJ42S9ybY7rg\\=\\=:focus{outline:1px dotted}}.o365cs-base .fHsS8WIbhHVDlPRycq1MWw\\=\\={height:100%;position:absolute;right:0;z-index:1000000;width:320px;border-style:solid;pointer-events:all;border-width:0 0 0 1px;box-sizing:content-box}.o365cs-base .xRFEaPmwULXdFRg6xb0jHA\\=\\={border-color:#000;border-left-width:1px!important}.o365cs-base ._0um\\+0lXKfaqA\\+25RpmAufw\\=\\={height:100%}.o365cs-base .Pq9Aph\\+WaJhC6xHpxryKyw\\=\\={position:relative;overflow-y:auto;overflow-x:hidden}.o365cs-base .WtohaYWvzS3cfEoZF4BuZA\\=\\={-ms-flex:1;flex:1;overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;height:100%}.o365cs-base .WtohaYWvzS3cfEoZF4BuZA\\=\\=:not(:-webkit-any-link){box-sizing:border-box}.o365cs-base .XlKf\\+hNIUsKJ42S9ybY7rg\\=\\={margin:0 auto 1px}.o365cs-base .ABsUeIawNiAydZM8TZ9GHg\\=\\={height:40px;width:40px;min-width:0;position:absolute;top:12px;left:calc(100% - 44px);padding:5px;border-width:0;background-color:transparent;text-align:center;cursor:pointer}.o365cs-base .ABsUeIawNiAydZM8TZ9GHg\\=\\=:focus{outline:1px dotted;outline:1px auto -webkit-focus-ring-color;outline-style:auto}.o365cs-base .jt1UvlCr1DTxe8MYybrikA\\=\\={-webkit-animation-name:flexPane-fadeIn,flexPane-slideRightIn;animation-name:flexPane-fadeIn,flexPane-slideRightIn;-webkit-animation-duration:.28s;animation-duration:.28s;-webkit-animation-timing-function:cubic-bezier(.8,0,.2,1);animation-timing-function:cubic-bezier(.8,0,.2,1)}.o365cs-base ._8OLH5zBoaL4dWYE73YqcfA\\=\\={-webkit-animation-name:flexPane-fadeOut,flexPane-slideRightOut;animation-name:flexPane-fadeOut,flexPane-slideRightOut;-webkit-animation-duration:.16s;animation-duration:.16s;-webkit-animation-timing-function:cubic-bezier(.8,0,.2,1);animation-timing-function:cubic-bezier(.8,0,.2,1);-webkit-animation-fill-mode:both;animation-fill-mode:both}.o365cs-base ._2\\/XVFgy7oOJ2PRdV0nb7xg\\=\\={visibility:hidden}@-webkit-keyframes flexPane-fadeIn{0%{visibility:hidden;opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}to{visibility:visible;opacity:1}}@keyframes flexPane-fadeIn{0%{visibility:hidden;opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}to{visibility:visible;opacity:1}}@-webkit-keyframes flexPane-fadeOut{0%{visibility:visible;opacity:1;-webkit-animation-timing-function:linear;animation-timing-function:linear}to{visibility:hidden;opacity:0}}@keyframes flexPane-fadeOut{0%{visibility:visible;opacity:1;-webkit-animation-timing-function:linear;animation-timing-function:linear}to{visibility:hidden;opacity:0}}@-webkit-keyframes flexPane-slideRightIn{0%{-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}to{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}}@keyframes flexPane-slideRightIn{0%{-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}to{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}}@-webkit-keyframes flexPane-slideRightOut{0%{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}to{-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}}@keyframes flexPane-slideRightOut{0%{-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}to{-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}}.o365cs-base .JQUzjR1BqzgYWBFcHEPQkQ\\=\\={-webkit-animation-name:flexPaneItem-slideContentIn;animation-name:flexPaneItem-slideContentIn;-webkit-animation-duration:.28s;animation-duration:.28s;-webkit-animation-timing-function:cubic-bezier(.8,0,.2,1);animation-timing-function:cubic-bezier(.8,0,.2,1);-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards;-webkit-animation-delay:.04s;animation-delay:.04s}.o365cs-base .hjnv9tRBywIVLOVT0rwOpA\\=\\={-webkit-animation-name:flexPane-fadeOut,flexPane-slideRightOut;animation-name:flexPane-fadeOut,flexPane-slideRightOut;-webkit-animation-duration:.16s;animation-duration:.16s;-webkit-animation-timing-function:cubic-bezier(.8,0,.2,1);animation-timing-function:cubic-bezier(.8,0,.2,1);-webkit-animation-fill-mode:backwards;animation-fill-mode:backwards}@-webkit-keyframes flexPaneItem-slideContentIn{0%{opacity:0;-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}to{opacity:1;-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}}@keyframes flexPaneItem-slideContentIn{0%{opacity:0;-webkit-transform:translate(80px);-ms-transform:translate(80px);transform:translate(80px)}to{opacity:1;-webkit-transform:translate(0);-ms-transform:translate(0);transform:translate(0)}}",""]),t.locals={flexPaneOverflowWidth:"360px",flexPaneWidth:"320px",thinFlexPaneOverflowWidth:"310px",thinFlexPaneWidth:"270px",flexPaneOverflowContainer:"_9i5RwVv0f00JLPQL7I+Y8Q==",flexPaneZoomIFrameHeight:"X6jmOJbtPxrdLcpMF7gbRg==",flexPaneHeightForThinHeader:"mdn3zwUjEpxe5XhvWdUUVg==",flexPaneHeightForShyHeader:"f3ZNvJ3t0PnWAgoWv5LY2g==",closeIcon:"XlKf+hNIUsKJ42S9ybY7rg==",flexPaneOverlay:"fHsS8WIbhHVDlPRycq1MWw==",darkBorder:"xRFEaPmwULXdFRg6xb0jHA==",flexPaneComponent:"_0um+0lXKfaqA+25RpmAufw==",flexPaneContainer:"Pq9Aph+WaJhC6xHpxryKyw==",verticalScrollRegion:"WtohaYWvzS3cfEoZF4BuZA==",closeButton:"ABsUeIawNiAydZM8TZ9GHg==",flexPaneShowRight:"jt1UvlCr1DTxe8MYybrikA==",flexPaneHideRight:"_8OLH5zBoaL4dWYE73YqcfA==",flexPaneHidden:"_2/XVFgy7oOJ2PRdV0nb7xg==",itemShow:"JQUzjR1BqzgYWBFcHEPQkQ==",itemHide:"hjnv9tRBywIVLOVT0rwOpA=="}},58984:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.o365cs-base .f5ba\\/8qghSGxJEKWPtai6A\\=\\={padding-left:16px;padding-right:16px}.o365cs-base ._6993O\\+eOvKnD2lo\\+d3S\\/KQ\\=\\={font:600 20px SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;display:inline-block;margin:0;line-height:27px;padding-left:16px;padding-top:20px;padding-bottom:18px;vertical-align:middle}.o365cs-base .\\/qOktybF63BhiAEUFHIu8A\\=\\={display:flex;font-family:SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif!important;font-weight:600;background:transparent!important;border:0;min-width:0;height:auto;text-decoration:none!important;cursor:pointer;display:inline-block;font-size:12px;vertical-align:middle;padding:10px 0 0 16px;width:auto}.o365cs-base .\\/qOktybF63BhiAEUFHIu8A\\=\\=>span{padding-bottom:2px;transition:border-bottom-color 83ms linear}.o365cs-base .\\/qOktybF63BhiAEUFHIu8A\\=\\=:hover>span{border-bottom:1px solid;padding-bottom:1px}.o365cs-base .N\\+CwwxeyNQqLhH2xWvWJ8w\\=\\={font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;font-size:14px;font-weight:600;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}',""]),t.locals={flexPaneSidePadding:"f5ba/8qghSGxJEKWPtai6A==",itemTitle:"_6993O+eOvKnD2lo+d3S/KQ==",backButton:"/qOktybF63BhiAEUFHIu8A==",backIcon:"N+CwwxeyNQqLhH2xWvWJ8w=="}},17168:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.o365cs-base.oxqgTC3pSRhOfrgHfYUrfw\\=\\={padding-bottom:2px;width:auto}.o365cs-base .MP9y\\+OCUQ0Dsy6Z6A0P7qg\\=\\={padding:12px 20px 12px 8px;font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;font-weight:400;line-height:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o365cs-base .U3BBQu\\+2xhg0uuDXS\\/n8\\+g\\=\\={display:"inline-block";font-size:16px;padding-right:16px;vertical-align:middle}.o365cs-base .Si\\+F1NEyl39azkbswg7g8w\\=\\={padding-left:16px}.o365cs-base ._21b4kBzHkdpWCgCgA\\+VRlQ\\=\\={left:16px;top:8px}.o365cs-base .FdC5CgNe2qQBXGbOKlNuew\\=\\={justify-content:flex-end;max-width:48px}',""]),t.locals={affordanceContextMenu:"oxqgTC3pSRhOfrgHfYUrfw==",affordanceContextMenuItem:"MP9y+OCUQ0Dsy6Z6A0P7qg==",affordanceContextMenuItemIcon:"U3BBQu+2xhg0uuDXS/n8+g==",affordanceContextMenuItemNoIcon:"Si+F1NEyl39azkbswg7g8w==",affordanceContextMenuItemBadgePosition:"_21b4kBzHkdpWCgCgA+VRlQ==",affordanceMenuContainer:"FdC5CgNe2qQBXGbOKlNuew=="}},35910:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.dQ8XLMIyNxl8MAYqMsUZFQ\\=\\={width:100%;height:50px;display:flex;border-spacing:0;white-space:nowrap;line-height:normal}.dQ8XLMIyNxl8MAYqMsUZFQ\\=\\= .hpyHhmSe9hmk5gopLr9a5Q\\=\\=,.dQ8XLMIyNxl8MAYqMsUZFQ\\=\\= a.rOy\\+Hn8kiD5J9v5VDCE3Dg\\=\\={vertical-align:top}.aU8N30IM3GcKO4KKz8lgNA\\=\\={display:none!important}.removeFocusOutline :focus{outline:none;box-shadow:none!important}.clgiLVKPzugZZns0LiPTqw\\=\\=,.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\={display:block;position:relative;margin:0;padding:0;min-width:48px;text-align:center;cursor:pointer;outline-offset:-1px}@media(-ms-high-contrast:active),(forced-colors:active){.clgiLVKPzugZZns0LiPTqw\\=\\=:focus,.clgiLVKPzugZZns0LiPTqw\\=\\=:hover+.icon,.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=:focus,.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=:hover+.icon{-ms-high-contrast-adjust:none;forced-color-adjust:none;background-color:Highlight!important;color:highlightText!important}}.clgiLVKPzugZZns0LiPTqw\\=\\=:hover,.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=:hover{-webkit-transition:background-color .467s cubic-bezier(.1,.9,.2,1) 34ms;transition:background-color .467s cubic-bezier(.1,.9,.2,1) 34ms}.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=,.BiD096xkmK8Uxwc5MTuOlw\\=\\={display:block;position:relative;margin:0;padding:0;min-width:48px;text-align:center;cursor:default}@media(-ms-high-contrast:active),(forced-colors:active){.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=:focus,.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\=:hover+.icon,.BiD096xkmK8Uxwc5MTuOlw\\=\\=:focus,.BiD096xkmK8Uxwc5MTuOlw\\=\\=:hover+.icon{-ms-high-contrast-adjust:none;forced-color-adjust:none}}.clgiLVKPzugZZns0LiPTqw\\=\\={background:transparent;border-width:0;width:auto;height:100%;box-sizing:border-box;line-height:48px;overflow:hidden}.clgiLVKPzugZZns0LiPTqw\\=\\=>.o365cs-base{height:100%;display:flex;align-items:center;justify-content:center}.clgiLVKPzugZZns0LiPTqw\\=\\= span[class*=" ms-Icon--"],.clgiLVKPzugZZns0LiPTqw\\=\\= span[class^=ms-Icon--]{line-height:48px}@media(-ms-high-contrast:active),(forced-colors:active){.clgiLVKPzugZZns0LiPTqw\\=\\=:focus+.icon,.clgiLVKPzugZZns0LiPTqw\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none;background-color:Highlight!important;color:highlightText!important}}.BiD096xkmK8Uxwc5MTuOlw\\=\\={background:transparent;border-width:0;width:auto;height:100%;box-sizing:border-box;line-height:48px;overflow:hidden;cursor:default}.BiD096xkmK8Uxwc5MTuOlw\\=\\=>.o365cs-base{height:100%;display:flex;align-items:center;justify-content:center}.BiD096xkmK8Uxwc5MTuOlw\\=\\= span[class*=" ms-Icon--"],.BiD096xkmK8Uxwc5MTuOlw\\=\\= span[class^=ms-Icon--]{line-height:48px}@media(-ms-high-contrast:active),(forced-colors:active){.BiD096xkmK8Uxwc5MTuOlw\\=\\=:focus+.icon,.BiD096xkmK8Uxwc5MTuOlw\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none}}.RGSb\\/1c4ex9CM0as0oaLQA\\=\\={display:inherit}.\\/l2PApUbI5EhJK0cmfHXqg\\=\\={min-width:68px}.SXGDf\\/jjzN5Yzn8eL0wHjg\\=\\={line-height:48px}.bfWNEPs24dESqyqDnh\\/7tA\\=\\={display:inline-block;vertical-align:middle;align-self:center;background-color:currentColor;margin-left:16px;margin-right:8px;height:28px;width:1px}html[dir=rtl] .bfWNEPs24dESqyqDnh\\/7tA\\=\\={margin-right:16px;margin-left:8px}.hpyHhmSe9hmk5gopLr9a5Q\\=\\={display:inline-block;font-weight:600;font-family:SegoeUI-SemiBold-final,Segoe UI Semibold,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;font-size:16px;line-height:48px;-webkit-font-smoothing:antialiased}.AzzTpbJF15SioND4vylW8A\\=\\={box-shadow:none!important}.yvHsK6IvuQovPfJmcAYOOg\\=\\={display:flex;flex-direction:row;justify-content:center;align-items:center;padding:0;width:48px;height:48px}.yvHsK6IvuQovPfJmcAYOOg\\=\\= a:focus-visible{outline-offset:11px}.yvHsK6IvuQovPfJmcAYOOg\\=\\= img{width:24px;height:24px;top:12px;left:12px}.UbbNU\\+CJSypYHluHed61kg\\=\\={display:inline-block;vertical-align:top;font-size:24px;margin-top:13px;margin-left:6px}.UbbNU\\+CJSypYHluHed61kg\\=\\=:before{vertical-align:top}.q8AbQOBpuy93yBfTeGfNaw\\=\\={margin-left:14px;margin-right:14px;height:25px;margin-top:12px;border-right:1px solid}html[dir=rtl] .UbbNU\\+CJSypYHluHed61kg\\=\\={margin-left:0;margin-right:6px}.e\\/Vl0j0zHQMhZT1vQ6J\\+SQ\\=\\={height:100%;display:flex;vertical-align:middle;outline-offset:-1px;padding:0 12px 0 8px;text-decoration:none}.e\\/Vl0j0zHQMhZT1vQ6J\\+SQ\\=\\= a{display:flex;text-decoration:none;color:inherit}html[dir=rtl] .e\\/Vl0j0zHQMhZT1vQ6J\\+SQ\\=\\={padding:0 8px 0 12px}._3rJAyyAtPSCl0uoYr\\+wuLA\\=\\={line-height:48px;height:100%;display:inline-block;vertical-align:top;padding-left:8px}html[dir=rtl] ._3rJAyyAtPSCl0uoYr\\+wuLA\\=\\={padding-right:8px;padding-left:0}.rOy\\+Hn8kiD5J9v5VDCE3Dg\\=\\={max-width:200px;max-height:48px;overflow:hidden;display:flex;align-items:center;justify-content:center;line-height:48px;font-size:0;height:100%}.rOy\\+Hn8kiD5J9v5VDCE3Dg\\=\\=:focus-visible{outline-offset:-2px}.rOy\\+Hn8kiD5J9v5VDCE3Dg\\=\\= img{max-width:200px;max-height:48px;border-style:none!important;vertical-align:middle}.tP6UdQAxefBu0rqv2chMeg\\=\\= img{width:auto;height:24px}@media (-ms-high-contrast:none),screen and (-ms-high-contrast:active){.tP6UdQAxefBu0rqv2chMeg\\=\\= img{max-width:200px;max-height:none;min-width:160px;width:100%;height:24px}}@media(min-width:640px){.H7wt1\\/T7kbyfSRNZ2JzVLA\\=\\={max-width:176px;text-decoration:none}}.\\/B1n\\/h6ibI5wVz7jdDIP0A\\=\\={height:100%;max-width:176px;display:flex}.HcKMEYhmL4uLyG\\+K4hy8pg\\=\\={text-align:right;vertical-align:middle;display:table-cell;overflow:hidden;max-width:120px;font-size:14px;font-family:SegoeUI-SemiLight-final,Segoe UI Semilight,SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;margin-left:4px}.HcKMEYhmL4uLyG\\+K4hy8pg\\=\\=>span{padding-left:4px;display:none}.U6Cnfo0RjXJ8UEwXhZV8mQ\\=\\={text-align:left;display:block;overflow:hidden;max-width:160px;font-size:13px;font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;line-height:48px}.U6Cnfo0RjXJ8UEwXhZV8mQ\\=\\=>span{padding-left:12px;padding-right:4px;display:none}html[dir=rtl] .HcKMEYhmL4uLyG\\+K4hy8pg\\=\\={text-align:left}html[dir=rtl] .HcKMEYhmL4uLyG\\+K4hy8pg\\=\\=>span{padding-left:0;padding-right:4px}html[dir=rtl] .U6Cnfo0RjXJ8UEwXhZV8mQ\\=\\=>span{padding-left:4px;padding-right:12px}.NK6YQ060InuEH1W1LbFJ4Q\\=\\={display:flex;align-items:center;justify-content:center;border-left-width:0!important}html[dir=rtl] .NK6YQ060InuEH1W1LbFJ4Q\\=\\={border-right-width:0!important}.x03Rvs3MQ7Id948TyiIkCQ\\=\\={overflow:hidden;display:inline-block;border-radius:50%;vertical-align:middle;font-size:6px}.x03Rvs3MQ7Id948TyiIkCQ\\=\\= .ms-Persona{right:2px;top:-2px}.x03Rvs3MQ7Id948TyiIkCQ\\=\\= .ms-Persona .ms-Image-image{overflow:hidden;top:0}html[dir=rtl] .x03Rvs3MQ7Id948TyiIkCQ\\=\\= .ms-Persona{left:2px;right:0}.\\+gKDxCURR5euwhVW2NK21g\\=\\={overflow:hidden;display:inline-block;border:thin solid;border-radius:50%;vertical-align:middle;font-size:6px}.u85SIhgERLuqcMUbt2s66A\\=\\={border-radius:50%;line-height:1!important}.u85SIhgERLuqcMUbt2s66A\\=\\=:before{margin-top:.4em}.SPrdsmCpZYS0tgvvd0cRgQ\\=\\={width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:13px;font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;border:1px solid;box-sizing:border-box;border-radius:50%;line-height:1!important}.SPrdsmCpZYS0tgvvd0cRgQ\\=\\=:before{margin-top:.4em}.x03Rvs3MQ7Id948TyiIkCQ\\=\\=,.u85SIhgERLuqcMUbt2s66A\\=\\=,.\\+gKDxCURR5euwhVW2NK21g\\=\\={width:32px;height:32px}.ieRo\\/OqPYB7kffRFKx2c9w\\=\\={align-items:center;justify-content:space-between;margin:0;padding:0;text-align:center;height:100%}._25CqRVKwE38X5RHExD4IyA\\=\\={display:flex;flex:1 0 auto;height:100%}._1tJrEjbv1Qkvxc\\/P7r3tZg\\=\\={display:flex;justify-content:flex-start}.S3TWafQDKD\\+3UQM7Jnziug\\=\\={display:flex;flex:1 0 auto;justify-content:center}._16lUvVUJZw68Zc4vFo8oMQ\\=\\={display:flex;justify-content:flex-end}.HV6lC9J8OUFpKJjfAr1Asw\\=\\={display:flex;flex:0 0 auto}.Bh46b1rd8BrU4zolL9RzUg\\=\\={height:100%;line-height:48px;display:flex}.hdkWCzc6sRQuamFV07Y3xQ\\=\\={right:24px;top:8px}html[dir=rtl] .hdkWCzc6sRQuamFV07Y3xQ\\=\\={right:0;left:24px}@-moz-document url-prefix(){.clgiLVKPzugZZns0LiPTqw\\=\\=:focus{outline:1px dotted}}#O365_NavHeader abbr,#O365_NavHeader address,#O365_NavHeader article,#O365_NavHeader aside,#O365_NavHeader audio,#O365_NavHeader b,#O365_NavHeader blockquote,#O365_NavHeader body,#O365_NavHeader body :focus,#O365_NavHeader body div,#O365_NavHeader caption,#O365_NavHeader cite,#O365_NavHeader code,#O365_NavHeader dd,#O365_NavHeader del,#O365_NavHeader details,#O365_NavHeader dfn,#O365_NavHeader dl,#O365_NavHeader dt,#O365_NavHeader em,#O365_NavHeader fieldset,#O365_NavHeader figure,#O365_NavHeader footer,#O365_NavHeader form,#O365_NavHeader h1,#O365_NavHeader h2,#O365_NavHeader h3,#O365_NavHeader h4,#O365_NavHeader h5,#O365_NavHeader h6,#O365_NavHeader header,#O365_NavHeader html,#O365_NavHeader i,#O365_NavHeader iframe,#O365_NavHeader img,#O365_NavHeader ins,#O365_NavHeader kbd,#O365_NavHeader label,#O365_NavHeader legend,#O365_NavHeader li,#O365_NavHeader mark,#O365_NavHeader menu,#O365_NavHeader nav,#O365_NavHeader object,#O365_NavHeader ol,#O365_NavHeader p,#O365_NavHeader pre,#O365_NavHeader q,#O365_NavHeader samp,#O365_NavHeader section,#O365_NavHeader small,#O365_NavHeader strong,#O365_NavHeader sub,#O365_NavHeader summary,#O365_NavHeader sup,#O365_NavHeader table,#O365_NavHeader tbody,#O365_NavHeader td,#O365_NavHeader tfoot,#O365_NavHeader th,#O365_NavHeader thead,#O365_NavHeader time,#O365_NavHeader tr,#O365_NavHeader ul,#O365_NavHeader var,#O365_NavHeader video,#O365fpcontainerid abbr,#O365fpcontainerid address,#O365fpcontainerid article,#O365fpcontainerid aside,#O365fpcontainerid audio,#O365fpcontainerid b,#O365fpcontainerid blockquote,#O365fpcontainerid body,#O365fpcontainerid body :focus,#O365fpcontainerid body div,#O365fpcontainerid caption,#O365fpcontainerid cite,#O365fpcontainerid code,#O365fpcontainerid dd,#O365fpcontainerid del,#O365fpcontainerid details,#O365fpcontainerid dfn,#O365fpcontainerid dl,#O365fpcontainerid dt,#O365fpcontainerid em,#O365fpcontainerid fieldset,#O365fpcontainerid figure,#O365fpcontainerid footer,#O365fpcontainerid form,#O365fpcontainerid h1,#O365fpcontainerid h2,#O365fpcontainerid h3,#O365fpcontainerid h4,#O365fpcontainerid h5,#O365fpcontainerid h6,#O365fpcontainerid header,#O365fpcontainerid html,#O365fpcontainerid i,#O365fpcontainerid iframe,#O365fpcontainerid img,#O365fpcontainerid ins,#O365fpcontainerid kbd,#O365fpcontainerid label,#O365fpcontainerid legend,#O365fpcontainerid li,#O365fpcontainerid mark,#O365fpcontainerid menu,#O365fpcontainerid nav,#O365fpcontainerid object,#O365fpcontainerid ol,#O365fpcontainerid p,#O365fpcontainerid pre,#O365fpcontainerid q,#O365fpcontainerid samp,#O365fpcontainerid section,#O365fpcontainerid small,#O365fpcontainerid strong,#O365fpcontainerid sub,#O365fpcontainerid summary,#O365fpcontainerid sup,#O365fpcontainerid table,#O365fpcontainerid tbody,#O365fpcontainerid td,#O365fpcontainerid tfoot,#O365fpcontainerid th,#O365fpcontainerid thead,#O365fpcontainerid time,#O365fpcontainerid tr,#O365fpcontainerid ul,#O365fpcontainerid var,#O365fpcontainerid video,.o365shell-popup abbr,.o365shell-popup address,.o365shell-popup article,.o365shell-popup aside,.o365shell-popup audio,.o365shell-popup b,.o365shell-popup blockquote,.o365shell-popup body,.o365shell-popup body :focus,.o365shell-popup body div,.o365shell-popup caption,.o365shell-popup cite,.o365shell-popup code,.o365shell-popup dd,.o365shell-popup del,.o365shell-popup details,.o365shell-popup dfn,.o365shell-popup dl,.o365shell-popup dt,.o365shell-popup em,.o365shell-popup fieldset,.o365shell-popup figure,.o365shell-popup footer,.o365shell-popup form,.o365shell-popup h1,.o365shell-popup h2,.o365shell-popup h3,.o365shell-popup h4,.o365shell-popup h5,.o365shell-popup h6,.o365shell-popup header,.o365shell-popup html,.o365shell-popup i,.o365shell-popup iframe,.o365shell-popup img,.o365shell-popup ins,.o365shell-popup kbd,.o365shell-popup label,.o365shell-popup legend,.o365shell-popup li,.o365shell-popup mark,.o365shell-popup menu,.o365shell-popup nav,.o365shell-popup object,.o365shell-popup ol,.o365shell-popup p,.o365shell-popup pre,.o365shell-popup q,.o365shell-popup samp,.o365shell-popup section,.o365shell-popup small,.o365shell-popup strong,.o365shell-popup sub,.o365shell-popup summary,.o365shell-popup sup,.o365shell-popup table,.o365shell-popup tbody,.o365shell-popup td,.o365shell-popup tfoot,.o365shell-popup th,.o365shell-popup thead,.o365shell-popup time,.o365shell-popup tr,.o365shell-popup ul,.o365shell-popup var,.o365shell-popup video{box-sizing:content-box}',""]),t.locals={header:"dQ8XLMIyNxl8MAYqMsUZFQ==",brandingText:"hpyHhmSe9hmk5gopLr9a5Q==",tenantLogo:"rOy+Hn8kiD5J9v5VDCE3Dg==",displayNone:"aU8N30IM3GcKO4KKz8lgNA==",button:"clgiLVKPzugZZns0LiPTqw==",link:"SXGDf/jjzN5Yzn8eL0wHjg==",nonInteractiveButton:"BiD096xkmK8Uxwc5MTuOlw==",icon:"RGSb/1c4ex9CM0as0oaLQA==",wideWaffle:"/l2PApUbI5EhJK0cmfHXqg==",appTitleLine:"bfWNEPs24dESqyqDnh/7tA==",brandingLink:"AzzTpbJF15SioND4vylW8A==",appBrandIcon:"yvHsK6IvuQovPfJmcAYOOg==",gallatinLogo:"UbbNU+CJSypYHluHed61kg==",separator:"q8AbQOBpuy93yBfTeGfNaw==",appTitle:"e/Vl0j0zHQMhZT1vQ6J+SQ==",tenantBranding:"_3rJAyyAtPSCl0uoYr+wuLA==",tenantLogoSVG:"tP6UdQAxefBu0rqv2chMeg==",rightHeaderButton:"H7wt1/T7kbyfSRNZ2JzVLA==",rightHeaderContainer:"/B1n/h6ibI5wVz7jdDIP0A==",rightHeaderTextContent:"HcKMEYhmL4uLyG+K4hy8pg==",rightHeaderTextContentMeControl:"U6Cnfo0RjXJ8UEwXhZV8mQ==",rightHeaderImg:"NK6YQ060InuEH1W1LbFJ4Q==",meHeaderPhotoContainer:"x03Rvs3MQ7Id948TyiIkCQ==",signInDoughboyContainer:"+gKDxCURR5euwhVW2NK21g==",rightHeaderDoughboy:"u85SIhgERLuqcMUbt2s66A==",rightHeaderThemedInitials:"SPrdsmCpZYS0tgvvd0cRgQ==",leftRegion:"ieRo/OqPYB7kffRFKx2c9w==",extensibleRegion:"_25CqRVKwE38X5RHExD4IyA==",leftExtensibleRegion:"_1tJrEjbv1Qkvxc/P7r3tZg==",centerExtensibleRegion:"S3TWafQDKD+3UQM7Jnziug==",rightExtensibleRegion:"_16lUvVUJZw68Zc4vFo8oMQ==",rightRegion:"HV6lC9J8OUFpKJjfAr1Asw==",control:"Bh46b1rd8BrU4zolL9RzUg==",headerButtonBadgePosition:"hdkWCzc6sRQuamFV07Y3xQ=="}},37948:function(e,t,n){(t=e.exports=n(63585)(!1)).push([e.id,'.M3pcB5evSAtYMozck1WU7A\\=\\={height:100%;line-height:48px;display:flex}._1QSK5lUhw5Gkh7SDz97ZPQ\\=\\={height:48px;display:flex}.siUMOJwnumycxvszBe3uzQ\\=\\={display:inherit;flex:inherit;justify-content:inherit;order:inherit;align-self:inherit;min-width:inherit}.\\/DyMYj2gNfPrYNbEWoV2\\/w\\=\\={font-size:14px;font-family:SegoeUI-Regular-final,Segoe UI,"Segoe UI Web (West European)",Segoe,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Tahoma,Helvetica,Arial,sans-serif;text-align:left;height:48px;line-height:48px;vertical-align:top;padding-left:8px;text-overflow:ellipsis!important;overflow:hidden!important;max-width:220px;cursor:pointer}@media(-ms-high-contrast:active),(forced-colors:active){.\\/DyMYj2gNfPrYNbEWoV2\\/w\\=\\=:focus,.\\/DyMYj2gNfPrYNbEWoV2\\/w\\=\\=:hover{-ms-high-contrast-adjust:none;forced-color-adjust:none;background-color:Highlight!important;color:highlightText!important}}.N9B5\\/L\\/KHHvT9WOBAb1beA\\=\\={padding-left:12px!important;padding-right:12px!important;justify-content:right!important;display:flex}',""]),t.locals={thinHeaderControlContainer:"M3pcB5evSAtYMozck1WU7A==",thinHeaderLayoutRegion:"_1QSK5lUhw5Gkh7SDz97ZPQ==",customControlContainer:"siUMOJwnumycxvszBe3uzQ==",buttonText:"/DyMYj2gNfPrYNbEWoV2/w==",buttonWithTextPadding:"N9B5/L/KHHvT9WOBAb1beA=="}},63585:function(e){"use strict"; +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=(a=o,s=btoa(unescape(encodeURIComponent(JSON.stringify(a)))),c="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(s),"/*# ".concat(c," */")),i=o.sources.map((function(e){return"/*# sourceURL=".concat(o.sourceRoot).concat(e," */")}));return[n].concat(i).concat([r]).join("\n")}// Adapted from convert-source-map (MIT) +var a,s,c;return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2],"{").concat(n,"}"):n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var o={},r=0;r{const t=(0,i.createSubscription)(e);return{store:e,subscription:t,getServerState:s?()=>s:void 0,stabilityCheck:c,noopCheck:l}}),[e,s,c,l]),d=o.useMemo((()=>e.getState()),[e]);(0,a.useIsomorphicLayoutEffect)((()=>{const{subscription:t}=u;return t.onStateChange=t.notifyNestedSubs,t.trySubscribe(),d!==e.getState()&&t.notifyNestedSubs(),()=>{t.tryUnsubscribe(),t.onStateChange=void 0}}),[u,d]);const p=t||r.ReactReduxContext;return o.createElement(p.Provider,{value:u},n)};t.default=c},81903:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.default=t.initializeConnect=void 0;var r=o(n(93288)),i=o(n(13739)),a=o(n(58722)),s=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=y(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var a=r?Object.getOwnPropertyDescriptor(e,i):null;a&&(a.get||a.set)?Object.defineProperty(o,i,a):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(90872)),c=n(45353),l=o(n(84904)),u=n(94236),d=n(76857),p=n(431),f=n(93961),h=n(19823),m=o(n(85824)),g=(o(n(80662)),n(80126)),b=n(8340);const v=["reactReduxForwardedRef"];function y(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(y=function(e){return e?n:t})(e)}let x=b.notInitialized;t.initializeConnect=e=>{x=e};const A=[null,null];function C(e,t,n,o,r,i){e.current=o,n.current=!1,r.current&&(r.current=null,i())}function S(e,t){return e===t}var w=function(e,t,n,{pure:o,areStatesEqual:b=S,areOwnPropsEqual:y=m.default,areStatePropsEqual:w=m.default,areMergedPropsEqual:k=m.default,forwardRef:P=!1,context:O=g.ReactReduxContext}={}){const I=O,D=(0,d.mapStateToPropsFactory)(e),T=(0,u.mapDispatchToPropsFactory)(t),E=(0,p.mergePropsFactory)(n),L=Boolean(e);return e=>{const t=e.displayName||e.name||"Component",n=`Connect(${t})`,o={shouldHandleStateChanges:L,displayName:n,wrappedComponentName:t,WrappedComponent:e,initMapStateToProps:D,initMapDispatchToProps:T,initMergeProps:E,areStatesEqual:b,areStatePropsEqual:w,areOwnPropsEqual:y,areMergedPropsEqual:k};function u(t){const[n,a,u]=s.useMemo((()=>{const{reactReduxForwardedRef:e}=t,n=(0,i.default)(t,v);return[t.context,e,n]}),[t]),d=s.useMemo((()=>n&&n.Consumer&&(0,c.isContextConsumer)(s.createElement(n.Consumer,null))?n:I),[n,I]),p=s.useContext(d),m=Boolean(t.store)&&Boolean(t.store.getState)&&Boolean(t.store.dispatch),g=Boolean(p)&&Boolean(p.store);const b=m?t.store:p.store,y=g?p.getServerState:b.getState,S=s.useMemo((()=>(0,l.default)(b.dispatch,o)),[b]),[w,k]=s.useMemo((()=>{if(!L)return A;const e=(0,f.createSubscription)(b,m?void 0:p.subscription),t=e.notifyNestedSubs.bind(e);return[e,t]}),[b,m,p]),P=s.useMemo((()=>m?p:(0,r.default)({},p,{subscription:w})),[m,p,w]),O=s.useRef(),D=s.useRef(u),T=s.useRef(),E=s.useRef(!1),M=(s.useRef(!1),s.useRef(!1)),F=s.useRef();(0,h.useIsomorphicLayoutEffect)((()=>(M.current=!0,()=>{M.current=!1})),[]);const N=s.useMemo((()=>()=>T.current&&u===D.current?T.current:S(b.getState(),u)),[b,u]),B=s.useMemo((()=>e=>w?function(e,t,n,o,r,i,a,s,c,l,u){if(!e)return()=>{};let d=!1,p=null;const f=()=>{if(d||!s.current)return;const e=t.getState();let n,f;try{n=o(e,r.current)}catch(e){f=e,p=e}f||(p=null),n===i.current?a.current||l():(i.current=n,c.current=n,a.current=!0,u())};return n.onStateChange=f,n.trySubscribe(),f(),()=>{if(d=!0,n.tryUnsubscribe(),n.onStateChange=null,p)throw p}}(L,b,w,S,D,O,E,M,T,k,e):()=>{}),[w]);var H,j,U;let R;H=C,j=[D,O,E,u,T,k],(0,h.useIsomorphicLayoutEffect)((()=>H(...j)),U);try{R=x(B,N,y?()=>S(y(),u):N)}catch(e){throw F.current&&(e.message+=`\nThe error may be correlated with this previous error:\n${F.current.stack}\n\n`),e}(0,h.useIsomorphicLayoutEffect)((()=>{F.current=void 0,T.current=void 0,O.current=R}));const _=s.useMemo((()=>s.createElement(e,(0,r.default)({},R,{ref:a}))),[a,e,R]);return s.useMemo((()=>L?s.createElement(d.Provider,{value:P},_):_),[d,_,P])}const d=s.memo(u);if(d.WrappedComponent=e,d.displayName=u.displayName=n,P){const t=s.forwardRef((function(e,t){return s.createElement(d,(0,r.default)({},e,{reactReduxForwardedRef:t}))}));return t.displayName=n,t.WrappedComponent=e,(0,a.default)(t,e)}return(0,a.default)(d,e)}};t.default=w},93876:function(e,t){"use strict";t.__esModule=!0,t.createInvalidArgFactory=function(e,t){return(n,o)=>{throw new Error(`Invalid value of type ${typeof e} for ${t} argument when connecting component ${o.wrappedComponentName}.`)}}},94236:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.mapDispatchToPropsFactory=function(e){return e&&"object"==typeof e?(0,i.wrapMapToPropsConstant)((t=>(0,r.default)(e,t))):e?"function"==typeof e?(0,i.wrapMapToPropsFunc)(e,"mapDispatchToProps"):(0,a.createInvalidArgFactory)(e,"mapDispatchToProps"):(0,i.wrapMapToPropsConstant)((e=>({dispatch:e})))};var r=o(n(86120)),i=n(77542),a=n(93876)},76857:function(e,t,n){"use strict";t.__esModule=!0,t.mapStateToPropsFactory=function(e){return e?"function"==typeof e?(0,o.wrapMapToPropsFunc)(e,"mapStateToProps"):(0,r.createInvalidArgFactory)(e,"mapStateToProps"):(0,o.wrapMapToPropsConstant)((()=>({})))};var o=n(77542),r=n(93876)},431:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.defaultMergeProps=a,t.wrapMergePropsFunc=s,t.mergePropsFactory=function(e){return e?"function"==typeof e?s(e):(0,i.createInvalidArgFactory)(e,"mergeProps"):()=>a};var r=o(n(93288)),i=(o(n(84026)),n(93876));function a(e,t,n){return(0,r.default)({},n,e,t)}function s(e){return function(t,{displayName:n,areMergedPropsEqual:o}){let r,i=!1;return function(t,n,a){const s=e(t,n,a);return i?o(s,r)||(r=s):(i=!0,r=s),r}}}},84904:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.pureFinalPropsSelectorFactory=a,t.default=function(e,t){let{initMapStateToProps:n,initMapDispatchToProps:o,initMergeProps:s}=t,c=(0,r.default)(t,i);const l=n(e,c),u=o(e,c),d=s(e,c);0;return a(l,u,d,e,c)};var r=o(n(13739));o(n(55932));const i=["initMapStateToProps","initMapDispatchToProps","initMergeProps"];function a(e,t,n,o,{areStatesEqual:r,areOwnPropsEqual:i,areStatePropsEqual:a}){let s,c,l,u,d,p=!1;function f(p,f){const h=!i(f,c),m=!r(p,s,f,c);return s=p,c=f,h&&m?(l=e(s,c),t.dependsOnOwnProps&&(u=t(o,c)),d=n(l,u,c),d):h?(e.dependsOnOwnProps&&(l=e(s,c)),t.dependsOnOwnProps&&(u=t(o,c)),d=n(l,u,c),d):m?function(){const t=e(s,c),o=!a(t,l);return l=t,o&&(d=n(l,u,c)),d}():d}return function(r,i){return p?f(r,i):(s=r,c=i,l=e(s,c),u=t(o,c),d=n(l,u,c),p=!0,d)}}},55932:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.default=function(e,t,n){i(e,"mapStateToProps"),i(t,"mapDispatchToProps"),i(n,"mergeProps")};var r=o(n(80662));function i(e,t){if(!e)throw new Error(`Unexpected value for ${t} in connect.`);"mapStateToProps"!==t&&"mapDispatchToProps"!==t||Object.prototype.hasOwnProperty.call(e,"dependsOnOwnProps")||(0,r.default)(`The selector for ${t} of connect did not specify a value for dependsOnOwnProps.`)}},77542:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.wrapMapToPropsConstant=function(e){return function(t){const n=e(t);function o(){return n}return o.dependsOnOwnProps=!1,o}},t.getDependsOnOwnProps=r,t.wrapMapToPropsFunc=function(e,t){return function(t,{displayName:n}){const o=function(e,t){return o.dependsOnOwnProps?o.mapToProps(e,t):o.mapToProps(e,void 0)};return o.dependsOnOwnProps=!0,o.mapToProps=function(t,n){o.mapToProps=e,o.dependsOnOwnProps=r(e);let i=o(t,n);return"function"==typeof i&&(o.mapToProps=i,o.dependsOnOwnProps=r(i),i=o(t,n)),i},o}};o(n(84026));function r(e){return e.dependsOnOwnProps?Boolean(e.dependsOnOwnProps):1!==e.length}},65367:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0;var r={Provider:!0,connect:!0,ReactReduxContext:!0,useDispatch:!0,createDispatchHook:!0,useSelector:!0,createSelectorHook:!0,useStore:!0,createStoreHook:!0,shallowEqual:!0};Object.defineProperty(t,"Provider",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(t,"connect",{enumerable:!0,get:function(){return a.default}}),Object.defineProperty(t,"ReactReduxContext",{enumerable:!0,get:function(){return s.ReactReduxContext}}),Object.defineProperty(t,"useDispatch",{enumerable:!0,get:function(){return c.useDispatch}}),Object.defineProperty(t,"createDispatchHook",{enumerable:!0,get:function(){return c.createDispatchHook}}),Object.defineProperty(t,"useSelector",{enumerable:!0,get:function(){return l.useSelector}}),Object.defineProperty(t,"createSelectorHook",{enumerable:!0,get:function(){return l.createSelectorHook}}),Object.defineProperty(t,"useStore",{enumerable:!0,get:function(){return u.useStore}}),Object.defineProperty(t,"createStoreHook",{enumerable:!0,get:function(){return u.createStoreHook}}),Object.defineProperty(t,"shallowEqual",{enumerable:!0,get:function(){return d.default}});var i=o(n(25548)),a=o(n(81903)),s=n(80126),c=n(94870),l=n(91801),u=n(40359),d=o(n(85824)),p=n(91853);Object.keys(p).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(r,e)||e in t&&t[e]===p[e]||Object.defineProperty(t,e,{enumerable:!0,get:function(){return p[e]}}))}))},94870:function(e,t,n){"use strict";t.__esModule=!0,t.createDispatchHook=i,t.useDispatch=void 0;var o=n(80126),r=n(40359);function i(e=o.ReactReduxContext){const t=e===o.ReactReduxContext?r.useStore:(0,r.createStoreHook)(e);return function(){return t().dispatch}}const a=i();t.useDispatch=a},58541:function(e,t,n){"use strict";t.__esModule=!0,t.createReduxContextHook=i,t.useReduxContext=void 0;var o=n(90872),r=n(80126);function i(e=r.ReactReduxContext){return function(){return(0,o.useContext)(e)}}const a=i();t.useReduxContext=a},91801:function(e,t,n){"use strict";t.__esModule=!0,t.createSelectorHook=c,t.useSelector=t.initializeUseSelector=void 0;var o=n(90872),r=n(58541),i=n(80126);let a=n(8340).notInitialized;t.initializeUseSelector=e=>{a=e};const s=(e,t)=>e===t;function c(e=i.ReactReduxContext){const t=e===i.ReactReduxContext?r.useReduxContext:(0,r.createReduxContextHook)(e);return function(e,n={}){const{equalityFn:r=s,stabilityCheck:i,noopCheck:c}="function"==typeof n?{equalityFn:n}:n;const{store:l,subscription:u,getServerState:d,stabilityCheck:p,noopCheck:f}=t(),h=((0,o.useRef)(!0),(0,o.useCallback)({[e.name](t){return e(t)}}[e.name],[e,p,i])),m=a(u.addNestedSub,l.getState,d||l.getState,h,r);return(0,o.useDebugValue)(m),m}}const l=c();t.useSelector=l},40359:function(e,t,n){"use strict";t.__esModule=!0,t.createStoreHook=i,t.useStore=void 0;var o=n(80126),r=n(58541);function i(e=o.ReactReduxContext){const t=e===o.ReactReduxContext?r.useReduxContext:(0,r.createReduxContextHook)(e);return function(){const{store:e}=t();return e}}const a=i();t.useStore=a},91112:function(e,t,n){"use strict";t.__esModule=!0;var o={batch:!0};Object.defineProperty(t,"batch",{enumerable:!0,get:function(){return a.unstable_batchedUpdates}});var r=n(71536),i=n(63770),a=n(40536),s=n(46766),c=n(91801),l=n(81903),u=n(65367);Object.keys(u).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(o,e)||e in t&&t[e]===u[e]||Object.defineProperty(t,e,{enumerable:!0,get:function(){return u[e]}}))})),(0,c.initializeUseSelector)(i.useSyncExternalStoreWithSelector),(0,l.initializeConnect)(r.useSyncExternalStore),(0,s.setBatch)(a.unstable_batchedUpdates)},91853:function(){},93961:function(e,t,n){"use strict";t.__esModule=!0,t.createSubscription=function(e,t){let n,i=r,a=0,s=!1;function c(){d.onStateChange&&d.onStateChange()}function l(){a++,n||(n=t?t.addNestedSub(c):e.subscribe(c),i=function(){const e=(0,o.getBatch)();let t=null,n=null;return{clear(){t=null,n=null},notify(){e((()=>{let e=t;for(;e;)e.callback(),e=e.next}))},get(){let e=[],n=t;for(;n;)e.push(n),n=n.next;return e},subscribe(e){let o=!0,r=n={callback:e,next:null,prev:n};return r.prev?r.prev.next=r:t=r,function(){o&&null!==t&&(o=!1,r.next?r.next.prev=r.prev:n=r.prev,r.prev?r.prev.next=r.next:t=r.next)}}}}())}function u(){a--,n&&0===a&&(n(),n=void 0,i.clear(),i=r)}const d={addNestedSub:function(e){l();const t=i.subscribe(e);let n=!1;return()=>{n||(n=!0,t(),u())}},notifyNestedSubs:function(){i.notify()},handleChangeWrapper:c,isSubscribed:function(){return s},trySubscribe:function(){s||(s=!0,l())},tryUnsubscribe:function(){s&&(s=!1,u())},getListeners:()=>i};return d};var o=n(46766);const r={notify(){},get:()=>[]}},46766:function(e,t){"use strict";t.__esModule=!0,t.getBatch=t.setBatch=void 0;let n=function(e){e()};t.setBatch=e=>n=e;t.getBatch=()=>n},86120:function(e,t){"use strict";t.__esModule=!0,t.default=function(e,t){const n={};for(const o in e){const r=e[o];"function"==typeof r&&(n[o]=(...e)=>t(r(...e)))}return n}},18865:function(e,t){"use strict";t.__esModule=!0,t.default=function(e){if("object"!=typeof e||null===e)return!1;let t=Object.getPrototypeOf(e);if(null===t)return!0;let n=t;for(;null!==Object.getPrototypeOf(n);)n=Object.getPrototypeOf(n);return t===n}},40536:function(e,t,n){"use strict";t.__esModule=!0,Object.defineProperty(t,"unstable_batchedUpdates",{enumerable:!0,get:function(){return o.unstable_batchedUpdates}});var o=n(9028)},85824:function(e,t){"use strict";function n(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}t.__esModule=!0,t.default=function(e,t){if(n(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;const o=Object.keys(e),r=Object.keys(t);if(o.length!==r.length)return!1;for(let r=0;r{throw new Error("uSES not initialized!")}},84026:function(e,t,n){"use strict";var o=n(75720);t.__esModule=!0,t.default=function(e,t,n){(0,r.default)(e)||(0,i.default)(`${n}() in ${t} must return a plain object. Instead received ${e}.`)};var r=o(n(18865)),i=o(n(80662))},80662:function(e,t){"use strict";t.__esModule=!0,t.default=function(e){"undefined"!=typeof console&&console.error;try{throw new Error(e)}catch(e){}}},71052:function(e,t,n){"use strict";function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}function r(e){var t=function(e,t){if("object"!=o(e)||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=o(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==o(t)?t:t+""}function i(e,t,n){return(t=r(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function s(e){for(var t=1;t=0&&d.splice(t,1)}function b(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var o=function(){0;return n.nc}();o&&(e.attrs.nonce=o)}return v(t,e.attrs),m(e,t),t}function v(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function y(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=u++;n=l||(l=b(t)),o=C.bind(null,n,a,!1),r=C.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",v(t,e.attrs),m(e,t),t}(t),o=w.bind(null,n,t),r=function(){g(n),n.href&&URL.revokeObjectURL(n.href)}):(n=b(t),o=S.bind(null,n),r=function(){g(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return f(n,t),function(e){for(var o=[],r=0;r0?e.appsPinnedData:g.bL(n);if(e.isInitialized){const e=(0,m.kx)(t,n);if(e){const t=e.filter(g.pf);a=t.map(g.sF),s=y(s,t),(null===(r=n.PrePinnedApps)||void 0===r?void 0:r.length)>0&&x(n.PrePinnedApps,e,s,"PrePinnedApp"),(null===(i=n.PromotedApps)||void 0===i?void 0:i.length)>0&&x(n.PromotedApps,e,s,"PromotedApp")}}s&&void 0===s.apps&&(s.apps=[]);const c=e.pinnedAppTiles&&e.pinnedAppTiles.length>0?e.pinnedAppTiles:s&&(0,m.Wb)(s.apps).map(g.sF),l=g.DD(n);return Object.assign(Object.assign({},e),{appsPinnedData:s,prePinnedApps:n.PrePinnedApps,promotedApps:n.PromotedApps,pinnedAppTiles:c,homeUrl:t.LogoNavigationUrl,environment:n.Environment,appGalleryUrl:n.AppGalleryUrl,showM365Experience:l,blockUnsafeUrls:n.BlockUnsafeUrls,coreAndSegmentAppTiles:a||e.coreAndSegmentAppTiles,waffleAllAppsViewDisabled:n.WaffleAllAppsViewDisabled})}return e}function y(e,t){let n;const o=null!=t?t:[];return e?(n=e,e.hasSegmentApps||(n.apps=o.concat(...e.apps))):n={apps:null!=o?o:[]},n.hasSegmentApps=!0,n}function x(e,t,n,o){e.forEach((e=>{if(null==(0,m.J0)(n.apps,e.CollectorId,e.Id)&&null==(0,m.J0)(n.unpinnedApps,e.CollectorId,e.Id)){const r=(0,m.J0)(t,e.CollectorId,e.Id);r?n.apps.push(r):(0,l.tZ)().tag("AppLauncher_Missing"+o,6,e.CollectorId,e.Id)}}))}const A={appLauncherState:function(e,t){if(!e){const n=t.shellInitData.shellInitDataState;e=v(h.P,n.navBarData,n.clientData)}switch(t.type){case b.ii:return function(e,t){var n;let o=t.appsPinnedData;const r=null===(n=t.appsData)||void 0===n?void 0:n.filter(g.pf);r&&(o=y(o,r));t.prePinnedApps&&x(t.prePinnedApps,t.appsData,o,"PrePinnedApp");t.promotedApps&&x(t.promotedApps,t.appsData,o,"PromotedApp");const i=o&&(0,m.Wb)(o.apps).map(g.sF);return Object.assign(Object.assign({},e),{isHidden:!1,isInitialized:!0,openedByTouchOrKeyPress:t.isTouchOrKeyPressed,openedTime:t.timestamp,appsPinnedData:o,coreAndSegmentAppTiles:r.map(g.sF),pinnedAppTiles:i,isStandalone:t.isStandalone,isNTP:t.isNTP})}(e,t);case b.dP:const n=t;return Object.assign(Object.assign({},e),{isHidden:!e.isHidden,openedByTouchOrKeyPress:e.isHidden?n.isTouchOrKeyPressed:null,openedTime:e.isHidden?n.timestamp:null,showAllView:!1});case b.kD:return Object.assign(Object.assign({},e),{isHidden:!0,openedTime:null,showAllView:!1,appDataDetails:null,statusAnnouncement:null});case b.O0:return Object.assign(Object.assign({},e),{showAllView:!0});case b.R7:return Object.assign(Object.assign({},e),{showAllView:!1});case f.nv:return function(e,t){const n=t.appsData&&t.appsData.filter(g.pf).map(g.sF);return Object.assign(Object.assign({},e),{coreAndSegmentAppTiles:n})}(e,t);case b.yk:return function(e,t){const n=t.appsPinnedData&&(0,m.Wb)(t.appsPinnedData.apps).map(g.sF);return Object.assign(Object.assign({},e),{appsPinnedData:t.appsPinnedData,pinnedAppTiles:n})}(e,t);case b.YH:return Object.assign(Object.assign({},e),{isCustomizable:!0});case b.Ul:return function(e,t){let n=e.appsPinnedData,o=e.pinnedAppTiles,r=t.appData;"LineOfBusiness"===r.CollectorId&&(r={CollectorId:r.CollectorId,Id:r.Id});if(n){if(null==(0,m.J0)(n.apps,r.CollectorId,r.Id)){let e=n.unpinnedApps;void 0!==e&&(e=e.filter((e=>e.Id!==r.Id||e.CollectorId!==r.CollectorId))),n=Object.assign(Object.assign({},n),{unpinnedApps:e,apps:n.apps.concat(r)}),o=o.concat(g.sF(r))}}else n={apps:[r]},o=[g.sF(r)];return Object.assign(Object.assign({},e),{appsPinnedData:n,pinnedAppTiles:o,statusAnnouncement:t.statusAnnouncement})}(e,t);case b.Tf:return function(e,t){let n=e.appsPinnedData,o=e.pinnedAppTiles;if(n){let e=n.unpinnedApps;void 0===e?e=[{Id:t.id,CollectorId:t.collectorId}]:0===e.filter((e=>e.Id===t.id&&e.CollectorId===t.collectorId)).length&&(e=e.concat({Id:t.id,CollectorId:t.collectorId})),n=Object.assign(Object.assign({},n),{unpinnedApps:e,apps:n.apps.filter((e=>e.CollectorId!==t.collectorId||e.Id!==t.id))}),o=o.filter((e=>e.collectorId!==t.collectorId||e.id!==t.id))}return Object.assign(Object.assign({},e),{appsPinnedData:n,pinnedAppTiles:o,statusAnnouncement:t.statusAnnouncement})}(e,t);case b.eE:return function(e,t){const n={CollectorId:t.collectorId,Id:t.id};return Object.assign(Object.assign({},e),{appDataDetails:n})}(e,t);case b.Sj:return function(e,t){const n={CollectorId:t.collectorId,Id:t.id};return Object.assign(Object.assign({},e),{appDataDetails:n})}(e,t);case b.JV:return Object.assign(Object.assign({},e),{appDataDetails:null});case b.bP:return function(e,t){let n=e.appDataDetails;n&&n.CollectorId===t.appDataDetails.CollectorId&&n.Id===t.appDataDetails.Id&&(n=t.appDataDetails);return Object.assign(Object.assign({},e),{appDataDetails:n})}(e,t);case b.a5:return Object.assign(Object.assign({},e),{hamburgerEnabled:!0});case f.l5:const o=t;return v(e,o.navBarData,o.shellClientData);case b.Qq:return function(e,t){const n=t.searchText;return Object.assign(Object.assign({},e),{searchText:n})}(e,t);default:return e}}};var C=n(99542),S=n(26335);class w{OnLinkClick(e){return(0,l.NP)().subscribe("LinkClick",e)}RemoveOnLinkClick(e){(0,l.NP)().unsubscribe("LinkClick",e)}OnHamburgerButtonClick(e){let t=document.getElementById(C.B2);t&&(t.style.display=""),(0,l.NP)().subscribe("HamburgerButtonClick",e),(0,c.O)().dispatch((0,S.XZ)())}EnterAccessibilityLoopInShell(){}ReverseEnterAccessibilityLoopInShell(){}SetForwardAccessibilityLoopOutsideHeaderElementId(e){}SetReverseAccessibilityLoopOutsideHeaderElementId(e){}}let k,P,O,I,D=!1,T=!1,E=!0;n.nc=window.oneShellUxNonce;const L=(0,a._)((()=>Promise.all([n.e("plus"),n.e("m365start")]).then(n.bind(n,1049)).then((e=>e.AppLauncherConnector))));(0,a._)((()=>n.e("applauncher").then(n.bind(n,80551)).then((e=>e.AppLauncherConnector))));function M(){s.h.register(A),(0,l.vm)().shouldRenderAppLauncher&&H(!1,!1),function(){let e=new w,t=window.O365Shell.Navigation;window.O365Shell.Navigation=e,t.applyCalls(e)}(),(0,l.NP)().subscribe("ShellDataUpdated",F,!0)}function F(e,t){try{(0,d.l)().getConfig().then((e=>{var n;e&&(e.M365CopilotRebrandingEnabled&&void 0===P&&(P=e.M365CopilotRebrandingEnabled),e.M365CopilotBannerEnabled&&void 0===O&&(O=e.M365CopilotBannerEnabled),e.M365CopilotBannerSelfHostInternalEnabled&&void 0===I&&(I=e.M365CopilotBannerSelfHostInternalEnabled)),t.IsConsumerShell?e&&e.DisableM365StartIntentsModule&&void 0===k&&(k=e.DisableM365StartIntentsModule):k=null!==(n=null==t?void 0:t.DisableM365StartIntentsModule)&&void 0!==n&&n}))}catch(e){}(0,l.NP)().unsubscribe("ShellDataUpdated",F)}function N(e){D=!1,"touchstart"===e.type&&(D=!0),"pointerdown"===e.type&&"touch"===e.pointerType&&(D=!0)}function B(e){E="mouseenter"===e.type}function H(e,t){const n=document.getElementById((0,l.GJ)().top),a=document.createElement("div");n.appendChild(a),(0,u.Wg)([p.ng,p.oB],"click keydown",j),(0,u.Wg)([p.ng,p.oB],"touchstart pointerdown",N),(0,u.Wg)([p.ng,p.oB],"mouseenter mouseleave",B);const s=()=>{(0,l.NP)().unsubscribe("InitialAppDataLoaded",s);const n=(0,c.O)();r.render(o.createElement(i.Provider,{store:n},o.createElement(L,{openedByTouchOrKeyPress:e,showFocusOutline:t,disableIntentsModule:k,m365CopilotRebrandingEnabled:P,m365CopilotBannerEnabled:O,m365CopilotBannerSelfHostInternalEnabled:I})),a,(()=>{}))};(0,l.NP)().subscribe("InitialAppDataLoaded",s,!0)}function j(e){if(e instanceof KeyboardEvent){if(T=!0,D=!0,"keydown"===e.type&&13!==e.which&&32!==e.which)return}else"click"===e.type&&(D=!E,T=!E);e.preventDefault(),H(D,T)}(0,u.lQ)([p.ng,p.oB],"click keydown",j),(0,u.lQ)([p.ng,p.oB],"touchstart pointerdown",N),(0,u.lQ)([p.ng,p.oB],"mouseenter mouseleave",B)},26335:function(e,t,n){"use strict";n.d(t,{Ee:function(){return c},H1:function(){return l},J8:function(){return d},J9:function(){return p},L4:function(){return f},Qg:function(){return r},RC:function(){return u},Ud:function(){return h},W4:function(){return a},XZ:function(){return i},YR:function(){return g},ib:function(){return s},ic:function(){return b},p6:function(){return m}});var o=n(91497);function r(e,t,n,r,i,a,s,c){return{type:o.ii,appsData:e,appsPinnedData:t,prePinnedApps:n,promotedApps:r,timestamp:i,isTouchOrKeyPressed:a,isStandalone:s,isNTP:c}}function i(){return{type:o.a5}}function a(e,t){return{type:o.dP,timestamp:e,isTouchOrKeyPressed:t}}function s(){return{type:o.kD}}function c(){return{type:o.O0}}function l(){return{type:o.R7}}function u(e){return{type:o.Qq,searchText:e}}function d(e){return{type:o.yk,appsPinnedData:e}}function p(){return{type:o.YH}}function f(e,t){return{type:o.Ul,appData:e,statusAnnouncement:t}}function h(e,t,n){return{type:o.Tf,collectorId:e,id:t,statusAnnouncement:n}}function m(e,t){return{type:o.eE,collectorId:e,id:t}}function g(){return{type:o.JV}}function b(e){return{type:o.bP,appDataDetails:e}}},91497:function(e,t,n){"use strict";n.d(t,{JV:function(){return h},O0:function(){return a},Qq:function(){return g},R7:function(){return s},Sj:function(){return f},Tf:function(){return d},Ul:function(){return u},YH:function(){return l},a5:function(){return b},bP:function(){return m},dP:function(){return r},eE:function(){return p},ii:function(){return o},kD:function(){return i},yk:function(){return c}});const o="suiteux-app-launcher.INIT_APP_LAUNCHER",r="suiteux-app-launcher.TOGGLE_APP_LAUNCHER_VISIBILITY",i="suiteux-app-launcher.CLOSE_APP_LAUNCHER",a="suiteux-app-launcher.SHOW_ALL_VIEW",s="suiteux-app-launcher.HIDE_ALL_VIEW",c="suiteux-app-launcher.SET_APPS_PINNED_DATA",l="suiteux-app-launcher.ENABLE_CUSTOMIZATION",u="suiteux-app-launcher.PIN_APP",d="suiteux-app-launcher.UNPIN_APP",p="suiteux-app-launcher.SHOW_APP_DETAILS_PANE",f="suiteux-app-launcher.SHOW_LEARN_MORE_POPUP",h="suiteux-app-launcher.HIDE_APP_DETAILS_PANE",m="suiteux-app-launcher.SET_APP_DATA_DETAILS",g="suiteux-app-launcher.ON_SEARCH_TEXT_CHANGED",b="suiteux-app-launcher.ENABLE_HAMBURGER"},54888:function(e,t,n){"use strict";n.d(t,{DD:function(){return u},LP:function(){return c},Ro:function(){return l},bL:function(){return s},kj:function(){return i},pf:function(){return r},sF:function(){return a}});var o=n(7667);function r(e){return"FirstParty"===e.CollectorId&&!e.IsAutoPinnedDisabled}function i(e){if(e.DateInstalled){let t=(0,o._)(e.DateInstalled);if(Date.now()-t.getTime()<6048e5)return!0}return!1}function a(e){return{collectorId:e.CollectorId,id:e.Id}}function s(e){let t=null;return null!=e.AppsPinnedData&&(t="string"==typeof e.AppsPinnedData?JSON.parse(e.AppsPinnedData):e.AppsPinnedData),t}function c(e){return e.sort(((e,t)=>null!=e.Title?e.Title.localeCompare(t.Title):1))}function l(e,t,n){if(e)for(let o of e)if(o.collectorId===t&&o.id===n)return o;return null}function u(e){let t=-1!==(e.ActiveExperiences||"").toLowerCase().split(",").indexOf("smb"),n=e.IsConsumerShell;return t||n}},18435:function(e,t,n){"use strict";var o;n.d(t,{B:function(){return o}}),function(e){e.KEYDOWN="keydown",e.KEYUP="keyup",e.KEYPRESS="keypress",e.CLICK="click",e.MOUSEDOWN="mousedown",e.MOUSEENTER="mouseenter",e.MOUSELEAVE="mouseleave",e.FOCUS="focus",e.BLUR="blur",e.RESIZE="resize",e.SCROLL="scroll",e.CONTEXTMENU="contextmenu",e.FOCUSIN="focusin",e.FOCUSOUT="focusout",e.MESSAGE="message"}(o||(o={}))},40141:function(e,t,n){"use strict";function o(){return window.O365ShellContext.ThemeManager.getThemeClassNames()}n.d(t,{e:function(){return o}})},39038:function(e,t,n){"use strict";n.d(t,{t:function(){return c}});var o=n(90872),r=n(22461),i=n(83694),a=n(36649),s=n(36764);class c extends o.Component{constructor(e){super(e),this.setRef=e=>this.contextMenu=e}componentWillMount(){this.props.scrollContainerId&&(this.virtualParent=document.getElementById(this.props.scrollContainerId),this.virtualParent.addEventListener("scroll",this.props.onDismiss)),this.previouslyFocusedElement=document.activeElement}render(){var e;const t=(0,r.A)(s.contextMenu,this.props.className);return o.createElement(i.z,{id:this.props.id,onDismiss:this.props.onDismiss,className:t,target:this.props.target,popupPosition:this.props.popupPosition,renderHost:this.props.renderHost,skipDismissForElement:this.props.skipDismissForElement,focusTrapSelector:"li",ariaLabel:this.props.ariaLabel,isArrowUpDownFocus:!0,skipTabFocus:null===(e=this.props.skipTabFocus)||void 0===e||e,isRtl:this.props.isRtl,skipAdjustPostion:this.props.skipAdjustPostion,shouldFocusPreviouslyFocusedElement:this.props.setFocusOnPreviouslyFocusedElement,elementToFocusOnClose:this.props.elementToFocusOnClose},o.createElement("ul",{className:(0,r.A)({[s.innerScroll]:this.props.isScrollHidden},s.defaultList,this.props.listClassName),ref:this.setRef,role:"menu"},this.props.children))}componentWillUnmount(){this.props.scrollContainerId&&document.getElementById(this.props.scrollContainerId).removeEventListener("scroll",this.props.onDismiss),this.props.elementToFocusOnClose?this.props.elementToFocusOnClose.focus():this.props.setFocusOnPreviouslyFocusedElement&&this.previouslyFocusedElement.focus()}componentDidMount(){this.props.scrollContainerId&&(0,a.g)(this.contextMenu,document.getElementById(this.props.scrollContainerId)),this.props.isKeyboardNavigation&&null!=this.contextMenu.children&&this.contextMenu.childElementCount>0&&this.contextMenu.children[0].focus()}}},79649:function(e,t,n){"use strict";n.d(t,{k:function(){return a}});var o=n(90872),r=n(22461),i=n(87871);class a extends o.Component{constructor(){super(...arguments),this.handleKeyDown=e=>{13===e.keyCode&&(e.preventDefault(),e.stopPropagation(),this.props.onclick&&this.props.onclick(e))}}render(){return o.createElement("li",{className:(0,r.A)(i.contextMenuItem,this.props.className),onClick:this.props.onclick,ref:this.props.setClickableElement,id:this.props.itemId,title:this.props.title?this.props.title:this.props.displayText,"aria-label":this.props.displayText,role:this.props.role,tabIndex:-1,onKeyDown:this.handleKeyDown,"aria-hidden":this.props.isAriaHidden},this.props.icon&&o.createElement("img",{src:this.props.icon,className:i.imgIcon,alt:"",role:"presentation","aria-hidden":!0}),this.props.customIcon,o.createElement("label",{"aria-hidden":!0},this.props.displayText),this.props.children)}}},10806:function(e,t,n){"use strict";n.d(t,{e:function(){return s}});var o=n(90872),r=n(61304),i=n(87948),a=n(24584);class s extends o.Component{constructor(e){super(e),this.isEndFocus=!1,this.resetEndFocus=!1,this.controlEndReference=null,this.setEventListeners=()=>{this.props.isActive&&this.props.controlElement&&(this.props.controlElement.addEventListener("keydown",this.onKeyDown),this.props.controlElement.addEventListener("blur",this.onControlBlur),this.props.controlElement.addEventListener("focus",this.onControlFocus))},this.onKeyDown=e=>{if(9===e.keyCode){if(!this.props.isActive)return;if(!this.isEndFocus){if(e.shiftKey)return;let t=document.getElementById("O365fp_firstFocusable");return t?void t.focus():(this.resetEndFocus=!0,void this.controlEndReference.focus())}if(e.shiftKey){let t=document.getElementById("flexPaneCloseButton");return t?(t.focus(),e.stopPropagation(),void e.preventDefault()):void 0}this.resetEndFocus=!0,this.controlEndReference.focus()}},this.onEndFocus=()=>{if(this.resetEndFocus)return this.isEndFocus=!1,void(this.resetEndFocus=!1);this.isEndFocus=!0,this.updateAccessibilityText(),this.props.controlElement.focus()},this.onControlBlur=()=>{this.isEndFocus=!1},this.onControlFocus=()=>{this.updateAccessibilityText()},this.setControlEndRef=e=>{this.controlEndReference=e}}componentDidUpdate(e,t){!e.isActive&&this.props.isActive&&this.props.controlElement&&(this.isEndFocus=!1,this.props.controlElement.addEventListener("keydown",this.onKeyDown),this.props.controlElement.addEventListener("blur",this.onControlBlur),this.props.controlElement.addEventListener("focus",this.onControlFocus)),e.isActive&&!this.props.isActive&&this.props.controlElement&&(this.props.controlElement.removeEventListener("keydown",this.onKeyDown),this.props.controlElement.removeEventListener("blur",this.onControlBlur),this.props.controlElement.removeEventListener("focus",this.onControlFocus))}componentWillUnmount(){this.props.isActive&&this.props.controlElement&&(this.props.controlElement.removeEventListener("keydown",this.onKeyDown),this.props.controlElement.removeEventListener("blur",this.onControlBlur),this.props.controlElement.removeEventListener("focus",this.onControlFocus))}render(){return this.updateAccessibilityText(),o.createElement("div",{className:a.entrypointContainer,onFocus:this.setEventListeners},this.props.children,this.props.isActive&&o.createElement("div",{id:this.props.controlID+"_end",tabIndex:-1,"aria-hidden":!0,onFocus:this.onEndFocus,ref:this.setControlEndRef}))}updateAccessibilityText(){if(this.props.controlElement&&this.props.isActive&&!this.isEndFocus){let e;this.controlAriaLabel||(this.controlAriaLabel=this.props.controlElement.getAttribute("aria-label")),e=(0,i.vQ)(this.controlAriaLabel)?r.D.FlexpaneEntrypointAriaLabelFallback:(0,i.JT)(r.D.FlexpaneEntrypointAriaLabel,this.controlAriaLabel),this.props.controlElement.setAttribute("aria-label",e)}!this.props.controlElement||this.props.isActive&&!this.isEndFocus||this.controlAriaLabel&&this.props.controlElement.setAttribute("aria-label",this.controlAriaLabel)}}},53512:function(e,t,n){"use strict";n.d(t,{_:function(){return i}});var o=n(90872),r=n(88242);function i(e){let t;const n=new Promise(((e,n)=>{t=e}));class i extends o.PureComponent{constructor(e){super(e),this.componentCancellablePromise=null,this.onFail=e=>{this.setState({failed:!0}),this.props.onLazyFailure&&this.props.onLazyFailure(e)},this.state={Component:i.Component,failed:!1}}componentDidMount(){if(!this.state.Component){let t;this.componentCancellablePromise=(0,r.l)(e?e():n),this.props.lazyTimeout&&(t=window.setTimeout((()=>{this.onFail(new Error("Component load timed out."))}),this.props.lazyTimeout)),this.componentCancellablePromise.promise.then((e=>{i.Component=e,this.setState({Component:e})})).catch((e=>{e&&e.isCancelled||this.onFail(e),window.clearTimeout(t)}))}}componentWillUnmount(){this.componentCancellablePromise&&this.componentCancellablePromise.cancel()}render(){const{Component:e,failed:t}=this.state;return e?o.createElement(e,Object.assign({},this.props)):t&&this.props.lazyFallbackComponent?this.props.lazyFallbackComponent():this.props.intermediateRenderComponent?this.props.intermediateRenderComponent(this.props):null}}return i.Component=null,i.setComponent=t,i}},93884:function(e,t,n){"use strict";n.d(t,{z:function(){return i}});var o=n(90872),r=n(90241);class i extends o.Component{constructor(){super(...arguments),this.onClick=e=>{const{link:t}=this.props;return this.props.onClick&&this.props.onClick(e,t),(0,r.onNavBarLinkClicked)(e,t)}}render(){const{link:e,className:t}=this.props;return o.createElement("a",{role:"link",href:e.Url,id:e.Id,tabIndex:0,target:e.TargetWindow||"_top",onClick:this.onClick,onKeyDown:this.props.onKeyDown,title:e.Title,"aria-label":e.Title||e.Text,className:t},e.Text)}componentDidMount(){this.props.shouldFocus&&window.setTimeout((()=>{let e=document.getElementById(this.props.link.Id);e&&e.focus()}),150)}}},83694:function(e,t,n){"use strict";n.d(t,{z:function(){return d}});var o=n(90872),r=n(9028),i=n(1742),a=n(18435),s=n(16968),c=n(22461),l=n(36649),u=n(17628);class d extends o.Component{constructor(e){super(e),this.setRootRef=e=>this.root=e,this.handleKeydown=e=>{let t=!1;switch(e.keyCode){case 9:this.props.skipTabFocus?t=!0:this.handleKey(e,e.shiftKey);break;case 27:t=!0;break;case 38:t=e.altKey,this.props.isArrowUpDownFocus&&this.handleKey(e,!0);break;case 40:this.props.isArrowUpDownFocus&&this.handleKey(e,!1)}t&&(e.stopPropagation(),e.preventDefault(),this.hidePopup(e),this.props.target instanceof HTMLElement&&!this.props.shouldFocusPreviouslyFocusedElement&&!this.props.elementToFocusOnClose&&this.props.target.focus())},this.handleBodyClick=e=>{if(null!==this.props.onDismiss&&!(this.root===document.activeElement||this.root.contains(document.activeElement)||this.root.contains(e.target)||(0,l.I)(this.root,e.target,!0)||this.props.skipDismissForElement&&this.props.skipDismissForElement===document.activeElement))try{"click"===e.type&&e instanceof PointerEvent&&"mouse"!==e.pointerType&&!("click"===e.type&&e instanceof PointerEvent&&"touch"===e.pointerType)||this.props.onDismiss(e)}catch(t){this.props.onDismiss(e)}},this.state={inlineStyle:{}}}componentDidMount(){this.setInlineStyles(),this.props.isPersistant||this.onOpened()}componentDidUpdate(){if(this.props.isPersistant){if(void 0===this.props.isVisible)return;this.props.isVisible?this.onOpened():this.onClosed()}}componentWillUnmount(){this.props.isPersistant||this.onClosed()}onOpened(){this.root?(this.root.addEventListener(a.B.KEYDOWN,this.handleKeydown),null!==this.props.onDismiss&&(document.body.addEventListener(a.B.CLICK,this.handleBodyClick),document.body.addEventListener(a.B.CONTEXTMENU,this.handleBodyClick)),(0,s.NP)().invoke("ContextMenuPopup",!0,this.props.id),this.props.noFocusOnRender||this.root.focus(),null!=this.props.onDisplay&&this.props.onDisplay()):(0,s.tZ)().tag("Popup_OnOpened_NoRootFound",4,this.props.id,this.props.isVisible)}onClosed(){this.root?(this.root.removeEventListener(a.B.KEYDOWN,this.handleKeydown),null!==this.props.onDismiss&&(document.body.removeEventListener(a.B.CLICK,this.handleBodyClick),document.body.removeEventListener(a.B.CONTEXTMENU,this.handleBodyClick)),(0,s.NP)().invoke("ContextMenuPopup",!1,this.props.id)):(0,s.tZ)().tag("Popup_OnClosed_NoRootFound",4,this.props.id,this.props.isVisible)}setInlineStyles(){if(!this.root)return;let e={},t=!1;if(!this.props.popupPosition&&this.props.target instanceof Element){const n={top:0,bottom:window.innerHeight,left:0,right:window.innerWidth},o=this.props.target.getBoundingClientRect();t=!this.props.skipAdjustPostion&&o.bottom+this.root.clientHeight>n.bottom&&o.top-this.root.clientHeight>n.top,e=this.props.isRtl?{right:o.right-this.root.clientWidthn.right&&o.right-this.root.clientWidth>n.left?o.right-this.root.clientWidth:o.left,top:t?o.top-this.root.clientHeight:o.top+o.height},r.createPortal&&(e.position="fixed"),e=Object.assign(Object.assign({},e),this.props.style),this.setState({inlineStyle:e})}if(!this.props.skipAdjustPostion){const n=40,o={top:0,bottom:window.innerHeight};if(this.props.popupPosition&&this.props.popupPosition.top)this.root.style.maxHeight=o.bottom-this.props.popupPosition.top-n+"px";else if(e&&e.top&&!t){const t=this.props.target.getBoundingClientRect(),r=this.props.style&&this.props.style.top?parseFloat(e.top):e.top,i=o.bottom-r-n,a=t.top-o.top;ii?(e.maxHeight=a,e.top=0):e.maxHeight=i,this.setState({inlineStyle:e})}}}render(){const{id:e,role:t,className:n,ariaLabel:a,ariaLabelledBy:s,ariaDescribedBy:l,renderHost:d,popupPosition:p}=this.props;let f={};p&&(f={left:p.left,right:p.right,top:p.top,bottom:p.bottom},r.createPortal&&(f.position="fixed"),f=Object.assign(Object.assign({},f),this.props.style));const h=o.createElement("div",{id:e,ref:this.setRootRef,tabIndex:0,className:(0,c.A)(i.WB,n||u.popup,{[u.react15Css]:!r.createPortal}),role:t,"aria-label":a,"aria-labelledby":s,"aria-describedby":l,style:p?f:this.state.inlineStyle,onAnimationEnd:this.props.onAnimationEnd},this.props.children);return r.createPortal?o.createElement("div",null,r.createPortal(h,d||document.body)):h}handleKey(e,t){let n,o=-1;const r=document.activeElement;if(this.props.focusTrapSelector){const e=this.root.querySelectorAll(this.props.focusTrapSelector),i=Array.prototype.slice.call(e);t?r===this.root||r===i[0]?n=i[i.length-1]:this.props.isArrowUpDownFocus&&(o=i.indexOf(r),n=i[o-1]):r===i[i.length-1]?n=i[0]:this.props.isArrowUpDownFocus&&(o=i.indexOf(r),n=i[o+1])}n&&(n.focus(),e.stopPropagation(),e.preventDefault())}hidePopup(e){null!=this.props.onDismiss&&this.props.onDismiss(e),e.preventDefault(),e.stopPropagation()}}},36649:function(e,t,n){"use strict";function o(e,t){let n=e,o=t;n.virtual||(n.virtual={children:[]});let r=n.virtual.parent;if(r&&r!==t){let e=r.virtual.children.indexOf(n);e>-1&&r.virtual.children.splice(e,1)}n.virtual.parent=o||void 0,o&&(o.virtual||(o.virtual={children:[]}),o.virtual.children.push(n))}function r(e,t,n){if(e&&t)if(n)for(;t;){let n=i(t);if(n===e)return!0;t=n}else if(e.contains)return e.contains(t);return!1}function i(e,t=!0){return e&&(t&&function(e){let t;var n;return e&&(n=e)&&n.virtual&&(t=e.virtual.parent),t}(e)||e.parentNode&&e.parentNode)}n.d(t,{I:function(){return r},g:function(){return o}})},46340:function(e,t,n){"use strict";n.d(t,{r:function(){return a}});var o=n(90872),r=n(22461),i=n(65874);class a extends o.PureComponent{constructor(e){super(e)}render(){let{fontSize:e,fontIconCss:t,className:n,fontFamily:a,fontValue:s}=this.props;const c={display:"inline-block"};return e&&(c.fontSize=e+"px"),t?n=(0,r.A)(t,n):a&&s&&(c.fontFamily=a),o.createElement("div",{className:"o365cs-base","aria-hidden":this.props.isAriaHidden},o.createElement("span",{className:(0,r.A)(n,{[i.iconFontRTL]:this.props.reverseIconInRtl}),style:c,role:"presentation"},s))}}},43246:function(e,t,n){"use strict";n.d(t,{r:function(){return o.r}});var o=n(46340)},95144:function(e,t,n){"use strict";n.d(t,{bS:function(){return C.bS},tz:function(){return r.t},kt:function(){return i.k},Bx:function(){return o.B},rP:function(){return s.r},z6:function(){return a.z},zD:function(){return c.z},l5:function(){return C.l5},zM:function(){return C.zM},qz:function(){return h},BE:function(){return C.BE},QR:function(){return C.QR},ui:function(){return C.ui},xw:function(){return v},B3:function(){return H},lQ:function(){return M.lQ},wk:function(){return B.wk},Rz:function(){return k},P3:function(){return P},AH:function(){return T.A},Fg:function(){return A.Fg},Wq:function(){return B.Wq},Oi:function(){return E},nQ:function(){return L},Jg:function(){return O},mD:function(){return F.mD},K$:function(){return D},_R:function(){return y},JT:function(){return g.JT},OU:function(){return I.O},YZ:function(){return g.YZ},vQ:function(){return g.vQ},BW:function(){return x},X7:function(){return w},Wg:function(){return M.Wg},lN:function(){return M.lN},j$:function(){return M.j$},h5:function(){return S.h},x_:function(){return N},qd:function(){return A.qd},ad:function(){return A.ad}});var o=n(18435),r=n(39038),i=n(79649),a=(n(10806),n(93884)),s=n(46340),c=n(83694),l=n(90872),u=n(61304),d=n(40141),p=n(49152),f=n(31556);class h extends l.Component{constructor(e){super(e),this.setRef=e=>this.searchControl=e,this.SearchBarKey=e=>{let t=e.currentTarget.value;this.setState((()=>({currentSearchText:t,showDismissButton:!0}))),this.props.onSearch(t)},this.DismissDefaultText=()=>{this.state.clearTextOnFocus?this.setState((()=>({currentSearchText:"",showDismissButton:!1}))):this.setState((()=>({showDismissButton:!0,clearTextOnFocus:!0})))},this.DefaultSearchText=()=>{""===this.state.currentSearchText?this.setState((()=>({currentSearchText:this.props.defaultText,showDismissButton:!1}))):this.setState((()=>({clearTextOnFocus:!1})))},this.ButtonClearText=()=>{this.searchControl.focus(),this.searchControl.placeholder="",this.setState((()=>({currentSearchText:"",showDismissButton:!1}))),this.props.onSearch("")},this.moveCursor=()=>{this.searchControl.focus()},this.props.currentSearchText?this.state={currentSearchText:this.props.currentSearchText,showDismissButton:!0,clearTextOnFocus:!1}:this.state={currentSearchText:this.props.defaultText,showDismissButton:!1,clearTextOnFocus:!0}}getSearchResultAriaLabel(){return(0,g.vQ)(this.state.currentSearchText)?"":(0,g.JT)(u.D.SearchBoxResultAriaLabel,`${this.props.searchResultCount}`)}render(){let e=(0,d.e)(),t=(0,p.g)();return l.createElement("div",{className:(0,T.A)(f.SearchControl,t?f.SearchControlZoomMargin:null,e.neutral.foregroundAlt.background)},l.createElement("div",{"aria-live":"polite",style:{position:"absolute",left:"-999em",top:"0em"}},this.getSearchResultAriaLabel()),this.state.showDismissButton?l.createElement("button",{onClick:this.ButtonClearText,"aria-label":u.D.SearchBoxClearButtonText,title:u.D.SearchBoxClearButtonText},l.createElement(s.r,{className:e.neutral.dark.font,fontIconCss:"ms-Icon--ChromeClose",fontSize:"12"})):l.createElement("button",{onClick:this.moveCursor,tabIndex:-1,"aria-hidden":!0},l.createElement(s.r,{className:e.neutral.dark.font,fontIconCss:"ms-Icon--Search",fontSize:"12"})),l.createElement("input",{className:(0,T.A)(f.inputBox,e.neutral.dark.font),type:"text",onFocus:this.DismissDefaultText,value:this.state.currentSearchText,onChange:this.SearchBarKey,onBlur:this.DefaultSearchText,ref:this.setRef,placeholder:this.props.defaultText,id:"appLauncherSearch",autoComplete:"off","aria-label":this.props.ariaLabel||this.props.defaultText}))}}var m=n(16968),g=n(87948),b=n(12424);class v extends l.Component{render(){var e,t,n,o,r;let i=(0,d.e)();if(null!=this.props.unseenItemCount&&0!==this.props.unseenItemCount){const a=null!==(e=this.props.badgeCharacter)&&void 0!==e?e:(0,g.d1)(this.props.unseenItemCount);let s=(0,T.A)(b.unseenCount,i.accent.border,{[i.badge]:!this.props.isParentHovered},{[b.emptyBadge]:""===this.props.badgeCharacter},{[b.emptyBadgeDarkMode]:""===this.props.badgeCharacter&&this.props.isDarkMode}),c={};return(null===(t=this.props.badgeColors)||void 0===t?void 0:t.badgeColor)&&(c.backgroundColor=this.props.badgeColors.badgeColor),(null===(n=this.props.badgeColors)||void 0===n?void 0:n.badgeFontColor)&&(c.color=this.props.badgeColors.badgeFontColor),this.props.isParentHovered&&(c.boxSizing="border-box",c.border="1px solid",(null===(o=this.props.badgeColors)||void 0===o?void 0:o.badgeHoverColor)?c.backgroundColor=this.props.badgeColors.badgeHoverColor:c.backgroundColor=(0,m.Vz)().getThemeData().AccentHover||"white",(null===(r=this.props.badgeColors)||void 0===r?void 0:r.badgeFontHoverColor)?c.color=this.props.badgeColors.badgeFontHoverColor:c.color="#106EBE"),l.createElement("div",{className:(0,T.A)(b.unseenitems,this.props.badgeStyles)},l.createElement("span",{style:c,className:s},a,this.props.children))}return null}}var y=n(31689),x=n(28942),A=n(93814),C=n(7102),S=n(25793);let w={notificationsEnabled:!1,toastsMuted:!1,bellHeaderButtonInLayout:!0,isSubscriptionReady:!1,systemNotificationsDisabled:!0,notifications:[]};n(84862);let k={timestamp:null,appsUpdateTimeSpan:null,appDataCache:null,moreAppDataAvailable:null,doNotCallGetAllAppsUntil:null,ShowConditionalAccessError:null};const P={isChatAPIInitialized:null,isChatRecentsPaneInitialized:!1,isChatAPIPreAuthCompleted:!1,unreadBadgeValue:0,chatEnabled:!1,chatWebLink:null,webChatSDKUrl:null,isTeamsChatActivated:!1,isTeamsChatAuthFailed:!1,chatButtonRenderedCallback:null,isConsumerShell:!1};let O={activeButtonId:"",customFlexPanes:{},customFlexPaneHash:void 0,customHeaderButtonFlexPaneTriggers:{},customHeaderButtons:[],badgeValues:{},badgeColors:{},badgeLabels:{},badgeCharacters:{},customFlexpaneWidth:void 0};n(82366),n(6062);var I=n(82453);n(31418);function D(e,t,n=0){let o=-1;for(let r=n;rt.trim()===e))}var B=n(50286),H=n(94190)},93814:function(e,t,n){"use strict";n.d(t,{Fg:function(){return p},Rm:function(){return u},UD:function(){return g},Zd:function(){return l},ad:function(){return c},mA:function(){return f},qd:function(){return d},rl:function(){return s},rv:function(){return h},vx:function(){return i},wZ:function(){return a},zh:function(){return m}});var o=n(16968),r=n(7102);function i(e,t,n){return{type:r.l5,navBarData:e,shellClientData:t,renderSettings:n}}function a(e){return{type:r.uU,shellStrings:e}}function s(e){return{type:r.zM,shellLayout:e}}function c(e){return(t,n,i)=>{t({type:r.QR,buttonId:e}),(0,o.NP)().invoke("ShellInteraction")}}function l(e,t){return{type:r.nv,appsData:e,appDataSource:t}}function u(e,t,n){return{type:r.c5,collectorId:e,id:t,imageDataUrl:n}}function d(e){return{type:r.BE,themeData:e}}function p(e){return{type:r.bS,themeInfo:e}}function f(e,t){return{type:r.j4,customFlexpane:e,customFlexpaneWidth:t}}function h(e){return{type:r.GY,customFlexpaneID:e}}function m(e){return{type:r.pL,m365CopilotBannerData:e}}function g(e){return{type:r.nJ,isCopilotBannerClicked:e}}},7102:function(e,t,n){"use strict";n.d(t,{BE:function(){return h},GY:function(){return c},QR:function(){return d},ZH:function(){return i},bS:function(){return m},c5:function(){return f},j4:function(){return s},l5:function(){return o},nJ:function(){return u},nv:function(){return p},pL:function(){return l},uU:function(){return a},ui:function(){return g},zM:function(){return r}});const o="suiteux-common.SHELL_INITDATA_CHANGED",r="suiteux-common.SHELL_LAYOUT_CHANGED",i="suiteux-common.RENDERSETTINGS_CHANGED",a="suiteux-common.SHELL_STRINGS_LOADED",s="suiteux-common.SHELL_FLEXPANES_CHANGED",c="suiteux-common.SHELL_FLEXPANE_REMOVE",l="suiteux-common.SET_M365COPILOT_BANNER_DATA",u="suiteux-common.SET_COPILOT_BANNER_CLICKED",d="suiteux-common.TOGGLE_ACTIVE_HEADERBUTTON",p="suiteux-common.SET_APPS_DATA",f="suiteux-common.SET_IMAGE_DATA_URL",h="suiteux-settings.THEMEDATA_CHANGED",m="suiteux-common.CURRENT_THEME_CHANGED",g="suiteux-common.UPDATE_IS_CHAT_RECENTS_OPEN"},25793:function(e,t,n){"use strict";n.d(t,{h:function(){return m}});var o=n(79627),r=n(87948),i=n(7102);let a={apps:[],imageDataUrls:{},source:0,m365CopilotBannerData:null,isCopilotBannerClicked:!1};function s(e,t){if(!e){let n=t.shellInitData.shellInitDataState;e=c(a,n.navBarData,n.clientData)}switch(t.type){case i.l5:let n=t;return c(e,n.navBarData,n.shellClientData);case i.nv:return function(e,t){let n=[...t.appsData];return Object.assign(Object.assign({},e),{apps:n,hash:(0,r.YZ)(JSON.stringify(n)),source:t.appDataSource})}(e,t);case i.c5:return function(e,t){let n=Object.assign({},e.imageDataUrls);return n[o.qH(t.collectorId,t.id)]=t.imageDataUrl,Object.assign(Object.assign({},e),{imageDataUrls:n})}(e,t);case i.pL:return function(e,t){return Object.assign(Object.assign({},e),{m365CopilotBannerData:t.m365CopilotBannerData})}(e,t);case i.nJ:return function(e,t){return Object.assign(Object.assign({},e),{isCopilotBannerClicked:t.isCopilotBannerClicked})}(e,t);default:return e}}function c(e,t,n){if(0!==e.source&&5!==e.source&&4!==e.source)return e;let i=o.kx(t,n);return Object.assign(Object.assign({},e),{apps:i,hash:(0,r.YZ)(JSON.stringify(i)),source:n&&n.MoreAppDataAvailable?5:4})}var l=n(94361);function u(e={},t){switch(t.type){case i.ZH:let n=t;return Object.assign(Object.assign({},e),{renderSettings:n.renderSettings});case i.l5:let o=t;return Object.assign(Object.assign({},e),{navBarData:o.navBarData,clientData:o.shellClientData});case i.zM:let r=t;return r.shellLayout&&r.shellLayout.centerCustomizationRegion&&d(r.shellLayout.centerCustomizationRegion,0),Object.assign(Object.assign({},e),{layout:r.shellLayout});default:return e}}function d(e,t){if((0,l.A6)(e)){e.regionID=e.regionID||`Region_${t}`,t++;for(let n of e.children)t=d(n,t)}else e.id=e.id||`Control_${t}`,t++;return t}var p=n(1742);function f(e,t){return e||(e={ThemeId:p.ux}),t.type===i.bS?function(e,t){const n=t.themeInfo||{};return n.DarkAccent=null!=n.DarkAccent&&""!==n.DarkAccent?n.DarkAccent:null,Object.assign(Object.assign({},e),n)}(e||{},t):e}function h(e={},t){if(t.type===i.l5){let n=t;return function(e,t,n){return Object.assign(Object.assign({},e),{cultureName:t.CultureName,isConsumer:n.IsConsumerShell,notManagedEmailAddress:n.NotManagedEmailAddress,truncatedUserDisplayName:t.TruncatedUserDisplayName,upn:n.UPN,userDisplayName:t.UserDisplayName,firstName:t.FirstName,lastName:t.LastName,isRtl:n.IsRTL,hasMailboxInCloud:n.HasMailboxInCloud,lcid:n.LCID,puid:n.PUID,tid:n.TID,uid:n.UID,emailAddress:n.EmailAddress})}(e,n.navBarData,n.shellClientData)}return e}let m=new class{constructor(){this.shellReducers={shellInitDataState:u,userState:h,appsDataState:s,themeState:f},this.reducerUpdatedCallback=null}register(e){Object.keys(e).forEach((t=>{this.shellReducers[t]=e[t]})),this.reducerUpdatedCallback&&this.reducerUpdatedCallback(this.getReducers())}getReducers(){return this.shellReducers}}},84862:function(e,t,n){"use strict";n.d(t,{P:function(){return o}});const o={isHidden:!1,isInitialized:!1,openedByTouchOrKeyPress:null,openedTime:null,coreAndSegmentAppTiles:[],isCustomizable:!1,showAllView:!1,hamburgerEnabled:!1,showM365Experience:!1,isStandalone:!1,isNTP:!1}},82366:function(e,t,n){"use strict";n.d(t,{R:function(){return o}});let o={isOpen:!1,activeProviderKey:null,activeProviderWidth:0,activeProviderTrigger:null,registeredProviders:[]}},6062:function(e,t,n){"use strict";n.d(t,{X:function(){return o}});const o={}},82453:function(e,t,n){"use strict";n.d(t,{O:function(){return b}});var o=n(71052);function r(e){return function(t){var n=t.dispatch,o=t.getState;return function(t){return function(r){return"function"==typeof r?r(n,o,e):t(r)}}}}var i=r();i.withExtraArgument=r;var a=i,s=n(16968),c=n(93814),l=n(25793);let u,d={shellInitDataState:{renderSettings:(0,s.GJ)()}},p=null;function f(){p||(p=b());let e=p.getState();e.appsDataState&&e.appsDataState.hash!==u&&(u=e.appsDataState.hash,function(e,t){let n={Apps:e,DataSource:t,FailureReason:0};(0,s.NP)().invoke("AppsRetrievalSucceeded",n)}(e.appsDataState.apps,e.appsDataState.source))}let h=null;const m=new Promise(((e,t)=>{(0,s.NP)().subscribe("SuiteAPILoaded",(t=>{e(t)}),!0)}));function g(e,t){const n=Object.keys(e).filter((t=>"function"==typeof e[t]));return(o={},r)=>{let i=!1;const a=n.reduce(((n,a)=>{if(a in n)throw Error(`Attempt to run reducer for key:${a} more than once. It should only be registered once.`);let s;if(s=void 0===o[a]?e[a](o[a],Object.assign(Object.assign({},r),t)):e[a](o[a],r),void 0===s)throw Error(`Reducer for key ${a} returned an undefined state.`);return n[a]=s,i=i||o[a]!==n[a],n}),{});return i?a:o}}function b(){if(h)return h;const e=g(l.h.getReducers(),{shellInitData:d}),t=window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__,n=t&&t({name:"SuiteUX"})||o.Zz;try{h=(0,o.y$)(e,d,n((0,o.Tw)(a.withExtraArgument(m))))}catch(e){(0,s.tZ)().exception("GetShellStore_CreateStoreFailure",6,e)}const r=(0,s.NP)();return r.subscribe("ShellDataUpdated",((e,t)=>{h.dispatch((0,c.vx)(e,t,(0,s.GJ)()))}),!0),r.subscribe("StringsLoaded",(e=>{h.dispatch((0,c.wZ)(e))}),!0),r.subscribe("ShellLayoutUpdated",(e=>{h.dispatch((0,c.rl)(e))}),!0),h.subscribe(f),l.h.reducerUpdatedCallback=e=>{h.replaceReducer(g(e,{shellInitData:h.getState()}))},h}},31418:function(e,t,n){"use strict";n.d(t,{i:function(){return s}});var o=n(16968),r=n(93814),i=n(82453);const a=e=>{(0,i.O)().dispatch((0,r.Fg)(e))};function s(){(0,o.NP)().subscribe("ThemeChanged",a,!0)}},79627:function(e,t,n){"use strict";n.d(t,{J0:function(){return i},Wb:function(){return a},kx:function(){return r},qH:function(){return u},w:function(){return l}});var o=n(61304);function r(e,t){let n=[];for(let o of function(e){let t=[];e&&(e.WorkloadLinks&&t.push(...e.WorkloadLinks),null!=e.AppsLinks&&t.push(...e.AppsLinks),null!=e.AdminLink&&t.push(e.AdminLink),null!=e.PartnerLink&&t.push(e.PartnerLink));return t}(e)){let r=s(o,e,t);if(t&&t.AppDataCache){let e=i(t.AppDataCache,r.CollectorId,r.Id);e&&(r.AlternateNames=e.AlternateNames,r.DateInstalled=e.DateInstalled)}n.push(r)}return t&&t.AppDataCache&&n.push(...t.AppDataCache.filter((e=>"FirstParty"!==e.CollectorId))),n}function i(e,t,n){if(e)for(let o of e)if(o.CollectorId===t&&o.Id===n)return o;return null}function a(e){return null==e?e:e.filter(((e,t,n)=>{for(let o=0;ot.Id===e.Id))||null!=t.AdminLink&&t.AdminLink.Id===e.Id||null!=t.PartnerLink&&t.PartnerLink.Id===e.Id}function l(e,t){return"remove"===t&&0===e.indexOf("Shell")?e.substr(5):"add"===t&&-1===e.indexOf("Shell")?"Shell"+e:e}function u(e,t){return`${e}.${t}`}},16968:function(e,t,n){"use strict";function o(){return window.O365ShellContext&&window.O365ShellContext.RenderSettings}function r(){return window.O365ShellContext&&window.O365ShellContext.CallbackManager}function i(){return window.O365ShellContext&&window.O365ShellContext.Logger}function a(){return window.O365ShellContext&&window.O365ShellContext.ChunkLoader}function s(){return window.O365ShellContext&&window.O365ShellContext.ThemeManager}function c(){return window.O365ShellContext&&window.O365ShellContext.LayoutManager}function l(){return window.O365ShellContext&&window.O365ShellContext.BootHeaderState}function u(){return window.O365ShellContext&&window.O365ShellContext.Aria}function d(){return window.O365ShellContext&&window.O365ShellContext.SearchBoxContext}function p(){var e,t;return null!==(t=null===(e=window.O365ShellContext)||void 0===e?void 0:e.IsEcsInitialized)&&void 0!==t&&t}function f(e){window.O365ShellContext&&(window.O365ShellContext.IsEcsInitialized=e)}n.d(t,{GD:function(){return f},GJ:function(){return o},NP:function(){return r},Vz:function(){return s},YF:function(){return c},l3:function(){return a},m5:function(){return u},mf:function(){return p},tZ:function(){return i},vk:function(){return d},vm:function(){return l}})},73637:function(e,t,n){"use strict";function o(e){let t=document.cookie.split(";"),n=null;for(let o=0;o{if(e)if("string"==typeof e)t.push(e);else{let n=Object.keys(e).filter((t=>!0===e[t]));n.length>0&&t.push(n)}})),t.join(" ")}n.d(t,{A:function(){return o}})},7667:function(e,t,n){"use strict";function o(e){let t;return t="string"==typeof e?0===e.indexOf("/Date(")?new Date(parseInt(e.match(/\d+/g)[0])):new Date(e):"number"==typeof e?new Date(e):new Date(e.getTime()),t}n.d(t,{_:function(){return o}})},90241:function(e,t,n){"use strict";n.r(t),n.d(t,{onNavBarLinkClicked:function(){return r}});var o=n(16968);function r(e,t){const n={Target:t.TargetWindow,Id:t.Id,Text:t.Text,Url:t.Url};return(0,o.NP)().invoke("LinkClick",n),!(null!=t.Action&&!1===t.Action()||n.Cancel)||(e&&e.preventDefault(),!1)}},87894:function(e,t,n){"use strict";function o(e,t){if(null===e)throw new Error(`Error: ${t} is null.`)}function r(e,t){if(void 0===e)throw new Error(`Error: ${t} is undefined.`)}function i(e,t){o(e,t),r(e,t)}function a(e,t){if(i(e,t),0===e.length)throw new Error(`Error: ${t} is an empty string.`)}function s(e,t){if(i(e,t),0===e.length)throw new Error(`Error: ${t} is a null or empty array.`)}n.r(t),n.d(t,{throwOnNull:function(){return o},throwOnNullOrEmpty:function(){return a},throwOnNullOrEmptyArray:function(){return s},throwOnNullOrUndefined:function(){return i},throwOnUndefined:function(){return r}})},33680:function(e,t,n){"use strict";n.d(t,{Fb:function(){return c},Wg:function(){return i},j$:function(){return s},lN:function(){return a},lQ:function(){return r}});var o=n(40141);function r(e,t,n){e=e instanceof Array?e:[e];for(let o of t.split(" "))for(let t of e)t=t instanceof HTMLElement?t:document.getElementById(t),t&&t.addEventListener(o,n)}function i(e,t,n){e=e instanceof Array?e:[e];for(let o of t.split(" "))for(let t of e)t=t instanceof HTMLElement?t:document.getElementById(t),t&&t.removeEventListener(o,n)}function a(e,t){if(e=e instanceof HTMLElement?e:document.getElementById(e)){c(e,(0,o.e)().activeHeaderButton,t)}}function s(e,t){let n=document.getElementById(e);if(n){let e=(0,o.e)();c(n,e.activeHeaderButton,t),c(n,e.headerButton,!t)}}function c(e,t,n){n?function(e,...t){if(e.classList)for(let n of t)e.classList.add(n);else for(let n of t)e.className.split(" ").some((e=>e===n))||(e.className+=" "+n)}(e,t):function(e,...t){if(e.classList)for(let n of t)e.classList.remove(n);else for(let n of t)e.className=e.className.split(" ").filter((e=>e!==n)).join(" ")}(e,t)}},94361:function(e,t,n){"use strict";function o(e,t){let n=null;if(t)for(let i of t){if(r(i))n=o(e,i.children);else{let t=i;t&&t.nativeControlID===e&&(n=t)}if(n)break}return n}function r(e){return e&&void 0!==e.children}n.d(t,{A6:function(){return r},mD:function(){return o}})},88242:function(e,t,n){"use strict";function o(e){let t=!1;return{promise:new Promise(((n,o)=>{e.then((e=>t?o({isCancelled:!0}):n(e)),(e=>o(t?{isCanceled:!0}:e)))})),cancel:()=>{t=!0}}}function r(e,t){return new Promise(((n,o)=>{e().then(n).catch((i=>{0===t?o(i):r(e,--t).then(n).catch(o)}))}))}n.d(t,{L:function(){return r},l:function(){return o}})},21622:function(e,t,n){"use strict";let o,r,i;function a(){const e=c();o=e.selectionStart,r=e.selectionEnd,i=e===document.activeElement}function s(){if(i){const e=c();e.focus(),e.selectionStart=o,e.selectionEnd=r,l()}}function c(){const e=document.getElementById("sbcId");if(e){const t=e.getElementsByTagName("input");if(t.length)return t[0]}return{selectionStart:0,selectionEnd:0,focus:()=>{}}}function l(){o=0,r=0,i=!1}n.d(t,{I7:function(){return a},KW:function(){return c},zi:function(){return s}}),l()},58059:function(e,t,n){"use strict";n.d(t,{b:function(){return a},n:function(){return i}});var o=n(87948);const r=/[0-9a-fA-F]{16}/;function i(e){return null!=e.SHSID}function a(e){if((0,o.vQ)(e))return!1;if(16!==e.length)return!1;if(!e.startsWith("0")&&!e.startsWith("1")&&!e.startsWith("2"))return!1;return!!e.match(r)}},87948:function(e,t,n){"use strict";function o(e,t){let n=e.lastIndexOf(t);return-1!==n&&n===e.length-t.length}function r(e,...t){return e?e.replace(/\{(\d+)\}/g,((e,n)=>void 0===t[n]?e:t[n])):""}function i(e){const t=e.length;let n=5381,o=0;for(;o0?e<100?e.toString():"99+":null}n.d(t,{JT:function(){return r},YZ:function(){return i},d1:function(){return s},d5:function(){return o},vQ:function(){return a}})},6936:function(e,t,n){"use strict";n.d(t,{Gj:function(){return i},I9:function(){return o},Q:function(){return r}});const o=6e4,r=60*o,i=24*r},50286:function(e,t,n){"use strict";n.d(t,{FY:function(){return a},Wq:function(){return i},wk:function(){return r}});var o=n(16968);function r(e,t,n){let o="?";return e.indexOf(o)>-1&&(o="&"),e+o+t+"="+n}function i(e){if(!e)return"";return encodeURI(e).replace(/#/g,"%23")}function a(e,t){if(null==e)return!0;if((e=(e=e.toLowerCase()).trim()).startsWith("https://")||!0===e.startsWith("http://"))return!0;{let n=e.indexOf("://"),r=null;return-1!==n&&(r=e.substring(0,n)),(0,o.tZ)().tag("Unsafe URL: "+{beforeColonUrl:r},6),!t}}},94190:function(e,t,n){"use strict";function o(){if(null!=navigator&&navigator.userAgent){let e=navigator.userAgent.toLowerCase(),t=navigator.maxTouchPoints||0;return e.indexOf("phone")>=0||e.indexOf("android")>=0||e.indexOf("mobile")>=0||e.indexOf("mowa")>=0||t>0&&e.indexOf("macintosh")>=0}return!1}function r(){return window.navigator.userAgent.indexOf("MSIE ")>0||!!navigator.userAgent.match(/Trident.*rv\:11\./)}function i(){return window.navigator.userAgent.indexOf("Edge")>-1}n.r(t),n.d(t,{isBrowserEdge:function(){return i},isBrowserIE:function(){return r},isMobileClient:function(){return o}})},66164:function(e,t,n){"use strict";function o(e){return"ShellMail"===e||"Exchange"===e}function r(e,t){return t?"shellofficepwa"===t.toLowerCase():"officepwa"===(e&&e.toLowerCase())}function i(e,t,n){let o="Unknown";switch(t?(o=t.replace(/^shell/i,""),"none"===o.toLowerCase()&&(o=e||"")):e&&(o=e),o.toLowerCase()){case"admin":switch(e.toLowerCase()){case"adminportal":o="AdminPortal";break;case"exchange":o="ExchangeAdmin";break;case"forefront":o="ForefrontAdmin";break;case"lync":o="SkypeAdmin";break;case"sharepoint":o="SharePointAdmin";break;case"sissync":o="Homeroom";break;default:o=e}break;case"documents":if("odbadmin"===e.toLowerCase())o="ODBAdmin";break;case"o365settings":if("aadux"===e.toLowerCase())o="AADUXAdmin";break;case"outlook":switch(e.toLowerCase()){case"forefront":o="Forefront";break;default:{let e=n.toLowerCase();o=e.indexOf("path=/option")>=0||e.indexOf("path=%2foption")>=0||e.indexOf("/ecp/")>=0?"OWASettings":e.indexOf("path=/bookings")>=0||e.indexOf("path=%2fbookings")>=0?"Bookings":e.indexOf("path=/calendar")>=0||e.indexOf("path=%2fcalendar")>=0?e.indexOf("path=/?nativeversion")>=0?"Monarch":"Calendar":e.indexOf("path=/group")>=0||e.indexOf("path=%2fgroup")>=0||e.indexOf("path=/people")>=0||e.indexOf("path=%2fpeople")>=0?e.indexOf("path=/?nativeversion")>=0?"Monarch":"People":e.indexOf("path=/tasks")>=0||e.indexOf("path=%2ftasks")>=0?"Tasks":e.indexOf("path=/mail/?nativeversion")>=0||e.indexOf("path=%2fmail/?nativeversion")>=0?"Monarch":e.indexOf("path=/mail")>=0||e.indexOf("path=%2fmail")>=0?"Mail":e.indexOf("modurl=1")>=0?"Calendar":e.indexOf("modurl=2")>=0?"People":e.indexOf("modurl=3")>=0?"Tasks":e.indexOf("modurl=4")>=0?"OWASettings":"Mail";break}}break;case"sites":case"sharepoint":o="SharePoint";break;case"iwapp":case"officedotcom":case"officepwa":case"office":o="officepwa"===o.toLowerCase()||"officepwa"===e.toLowerCase()?"OfficePWA":(o.toLowerCase(),"OfficeDotCom")}return o}n.d(t,{Uc:function(){return o},bi:function(){return r},ic:function(){return i}})},98499:function(e,t,n){"use strict";n.d(t,{l:function(){return f}});var o,r,i,a,s=n(16533);!function(e){e.Int_ClientApps="https://config.edge.skype.net",e.Int_InternalServices="https://s2s.config.skype.net",e.Prod_M365ClientApps="https://ecs.office.com",e.Prod_ConsumerClientApps="https://config.edge.skype.com",e.Prod_TeamsClientApps="https://config.teams.microsoft.com",e.Prod_InternalServices="https://s2s.config.skype.com"}(o||(o={})),function(e){e[e.Valid=0]="Valid",e[e.Invalid=1]="Invalid",e[e.Expired=2]="Expired",e[e.NoData=3]="NoData",e[e.NoCache=4]="NoCache"}(r||(r={})),function(e){e.Filters="Filters",e.None="None",e.ConsumerKey="ConsumerKey"}(i||(i={})),function(e){e.OnExpiry="OnExpiry",e.Never="Never"}(a||(a={}));var c=n(16968);const l="OneShellECSClient";class u{constructor(){this._settled=!1,this.promise=new Promise(((e,t)=>{this.resolve=e}))}createResolvedPromise(e){this.promise=new Promise(((t,n)=>{t(e)}))}set(e){this._settled?this.createResolvedPromise(e):(this._settled=!0,this.resolve(e))}get getPromise(){return this.promise}}class d{constructor(){this.ecsConfig=new u,this.parameters={client:"Oneshell",version:"1.0.0.0",domain:o.Prod_M365ClientApps}}setParameters(e){return(0,s.__awaiter)(this,void 0,void 0,(function*(){this.parameters=e;try{yield this.updateClient(),this.client.startFetchSchedule(window,this.updateEcsConfig.bind(this));const e=this.client.get();if(this.client.cacheState===r.Valid&&e)return void this.updateEcsConfig(e);const t=yield this.client.fetch();this.updateEcsConfig(t)}catch(e){(0,c.tZ)().exception("ECSClient_SetEcsConfig_Failed",6,e)}}))}updateEcsConfig(e){var t;(null===(t=e.ecsConfiguration)||void 0===t?void 0:t.OneShell)?this.ecsConfig.set(e.ecsConfiguration.OneShell):(0,c.tZ)().exception("ECSClient_UpdateEcsConfig_Failed",6,new Error("OneShell config not found in ECS data"))}updateClient(){return(0,s.__awaiter)(this,void 0,void 0,(function*(){if(this.client)return void this.client.updateParameters(this.parameters);const e=(0,c.l3)();if(!e||"function"!=typeof e.loadChunk)throw new Error("Chunk loader is not available to load ecsclient chunk");yield e.loadChunk("ecsclient"),this.client=yield window.createClient(this.parameters)}))}getConfig(e=2e3){const t=new Promise(((t,n)=>{setTimeout((()=>{n(new Error(`ECSClient_GetConfig timedout after ${e}`))}),e)}));return Promise.race([this.ecsConfig.getPromise,t]).then((e=>e)).catch((e=>((0,c.tZ)().exception("ECSClient_GetConfig_Failed",6,e),{})))}}const p=e=>!(!e.EnableClientECSFetch&&!e.IsConsumerShell)||!e.Environment,f=()=>((0,c.mf)()||((0,c.GD)(!0),(()=>{if(!localStorage)return void(0,c.tZ)().exception("ECS_InitECS_Failed",4,new Error("Localstorage is not available"));const e=(t,n)=>{if(p(n)){const{TID:t,UPN:r,IsConsumerShell:i,WorkloadId:a,UID:s}=n,u={client:"Oneshell",version:"1.0.0.0",domain:o.Prod_M365ClientApps,filters:{IsConsumer:i?"true":"false",WorkloadId:a,TenantId:t,UserId:i?r:s,UPN:r}};(0,c.tZ)().tag("ECS_Initialized",1,`Initialized ECS for ${a}`),window[l].setParameters(u),(0,c.NP)().unsubscribe("ShellDataUpdated",e)}};window[l]=new d,(0,c.NP)().subscribe("ShellDataUpdated",e,!0)})()),window[l])},6330:function(e,t,n){"use strict";n.d(t,{q:function(){return i}});var o=n(90872),r=n(22461);class i extends o.Component{constructor(e){super(e)}componentDidMount(){this.OnFlexPaneFocus=()=>{if(null==this.initialFocusElement&&(this.initialFocusElement=document.getElementById("O365fp_firstFocusable")),this.initialFocusElement){let e=this.initialFocusElement;window.setTimeout((()=>e.focus()),100)}},this.props.isActive&&this.onComponentVisible()}componentWillUnmount(){this.props.isActive&&this.onComponentHide()}componentDidUpdate(e,t){this.props.isActive!==e.isActive&&(this.props.isActive?this.onComponentVisible():this.onComponentHide())}render(){return o.createElement("div",{id:`FlexPane_${this.props.flexPaneProviderID}`,className:(0,r.A)(this.props.className),style:{display:this.props.isActive?"":"none"}},this.props.children)}onComponentVisible(){let e=document.getElementById("O365fp_lastFocusable");e&&this.OnFlexPaneFocus&&e.addEventListener("focus",this.OnFlexPaneFocus)}onComponentHide(){let e=document.getElementById("O365fp_lastFocusable");e&&this.OnFlexPaneFocus&&e.removeEventListener("focus",this.OnFlexPaneFocus)}}},8428:function(e,t,n){"use strict";n.d(t,{E:function(){return C},x:function(){return A}});var o=n(57556),r=n(90872),i=n(9028),a=n(40141),s=n(46340),c=n(16968),l=n(22461),u=n(33680),d=n(98499),p=n(99542),f=n(49152),h=n(45557),m=n(1742),g=n(53644),b=n(61304),v=n(13825),y=n(40192),x=n(7818);const A=320;class C extends r.Component{constructor(e){super(e),this.boundListeners={},this.scrollListeners={},this.secondFocussableSkipOnFocusBehavior=!1,this.focusTrapInFlexPane=!1,this.setScrollRegion=e=>{this.flexPaneRegion=e},this.setFocusRegion=e=>{this.flexPaneFocusRegion=e},this.setFirstFocusable=e=>{this.flexPaneFirstFocussable=e},this.setSecondFocusable=e=>{this.flexPaneSecondFocussable=e},this.setFocusSkipperStart=e=>{this.flexPaneFocusSkipperStart=e},this.setFocusSkipperEnd=e=>{this.flexPaneFocusSkipperEnd=e},this.setCloseButton=e=>{this.flexPaneCloseButton=e},this.flexPaneHandleKeydown=e=>{let t=!1;switch(e.keyCode){case 27:t=!0;break;case 38:t=e.altKey}t&&(this.closeFlexPane(e),e.preventDefault())},this.handleKeyClose=e=>{switch(e.keyCode){case 13:case 32:this.closeFlexPane(e),e.preventDefault();break;case 9:if(e.shiftKey)break;if(!0===this.focusTrapInFlexPane&&this.flexPaneFirstFocussable){this.flexPaneFirstFocussable.focus(),e.preventDefault();break}if(!this.props.activeHeaderButtonId||!document.getElementById(this.props.activeHeaderButtonId+"_end")){this.secondFocussableSkipOnFocusBehavior=!0,this.flexPaneSecondFocussable.focus();break}if(this.props.activeHeaderButtonId){let e=document.getElementById(this.props.activeHeaderButtonId);e&&e.focus();break}break;default:return}},this.focusSkipperStartOnKeyDown=e=>{if(9===e.keyCode)if(e.shiftKey){const e=document.getElementById(this.props.activeHeaderButtonId);e&&e.focus()}else{if(!0===this.focusTrapInFlexPane){if(!this.flexPaneCloseButton)return;this.flexPaneCloseButton.focus()}this.flexPaneFocusSkipperEnd.focus()}},this.focusSkipperStartOnFocus=()=>{if(this.focusTrapInFlexPane){const e=document.activeElement;e&&this.flexPaneFocusRegion&&!this.flexPaneFocusRegion.contains(e)&&this.flexPaneFirstFocussable&&this.flexPaneFirstFocussable.focus()}else{if(!this.flexPaneCloseButton)return;this.flexPaneCloseButton.focus()}},this.focusSkipperEndOnKeyDown=e=>{9===e.keyCode&&e.shiftKey&&this.flexPaneFocusSkipperStart.focus()},this.firstFocusableOnFocus=()=>{this.flexPaneSecondFocussable&&(this.secondFocussableSkipOnFocusBehavior=!0,this.flexPaneSecondFocussable.focus()),this.setState({showFocusOutline:!0})},this.secondFocusableOnFocus=()=>{if(this.secondFocussableSkipOnFocusBehavior)this.secondFocussableSkipOnFocusBehavior=!1;else if(this.props.activeHeaderButtonId&&document.getElementById(this.props.activeHeaderButtonId+"_end")){if(this.props.activeHeaderButtonId){let e=document.getElementById(this.props.activeHeaderButtonId);e&&e.focus()}}else this.flexPaneCloseButton.focus()},this.registerScrollListener=(e,t)=>(this.scrollListeners[e]=(this.scrollListeners[e]||[]).concat([t]),this.flexPaneRegion&&this.flexPaneRegion.addEventListener("scroll",t,{passive:!0}),()=>{this.flexPaneRegion&&this.flexPaneRegion.removeEventListener("scroll",t)}),this.closeFlexPane=e=>{var t,n;let o=null;if(this.props.registeredProviders.some((e=>this.props.activeProviderKey===e.key&&(o=e,!0))),o){(0,c.tZ)().click("Close",this.props.activeProviderKey+"Pane",e&&e.currentTarget?e.currentTarget.id:"",null,this.props.activeProviderKey);let r=o.btnId?o.btnId:(0,p.nO)(o.nativeControlID),i=document.getElementById(r)||document.getElementById(g.Hp);"Feedback"===o.key&&(i=null!==(n=null!==(t=document.getElementById(p.cQ))&&void 0!==t?t:document.getElementById(p.Pn))&&void 0!==n?n:document.getElementById(p.a_)),i&&e&&e&&i.focus()}this.props.toggle(null,null),(0,x.f1)()},this.state={isOpenStateTransitioning:!1,showFocusOutline:!1,isShyHeaderActive:!1,isFourHundredPercentZoomed:(0,f.g)()},(0,c.NP)().subscribe("ShyHeaderActivated",(e=>{this.setState({isShyHeaderActive:e})}),!0),(0,c.NP)().subscribe("FlexPane400ZoomActivated",(e=>{this.setState({isFourHundredPercentZoomed:e})}),!0);try{(0,d.l)().getConfig().then((e=>{e&&void 0!==e.FocusTrapInFlexPane&&!0===e.FocusTrapInFlexPane&&(this.focusTrapInFlexPane=!0)}))}catch(e){}}componentWillUnmount(){for(let e of this.props.registeredProviders)(0,u.Wg)(e.btnId,"click keydown",this.boundListeners[e.key]);this.focusBehavior.remove(),this.focusBehavior=null}registerListener(e){e.btnId&&(this.boundListeners[e.key]={handleEvent:t=>{if(!!e.overrideOnClick&&e.overrideOnClick())(0,c.tZ)().click(e.key,e.key+"Pane");else{if("keydown"===t.type){switch(t.which){case 13:case 32:t.preventDefault();break;case 40:break;default:return}this.setState({showFocusOutline:!0})}else this.setState({showFocusOutline:!1});this.props.toggle(e.key,e.btnId)}}},(0,u.lQ)(e.btnId,"click keydown",this.boundListeners[e.key]))}componentWillReceiveProps(e){this.props.isOpen!==e.isOpen&&this.setState({isOpenStateTransitioning:!0},(()=>{setTimeout((()=>{this.setState({isOpenStateTransitioning:!1},(()=>{this.props.isOpen&&this.flexPaneRegion&&this.focusOnFlexPane()}))}),280)}))}componentDidUpdate(e){e.registeredProviders.forEach((e=>{!this.props.registeredProviders.some((t=>t.key===e.key))&&this.boundListeners[e.key]&&(0,u.Wg)(e.btnId,"click keydown",this.boundListeners[e.key])})),this.props.registeredProviders.forEach((t=>{let n=e.registeredProviders.filter((e=>e.key===t.key));if(0===n.length)this.registerListener(t);else{let e=n[0];n.length,t.btnId!==e.btnId&&((0,u.Wg)(e.btnId,"click keydown",this.boundListeners[e.key]),this.registerListener(t))}})),e.registeredProviders.forEach((e=>{this.props.registeredProviders.some((t=>t.key===e.key))||this.unregisterListener(e)}));let t=this.props.activeProviderWidth||A,n=e.activeProviderWidth||A;this.props.isOpen===e.isOpen&&t===n&&this.props.activeProviderKey===e.activeProviderKey||(0,c.NP)().invoke("FlexPaneVisibilityChanged",this.props.isOpen,{width:t,providerId:this.props.activeProviderKey}),this.props.isOpen&&this.props.activeProviderKey!==e.activeProviderKey&&this.onShowNewPane(this.props.activeProviderKey,e.activeProviderKey)}onShowNewPane(e,t){(0,c.tZ)().impression(`${e}Pane`,"FlexPane"),this.flexPaneRegion&&(t&&((this.scrollListeners[t]||[]).forEach((e=>this.flexPaneRegion.removeEventListener("scroll",e))),this.scrollListeners[t]=[]),(this.scrollListeners[e]||[]).forEach((e=>this.flexPaneRegion.addEventListener("scroll",e,{passive:!0}))),this.focusBehavior&&this.focusBehavior.remove(),this.focusBehavior=new h.J(this.flexPaneFocusRegion).attach(),this.focusBehavior.onShowFocusHighlight((()=>this.setState({showFocusOutline:!0}))),this.focusBehavior.onHideFocusHighlight((()=>this.setState({showFocusOutline:!1}))),window.setTimeout((()=>this.focusOnFlexPane()),300)),(0,x.Z_)()}focusOnFlexPane(){null==this.flexPaneFirstFocussable||this.props.activeHeaderButtonId&&""!==this.props.activeHeaderButtonId||this.flexPaneFirstFocussable.focus()}componentDidCatch(e,t){(0,c.tZ)().exception("FlexPaneGenericError",6,e,e.name,e.message,t.componentStack)}render(){let e=null;this.props.registeredProviders.forEach((t=>{const n=t.component;(0,u.lN)(t.btnId,this.props.activeProviderKey===t.key);const o=this.props.activeProviderKey===t.key;let i=(0,l.A)({[y.flexPaneComponent]:o},{[y.itemShow]:o},{[y.itemHide]:!o});o&&(e=r.createElement("div",{key:t.key,className:i},r.createElement(n,{isActive:o,showBackButton:!1,flexPaneProviderID:t.key,closeFlexPane:this.closeFlexPane,registerScrollListener:this.registerScrollListener})))}));const t=this.state.isOpenStateTransitioning&&!this.props.isOpen,n=this.state.isOpenStateTransitioning&&this.props.isOpen,c=this.props.hideFlexPane||!this.state.isOpenStateTransitioning&&!this.props.isOpen;let d=(0,a.e)(),f=(0,l.A)(y.flexPaneOverlay,d.neutral.lighterAlt.background,d.neutral.lightAlt.border,{[y.darkBorder]:this.props.isDarkMode,[y.flexPaneHideRight]:t,[y.flexPaneShowRight]:n,[y.flexPaneHidden]:c}),g=r.createElement("div",{id:p.$t,className:(0,l.A)(m.WB,y.flexPaneOverflowContainer,y.flexPaneHeightForThinHeader,{[y.flexPaneHeightForShyHeader]:this.state.isShyHeaderActive},{[y.flexPaneZoomIFrameHeight]:this.state.isFourHundredPercentZoomed}),role:"region",style:{width:this.props.activeProviderWidth?`${this.props.activeProviderWidth+60}px`:null,display:c?"none":null}},r.createElement("div",{id:"O365fp_focusSkipperStart",tabIndex:0,onKeyDown:this.focusSkipperStartOnKeyDown,onFocus:this.focusSkipperStartOnFocus,ref:this.setFocusSkipperStart,role:"region"}),r.createElement("div",{id:p.Cu,className:f,onKeyDown:this.flexPaneHandleKeydown,style:{width:this.props.activeProviderWidth?`${this.props.activeProviderWidth}px`:null,boxShadow:o.f.depth4},role:"region",ref:this.setFocusRegion},r.createElement("div",{id:"O365fp_firstFocusable",tabIndex:-1,onFocus:this.firstFocusableOnFocus,ref:this.setFirstFocusable,"aria-hidden":!0}),r.createElement("div",{id:"O365fp_secondFocusable",tabIndex:-1,onFocus:this.secondFocusableOnFocus,ref:this.setSecondFocusable,"aria-hidden":!0}),r.createElement("div",{id:"flexPaneScrollRegion",role:"region",className:(0,l.A)(y.flexPaneContainer,y.verticalScrollRegion,v.scrollbar,d.neutral.lighterAlt.background,{[h.J.RemoveFocusOutlineClassName]:!this.state.showFocusOutline}),ref:this.setScrollRegion},e,r.createElement("button",{id:"flexPaneCloseButton",type:"button",role:"button",tabIndex:0,className:(0,l.A)(y.closeButton,d.neutral.light.hover.background,d.neutral.secondary.font),title:b.D.FlexpaneCloseButton,"aria-label":b.D.FlexpaneCloseButton,onClick:this.closeFlexPane,onKeyDown:this.handleKeyClose,ref:this.setCloseButton},r.createElement(s.r,{className:y.closeIcon,fontSize:"12",fontIconCss:"ms-Icon--ChromeClose"}))),r.createElement("div",{id:"O365fp_lastFocusable",tabIndex:0})),r.createElement("div",{id:"O365fp_focusSkipperEnd",tabIndex:0,onKeyDown:this.focusSkipperEndOnKeyDown,ref:this.setFocusSkipperEnd,role:"region"}));return null!=i.createPortal?null!=e||t?r.createElement("div",null,i.createPortal(g,this.props.renderHost||document.body)):null:g}unregisterListener(e){e.btnId&&this.boundListeners[e.key]&&(0,u.Wg)(e.btnId,"click keydown",this.boundListeners[e.key])}}},7818:function(e,t,n){"use strict";n.d(t,{Z_:function(){return d},f1:function(){return p},oB:function(){return u}});var o=n(18435),r=n(99542),i=n(40192);let a,s,c,l;function u(){a=window.matchMedia("(max-width: 320px)"),window.addEventListener(o.B.RESIZE,d),d()}function d(){a.matches&&!s?(c=document.getElementById(r.$t),l=document.getElementById(r.Cu),c&&l&&(c.style.width=i.thinFlexPaneOverflowWidth,l.style.width=i.thinFlexPaneWidth,s=!0)):!a.matches&&s&&(c=document.getElementById(r.$t),l=document.getElementById(r.Cu),c&&l&&(c.style.width=i.flexPaneOverflowWidth,l.style.width=i.flexPaneWidth,s=!1))}function p(){s=!1}},28370:function(e,t,n){"use strict";n.d(t,{qs:function(){return y.q},xk:function(){return d.x},eb:function(){return P},M8:function(){return I},ZM:function(){return p.ZM},IZ:function(){return p.IZ}});var o=n(90872),r=n(9028),i=n(91112),a=n(25793),s=n(82453),c=n(16968),l=n(7818),u=n(93814),d=n(8428),p=n(95422);const f=(0,i.connect)(((e,t)=>{var n,o;return{isOpen:e.flexPaneState.isOpen,isDarkMode:e.themeState.IsDarkMode,activeProviderKey:e.flexPaneState.activeProviderKey,activeProviderWidth:e.flexPaneState.activeProviderWidth,registeredProviders:e.flexPaneState.registeredProviders,activeHeaderButtonId:null!==(o=null===(n=e.extensibilityState)||void 0===n?void 0:n.activeButtonId)&&void 0!==o?o:"",renderHost:t.renderHost,hideFlexPane:e.flexPaneState.hideFlexPane}}),(e=>({toggle:(t,n)=>{e((0,u.ad)(n)),e((0,p.IZ)(t))}})))(d.E);var h=n(82366),m=n(6806);function g(e,t){let n=t.providerKey,o=null!==n&&e.activeProviderKey!==n,r=null;if(o)for(let t of e.registeredProviders)t.key===n&&(r=t);return o&&null==r&&null==e.activeProviderKey?Object.assign(Object.assign({},e),{pendingProviderKey:n}):Object.assign(Object.assign({},e),{isOpen:null!=r,hideFlexPane:r?r.hideFlexPane:e.hideFlexPane,activeProviderKey:r?r.key:null,activeProviderWidth:r?r.width:e.activeProviderWidth,activeProviderTrigger:r&&(r.btnId||r.nativeControlID),pendingProviderKey:r?void 0:e.pendingProviderKey})}let b={flexPaneState:function(e=h.R,t){switch(t.type){case m.w1:return g(e,t);case m.vG:return function(e,t){let n=Object.assign(Object.assign({},e),{registeredProviders:e.registeredProviders.concat(t.newProvider),hideFlexPane:t.newProvider.hideFlexPane});return t.newProvider.key===e.pendingProviderKey?g(n,{providerKey:t.newProvider.key}):n}(e,t);case m.YO:return function(e,t){let n=Object.assign(Object.assign({},e),{registeredProviders:e.registeredProviders.filter((e=>e.key!==t.providerKey)),hideFlexPane:!1});return n}(e,t);default:return e}}};class v{OpenFlexPaneForProvider(e){let t=(0,s.O)(),n=t.getState().flexPaneState;const o=n.registeredProviders.filter((t=>t.key.toLowerCase()===e.toLowerCase()))[0],r=n.activeProviderKey;return!(!o||r!==o.key)||(t.dispatch((0,p.IZ)(e)),null!=o&&t.dispatch((0,u.ad)(o.btnId)),null!=o)}CloseFlexPaneForProvider(e){const t=(0,s.O)().getState().flexPaneState;return!(!t.isOpen||t.activeProviderKey!==e&&null!==e)&&((0,s.O)().dispatch((0,p.IZ)(null)),!0)}OnFlexPaneVisibilityChanged(e){return(0,c.NP)().subscribe("FlexPaneVisibilityChanged",e,!1)}RemoveOnFlexPaneVisibilityChanged(e){(0,c.NP)().unsubscribe("FlexPaneVisibilityChanged",e)}OnFlexPaneZoomChanged(e){return(0,c.NP)().subscribe("FlexPane400ZoomActivated",e,!1)}RemoveOnFlexPaneZoomChanged(e){(0,c.NP)().unsubscribe("FlexPane400ZoomActivated",e)}}var y=n(6330),x=n(40141),A=n(46340),C=n(22461),S=n(87948),w=n(61304),k=n(50791);class P extends y.q{constructor(){super(...arguments),this.FlexpaneBackButton="FlexpaneBackButton"}onComponentVisible(){super.onComponentVisible(),this.customTitleContainer&&this.props.customTitle&&this.props.customTitle(this.customTitleContainer)}componentWillUnmount(){this.customTitleContainer&&r.unmountComponentAtNode(this.customTitleContainer),super.componentWillUnmount()}render(){let e=(0,x.e)(),t=this.props.title?(0,S.JT)(w.D.FlexpaneBackWithTitle,this.props.title.toLowerCase()):w.D.FlexpaneBack;return o.createElement(y.q,{isActive:this.props.isActive,showBackButton:this.props.showBackButton,flexPaneProviderID:this.props.flexPaneProviderID},this.props.showBackButton&&o.createElement("button",{id:this.FlexpaneBackButton,className:k.backButton,title:t,"aria-label":t,tabIndex:0,onClick:this.props.onBackButtonClicked},o.createElement(A.r,{className:(0,C.A)(k.backIcon,e.neutral.accent.font),fontIconCss:"ms-Icon--Back"})),!this.props.hideTitle&&this.renderTitleArea(),o.createElement("div",{className:(0,C.A)(k.flexPaneSidePadding,this.props.className||"")},this.props.children))}renderTitleArea(){let e=(0,x.e)(),t=(0,C.A)(k.itemTitle,e.neutral.dark.font);return this.props.customTitleClassName&&(t=this.props.customTitleClassName),this.props.customTitle?o.createElement("div",{className:t,ref:e=>this.customTitleContainer=e}):o.createElement("h2",{className:(0,C.A)(k.itemTitle,e.neutral.dark.font)},this.props.title)}}let O=!1;function I(){a.h.register(b),function(){let e=new v,t=window.O365Shell.FlexPane;window.O365Shell.FlexPane=e,t.applyCalls(e)}(),function(){let e=(0,s.O)(),t=(0,c.GJ)();if(t){let n=document.getElementById(t.top);if(n){let t=document.createElement("div");t.id="o365cs-flexpane-overlay",n.appendChild(t),r.render(o.createElement(i.Provider,{store:e},o.createElement(f,null)),t)}}}(),O||((0,l.oB)(),O=!0)}},95422:function(e,t,n){"use strict";n.d(t,{IZ:function(){return r},Ig:function(){return a},ZM:function(){return i}});var o=n(6806);function r(e){return{type:o.w1,providerKey:e}}function i(e){return{type:o.vG,newProvider:e}}function a(e){return{type:o.YO,providerKey:e}}},6806:function(e,t,n){"use strict";n.d(t,{YO:function(){return i},vG:function(){return r},w1:function(){return o}});const o="suiteux-flexpane.TOGGLE_FLEX_PANE",r="suiteux-flexpane.REGISTER_FLEX_PANE_PROVIDER",i="suiteux-flexpane.UNREGISTER_FLEX_PANE_PROVIDER"},85348:function(e,t,n){"use strict";n.d(t,{v:function(){return l}});var o=n(90872),r=n(40141),i=n(79649),a=n(22461),s=n(69663),c=n(72720);class l extends o.Component{render(){let e=(0,r.e)();return this.props.isVisible&&!this.props.hideButton&&o.createElement("div",{style:{position:"relative"},role:"presentation",onClick:this.props.onClick,title:this.props.ariaLabel,"aria-label":this.props.ariaLabel,id:`${this.props.controlID}_div`},o.createElement(i.k,{itemId:this.props.controlID,title:this.props.ariaLabel,displayText:this.props.affordanceMenuItemText,className:(0,a.A)(s.affordanceContextMenuItem,e.neutral.foreground.background,e.neutral.dark.font,e.neutral.light.hover.background),customIcon:this.renderIcon(),onclick:this.props.onClick,setClickableElement:this.props.setClickableElement,isAriaHidden:!1,role:"menuitem"},this.props.children))}renderIcon(){const e=this.props.iconData;return(0,c.j)(e)?this.renderJsxIconData(e):this.renderFontIcon(null!=e?e:this.props)}renderJsxIconData(e){const t=e.shouldShellAddAffordanceMenuItemIconPadding,n=e.element,o=(0,a.A)(s.affordanceContextMenuItemIcon),r=this.cloneElement(n,o);return t?r:n}cloneElement(e,t){var n;const r=t+" "+(null!==(n=e.props.className)&&void 0!==n?n:"");return o.cloneElement(e,{className:r})}renderFontIcon(e){let t=e.iconID?`ms-Icon--${e.iconID}`:e.iconCssClass;return t||e.iconFontFamily&&e.iconFontName||(t=s.affordanceContextMenuItemNoIcon),o.createElement("span",{style:{fontFamily:e.iconFontFamily},className:(0,a.A)(t,s.affordanceContextMenuItemIcon),role:"presentation","aria-hidden":"true"},e.iconFontName)}}},72720:function(e,t,n){"use strict";function o(e){return!!e&&"element"in e}n.d(t,{j:function(){return o}})},83496:function(e,t,n){"use strict";n.d(t,{h:function(){return d}});var o=n(90872),r=n(40141),i=n(10806),a=n(43246),s=n(22461),c=n(82871),l=n(2667),u=n(72720);class d extends o.PureComponent{constructor(){super(...arguments),this.buttonReference=null,this.onKeyDown=e=>{40===e.keyCode&&e.altKey&&e.currentTarget.click()},this.onMouseEnter=()=>{this.props.onHoverStateChanged&&this.props.onHoverStateChanged(!0)},this.onMouseLeave=()=>{this.props.onHoverStateChanged&&this.props.onHoverStateChanged(!1)},this.setButtonRef=e=>{this.buttonReference=e,this.props.setClickableElement&&this.props.setClickableElement(e)}}componentDidMount(){this.props.onDimensionsChanged&&this.props.onDimensionsChanged(this.props.isVisible.toString())}componentDidUpdate(e){null!=this.props.hideButton?this.props.onDimensionsChanged&&(e.hideButton&&e.isVisible)!==(this.props.hideButton&&this.props.isVisible)&&this.props.onDimensionsChanged((this.props.isVisible&&this.props.hideButton).toString()):this.props.onDimensionsChanged&&e.isVisible!==this.props.isVisible&&this.props.onDimensionsChanged(this.props.isVisible.toString())}render(){let e=(0,r.e)();return this.props.isNoninteractive?this.props.isVisible&&!this.props.hideButton&&o.createElement(i.e,{controlID:this.props.controlID,isActive:this.props.isActive,controlElement:this.buttonReference},o.createElement("span",{className:(0,s.A)(c.nonInteractiveButton,e.nonInteractiveButton,{[e.activeHeaderButton]:this.props.isActive},{[l.buttonWithTextPadding]:!!this.props.buttonText}),id:this.props.controlID,onClick:null,onKeyDown:this.onKeyDown,onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave,"aria-label":this.props.onlyUseTitle?void 0:this.props.ariaLabel,"aria-labelledby":this.props.ariaLabelledBy,role:"presentation",ref:this.setButtonRef,title:this.props.ariaLabel,"aria-expanded":this.props.isActive},this.renderIcon(),this.props.buttonText&&2===this.props.responsiveStep&&o.createElement("label",{className:(0,s.A)(l.buttonText)},this.props.buttonText),this.props.children)):this.props.isVisible&&!this.props.hideButton&&o.createElement(i.e,{controlID:this.props.controlID,isActive:this.props.isActive,controlElement:this.buttonReference},o.createElement("button",{className:(0,s.A)(c.button,e.headerButton,{[e.activeHeaderButton]:this.props.isActive},{[l.buttonWithTextPadding]:!!this.props.buttonText}),id:this.props.controlID,onClick:this.props.onClick,onKeyDown:this.onKeyDown,onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave,"aria-label":this.props.onlyUseTitle?void 0:this.props.ariaLabel,"aria-labelledby":this.props.ariaLabelledBy,role:"button",type:"button",ref:this.setButtonRef,title:this.props.ariaLabel,"aria-expanded":this.props.isActive,accessKey:this.props.accessKey},this.renderIcon(),this.props.buttonText&&2===this.props.responsiveStep&&o.createElement("label",{className:(0,s.A)(l.buttonText)},this.props.buttonText),this.props.children))}renderIcon(){var e;if((0,u.j)(this.props.iconData))return this.props.iconData.element;{const{iconID:t,iconCssClass:n,iconFontFamily:r,iconFontName:i,iconFontSize:l}=null!==(e=this.props.iconData)&&void 0!==e?e:this.props;return o.createElement(a.r,{fontIconCss:t&&`ms-Icon--${t}`,fontFamily:r,fontValue:i,className:(0,s.A)(n,c.icon),fontSize:l,isAriaHidden:!0})}}}},79028:function(e,t,n){"use strict";n.d(t,{vO:function(){return ie.v},hp:function(){return Z.h},Nv:function(){return ae}});var o=n(90872),r=n(91112),i=n(25793),a=n(82453),s=n(31418),c=n(16968),l=n(21622),u=n(66309),d=n(28569);const p="LazyAffordanceMenu";(0,d.E)(p);var f=n(40141),h=n(43246);const m=()=>o.createElement("svg",{version:"1.1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 576 265.91",style:{enableBackground:"0 0 576 265.91"},xmlSpace:"preserve"},o.createElement("style",{type:"text/css"},".st0{fill:none;}.st1{fill:currentcolor;}"),o.createElement("g",{id:"Clear_x5F_Space"},o.createElement("rect",{className:"st0",width:"575.99",height:"265.91"})),o.createElement("g",{id:"Logo"},o.createElement("g",null,o.createElement("path",{className:"st1",d:"M109.11,181.29h7.21v26.23h16.35v6.56h-23.56V181.29L109.11,181.29z"}),o.createElement("path",{className:"st1",d:"M152.65,197.78v-0.09c0-9.32,7.35-16.95,17.47-16.95s17.38,7.54,17.38,16.86v0.09\n\t\t\tc0,9.32-7.35,16.95-17.47,16.95S152.65,207.1,152.65,197.78z M179.96,197.78v-0.09c0-5.62-4.12-10.31-9.93-10.31\n\t\t\tc-5.81,0-9.84,4.59-9.84,10.21v0.09c0,5.62,4.12,10.31,9.93,10.31C175.94,207.99,179.96,203.4,179.96,197.78L179.96,197.78z"}),o.createElement("path",{className:"st1",d:"M215.23,200.03v-18.74h7.21v18.55c0,5.34,2.67,8.1,7.07,8.1s7.07-2.67,7.07-7.87v-18.79h7.21v18.5\n\t\t\tc0,9.93-5.58,14.8-14.38,14.8S215.23,209.67,215.23,200.03L215.23,200.03z"}),o.createElement("path",{className:"st1",d:"M276.06,181.29h12.79c10.31,0,17.42,7.07,17.42,16.3v0.09c0,9.23-7.12,16.4-17.42,16.4h-12.79V181.29\n\t\t\tL276.06,181.29z M283.27,187.79v19.77h5.58c5.9,0,9.88-3.98,9.88-9.79v-0.09c0-5.81-3.98-9.88-9.88-9.88L283.27,187.79\n\t\t\tL283.27,187.79z"}),o.createElement("path",{className:"st1",d:"M78.16,207.57h-9.14c-5.9,0-9.88-4.07-9.88-9.88v-0.09c0-5.81,3.98-9.79,9.88-9.79h9.14v-6.51h-9.14\n\t\t\tc-10.31,0-17.42,7.17-17.42,16.4v0.09c0,9.23,7.12,16.3,17.42,16.3h9.14v-6.51V207.57z"})),o.createElement("g",null,o.createElement("path",{className:"st1",d:"M524.16,125.5c0-36.54-53.17-24.95-53.17-45.74c0-8.46,6.09-12.47,14.26-12.18\n\t\t\tc8.91,0.15,14.4,5.49,14.85,12.33h22.87c-1.34-18.71-15.89-29.55-37.13-29.55s-36.54,11.29-36.54,30\n\t\t\tc-0.15,37.57,53.32,24.06,53.32,46.48c0,7.42-5.79,12.62-15.59,12.62s-15.15-5.49-15.74-13.81h-22.28\n\t\t\tc0.3,19.6,16.93,30.89,38.47,30.89C511.09,156.53,524.16,141.83,524.16,125.5"}),o.createElement("polygon",{className:"st1",points:"275.87,51.83 275.87,155.5 330.81,155.5 330.81,139.01 296.66,139.01 296.66,51.83 275.86,51.83\n\t\t\t"}),o.createElement("path",{className:"st1",d:"M260.57,100.92c0-30.23-20.72-50.57-50.02-50.57s-51.32,20.71-51.32,53s21.83,53.19,51.32,53.19\n\t\t\tc25.2,0,41.43-14.37,47.21-32.29h-22.95c-3.92,8.02-11.2,14.37-24.26,14.37c-15.68,0-27.81-10.27-29.3-27.24h78.56\n\t\t\tc0.56-3.54,0.75-6.9,0.75-10.45L260.57,100.92z M181.44,94.2c2.24-16.23,13.81-25.94,28.18-25.94c15.86,0,28.37,10.08,28.74,25.94\n\t\t\tH181.44z"}),o.createElement("path",{className:"st1",d:"M72.62,137.82V69.36h20.45c21.83,0,34.16,12.92,34.16,34.45s-12.33,34.01-34.16,34.01H72.62z M93.81,51.83\n\t\t\tH51.83v103.66h41.98c33.12,0,54.65-20.35,54.65-51.68S126.93,51.83,93.81,51.83"})),o.createElement("path",{className:"st1",d:"M384.71,50.35c-29.26,0-53.16,21.98-53.16,53.01s23.91,53.16,53.16,53.16s53.01-21.98,53.01-53.16\n\t\tS414.27,50.35,384.71,50.35z M384.71,137.96c-18.86,0-31.78-13.52-31.78-34.6s12.92-34.3,31.78-34.3\n\t\tc18.86,0,31.63,13.22,31.63,34.3S403.43,137.96,384.71,137.96z"}))),g=()=>o.createElement("svg",{version:"1.1",id:"Calque_1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 784 352",style:{enableBackground:"new 0 0 784 352"},xmlSpace:"preserve"},o.createElement("style",{type:"text/css"},".st0{fill:currentcolor;}"),o.createElement("g",null,o.createElement("g",null,o.createElement("g",null,o.createElement("path",{className:"st0",d:"M338.3,116.1l58.8,0.2c20.7,0.1,34.2,12,34.1,30.2c0,11.5-5.4,20.4-13.9,24.2l0,0.3\n c10.8,3.9,18.2,14.1,18.1,27.9c-0.1,22.4-14.3,34.4-41.3,34.3L338,233L338.3,116.1z M391.6,220c20.4,0.1,29.2-6.4,29.3-21\n c0-14.9-8.3-20.9-28.6-21l-39.7-0.1l-0.1,41.9L391.6,220z M393.8,165.7c15.4,0,22.9-6.1,22.9-18.6c0-11.4-7.8-17.6-22.8-17.6\n l-41.2-0.1l-0.1,36.2L393.8,165.7z"}),o.createElement("path",{className:"st0",d:"M458.5,111.5l13.7,0l-0.4,121.9l-13.7,0L458.5,111.5z"}),o.createElement("path",{className:"st0",d:"M491.3,189.8c0.1-28.4,19.5-47.2,47.2-47.1c26.2,0.1,46,19.4,45.9,46.7l0,5l-79.3-0.3\n c0.1,17.9,14.9,30.3,33.3,30.3c13.9,0,24.9-6.1,32.4-18.8l10.8,7.2c-9.4,15.5-24.4,23.3-43.3,23.2\n C510.1,236.1,491.2,217.8,491.3,189.8z M570.5,183.3c-1.1-16.2-14.9-28.9-32-29c-18.5-0.1-32.1,12.4-33.1,28.8L570.5,183.3z"}),o.createElement("path",{className:"st0",d:"M602.1,198.1l0.2-52.8l13.7,0l-0.2,50.1c-0.1,18.2,10.1,28.9,28.1,29c17.2,0.1,29.6-11.9,29.6-29l0.2-49.9\n l13.7,0l-0.3,88.5l-13.4,0l0-11l-0.3,0c-6.7,8.5-18.4,13.5-32.8,13.4C617.1,236.4,602.1,221.5,602.1,198.1z"}))),o.createElement("g",null,o.createElement("g",null,o.createElement("ellipse",{transform:"matrix(0.9732 -0.2298 0.2298 0.9732 -34.6215 54.6505)",className:"st0",cx:"217.4",cy:"176",rx:"79",ry:"79"}),o.createElement("path",{className:"st0",d:"M97,177c0,27.7,8.9,53.2,24,74l0-148C105.9,123.8,97,149.3,97,177z"})))));var b=n(87948),v=n(99542),y=n(1742),x=n(61304);let A=window.O365ShellContext.ControlRenderer.GetHeaderClassName;class C extends o.PureComponent{constructor(){super(...arguments),this.onAppTitleLinkClick=e=>{(0,c.tZ)().click("O365BrandingLogo","NavBar",null,this.props.appTitleRefId),null!=this.props.appTitleLinkAction&&(this.props.appTitleLinkAction(),e.preventDefault())}}componentDidMount(){if(null!=this.props.controlDimensionsChanged)return this.props.controlDimensionsChanged((0,b.YZ)(JSON.stringify(this.props)).toString())}componentDidUpdate(e){null==this.props.controlDimensionsChanged||e.appTitleText===this.props.appTitleText&&e.brandLogoID===this.props.brandLogoID&&e.showAppBrandIcon===this.props.showAppBrandIcon&&e.appBrandIconUrl===this.props.appBrandIconUrl||this.props.controlDimensionsChanged((0,b.YZ)(JSON.stringify(this.props)).toString())}render(){const e=(0,f.e)(),t=!this.props.shouldDisableGallatin&&/^o365gallatinlogo/.test(this.props.brandLogoID),n=/^o365frlogo/.test(this.props.brandLogoID),r=/^o365delogo/.test(this.props.brandLogoID),i=this.getStyleForElementBetweenComponentAndAppTitle();return o.createElement("div",{className:`${A(y.f7.appTitle)} ${e.appName}`,style:i},t&&this.renderSuiteBrand(),t&&o.createElement("span",{className:A(y.f7.separator)}),n&&this.renderFrLogo(),n&&o.createElement("span",{className:A(y.f7.separator)}),r&&this.renderDeLogo(),r&&o.createElement("span",{className:A(y.f7.separator)}),this.props.showAppBrandIcon&&this.renderAppBrandIcon(),this.renderAppTitle())}getStyleForElementBetweenComponentAndAppTitle(){return this.props.truncateAppTitleOnOverflow?{minWidth:"0"}:{}}renderGallatinLogo(){return o.createElement(h.r,{fontIconCss:"ms-Icon--GallatinLogo",className:A(y.f7.gallatinLogo)})}renderFrLogo(){return o.createElement("a",{href:"https://www.bleucloud.fr/",role:"link",id:"O365_BrandingLogo"},o.createElement(g,null))}renderDeLogo(){return o.createElement("a",{href:"https://www.deloscloud.de/",role:"link",id:"O365_BrandingLogo"},o.createElement(m,null))}renderAppTitleText(){let e,t={};return this.props.truncateAppTitleOnOverflow&&(t={textOverflow:"ellipsis",overflow:"hidden",whiteSpace:"nowrap"},e=this.props.appTitleText),o.createElement("span",{title:e,className:A(y.f7.brandingText),style:t},this.props.appTitleText)}renderAppTitle(){let e=null,t=(0,f.e)(),n=this.props.appTitleLinkUrl?this.props.appTitleLinkUrl:"";return""!==this.props.appTitleText&&(e=this.props.appTitleLinkUrl||this.props.appTitleLinkAction?o.createElement("a",{href:n,role:"link",id:"O365_AppName",style:this.getStyleForElementBetweenComponentAndAppTitle(),"aria-label":this.props.appTitleAriaLabel,onClick:this.onAppTitleLinkClick,className:`${A(y.f7.brandingLink)} ${t.appBrandLink}`},this.renderAppTitleText()):this.renderAppTitleText()),e}renderAppBrandIcon(){let e=null,t=(0,f.e)();return e=this.props.appTitleLinkUrl?o.createElement("div",{className:`${A(y.f7.appBrandIcon)}`},o.createElement("a",{href:this.props.appTitleLinkUrl,role:"link",id:"O365_AppBrandIcon","aria-label":this.props.appTitleAriaLabel,onClick:this.onAppTitleLinkClick,title:x.D.App_Brand_Icon_Title,className:`${A(y.f7.brandingLink)} ${t.appBrandLink}`},this.renderAppBrandIconImage())):o.createElement("div",{className:`${A(y.f7.appBrandIcon)}`},this.renderAppBrandIconImage()),e}renderAppBrandIconImage(){return o.createElement("img",{className:`${A(y.f7.appBrandIcon)}`,id:v.wB,src:this.props.appBrandIconUrl,title:x.D.App_Brand_Icon_Title})}renderSuiteBrand(){const e=(0,c.GJ)();let t=this.props.suiteBrandNavigationUrl;const n=e&&e.m365CopilotRebrandingEnabled?null===x.D||void 0===x.D?void 0:x.D.Microsoft365Copilot:null===x.D||void 0===x.D?void 0:x.D.Microsoft365;let r=this.props.showResellerExperience?x.D.Microsoft:n;return null!=t&&this.props.isAuthenticated?o.createElement("a",{"aria-label":r,href:t,role:"link",id:"O365_BrandingLogo"},o.createElement("span",{className:A(y.f7.brandingText)},r),this.renderGallatinLogo()):o.createElement("div",null,o.createElement("span",{className:A(y.f7.brandingText)},r," "),this.renderGallatinLogo())}}const S="LazySuiteBranding";(0,d.E)(S);var w=n(81578),k=n.n(w);var P=n(22461),O=n(53644);let I=window.O365ShellContext.ControlRenderer.GetHeaderClassName;class D extends o.Component{constructor(e){super(e),this.updateDimensions=()=>{if(null!=this.props.controlDimensionsChanged){const e=Object.assign(Object.assign({},this.props),this.state),t=(0,b.YZ)(JSON.stringify(e)).toString();this.props.controlDimensionsChanged(t)}},this.handleClick=()=>{(0,c.tZ)().click("TenantBranding","NavBar","NavLink","CompanyInternet")},this.onImageLoad=()=>{if(this.tenantLogoImgElement){let e=D.tenantLogoWidths[this.props.tenantLogoImageUrl];null!=e&&this.state.imageWidth!==e?this.setState({imageWidth:e}):(e=this.tenantLogoImgElement.clientWidth,e>0&&this.tenantLogoImgElement.clientWidth!==D.tenantLogoWidths[this.props.tenantLogoImageUrl]&&(D.tenantLogoWidths[this.props.tenantLogoImageUrl]=e,null!=e&&this.state.imageWidth!==e&&this.setState({imageWidth:e})))}},this.setTenantLogoImgElement=e=>{null!=e&&null==this.tenantLogoImgElement&&(this.tenantLogoImgElement=e,this.tenantLogoImgElement.addEventListener("load",this.onImageLoad),window.requestAnimationFrame(this.updateDimensions))},this.state={imageWidth:D.tenantLogoWidths[e.tenantLogoImageUrl]||0}}componentDidMount(){this.updateDimensions()}componentDidUpdate(e,t){e.showTenantBranding===this.props.showTenantBranding&&e.tenantLogoImageUrl===this.props.tenantLogoImageUrl&&t.imageWidth===this.state.imageWidth||this.updateDimensions()}render(){let e=(0,f.e)();const t=!!this.props.tenantLogoImageUrl&&(this.props.tenantLogoImageUrl.indexOf("image/svg+xml")>-1||this.props.tenantLogoImageUrl.indexOf(".svg")>-1),n=this.context,r=(0,O.X3)(n),i=this.props.tenantName?this.props.tenantName:x.D.Tenant_Logo_Title;return this.props.showTenantBranding&&(a=[o.createElement("div",{key:"TenantItem1",className:(0,P.A)(I(y.f7.tenantBranding),e.primary.font)},o.createElement("a",{id:v.RO,className:(0,P.A)(I(y.f7.tenantLogo),{[I(y.f7.tenantLogoSVG)]:t},e.appBrandLink),target:this.props.tenantLogoTargetWindow,title:i,"aria-label":i,href:this.props.tenantLogoNavigationUrl,onClick:this.handleClick},o.createElement("img",{ref:this.setTenantLogoImgElement,id:v.oI,alt:i,title:i,src:this.props.tenantLogoImageUrl,style:{minWidth:r&&null!=this.state.imageWidth?`${this.state.imageWidth}px`:void 0}}))),o.createElement("div",{key:"TenantItem2",className:(0,P.A)(I(y.f7.appTitleLine),e.appName)})],o.version>="16.2"?o.createElement(o.Fragment,null,a):o.createElement("div",null,a));var a}}D.contextTypes={isMeasured:k().bool},D.tenantLogoWidths={};const T="LazyTenantBranding";(0,d.E)(T);var E=n(39038),L=n(79649),M=n(94190),F=n(57530),N=n(49852),B=n(89959),H=n(70238),j=n(71936),U=n(21226),R=n(36558),_=n(98052),Q=n(2667),z=n.n(Q),W=n(69663),Z=n(83496);class K extends o.Component{constructor(e){super(e),this.setContainer=e=>{this.affordanceHeaderButtonContainer=e},this.controlDimensionsChanged=()=>{if(null!=this.affordanceHeaderButtonContainer){let e=this.shouldShowAffordanceMenu().toString();(0,c.NP)().invoke("CenterBufferingRecalc",O.Hp,e,this.affordanceHeaderButtonContainer),(0,c.NP)().invoke("ResizeGroupRecalc",O.Hp,e)}},this.toggleContextMenu=e=>{e.stopPropagation(),e.preventDefault(),(0,c.tZ)().click("Affordance","NavBar",null,null,`affordanceMenuOpen: ${this.state.affordanceMenuOpen}`),this.setState({affordanceMenuOpen:!this.state.affordanceMenuOpen})},this.dismissContextMenu=e=>{if(this.state.affordanceMenuOpen){if(e&&e.target){if(document.getElementById(O.Hp).contains(e.target))return}this.setState({affordanceMenuOpen:!1})}},this.onMouseEnter=()=>{this.isMouseActivated=!0},this.onMouseLeave=()=>{this.isMouseActivated=!1},this.state={affordanceMenuOpen:!1}}componentDidUpdate(e){e.affordanceMenu.length!==this.props.affordanceMenu.length&&0===this.props.affordanceMenu.length&&this.setState({affordanceMenuOpen:!1})}render(){let e=(0,f.e)(),t=(0,M.isMobileClient)();return o.createElement("div",{className:(0,P.A)(z().thinHeaderControlContainer,W.affordanceMenuContainer),onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave},o.createElement(Z.h,{controlID:O.Hp,isVisible:this.shouldShowAffordanceMenu(),ariaLabel:x.D.Affordance_Title,onlyUseTitle:!0,iconID:"More",iconFontSize:F.LV.toString(),isActive:this.state.affordanceMenuOpen||this.props.hasActiveFlexPaneButton,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.toggleContextMenu,onDimensionsChanged:this.controlDimensionsChanged}),o.createElement("div",{ref:this.setContainer}),this.shouldShowAffordanceMenu()&&this.state.affordanceMenuOpen&&this.affordanceHeaderButtonContainer&&o.createElement(E.t,{className:(0,P.A)(y.WB,W.affordanceContextMenu),onDismiss:this.dismissContextMenu,isKeyboardNavigation:!this.isMouseActivated,renderHost:this.affordanceHeaderButtonContainer,setFocusOnPreviouslyFocusedElement:!0,ariaLabel:x.D.Affordance_Title,skipTabFocus:!t,popupPosition:this.props.isRtl?{top:48,left:0}:{top:48,right:0}},this.props.affordanceMenu.map((t=>{let n=null;if(this.isCustomAffordanceBehavior(t)){let r=e=>{t.onAffordanceMenuItemClicked(),this.toggleContextMenu(e)},i="function"==typeof t.affordanceMenuItemText?t.affordanceMenuItemText():t.affordanceMenuItemText;n=o.createElement(L.k,{key:t.affordanceMenuItemId,title:i,displayText:i,className:(0,P.A)(W.affordanceContextMenuItem,e.neutral.foreground.background,e.neutral.dark.font,e.neutral.light.hover.background),onclick:r,role:"menuitem",customIcon:o.createElement("span",{className:(0,P.A)(t.affordanceMenuItemIconCss||W.affordanceContextMenuItemNoIcon,W.affordanceContextMenuItemIcon),role:"presentation"})})}else if(this.isNativeAffordanceBehavior(t)){let e=`${(0,v.nO)(t.nativeControlID)}_Affordance`,r={id:e,key:e,isAvailable:!1,renderContext:1,isActive:!1,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.toggleContextMenu,controlDimensionsChanged:null};switch(t.nativeControlID){case"ChatIcon":n=o.createElement(B.e,Object.assign({},r));break;case"NotificationBellIcon":n=o.createElement(N.P,Object.assign({},r));break;case"SettingsIcon":n=o.createElement(U.s,Object.assign({},r));break;case"HelpIcon":n=o.createElement(R.z,Object.assign({},r,{flipHelpIcon:!1}));break;case"FeatureFlags":n=o.createElement(j.r,Object.assign({},r));break;case"MyDay":n=o.createElement(_.M,Object.assign({},r));break;default:(0,c.tZ)().tag("UnknownNativeControlSpecified",6,t.nativeControlID,"AffordanceMenu")}}else{let e=t.customButtonRenderData.id+"_Affordance";n=o.createElement(H.F,Object.assign({id:e,key:e,isAvailable:!0,renderContext:1,isActive:!1,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.toggleContextMenu,controlDimensionsChanged:null},t.customButtonRenderData))}return n}))))}isCustomAffordanceBehavior(e){return e&&void 0!==e.affordanceMenuItemText}isNativeAffordanceBehavior(e){return e&&void 0!==e.nativeControlID}shouldShowAffordanceMenu(){return this.props.affordanceMenu.length>0}}const V=(0,r.connect)(((e,t)=>{let n=!1,o=null;return o=e.headerState.appBrandIconUrl||t.appBrandIconUrl,n=o&&(0,c.Vz)().shouldUseAppBrandIcon(),{brandLogoID:e.headerState.brandLogoID,appTitleText:e.headerState.useCurrentMainLinkForTitle?e.headerState.appTitleText:e.headerState.customAppTitleText,appTitleLinkUrl:e.headerState.useCurrentMainLinkForTitle?e.headerState.appTitleLinkUrl:e.headerState.customAppTitleLinkUrl,appTitleLinkAction:e.headerState.customAppTitleLinkAction,appBrandIconUrl:o,showAppBrandIcon:n,appTitleRefId:t.appTitleRefId,appTitleAriaLabel:e.headerState.appTitleAriaLabel,showResellerExperience:e.headerState.showResellerExperience,suiteBrandNavigationUrl:e.headerState.suiteBrandNavigationUrl,isAuthenticated:e.headerState.isAuthenticated,controlDimensionsChanged:t.controlDimensionsChanged,shouldDisableGallatin:e.headerState.disableGallatinBranding,truncateAppTitleOnOverflow:t.truncateAppTitleOnOverflow}}))(C);var q=n(66164);const G=(0,r.connect)(((e,t)=>({showTenantBranding:(0,c.Vz)().shouldUseTenantBranding(),tenantLogoTargetWindow:(0,q.bi)(e.shellInitDataState.clientData.WorkloadId,e.shellInitDataState.navBarData.CurrentMainLinkElementID)?"_blank":void 0,tenantLogoImageUrl:e.headerState.tenantLogoImageUrl,tenantLogoNavigationUrl:e.headerState.tenantLogoNavigationUrl,tenantName:e.shellInitDataState.navBarData.CompanyDisplayName,controlDimensionsChanged:t.controlDimensionsChanged})))(D),J="suiteux-header-redux.SET_APPLINK_DATA",Y="suiteux-header-redux.SET_TENANTBRANDING_DATA",X="suiteux-header-redux.SET_NAVBARDATA_UNAVAILABLE";var $=n(7102),ee=n(6062),te=n(79627);const ne={headerState:function(e,t){let n=[];if(!e){const o=t.shellInitData;n=o.appsDataState&&o.appsDataState.apps,e=oe(ee.X,n||[],o.shellInitDataState.navBarData,o.shellInitDataState.clientData,o.shellInitDataState.renderSettings)}switch(t.type){case $.l5:const c=t;return oe(e,n,c.navBarData,c.shellClientData,c.renderSettings);case $.nv:const l=t;return e.useCurrentMainLinkForTitle?re(e,l.appsData):e;case J:const u=t;return o=e,r=u.headerAppLinkText,i=u.headerAppLinkUrl,a=u.headerAppLinkUrlAction,s=u.appBrandIconUrl,Object.assign(Object.assign({},o),{useCurrentMainLinkForTitle:null===i&&null===r,customAppTitleText:r,customAppTitleLinkUrl:i,customAppTitleLinkAction:a,appBrandIconUrl:s,appTitleAriaLabel:(0,b.JT)(x.D.GoTo,r)});case Y:const d=t;return function(e,t,n,o){return Object.assign(Object.assign({},e),{tenantBrandingSpecified:null!=t?t:e.tenantBrandingSpecified,tenantLogoImageUrl:n||e.tenantLogoImageUrl,tenantLogoNavigationUrl:o||e.tenantLogoNavigationUrl})}(e,d.showBranding,d.logoUrl,d.logoNavigationUrl);case X:return function(e){return Object.assign(Object.assign({},e),{isNavBarDataUnavailable:!0})}(e);default:return e}var o,r,i,a,s}};function oe(e,t,n,o,r){var i;let a=e;return n&&o&&(a=Object.assign(Object.assign({},e),{flipHelpIcon:n.FlipHelpIcon,brandLogoID:n.LogoIconID,currentMainLinkID:n.CurrentMainLinkElementID,tenantBrandingSpecified:n.HasTenantBranding,tenantLogoNavigationUrl:n.TenantLogoNavigationUrl?n.TenantLogoNavigationUrl.Url:n.LogoNavigationUrl,tenantLogoImageUrl:n.TenantLogoUrl&&n.TenantLogoUrl.Url,appBrandIconUrl:o.AppBrandIconUrl,showResellerExperience:o.IsPartnerResellerPage,suiteBrandNavigationUrl:n.LogoNavigationUrl,isAuthenticated:!o.IsThirdPartyShell&&n.IsAuthenticated,disableGallatinBranding:r.disableGallatinBranding}),o.AppHeaderLinkUrl||o.AppHeaderLinkText||a.customAppTitleLinkUrl||a.customAppTitleText?(a.useCurrentMainLinkForTitle=!1,o.AppHeaderLinkUrl&&(a.customAppTitleLinkUrl=o.AppHeaderLinkUrl),o.AppHeaderLinkText&&(a.customAppTitleText=o.AppHeaderLinkText),o.AppHeaderLinkAction&&(a.customAppTitleLinkAction=o.AppHeaderLinkAction),a.appTitleAriaLabel=(0,b.JT)(x.D.GoTo,null!==(i=a.appTitleText)&&void 0!==i?i:a.customAppTitleText)):(0===t.length&&(t=(0,te.kx)(n,o)),a=re(a,t),a.useCurrentMainLinkForTitle=!0,a.appTitleText&&a.appTitleText!==o.AppHeaderLinkText&&(0,c.NP)().invoke("AppNameChanged",a.appTitleText))),a}function re(e,t){let n=e,o=null;if(e.currentMainLinkID&&t){const n=t.filter((t=>"Shell"+t.Id===e.currentMainLinkID));if(n.length>0){const e=n[0],t=e.BrandBarText||e.Title;o={appTitleLinkUrl:e.LaunchFullUrl,appTitleText:t,appTitleAriaLabel:(0,b.JT)(x.D.GoTo,t)}}}return o&&(n=Object.assign(Object.assign({},e),o)),n}var ie=n(85348);function ae(){if((0,s.i)(),i.h.register(ne),!u.QJ.useLegacyHeader){const e=(0,a.O)();(0,l.I7)(),window.O365ShellContext.ControlRenderer.ConnectResizeGroupToStore((t=>o.createElement(r.Provider,{store:e},t))),(0,l.zi)();const t=(0,c.NP)();t.invoke("LazyComponentLoaded",T,G),t.invoke("LazyComponentLoaded",S,V),t.invoke("LazyComponentLoaded",p,K),t.subscribe("HeaderBrandingDataUpdated",((t,n,o,r)=>{e.dispatch(function(e,t,n,o){return{type:J,headerAppLinkText:e,headerAppLinkUrl:t,headerAppLinkUrlAction:n,appBrandIconUrl:o}}(t,n,o,r))}),!0),t.subscribe("TenantBrandingChanged",(t=>{var n,o,r;e.dispatch((n=t.isLogoVisible,o=t.logoUrl,r=t.logoNavigationUrl,{type:Y,showBranding:n,logoUrl:o,logoNavigationUrl:r}))}),!0),t.subscribe("NavBarDataUnavailable",(()=>{e.dispatch({type:X})}),!0)}}},99542:function(e,t,n){"use strict";n.d(t,{$t:function(){return y},B2:function(){return f},Cu:function(){return x},DP:function(){return b},On:function(){return i},Pn:function(){return S},RO:function(){return u},Xf:function(){return c},Xv:function(){return m},YZ:function(){return g},a_:function(){return C},cQ:function(){return A},dK:function(){return h},hl:function(){return a},nO:function(){return w},oI:function(){return d},rv:function(){return l},wB:function(){return p},yG:function(){return r}});var o=n(16968);const r="O365_NavHeader",i="O365_HeaderRightRegion",a="O365_MainLink_Help",s="O365_MainLink_Day",c="O365_MainLink_Settings",l="O365_SearchBoxContainer",u="O365_MainLink_TenantLogo",d="O365_MainLink_TenantLogoImg",p="O365_MainLink_APPBrandIconImg",f="O365_MainLink_HamburgerButton",h="O365_MainLink_Chat_Container",m="O365_MainLink_Bell",g="O365_MainLink_Chat",b="O365_Feature_Flags",v="O365_DocTitle",y="FlexPane_Overflow_Container",x="O365fpcontainerid",A="feedbackContainer",C="ShellFeedback",S="GiveFeedbackButton";function w(e){switch(e){case"O365Branding":return"O365_SuiteBranding";case"TenantLogo":return u;case"SearchBox":return l;case"HelpIcon":return a;case"SettingsIcon":return c;case"NotificationBellIcon":return m;case"ChatIcon":return g;case"FeatureFlags":return b;case"MyDay":return s;case"DocumentTitle":return v;default:return(0,o.tZ)().tag("UnknownNativeControlSpecified",6,e,"DeriveDomControlID"),null}}},57530:function(e,t,n){"use strict";n.d(t,{Fb:function(){return c},LV:function(){return o},Lu:function(){return s},Ux:function(){return r},YV:function(){return a}});const o=16;function r(e,t,n){let o=i("div",e,t);return n&&o.setAttribute("role",n),o}function i(e,t,n,o){let r=document.createElement(e);return n&&(r.id=n),t&&(r.className=t),o&&r.setAttribute("role",o),r}function a(e,...t){if(e.classList)for(let n of t)e.classList.add(n);else for(let n of t)e.className.split(" ").some((e=>e===n))||(e.className+=" "+n)}function s(e,...t){if(e.classList)for(let n of t)e.classList.remove(n);else for(let n of t)e.className=e.className.split(" ").filter((e=>e!==n)).join(" ")}function c(e,t,n){n?a(e,t):s(e,t)}},84107:function(e,t,n){"use strict";function o(e){return null!=e&&0!==e.length&&e.some((e=>r(e)))}function r(e){return!(null==e||i(e.Id)||i(e.Text)||i(e.Url)&&null==e.Action)}function i(e){return""===e||null==e}n.d(t,{l:function(){return r},v:function(){return o}})},49152:function(e,t,n){"use strict";n.d(t,{C:function(){return r},g:function(){return i}});var o=n(16968);let r=240;function i(){let e=(0,o.GJ)(),t=e&&e.shyHeaderActivationHeight?e.shyHeaderActivationHeight:r;return window.matchMedia(`(max-height: ${t}px)`).matches}},45557:function(e,t,n){"use strict";n.d(t,{J:function(){return r}});var o=n(57530);class r{constructor(e){this.attachedNode=e,this.showFocusHighlight=()=>{(0,o.Lu)(this.attachedNode,r.RemoveFocusOutlineClassName)},this.hideFocusHighlight=()=>{(0,o.YV)(this.attachedNode,r.RemoveFocusOutlineClassName)},this.handleMouseDown=e=>{this.hideFocusHighlight()},this.handleKeyDown=e=>{e instanceof KeyboardEvent&&(9===e.which||40===e.which||38===e.which||37===e.which||39===e.which||117===e.which&&e.ctrlKey)&&this.showFocusHighlight()}}onShowFocusHighlight(e){this.showFocusHighlight=e}onHideFocusHighlight(e){this.hideFocusHighlight=e}attach(){return this.attachedNode.addEventListener("mousedown",this.handleMouseDown),this.attachedNode.addEventListener("keydown",this.handleKeyDown),this}remove(){this.attachedNode.removeEventListener("mousedown",this.handleMouseDown),this.attachedNode.removeEventListener("keydown",this.handleKeyDown)}}r.RemoveFocusOutlineClassName="removeFocusOutline"},5232:function(e,t,n){"use strict";n.d(t,{i1:function(){return s},kT:function(){return r},qg:function(){return i},yd:function(){return c},zA:function(){return a}});var o=n(94190);n(82871),n(66309);const r="O365_MainLink_Me",i="O365_MainLink_MePhoto",a="O365_UniversalMeContainer",s="mectrl_main_trigger",c="mectrl_currentAccount_picture";(0,o.isMobileClient)()},71173:function(e,t,n){"use strict";n.d(t,{ng:function(){return o},oB:function(){return r}});n(82871),n(66309);const o="O365_MainLink_NavMenu",r="O365_MainLink_NavMenu_Responsive"},66309:function(e,t,n){"use strict";var o;n.d(t,{QJ:function(){return r},om:function(){return i}}),function(e){e.CenterRegion="CenterRegion"}(o||(o={}));n(1742),n(45557),n(5232),n(82871);n(71173);let r={appHeaderLinkUrl:"",appHeaderLinkText:"",appHeaderLinkAction:void 0,appBrandIconUrl:"",signInLink:void 0,meDisplayName:"",isMeControlEnabled:!0,userEmail:"",useFullName:!1,isThirdParty:!1,isAuthenticated:!0,useLegacyHeader:!1,showWaffle:!1,searchUXEnabled:!1,vanillaSearchBoxEnabled:!1,SearchBox2Enabled:!1,shouldRenderAppLauncher:!1,roundedCornersSearchBoxEnabled:!1};function i(e,t){return null==e.UserDisplayName?t.NotManagedEmailAddress||t.UPN:e.TruncatedUserDisplayName||e.UserDisplayName||t.UPN}},1742:function(e,t,n){"use strict";var o;n.d(t,{Fx:function(){return c},D5:function(){return i},f7:function(){return o},Mm:function(){return s},ux:function(){return r},$5:function(){return l},WB:function(){return a},I_:function(){return u}}),function(e){e[e.gallatinLogo=0]="gallatinLogo",e[e.brandingText=1]="brandingText",e[e.brandingLink=2]="brandingLink",e[e.appTitle=3]="appTitle",e[e.appBrandIcon=4]="appBrandIcon",e[e.tenantBranding=5]="tenantBranding",e[e.tenantLogo=6]="tenantLogo",e[e.tenantLogoSVG=7]="tenantLogoSVG",e[e.appTitleLine=8]="appTitleLine",e[e.separator=9]="separator"}(o||(o={}));const r="base",i="contrast",a="o365cs-base",s="office",c="basewithofficethemepreferred";var l;function u(e){switch((e||"").toUpperCase()){case"banner":case"SPAN1X5":default:return l.SPAN1X5;case"card":case"SPAN2X3":return l.SPAN2X3}}!function(e){e.SPAN1X5="SPAN1X5",e.SPAN2X3="SPAN2X3"}(l||(l={})),n.nc=window.oneShellUxNonce},45011:function(e,t,n){"use strict";n.d(t,{AL:function(){return i},Gp:function(){return d},J9:function(){return c},Ph:function(){return b},Ru:function(){return u},ZR:function(){return m},eh:function(){return l},i5:function(){return g},zj:function(){return f}});var o=n(71250),r=n(89682);const i=1e3,a=new RegExp("[a-zA-Z0-9_\\-\\.#]+(@|%40|%2540)[a-zA-Z0-9_\\-\\.]+\\.[a-zA-Z]{2,5}","g"),s="email_removed";function c(e,t){if(null==e)return"";if(e===r.Rh)return"Microsoft365";if(e===r.sE)return"AppsModule";let n=e.replace(/^shell/i,"");switch(t&&"FirstParty"!==t&&(n=t+"App_"+n),n.toLowerCase()){case"admin":n="AdminPortal";break;case"iwapp":n="OfficeDotCom"}return n}function l(e,t=""){if(null===e)return"";let n=c(e,t);const o=new RegExp("^([a-zA-Z0-9_]+App)_","g").exec(n);return null!=o&&o.length>1&&(n=o[1]),n}function u(e){return e&&(e=e.replace(a,s)),e}function d(e){return p(e,"?")}function p(e,t){if(e){const n=e.indexOf(t);if(n>=0)return e.substring(0,n)}return e}function f(e){let t="";switch(e){case 0:t="Trace";break;case 1:t="Info";break;case 4:t="Warning";break;case 6:t="Error"}return t}const h=/suiteux\.shell\.(\w+)\.?([\w\d]*)\.(js|css)$/;function m(e){if(!e)return null;const t=e.match(h);return null==t?null:{name:t[1],hash:t[2]}}function g(e,t){if(t)return"DogFood";if(!e)return null;const n=e.toLowerCase();return-1!==n.indexOf("worldwide")?"Production":-1!==n.indexOf("msit")||-1!==n.indexOf("preview")||-1!==n.indexOf("compass")||-1!==n.indexOf("stagedrolloutone")||-1!==n.indexOf("firstrelease")?"Microsoft":-1!==n.indexOf("dogfood")?"DogFood":null}function b(e,t,n){if(t&&t.length>0)return t;if(e){const t=e.toLowerCase();if(-1!==t.indexOf("tbprod"))return o.d.USGOV_DOJ;if(-1!==t.indexOf("pfprod"))return o.d.USGOV_DOD}return n?o.d.EUDB:o.d.PUBLIC}},98981:function(e,t,n){"use strict";n.d(t,{KA:function(){return o},Mq:function(){return a},XC:function(){return i},FY:function(){return r},IJ:function(){return g}});var o,r,i={};n.r(i),n.d(i,{getNewID:function(){return c},getSessionId:function(){return l}});class a{constructor(e,t,n=0,o=0){this.name=e,this.value=t,this.piiKind=n,this.type=o}}!function(e){e[e.Monitoring=0]="Monitoring",e[e.Click=1]="Click",e[e.Impression=2]="Impression",e[e.ServerRequest=3]="ServerRequest",e[e.Performance=4]="Performance",e[e.Timer=5]="Timer",e[e.Resource=6]="Resource"}(o||(o={})),function(e){e[e.TagID=0]="TagID",e[e.Exception=1]="Exception",e[e.Message=2]="Message",e[e.Click=3]="Click",e[e.Impression=4]="Impression",e[e.ServerRequest=5]="ServerRequest",e[e.Performance=6]="Performance",e[e.Timer=7]="Timer",e[e.Resource=8]="Resource"}(r||(r={}));var s=n(73637);function c(){return(new Date).getTime()+"_"+Math.random()}function l(){const e="ShCLSessionID";let t=(0,s.R)(e);return t||(t=c(),document.cookie=`${e}=${t};path=/`),t}var u=n(16533),d=n(16968),p=n(45011);class f{constructor(e,t,n=(new Date).getTime(),o){this.properties=[],this.timestamp=n,this.name=e,this.type=t,this.elementName=o}SetProperty(e,t,n=0,o=0){this.properties.push(new a(e,t,o,n))}SetAdHocProperties(e,t){for(let n=0;n{let n;if(this.isPerformanceMarkerWritten&&null==t){if(!window.performance)return;if(null==t){const t=window.performance.getEntriesByType("resource").filter((e=>null!=(0,p.ZR)(e.name)));let o={};t.forEach((t=>{t.name.indexOf(e)>-1&&(o=t)})),n=`${o.name||e}|${o.encodedBodySize||""}|${Math.round(o.startTime)}|${Math.round(o.duration)}`}}else null!=t&&(n=`${e}|ERROR|${JSON.stringify(t)}|${window.performance.now()}`);if(n){const e=new f(o.Resource,r.Resource);e.SetProperty("ResourceTiming",n),this.writeEvent(e)}},this.writeNavPerfMarker=()=>{this.perfMarker("NavigationAway")},this.writePerfMarkerEvent=()=>(0,u.__awaiter)(this,void 0,void 0,(function*(){if(!this.isPerformanceMarkerWritten){0!==this.performanceTimeoutID&&(window.clearTimeout(this.performanceTimeoutID),this.performanceTimeoutID=0),window.removeEventListener("beforeunload",this.writeNavPerfMarker),this.logPerformanceMarkers.BootStrapperLoadingStarted=this.getPerfMarkerStartTime("shell_bootstrapper_start"),this.logPerformanceMarkers.BootStrapperLoadingComplete=this.getPerfMarkerStartTime("shell_bootstrapper_end"),this.logPerformanceMarkers.HeaderLoadingStarted=this.getPerfMarkerStartTime("shell_header_start"),this.logPerformanceMarkers.HeaderLoadingComplete=this.getPerfMarkerStartTime("shell_header_end"),this.logPerformanceMarkers.LegacyHeaderLoadingStarted=this.getPerfMarkerStartTime("shell_legacyheader_start"),this.logPerformanceMarkers.LegacyHeaderLoadingComplete=this.getPerfMarkerStartTime("shell_legacyheader_end"),this.logPerformanceMarkers.ResponsiveLoadingStarted=this.getPerfMarkerStartTime("shell_responsive_start"),this.logPerformanceMarkers.ResponsiveLoadingComplete=this.getPerfMarkerStartTime("shell_responsive_end"),this.logPerformanceMarkers.shell_string_download_started=this.getPerfMarkerStartTime("shell_string_download_started"),this.logPerformanceMarkers.shell_string_download_ended=this.getPerfMarkerStartTime("shell_string_download_ended"),this.logPerformanceMarkers.SearchLoadingStarted=this.getPerfMarkerStartTime("shell_searchbox_start"),this.logPerformanceMarkers.SearchLoadingComplete=this.getPerfMarkerStartTime("shell_searchbox_end"),this.logPerformanceMarkers.CoreLoadingStarted=this.getPerfMarkerStartTime("shell_core_start"),this.logPerformanceMarkers.CoreLoadingComplete=this.getPerfMarkerStartTime("shell_core_end"),this.logPerformanceMarkers.PlusLoadingStarted=this.getPerfMarkerStartTime("shell_plus_start"),this.logPerformanceMarkers.PlusLoadingComplete=this.getPerfMarkerStartTime("shell_plus_end"),this.logPerformanceMarkers.shell_bootinfo_request_start=this.getPerfMarkerStartTime("shell_bootinfo_request_start"),this.logPerformanceMarkers.shell_bootinfo_request_end=this.getPerfMarkerStartTime("shell_bootinfo_request_end"),this.logPerformanceMarkers.PlusRenderComplete=this.getPerfMarkerStartTime("PlusRenderComplete"),this.logPerformanceMarkers.RenderImplementationStart=this.getPerfMarkerStartTime("RenderImplementationStart"),this.logPerformanceMarkers.RenderAsync=this.getPerfMarkerStartTime("RenderAsync"),this.logPerformanceMarkers.FirstContentfulPaint=this.getPerfMarkerStartTime("FirstContentfulPaint"),this.logPerformanceMarkers.shell_render_headerresizegroup_start=this.getPerfMarkerStartTime("shell_render_headerresizegroup_start"),this.logPerformanceMarkers.shell_render_headerresizegroup_end=this.getPerfMarkerStartTime("shell_render_headerresizegroup_end"),this.logPerformanceMarkers.SearchRenderComplete=this.getPerfMarkerStartTime("SearchRenderComplete"),this.logPerformanceMarkers.SearchFastPathTriggered=this.getPerfMarkerStartTime("SearchFastPathTriggered"),this.logPerformanceMarkers.shell_applauncher_start=this.getPerfMarkerStartTime("shell_applauncher_start"),this.logPerformanceMarkers.shell_applauncher_end=this.getPerfMarkerStartTime("shell_applauncher_end"),this.logPerformanceMarkers.shell_ecs_fetch_start=this.getPerfMarkerStartTime("shell_ecs_fetch_start"),this.logPerformanceMarkers.shell_ecs_fetch_end=this.getPerfMarkerStartTime("shell_ecs_fetch_end"),this.logPerformanceMarkers.shell_m365start_start=this.getPerfMarkerStartTime("shell_m365start_start"),this.logPerformanceMarkers.shell_m365start_end=this.getPerfMarkerStartTime("shell_m365start_end"),this.logPerformanceMarkers.shell_bootstrapper_executioncomplete=this.getPerfMarkerStartTime("shell_bootstrapper_executioncomplete"),this.logPerformanceMarkers.shell_legacyheader_executioncomplete=this.getPerfMarkerStartTime("shell_legacyheader_executioncomplete"),this.logPerformanceMarkers.shell_responsive_executioncomplete=this.getPerfMarkerStartTime("shell_responsive_executioncomplete"),this.logPerformanceMarkers.shell_core_executioncomplete=this.getPerfMarkerStartTime("shell_core_executioncomplete"),this.logPerformanceMarkers.shell_plus_executioncomplete=this.getPerfMarkerStartTime("shell_plus_executioncomplete"),this.getHeaderTTI(),this.isPerformanceMarkerWritten=!0;const e=Object.keys(this.logPerformanceMarkers);if(e.length>0){const t=new f(o.Performance,r.Performance);e.forEach((e=>{"BeginningOfTime"===e?t.SetProperty(e,Math.round(this.logPerformanceMarkers[e])):this.logPerformanceMarkers[e]>0?t.SetProperty(e,Math.round(this.logPerformanceMarkers[e]-this.logPerformanceMarkers.BeginningOfTime)):t.SetProperty(e,Math.round(this.logPerformanceMarkers[e]))}));const n=window.performance?window.performance.getEntriesByType("resource").filter((e=>null!=(0,p.ZR)(e.name))):[];if(n.length){const e=n.map((e=>`${e.name}|${e.encodedBodySize||""}|${Math.round(e.startTime)}|${Math.round(e.duration)}`)).join(";");t.SetProperty("ResourceTiming",e)}this.writeEvent(t)}}}))}init(){this.performanceTimeoutID=window.setTimeout((()=>{this.perfMarker("Timeout")}),this.defaultPerfMarkerTimeout),h&&window.addEventListener("beforeunload",this.writeNavPerfMarker),(0,d.l3)().registerChunkLoadedCallback(this.resourceLoaded)}registerService(e){if(null!=e&&-1===this.logServices.indexOf(e)){this.logContext.forEach((t=>{e.registerContextParam(t.name,t.value,t.piiKind,t.type)})),this.logServices.push(e);const t=this.eventBuffer.length;for(let n=0;n0&&(l=a.join(",")),c.SetProperty("Impression_Inventory",l),this.writeEvent(c)}timer(e,t,...n){this.timerImp((new Date).getTime(),e,t,...n)}timerImp(e,t,n,...i){const a=new f(o.Timer,r.Timer,e);a.SetProperty("Timer_Name",t),a.SetProperty("Timer_Value",Math.round(n)),a.SetAdHocProperties("Timer_AdHoc",i),this.writeEvent(a)}serverRequest(e,t,n,o,r,i=!1,a=-1,s=-1){this.serverRequestImp((new Date).getTime(),e,t,n,o,r,i,a,s)}serverRequestImp(e,t,n,i,a,s,c=!1,l=-1,u=-1){1223===s&&(s=204);const d=new f(o.ServerRequest,r.ServerRequest,e),h=this.parseRequestAction(t,a);d.SetProperty("ServerRequest_Name",t),d.SetProperty("ServerRequest_Method",n),d.SetProperty("ServerRequest_IFrame",i),d.SetProperty("ServerRequest_Url",(0,p.Ru)(a)),d.SetProperty("ServerRequest_Action",h),d.SetProperty("ServerRequest_Status",s),d.SetProperty("ServerRequest_IsTokenGeneratedFromWorkload",c),d.SetProperty("ServerRequest_Latency",Math.round(l)),d.SetProperty("ServerRequest_Size",Math.round(u)),this.writeEvent(d)}perfMarker(e){return(0,u.__awaiter)(this,arguments,void 0,(function*(e,t=-1){if(void 0===this.logPerformanceMarkers[e]&&h){const n=e;-1===t&&window.performance.mark(n),this.logPerformanceMarkers[n]=-1===t?this.getPerfMarkerStartTime(n):t,void 0===this.logPerformanceMarkers.BeginningOfTime&&(this.logPerformanceMarkers.BeginningOfTime=this.getPerfMarkerStartTime("shell_bootstrapper_start")),"FirstContentfulPaint"===e&&-1!==this.getPerfMarkerStartTime("shell_bootstrapper_start")&&-1!==this.getPerfMarkerStartTime("FirstContentfulPaint")&&window.performance.measure("Shell_FCP","shell_bootstrapper_start","FirstContentfulPaint"),"NavigationAway"!==e&&"Timeout"!==e||(yield this.writePerfMarkerEvent())}}))}perfMeasure(e,t,n){try{h&&window.performance.measure(e,t,n)}catch(e){}}getAppTileLabel(e){if(null==e)return"";let t=e;if(0===t.toLowerCase().indexOf("shell"))t=t.substr(5);else{const e=new RegExp("^([a-zA-Z0-9_]+App)_").exec(t);null!=e&&e.length>1&&(t=e[1])}return t}parseRequestAction(e,t){let n=null;if("Query"===e&&null!=t){const e=["action=([_0-9a-zA-Z]+)","/api/([/_0-9a-zA-Z]+)","ev=([_0-9a-zA-Z]+)",".([_0-9a-zA-Z]+).model","/ocs/([/_0-9a-zA-Z]+)"];let o=0;for(let r=0;r1){n=i[1];break}o++}null!=n&&(1===o&&0===n.indexOf("Notifications")&&(n="Notifications"),"/"===n.charAt(n.length-1)&&(n=n.substring(0,n.length-1)))}return n}writeEvent(e){this.logServices.forEach((t=>{t.writeEvent(e)})),window.O365ShellContext.DiagnosticsEnabled&&window.O365ShellContext.Diagnostics.push(JSON.stringify(e)),this.eventBuffer.length0)return Math.round(t[0].startTime)}}catch(e){}return-1}getHeaderTTI(){const e=this.getMarker("HelpTimeToInteractive"),t=this.getMarker("ChatTimeToInteractive"),n=this.getMarker("BellTimeToInteractive"),o=this.getMarker("SettingsTimeToInteractive"),r=this.getMarker("SearchRenderComplete");let i=e>t?e:t;return i=n>i?n:i,i=o>i?o:i,i=r>i?r:i,this.perfMarker("TimeToInteractive",i),i>0&&window.performance.measure("Shell_TTI","shell_bootstrapper_start"),i}getMarker(e){if(e){const t=this.logPerformanceMarkers[e];if(void 0!==t)return t}return 0}}function g(){let e=new m,t=window.O365ShellContext.Logger;(function(e){return void 0!==e.applyCalls})(t)&&(e.init(),t.applyCalls(e),window.O365ShellContext.Logger=e)}},89682:function(e,t,n){"use strict";n.d(t,{AG:function(){return d},C$:function(){return c},G4:function(){return l},Ii:function(){return f},Rh:function(){return i},Zy:function(){return r},bT:function(){return u},lX:function(){return o},sE:function(){return a},uI:function(){return p},wu:function(){return s}});const o="createHomepage",r="intentTile_",i="Microsoft365Tile",a="MoreAppsTile",s="O365_AppTile_",c="88001254",l="88001253",u=5,d=20,p=100,f=450},91016:function(e,t,n){"use strict";var o,r,i,a,s,c,l,u,d,p,f,h;n.d(t,{CS:function(){return p},P1:function(){return l},_e:function(){return r},sO:function(){return c}}),function(e){e.Smile="Smile",e.Frown="Frown",e.Idea="Idea",e.Unclassified="Unclassified",e.Survey="Survey",e.ThumbsUp="ThumbsUp",e.ThumbsDown="ThumbsDown"}(o||(o={})),function(e){e.Undefined="Undefined",e.MinorWithoutParentalConsent="MinorWithoutParentalConsent",e.MinorWithParentalConsent="MinorWithParentalConsent",e.NotAdult="NotAdult",e.Adult="Adult",e.MinorNoParentalConsentRequired="MinorNoParentalConsentRequired"}(r||(r={})),function(e){e.DropDown="DropDown",e.MultiSelect="MultiSelect",e.Rating="Rating",e.SingleSelect="SingleSelect",e.SingleSelectHorizontal="SingleSelectHorizontal"}(i||(i={})),function(e){e.FeatureArea="FeatureArea",e.ResponsibleAI="ResponsibleAI",e.Experience="Experience",e.ProductSatisfaction="ProductSatisfaction",e.CrashImpact="CrashImpact",e.Custom="Custom",e.AIThumbsDown="AIThumbsDown",e.AIThumbsUp="AIThumbsUp",e.PromptSuggestion="PromptSuggestion"}(a||(a={})),function(e){e.QuestionNotRequired="QuestionNotRequired",e.CommentNotRequired="CommentNotRequired",e.CommentRequiredWithLastOption="CommentRequiredWithLastOption"}(s||(s={})),function(e){e.MSA="MSA",e.AAD="AAD",e.Unauthenticated="Unauthenticated"}(c||(c={})),function(e){e.Enabled="Enabled",e.Disabled="Disabled",e.NotConfigured="Not Configured"}(l||(l={})),function(e){e.JPEG="jpeg",e.PNG="png"}(u||(u={})),function(e){e.AutoCapture="AutoCapture",e.AutoCaptureWithHtml2Canvas="AutoCaptureWithHtml2Canvas",e.ProvidedAtInitialization="ProvidedAtInitialization",e.DynamicallyProvided="DynamicallyProvided"}(d||(d={})),function(e){e.SidePane="SidePane",e.Modal="Modal",e.NoSurface="NoSurface",e.CallOut="CallOut",e.NoSurfaceWithoutTitle="NoSurfaceWithoutTitle"}(p||(p={})),function(e){e.Windows="Windows",e.Android="Android",e.WacTaskPane="WacTaskPane",e.MacOS="MacOS",e.Web="Web"}(f||(f={})),function(e){e.Success="Success",e.Error="Error",e.Warning="Warning"}(h||(h={}))},51545:function(e,t,n){"use strict";n.d(t,{k:function(){return r},m:function(){return i}});var o=n(91016);function r(e){if(!e)return null;const t=e.trim().toLowerCase();return{sidepane:o.CS.SidePane,modal:o.CS.Modal,nosurface:o.CS.NoSurface,callout:o.CS.CallOut,nosurfacewithouttitle:o.CS.NoSurfaceWithoutTitle}[t]||null}function i(e){return null!=e&&(e===o.CS.NoSurface||e===o.CS.NoSurfaceWithoutTitle)}},49852:function(e,t,n){"use strict";n.d(t,{B:function(){return r},P:function(){return i}});var o=n(28569);const r="LazyBellHeaderButton",i=(0,o.E)(r)},89959:function(e,t,n){"use strict";n.d(t,{Y:function(){return r},e:function(){return i}});var o=n(28569);const r="LazyChatHeaderButton",i=(0,o.E)(r)},70238:function(e,t,n){"use strict";n.d(t,{F:function(){return i},J:function(){return r}});var o=n(28569);const r="LazyCustomHeaderButton",i=(0,o.E)(r)},71936:function(e,t,n){"use strict";n.d(t,{p:function(){return r},r:function(){return i}});var o=n(28569);const r="LazyFeatureFlagsHeaderButton",i=(0,o.E)(r)},21226:function(e,t,n){"use strict";n.d(t,{$:function(){return r},s:function(){return i}});var o=n(28569);const r="LazyGearHeaderButton",i=(0,o.E)(r)},36558:function(e,t,n){"use strict";n.d(t,{V:function(){return r},z:function(){return i}});var o=n(28569);const r="LazyHelpHeaderButton",i=(0,o.E)(r)},98052:function(e,t,n){"use strict";n.d(t,{M:function(){return i},q:function(){return r}});var o=n(28569);const r="LazyMyDayHeaderButton",i=(0,o.E)(r)},28569:function(e,t,n){"use strict";n.d(t,{E:function(){return i}});var o=n(53512),r=n(16968);function i(e){let t=(0,o._)();return(0,r.NP)().subscribe("LazyComponentLoaded",((n,o)=>{n===e&&t.setComponent(o)}),!0),t}},53644:function(e,t,n){"use strict";n.d(t,{Hp:function(){return o},X3:function(){return r}});n(90872);const o="O365_MainLink_Affordance";function r(e){return null!=e&&e.isMeasured}},13780:function(e,t,n){"use strict";var o;n.d(t,{c:function(){return o}}),function(e){e.Theme="theme",e.LanguageAndRegion="languageandregion",e.NavBarDataLinks="navbardatalinks",e.ChangePassword="changepassword",e.ContactPreferences="contactpreferences",e.AboutBase="aboutbase",e.About="about",e.DarkMode="darkmode",e.CPNIPin="cpnipin",e.Copilot="copilot",e.Feedback="feedback",e.AppLaunch="applaunch",e.FileOpenSettings="fileopensettings"}(o||(o={}))},33106:function(e,t,n){"use strict";n.d(t,{EU:function(){return g},G4:function(){return i},Gf:function(){return f},H5:function(){return x},Jy:function(){return m},M9:function(){return l},MQ:function(){return A},S:function(){return a},Xm:function(){return r},bs:function(){return v},hK:function(){return u},ii:function(){return b},l4:function(){return h},ty:function(){return s},vJ:function(){return p},vo:function(){return c},wb:function(){return y},zH:function(){return d}});var o=n(42970);function r(e){return{type:o.cj,newWorkloadSettingLink:e}}function i(e){return{type:o.XL,settingLinkID:e}}function a(e){return{type:o.Rq,newWorkloadSettingsLinks:e}}function s(e){return{type:o._f,cardData:e}}function c(e){return{type:o.Eh,selectedLanguage:e}}function l(e){return{type:o.T9,languageChoices:e}}function u(e){return{type:o.u4,selectedTimeZone:e}}function d(e,t,n){return{type:o.wS,timeZoneChoice:e,dateFormatChoice:t,timeFormatChoice:n}}function p(e){return{type:o.Kt,timeZoneChoices:e}}function f(e){return{type:o.nf,selectedLanguage:e}}function h(e){return{type:o.Ul,selectedDateFormat:e}}function m(e){return{type:o.uT,dateFormatChoices:e}}function g(e){return{type:o.nt,selectedTimeFormat:e}}function b(e){return{type:o.jj,timeFormatChoices:e}}function v(){return{type:o.ar}}function y(){return{type:o.Xu}}function x(e){return{type:o.dE,cardId:e}}function A(e){return{type:o.oc,isExpanded:e}}},42970:function(e,t,n){"use strict";n.d(t,{Eh:function(){return l},Kt:function(){return f},Rq:function(){return s},T9:function(){return u},Ul:function(){return m},XL:function(){return a},Xu:function(){return r},_f:function(){return c},ar:function(){return o},cj:function(){return i},dE:function(){return y},jj:function(){return v},nf:function(){return h},nt:function(){return b},oc:function(){return x},u4:function(){return d},uT:function(){return g},wS:function(){return p}});const o="suiteux-settings.SAVE_SELECTIONS",r="suiteux-settings.CANCEL_SELECTIONS",i="suiteux-settings.ADDORUPDATE_WORKLOADSETTINGLINK",a="suiteux-settings.REMOVE_WORKLOADSETTINGLINK",s="suiteux-settings.SET_WORKLOADSETTINGSLINKS",c="suiteux-settings.INITIALCARDS_AVAILABLE",l="suiteux-settings.LANGUAGECHOICE_AVAILABLE",u="suiteux-settings.LANGUAGECHOICES_AVAILABLE",d="suiteux-settings.SELECTEDTIMEZONE_CHANGED",p="suiteux-settings.TIMEZONEANDFORMATSCHOICE_AVAILABLE",f="suiteux-settings.TIMEZONECHOICES_AVAILABLE",h="suiteux-settings.SELECTEDLANGUAGE_CHANGED",m="suiteux-settings.SELECTEDDATEFORMAT_CHANGED",g="suiteux-settings.DATEFORMATCHOICES_AVAILABLE",b="suiteux-settings.SELECTEDTIMEFORMAT_CHANGED",v="suiteux-settings.TIMEFORMATCHOICES_AVAILABLE",y="suiteux-settings.NAVIGATE_TO_CARD",x="suiteux-settings.O365_SETTINGS_EXPANDED"},92720:function(e,t,n){"use strict";n.d(t,{S:function(){return b}});var o=n(13780);const r=[o.c.LanguageAndRegion,o.c.ChangePassword,o.c.ContactPreferences,o.c.NavBarDataLinks],i=[o.c.NavBarDataLinks,o.c.Theme,o.c.LanguageAndRegion,o.c.ChangePassword,o.c.ContactPreferences],a={default:[o.c.NavBarDataLinks,o.c.Theme,o.c.LanguageAndRegion,o.c.DarkMode,o.c.ChangePassword,o.c.ContactPreferences],iwapp:[o.c.NavBarDataLinks,o.c.Theme,o.c.Copilot,o.c.LanguageAndRegion,o.c.DarkMode,o.c.ChangePassword,o.c.ContactPreferences,o.c.Feedback],exchange:[],exchangeadmin:i,officepwa:[o.c.Theme,o.c.Copilot,o.c.AppLaunch,o.c.FileOpenSettings,o.c.DarkMode,o.c.AboutBase,o.c.NavBarDataLinks],officepwamac:[o.c.Theme,o.c.Copilot,o.c.AboutBase,o.c.NavBarDataLinks],botdesigner:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],dynamics365:i,dynamics365ci:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],dynamics365fraudprotection:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],dynamics365powerplatform:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],dynamics365productinsights:[o.c.NavBarDataLinks,o.c.ChangePassword,o.c.ContactPreferences],adminportal:[o.c.NavBarDataLinks,o.c.Theme,o.c.LanguageAndRegion,o.c.ChangePassword,o.c.ContactPreferences],flow:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],teamsappstudio:[o.c.NavBarDataLinks,o.c.LanguageAndRegion,o.c.ChangePassword,o.c.ContactPreferences],microsoftstream:[o.c.NavBarDataLinks,o.c.LanguageAndRegion,o.c.DarkMode,o.c.ChangePassword,o.c.ContactPreferences],todo:[o.c.NavBarDataLinks,o.c.LanguageAndRegion,o.c.DarkMode,o.c.ChangePassword,o.c.ContactPreferences],microsoftclipchamp:[o.c.NavBarDataLinks,o.c.LanguageAndRegion,o.c.ChangePassword,o.c.ContactPreferences],powerappsportal:[o.c.NavBarDataLinks,o.c.Theme,o.c.ChangePassword,o.c.ContactPreferences],vivagoals:[],promptlibbie:[],vivaglint:[o.c.NavBarDataLinks,o.c.Theme,o.c.DarkMode,o.c.ChangePassword,o.c.ContactPreferences],vivalearning:[o.c.NavBarDataLinks,o.c.Theme,o.c.DarkMode],protectioncenter:i,wordonline:r,powerpointonline:r,excelonline:r,visioonline:r,onenoteonline:r,wac:r,officeonline:r};var s=n(61304);let c={[o.c.NavBarDataLinks]:{EnableConsumer:!0},[o.c.Theme]:{Title:s.D.Themes||"Themes",EnableConsumer:!0},[o.c.Copilot]:{EnableConsumer:!1},[o.c.ChangePassword]:{Title:s.D.Password,Description:s.D.PasswordDescription||"Change your password",EnableConsumer:!1,ChangePasswordCardData:[{WorkloadId:"dynamics365businesscentral",QueryStringData:[{Key:"ru",Value:"https://businesscentral.dynamics.com?redirectedfromsignup=1"}]}]},[o.c.ContactPreferences]:{Title:s.D.ContactPreferences,Description:s.D.ContactPreferencesDescription||"Update contact preferences",EnableConsumer:!1},[o.c.LanguageAndRegion]:{Title:s.D.LanguageAndTimeZone,Description:s.D.LanguageAndTimeZoneDescription||"Change your language",EnableConsumer:!1},[o.c.Feedback]:{Title:s.D.FeedbackButtonTitle||"Feedback",EnableConsumer:!1},[o.c.AppLaunch]:{Title:s.D.AppLaunchCardTitle||"App Launch",EnableConsumer:!0},[o.c.FileOpenSettings]:{Title:s.D.FileOpenSettingsCardTitle||"File Opening",EnableConsumer:!0},[o.c.AboutBase]:{Title:s.D.About,EnableConsumer:!0,ChildCardIds:[o.c.About]},[o.c.About]:{Title:s.D.About,EnableConsumer:!0},[o.c.DarkMode]:{Title:s.D.DarkThemeTitle||"Dark Mode",EnableConsumer:!1},[o.c.CPNIPin]:{Title:s.D.CPNIPinCardTitle,EnableConsumer:!1}};var l=n(16968),u=n(66164),d=n(84107);function p(e){return!e.UseSimplifiedLanguageCard&&!(1&~e.UserType||(0,u.Uc)(e.WorkloadId))}function f(e){return!e.ShowContactPreferencesCard}function h(e){return!(0,d.v)(e)}function m(e){const t=(0,l.Vz)().getThemeState().disableTheming;return e.IsConsumerShell?!(e.CSSExperiencesEnabled&&e.ConsumerThemingEnabled):!!t}const g="default";function b(e,t,n){var r;const i={[o.c.LanguageAndRegion]:p(e),[o.c.NavBarDataLinks]:h(n),[o.c.Theme]:m(e),[o.c.ContactPreferences]:f(e)};let s;const l=null!==(r=window.isMacApp)&&void 0!==r&&r;s=e.CurrentMainLinkElementID&&"shellofficedotcom"===e.CurrentMainLinkElementID.toLowerCase()?"iwapp":e.CurrentMainLinkElementID&&"shellofficepwa"===e.CurrentMainLinkElementID.toLowerCase()?l?"officepwamac":"officepwa":e.CurrentMainLinkElementID&&"shellstream"===e.CurrentMainLinkElementID.toLowerCase()?"microsoftstream":e.CurrentMainLinkElementID&&"clipchamp"===e.CurrentMainLinkElementID.toLowerCase()?"microsoftclipchamp":e.WorkloadId.toLowerCase();let u=null!=t?c[t].ChildCardIds:a[s]?a[s]:a[g],d=e.IsConsumerShell;return u?u.filter((t=>!e.IsGuestMode||t===o.c.NavBarDataLinks)).filter((e=>!d||c[e].EnableConsumer)).filter((e=>!i[e])).map((e=>Object.assign({Id:e},c[e]))):[]}},61304:function(e,t,n){"use strict";n.d(t,{D:function(){return i}});var o=n(16968);let r={};const i={};let a;const s=e=>{!function(e){r=Object.assign(Object.assign({},r),e),Object.getOwnPropertyNames(e).forEach((e=>{i.hasOwnProperty(e)||Object.defineProperty(i,e,{get:()=>r[e]})}))}(e),a&&(0,o.NP)().unsubscribe("StringsLoaded",a)};let c=(0,o.NP)();c&&(a=c.subscribe("StringsLoaded",s,!0))},67172:function(e,t,n){"use strict";n.d(t,{jI:function(){return v},Gy:function(){return m},cv:function(){return b}});var o=n(16968),r=n(1742);const i=[[0,-.362790697674419],[0,-.186046511627907],[0,-.186046511627907],[0,0],[-.270491803278688,.230508474576271],[-.442857142857143,.583050847457627],[-.275862068965518,.861016949152542],[-.333333333333334,.955932203389831],[-.333333333333334,.955932203389831]],a=/^#((?:[0-9a-fA-F]{3}){1,2})$/,s=/rgba?\((\d{0,3})\s?,\s?(\d{0,3})\s?,\s?(\d{0,3})\s?,?(\s?(\d?\.\d+))?\)/;function c(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}function l(e){let t=1;9===e.length&&(t=c(parseInt(e.substring(7),16)/255,2),e=e.substr(0,7));let n=a.exec(e),o="";return null!=n&&n.length>1?(o=6===n[1].length?n[1]:n[1].split("").map((e=>e.concat(e))).join(""),[parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16),t]):[0,0,0,0]}function u(e,t=!1){return e.some((e=>e<0||e>255))?"#00000000":(null!=e[3]&&e[3]<1&&!t?e[3]=Math.round(255*e[3]):e.splice(3,1),"#"+e.map((e=>{let t=e.toString(16);return 1===t.length?"0"+t:t})).join(""))}function d(e,t,n){let[o,r,i,a]=function([e,t,n,o]){if([e,t,n].some((e=>e<0||e>255)))return[0,0,0,0];[e,t,n]=[e,t,n].map((e=>e/255));let r=Math.max(e,t,n),i=Math.min(e,t,n),a=r-i,s=0,l=0,u=(i+r)/2;if(0!==a){switch(l=a/(1-Math.abs(2*u-1)),r){case e:s=(t-n)/a%6;break;case t:s=(n-e)/a+2;break;case n:s=(e-t)/a+4}s*=60,s=(s+360)%360}return[Math.round(s),c(l,2),c(u,2),o]}(l(e));return r=Math.min(1,r*(1+t)),i=n>0?(1-i)*n+i:i*(1+n),u(function([e,t,n,o]){let r=(1-Math.abs(2*n-1))*t,i=(e=(e%360+360)%360)/60,a=r*(1-Math.abs(i%2-1)),[s,c,l]=[0,0,0];i>0&&i<=1?[s,c,l]=[r,a,0]:i>1&&i<=2?[s,c,l]=[a,r,0]:i>2&&i<=3?[s,c,l]=[0,r,a]:i>3&&i<=4?[s,c,l]=[0,a,r]:i>4&&i<=5?[s,c,l]=[a,0,r]:i>5&&i<=6&&([s,c,l]=[r,0,a]);let u=n-r/2;return[s,c,l].map((e=>Math.min(255,Math.round(255*(e+u))))).concat([o])}([o,r,i,a]),!0)}function p(e){let t=e.Primary;const n=t.match(s);return null!=n&&(t=u(n.slice(1,5).map((e=>parseFloat(e)||1)),!0)),{Darker:e.Darker||d(t,i[0][0],i[0][1]),Dark:e.Dark||d(t,i[1][0],i[1][1]),DarkAlt:e.DarkAlt||d(t,i[2][0],i[2][1]),Primary:t,Secondary:e.Secondary||d(t,i[4][0],i[4][1]),Tertiary:e.Tertiary||d(t,i[5][0],i[5][1]),Light:e.Light||d(t,i[6][0],i[6][1]),Lighter:e.Lighter||d(t,i[7][0],i[7][1]),LighterAlt:e.LighterAlt||d(t,i[8][0],i[8][1])}}var f=n(87529);function h(e,t,n,o){const r=p(e),i=(0,f.er)(e,t),a=(0,f.Ve)(t);return e=n?{NavBar:a.NavBar,AppName:e.AppName,DefaultText:a.Darker,DefaultBackground:a.NavBar,SelectedBackground:a.Lighter,SelectedText:a.Darker,Accent:r.Dark,HoverBackground:r.Dark,HoverText:i.white,PressedText:i.white,DarkAlt:r.DarkAlt,Primary:e.Primary,Secondary:e.Secondary,Tertiary:e.Tertiary}:Object.assign({NavBar:e.Primary,AppName:i.white,DefaultText:i.white,DefaultBackground:e.NavBar||e.Primary,SelectedBackground:i.lighter,SelectedText:i.dark,Accent:r.Dark,HoverBackground:r.Darker,HoverText:i.white,PressedText:i.white,PressedBackground:r.Darker,DarkAlt:r.DarkAlt},e),o?null!=e.FullBleedImages&&(e.DefaultBackground=e.NavBar):delete e.FullBleedImages,e=Object.assign({SearchNavBar:e.NavBar===e.Primary?r.Dark:p({Primary:e.NavBar}).Dark,SearchHoverBackground:p({Primary:e.HoverBackground}).Dark,SearchAccent:p({Primary:e.Accent}).Dark,SearchDefaultText:i.white,WaffleBackground:e.DefaultBackground,WaffleIcon:e.DefaultText,FlexPaneAccent:e.Accent,BackgroundImageRepeat:!0,BadgeText:i.foreground,BadgeBackground:e.Accent},e)}function m(){(0,o.NP)().subscribe("ThemeUpdated",g),(0,o.Vz)().updateThemeCss(!1)}function g(e=!1){let t=(0,o.Vz)(),n=t.getThemeClassNames();const r=t.getThemeData();let i={[`.${n.highContrastButton}`]:{"@media screen and (-ms-high-contrast: black-on-white), (forced-colors: active) and (prefers-color-scheme: light)":{color:"black","-ms-high-contrast-adjust":"none","forced-color-adjust":"none","background-color":"white"},"@media screen and (-ms-high-contrast: white-on-black), (forced-colors: active) and (prefers-color-scheme: dark)":{color:"white","-ms-high-contrast-adjust":"none","forced-color-adjust":"none","background-color":"black"},"&:hover, &:focus":{"@media screen and (-ms-high-contrast: white-on-black), (forced-colors: active) and (prefers-color-scheme: dark)":{"background-color":"#1AEBFF"},"@media screen and (-ms-high-contrast: black-on-white), (forced-colors: active) and (prefers-color-scheme: light)":{"background-color":"#37006E"}}},[`.${n.activeHeaderButton}`]:{color:`${r.SelectedText}`,backgroundColor:`${r.SelectedBackground}`,"&:focus":{outline:`${r.Primary} 1px solid`}},[`.${n.accent.link}`]:{backgroundColor:r.Accent},[`.${n.accent.font}`]:{backgroundColor:r.Accent},[`.${n.accent.background}`]:{backgroundColor:r.Accent},[`.${n.accent.border}`]:{borderColor:r.Accent},[`.${n.searchNav}.${n.navbar}`]:e?{backgroundColor:r.SearchNavBar,backgroundImage:"none",[`& .${n.appName}, & .${n.appName}:hover, & .${n.appName}:visited, & .${n.appName}:focus`]:{color:r.SearchDefaultText,backgroundColor:r.SearchNavBar},[`& .${n.appBrandLink}`]:{"&:focus":{outline:`${r.DefaultText} 1px solid`}},[`& .${n.headerButton}`]:{color:r.SearchDefaultText,backgroundColor:r.SearchNavBar,"&:hover, &:focus":{backgroundColor:r.SearchHoverBackground},"&:focus":{outline:`${r.DefaultText} 1px solid`}},[`& .${n.nonInteractiveButton}`]:{color:r.SearchDefaultText,backgroundColor:r.SearchNavBar,"&:hover, &:focus":{backgroundColor:null},"&:focus":{outline:null}},[`& .${n.activeHeaderButton}, & .${n.activeHeaderButton}:hover, & .${n.activeHeaderButton}:focus`]:{color:`${r.SelectedText}`,backgroundColor:`${r.SelectedBackground}`},[`& .${n.accent.font}`]:{backgroundColor:r.SearchAccent},[`& .${n.accent.background}`]:{backgroundColor:r.SearchAccent},[`& .${n.accent.border}`]:{borderColor:r.SearchAccent}}:null},a=JSON.stringify(i).replace("{",",");t.setState({additionalStyles:a})}function b(e,t,n,i){const a={};if(e.forEach(((e,t)=>{a[e.Id.toLowerCase()]=t})),i){let i=JSON.parse(JSON.stringify(e));(0,o.Vz)().getThemeState().tenantTheme&&(i.push({Id:r.Mm,Order:20}),a[r.Mm]=i.length-1),t=t===r.ux&&n?r.Mm:t;let s=i.splice(a[t],1)[0],c=i.sort(((e,t)=>e.Order-t.Order));return c.unshift(s),c}return[e[a[r.ux]],e[a[r.D5]]]}function v(e,t,n,o){var i,a;const s=e.Id.toLowerCase();return e=Object.assign(Object.assign({},e),{ThemeType:"User",Name:null!==(i=t[`ThemeName_${s}`])&&void 0!==i?i:e.Name}),s===r.ux&&n.tenantTheme?e=Object.assign(Object.assign(Object.assign({},e),h(n.tenantTheme,!1,!1,!1)),{ThemeType:"Tenant"}):s!==r.Mm&&s!==r.ux||(o?e=Object.assign(Object.assign(Object.assign({},e),h(o,!1,n.isMicaEnabled,!1)),{Name:null!==(a=t.NeutralTheme)&&void 0!==a?a:"Neutral theme",Order:20,ThemeType:"App"}):e.ThemeType=null),e}},87529:function(e,t,n){"use strict";n.d(t,{Ve:function(){return r},_Q:function(){return i},er:function(){return o}});function o(e,t){return t?{white:"#FFFFFF",black:"#000000",foreground:"#212121",foregroundAlt:"#555555",accent:e.Dark||e.DarkAccent||"#B3D6F2",staticAccent:e.Dark||e.DarkAccent||"#106EBE",light:"#555555",lightAlt:"#999999",lighter:"#3C3C3C",lighterAlt:"#212121",dark:"#FFFFFF",primary:"#797775",secondary:"#FFFFFF",tertiary:"#FFFFFF",darkRed:"#F4ABBA"}:{white:"#FFFFFF",black:"#000000",foreground:"#FFFFFF",foregroundAlt:"#FFFFFF",staticAccent:e.FlexPaneAccent,accent:e.FlexPaneAccent,light:"#E1DFDD",lightAlt:"#EDEBE9",lighter:"#F3F2F1",lighterAlt:"#FAF9F8",dark:"#252423",primary:"#BEBBB8",secondary:"#484644",tertiary:"#605E5C",darkRed:"#A80000"}}function r(e){return e?{NavBar:"transparent",Dark:"#ffffff80",Darker:"#ffffffb3",DarkAlt:"#ffffffb3",Light:"#24242480",Lighter:"#242424cc",LighterAlt:"#242424cc"}:{NavBar:"transparent",Dark:"#24242480",Darker:"#242424cc",DarkAlt:"#242424cc",Light:"#ffffff80",Lighter:"#ffffffb3",LighterAlt:"#ffffffb3"}}function i(e="#B3D6F2"){return{NavBar:"#1B1A19",Dark:e,Darker:e,DarkAlt:e,Primary:e,Secondary:e,DefaultBackground:"#1B1A19",HoverBackground:"#252423",SelectedBackground:"#252423",Tertiary:e,Light:e,Lighter:e,LighterAlt:e,Disabled:!0}}},90872:function(e){"use strict";e.exports=O365ShellContext.React},9028:function(e){"use strict";e.exports=O365ShellContext.ReactDOM},93288:function(e){function t(){return e.exports=t=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0;s--)(r=e[s])&&(a=(i<3?r(a):i>3?r(t,n,a):r(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}function c(e,t){return function(n,o){t(n,o,e)}}function l(e,t,n,o,r,i){function a(e){if(void 0!==e&&"function"!=typeof e)throw new TypeError("Function expected");return e}for(var s,c=o.kind,l="getter"===c?"get":"setter"===c?"set":"value",u=!t&&e?o.static?e:e.prototype:null,d=t||(u?Object.getOwnPropertyDescriptor(u,o.name):{}),p=!1,f=n.length-1;f>=0;f--){var h={};for(var m in o)h[m]="access"===m?{}:o[m];for(var m in o.access)h.access[m]=o.access[m];h.addInitializer=function(e){if(p)throw new TypeError("Cannot add initializers after decoration has completed");i.push(a(e||null))};var g=(0,n[f])("accessor"===c?{get:d.get,set:d.set}:d[l],h);if("accessor"===c){if(void 0===g)continue;if(null===g||"object"!=typeof g)throw new TypeError("Object expected");(s=a(g.get))&&(d.get=s),(s=a(g.set))&&(d.set=s),(s=a(g.init))&&r.unshift(s)}else(s=a(g))&&("field"===c?r.unshift(s):d[l]=s)}u&&Object.defineProperty(u,o.name,d),p=!0}function u(e,t,n){for(var o=arguments.length>2,r=0;r0&&r[r.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function y(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var o,r,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(o=i.next()).done;)a.push(o.value)}catch(e){r={error:e}}finally{try{o&&!o.done&&(n=i.return)&&n.call(i)}finally{if(r)throw r.error}}return a}function x(){for(var e=[],t=0;t1||s(e,t)}))})}function s(e,t){try{(n=r[e](t)).value instanceof S?Promise.resolve(n.value.v).then(c,l):u(i[0][2],n)}catch(e){u(i[0][3],e)}var n}function c(e){s("next",e)}function l(e){s("throw",e)}function u(e,t){e(t),i.shift(),i.length&&s(i[0][0],i[0][1])}}function k(e){var t,n;return t={},o("next"),o("throw",(function(e){throw e})),o("return"),t[Symbol.iterator]=function(){return this},t;function o(o,r){t[o]=e[o]?function(t){return(n=!n)?{value:S(e[o](t)),done:!1}:r?r(t):t}:r}}function P(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=v(e),t={},o("next"),o("throw"),o("return"),t[Symbol.asyncIterator]=function(){return this},t);function o(n){t[n]=e[n]&&function(t){return new Promise((function(o,r){(function(e,t,n,o){Promise.resolve(o).then((function(t){e({value:t,done:n})}),t)})(o,r,(t=e[n](t)).done,t.value)}))}}}function O(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var I=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t};function D(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&g(t,e,n);return I(t,e),t}function T(e){return e&&e.__esModule?e:{default:e}}function E(e,t,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(e):o?o.value:t.get(e)}function L(e,t,n,o,r){if("m"===o)throw new TypeError("Private method is not writable");if("a"===o&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===o?r.call(e,n):r?r.value=n:t.set(e,n),n}function M(e,t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Cannot use 'in' operator on non-object");return"function"==typeof e?t===e:e.has(t)}function F(e,t,n){if(null!=t){if("object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object expected.");var o;if(n){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");o=t[Symbol.asyncDispose]}if(void 0===o){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");o=t[Symbol.dispose]}if("function"!=typeof o)throw new TypeError("Object not disposable.");e.stack.push({value:t,dispose:o,async:n})}else n&&e.stack.push({async:!0});return t}var N="function"==typeof SuppressedError?SuppressedError:function(e,t,n){var o=new Error(n);return o.name="SuppressedError",o.error=e,o.suppressed=t,o};function B(e){function t(t){e.error=e.hasError?new N(t,e.error,"An error was suppressed during disposal."):t,e.hasError=!0}return function n(){for(;e.stack.length;){var o=e.stack.pop();try{var r=o.dispose&&o.dispose.call(o.value);if(o.async)return Promise.resolve(r).then(n,(function(e){return t(e),n()}))}catch(e){t(e)}}if(e.hasError)throw e.error}()}t.default={__extends:r,__assign:i,__rest:a,__decorate:s,__param:c,__metadata:f,__awaiter:h,__generator:m,__createBinding:g,__exportStar:b,__values:v,__read:y,__spread:x,__spreadArrays:A,__spreadArray:C,__await:S,__asyncGenerator:w,__asyncDelegator:k,__asyncValues:P,__makeTemplateObject:O,__importStar:D,__importDefault:T,__classPrivateFieldGet:E,__classPrivateFieldSet:L,__classPrivateFieldIn:M,__addDisposableResource:F,__disposeResources:B}}},a={};function s(e){var t=a[e];if(void 0!==t)return t.exports;var n=a[e]={id:e,loaded:!1,exports:{}};return i[e].call(n.exports,n,n.exports,s),n.loaded=!0,n.exports}s.m=i,e=[],s.O=function(t,n,o,r){if(!n){var i=1/0;for(u=0;u=r)&&Object.keys(s.O).every((function(e){return s.O[e](n[c])}))?n.splice(c--,1):(a=!1,r0&&e[u-1][2]>r;u--)e[u]=e[u-1];e[u]=[n,o,r]},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},s.t=function(e,o){if(1&o&&(e=this(e)),8&o)return e;if("object"==typeof e&&e){if(4&o&&e.__esModule)return e;if(16&o&&"function"==typeof e.then)return e}var r=Object.create(null);s.r(r);var i={};t=t||[null,n({}),n([]),n(n)];for(var a=2&o&&e;"object"==typeof a&&!~t.indexOf(a);a=n(a))Object.getOwnPropertyNames(a).forEach((function(t){i[t]=function(){return e[t]}}));return i.default=function(){return e},s.d(r,i),r},s.d=function(e,t){for(var n in t)s.o(t,n)&&!s.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},s.f={},s.e=function(e){return Promise.all(Object.keys(s.f).reduce((function(t,n){return s.f[n](e,t),t}),[]))},s.u=function(e){return"suiteux.shell."+e+"."+{search:"72374ded6a4436e6d5a3",plus:"347d8a006b7d18a62075",m365start:"d031742c5a4998c8f1e0",applauncher:"70ca3eb00d24d2dfd80b",featureflags:"0516a3d130550c98fe9b",myday:"32e29826618934c45028",extraflexpane:"7683686474028a0ae015",searchbox:"e3cf4f28b9f7615d3151",msrcrypto:"ef97e77ffce8e3a34924",abt:"c51492c889ed696ce727",abtprompt:"f10eaf4f716be14c2cae",exchangedata:"bcc9747a23eb8b33ad69",chat:"865271a68f42a8a868d7",diagnostics:"dffef2692eec12b139c1",dtt:"89a0192524c23814c05a",mast:"75247141eba989d40b6d",mastprompt:"8bbc3c2b11b47f5f3ab3",notifications:"17728645f935f656385f",otellogging:"2bb510bca5cad7db54a6",npm_mecontrol:"81346e124bdb0aabf33e",umc_mecontrol:"663e3f8156b95d75a796",changephoto:"84a52346b300fb3c0016",docsmodule:"9966cf4d9dfd018114bf",searchux:"1b0ce5930fd142388c50","sb-strings":"951aed60066ec47a4686",chatbase:"5635bed000a93a8e6b4c",notificationflex:"b4d65b513bf46c7f7934","oneds-analytics-js":"81344a1a3a3a2fd695aa","_store_mecontrol-fluent-web_3_28_4-preview_4-5af2d876fcb7dd9a55e8_node_modules_mecontrol_flue-994e90":"d3ea95f756b137caa632",chaterror:"197d4b97606ddf47ab47","_store_mecontrol-fluent-web_3_28_4-preview_4-5af2d876fcb7dd9a55e8_node_modules_mecontrol_flue-bb9c4f":"6ebe459ea8786a0b0950"}[e]+".js"},s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o={},r="@1js/suiteux-shell:",s.l=function(e,t,n,i){if(o[e])o[e].push(t);else{var a,c;if(void 0!==n)for(var l=document.getElementsByTagName("script"),u=0;u{(n.IsConsumerShell||(0,l.n)(n)&&t.SessionID)&&(d||(d=!0,(0,r.tZ)().impression("NavBarFull","NavBar",0,null,function(e,t,n){var o,i;let a="";if(t&&e){n&&n.testTraffic&&(a+="TestTraffic:1;"),e.HasTenantBranding&&(e.TenantLogoUrl&&(a+="TenantLogo:1;"),t.TenantThemeColors&&(a+=`TenantThemeColors:${t.TenantThemeColors.join(",")};`)),t.UserPersonalizationAllowed||(a+="UserThemeDisabled:1;");let o="UserTheme:{0};";t.UserThemeId&&(t.UserPersonalizationAllowed||"contrast"===t.UserThemeId.toLowerCase())&&"base"!==t.UserThemeId.toLowerCase()?a+=(0,u.JT)(o,t.UserThemeId):t.UserThemeId&&"base"===t.UserThemeId.toLowerCase()&&(t.PreferOfficeTheme&&t.UserPersonalizationAllowed?a+=(0,u.JT)(o,"Office"):e.HasTenantBranding&&(a+=(0,u.JT)(o,"Tenant"))),n&&(n.isDarkMode||t.IsDarkMode)&&n.darkAccent&&(a+="DarkMode:1;"),n&&(n.initialRenderData.UPN||(a+="UPNSupplied:0;"),n.initialRenderData.UserID||(a+="UserIDSupplied:0;"))}t&&t.AuthAbtEnabled&&n&&n.abtTimeout&&(a+="AbtEnabled:",n.abtSessionId&&(a+=n.abtSessionId),a+=";"),t&&t.AriaViewportLoggingEnabled&&(document.documentElement.clientWidth&&(a+="ViewportWidth:"+document.documentElement.clientWidth.toString()+";"),document.documentElement.clientHeight&&(a+="ViewportHeight:"+document.documentElement.clientHeight.toString()+";"));let s=window.O365ShellContext.React;if(a+="ReactVersion:"+(s&&s.version)+";",n.enableDelayLoading&&(a+="DelayLoad:1;"),n.isThinHeader&&(a+="ThinHeader:1;"),(0,r.YF)().CustomLayoutSpecified&&(a+="CustomLayout:1;"),t&&t.SearchUXAvailable&&n&&n.enableSearchUX&&(a+="SearchUXEnabled:1;"),(null===(o=null==n?void 0:n.initialRenderData)||void 0===o?void 0:o.ShellAssetsContainerOverride)&&(a+="IsNPM:1;"),(null===(i=null==n?void 0:n.initialRenderData)||void 0===i?void 0:i.ShellBootHost)&&(a+=`ShellBootHost:${n.initialRenderData.ShellBootHost};`),t&&"IWApp"===t.WorkloadId&&document.referrer)try{a+="Referrer:"+document.referrer.replace("http://","").replace("https://","").split(/[/?#]/)[0]+";"}catch(e){}return a}(t,n,(0,r.GJ)())),(0,r.NP)().unsubscribe("ShellDataUpdated",e)))}),!0)}var f=s(95144),h=s(28370),m=s(70238),g=s(91112),b=s(90872),v=s(9028),y=s(4963);class x extends h.qs{constructor(e){super(e),this.preventEscPropagation=e=>{27===e.keyCode&&e.stopPropagation()},this.state={isShyHeaderActive:!1},(0,r.NP)().subscribe("ShyHeaderActivated",(e=>{this.setState({isShyHeaderActive:e})}),!0)}onComponentVisible(){super.onComponentVisible(),(0,r.tZ)().impression("CustomFlexPane","FlexPane",0,void 0,"Loaded"),this.props.onFlexPaneOpen&&this.props.onFlexPaneOpen(),this.customRenderContainer&&this.props.render&&this.props.render(this.customRenderContainer)}onComponentHide(){super.onComponentHide(),this.props.onFlexPaneClose&&this.props.onFlexPaneClose()}componentWillUnmount(){this.customRenderContainer&&v.unmountComponentAtNode(this.customRenderContainer),super.componentWillUnmount()}render(){return b.createElement(h.eb,{isActive:this.props.isActive,title:this.props.flexPaneTitle(),customTitle:this.props.customTitle,customTitleClassName:this.props.customTitleClassName,flexPaneProviderID:this.props.flexPaneProviderID,className:this.props.className},b.createElement("div",{id:`CustomFlexPane_${this.props.flexPaneProviderID}`,role:"region",className:(0,f.AH)(y.flexPaneContentContainer,y.flexPaneContentContainerForThinHeader,{[y.flexPaneContentContainerForShyHeader]:this.state.isShyHeaderActive}),onKeyDown:this.props.customEscapeKeyHandling&&this.preventEscPropagation,ref:e=>this.customRenderContainer=e}))}}const A=(0,g.connect)(((e,t)=>{let n=e.extensibilityState.customFlexPanes[t.flexPaneProviderID];return n?Object.assign(Object.assign({},t),{className:n.containerClassName,flexPaneTitle:()=>"function"==typeof n.flexPaneTitle?n.flexPaneTitle():n.flexPaneTitle,customTitle:n.customTitle,customTitleClassName:n.customTitleClassName,render:n.render,customEscapeKeyHandling:n.customEscapeKeyHandling,onFlexPaneOpen:n.onFlexPaneOpen,onFlexPaneClose:n.onFlexPaneClose,triggerControlID:n.triggerControlID}):((0,r.tZ)().tag("UnrecognizedCustomFlexPane",6,t.flexPaneProviderID),null)}))(x);var C=s(69663),S=s.n(C),w=s(57530),k=s(82871),P=s.n(k),O=s(61304);function I(e){return!!e&&"iconFontName"in e}const D="ShellFabricMDL2IconsLite,ShellFabricMDL2Icons";class T extends b.Component{constructor(e){super(e),this.setClickableElement=e=>{this.headerButtonElement=e},this.onClick=e=>{this.props.isStateless&&this.props.onShow&&this.props.onShow(e.currentTarget.getBoundingClientRect()),this.props.onClick&&this.props.onClick(e)},this.state={isHovered:!1}}componentDidUpdate(e,t){this.props.isActive&&!e.isActive&&null!=this.headerButtonElement?this.props.onShow&&this.props.onShow(this.headerButtonElement.getBoundingClientRect()):!this.props.isActive&&e.isActive&&this.props.onHide&&this.props.onHide()}getArialLabel(){var e,t;const n="function"==typeof this.props.ariaLabel?this.props.ariaLabel():this.props.ariaLabel;if(void 0!==this.props.badgeValue&&0!==this.props.badgeValue){if(!this.props.badgeLabel||this.props.badgeLabel.includes("{1}"))return(0,f.JT)(null!==(e=this.props.badgeLabel)&&void 0!==e?e:O.D.UnreadBadge_Count,`${n}`,`${this.props.badgeValue}`);if(null===(t=this.props.badgeLabel)||void 0===t?void 0:t.includes("{0}"))return(0,f.JT)(this.props.badgeLabel,`${this.props.badgeValue}`)}return n}render(){const e={controlID:this.props.id,isVisible:this.props.isAvailable,ariaLabel:this.getArialLabel(),affordanceMenuItemText:"function"==typeof this.props.affordanceMenuItemText?this.props.affordanceMenuItemText():this.props.affordanceMenuItemText,iconData:this.props.iconData?I(this.props.iconData)?{iconFontName:this.props.iconData.iconFontName,iconFontFamily:this.props.iconData.iconFontFamily||D,iconFontSize:w.LV.toString()}:this.props.iconData:{iconFontName:this.props.iconFontName,iconFontFamily:this.props.iconFontFamily||D,iconFontSize:w.LV.toString()},isActive:this.props.isActive,isDarkModeEnabled:!!this.props.isDarkMode,onClick:this.onClick,onHoverStateChanged:e=>{this.setState({isHovered:e})},onDimensionsChanged:this.props.controlDimensionsChanged,setClickableElement:this.setClickableElement,buttonText:this.props.buttonText,responsiveStep:this.props.responsiveStep,hideButton:this.props.hideButton,isNoninteractive:this.props.isNoninteractive,badgeLabel:this.props.badgeLabel};return 0===this.props.renderContext?b.createElement(a.hp,Object.assign({},e),b.createElement(f.xw,{unseenItemCount:this.props.badgeValue,isParentHovered:this.state.isHovered,badgeStyles:P().headerButtonBadgePosition,badgeColors:this.props.badgeColors,badgeCharacter:this.props.badgeCharacter,isDarkMode:!!this.props.isDarkMode})):b.createElement(a.vO,Object.assign({},e),b.createElement(f.xw,{unseenItemCount:this.props.badgeValue,isParentHovered:this.state.isHovered,badgeStyles:S().affordanceContextMenuItemBadgePosition,badgeColors:this.props.badgeColors,badgeCharacter:this.props.badgeCharacter,isDarkMode:!!this.props.isDarkMode}))}}const E=(0,g.connect)(((e,t)=>Object.assign(Object.assign({},t),{badgeValue:e.extensibilityState.badgeValues[t.id],badgeColors:e.extensibilityState.badgeColors[t.id],isActive:!!e.extensibilityState&&t.id===e.extensibilityState.activeButtonId,flexPaneProviderID:e.extensibilityState.customHeaderButtonFlexPaneTriggers[t.id],badgeLabel:e.extensibilityState.badgeLabels[t.id],isDarkMode:e.themeState.IsDarkMode,badgeCharacter:e.extensibilityState.badgeCharacters[t.id]})),((e,t)=>({onClickDispatch:(n,o)=>{o.stopPropagation(),t.onClick&&t.onClick(o),t.isStateless||e((0,f.ad)(o.currentTarget&&o.currentTarget.id)),n&&e((0,h.IZ)(n))}})),((e,t)=>Object.assign(Object.assign(Object.assign({},e),t),{onClick:n=>{t.onClickDispatch(e.flexPaneProviderID,n)}})))(T);var L=s(7102),M=s(6806);const F="suiteux-extensibility.SET_BADGE_VALUE",N="suiteux-extensibility.SET_BADGE_COLOR",B="suiteux-extensibility.SET_BADGE_LABEL",H="suiteux-extensibility.SET_BADGE_CHARACTER";function j(e,t,n,o){let r=Object.assign({},e);t&&t.flexPaneCollection&&t.flexPaneCollection.forEach((e=>{let t=e;t.render&&(r.customFlexPanes[t.flexPaneID]=t)})),n&&(r.customFlexPanes[n.flexPaneID]=n),o&&(r.customFlexpaneWidth=o);let i=Object.keys(r.customFlexPanes).sort();return r.customFlexPaneHash=(0,f.YZ)(JSON.stringify(i)),r}let U={extensibilityState:function(e,t){if(!e){let n=t.shellInitData.shellInitDataState;e=j(f.Jg,n.layout)}switch(t.type){case f.QR:return function(e,t){let n=t.buttonId;e.activeButtonId===n&&(n="");return Object.assign(Object.assign({},e),{activeButtonId:n})}(e,t);case f.zM:return j(e,t.shellLayout);case"suiteux-extensibility.UPDATE_CUSTOMHEADERBUTTON":return function(e,t){let n=Object.assign({},e);for(let o=0;oe.id===r.id));i>=0?n.customHeaderButtons=[...e.customHeaderButtons.slice(0,i),r,...e.customHeaderButtons.slice(i+1)]:(n.customHeaderButtons=[...e.customHeaderButtons],n.customHeaderButtons.unshift(r))}return n}(e,t);case L.j4:let n=t;return j(e,null,n.customFlexpane,n.customFlexpaneWidth);case L.GY:return function(e,t){let n=Object.assign({},e);delete n.customFlexPanes[t];let o=Object.keys(n.customFlexPanes).sort();return n.customFlexPaneHash=(0,f.YZ)(JSON.stringify(o)),n}(e,t.customFlexpaneID);case M.vG:return function(e,t){let n=e;t.newProvider.shellControlID&&e.customHeaderButtonFlexPaneTriggers[t.newProvider.shellControlID]!==t.newProvider.key&&(n=Object.assign(Object.assign({},e),{customHeaderButtonFlexPaneTriggers:Object.assign({},e.customHeaderButtonFlexPaneTriggers)}),n.customHeaderButtonFlexPaneTriggers[t.newProvider.shellControlID]=t.newProvider.key);return n}(e,t);case F:return function(e,t){let n=e;e.badgeValues[t.buttonID]!==t.badgeValue&&(n=Object.assign(Object.assign({},e),{badgeValues:Object.assign({},e.badgeValues)}),n.badgeValues[t.buttonID]=t.badgeValue);return n}(e,t);case B:return function(e,t){let n=Object.assign({},e);e.badgeLabels[t.buttonID]!==t.badgeLabel&&(n.badgeLabels[t.buttonID]=t.badgeLabel);return n}(e,t);case N:return function(e,t){let n=e;e.badgeColors[t.buttonID]!==t.badgeColors&&(n=Object.assign(Object.assign({},e),{badgeColors:Object.assign({},e.badgeColors)}),n.badgeColors[t.buttonID]=t.badgeColors);return n}(e,t);case H:return function(e,t){let n=e;e.badgeCharacters[t.buttonID]!==t.badgeCharacter&&(n=Object.assign(Object.assign({},e),{badgeCharacters:Object.assign({},e.badgeCharacters)}),n.badgeCharacters[t.buttonID]=t.badgeCharacter);return n}(e,t);default:return e}}};var R=s(93814),_=s(95422),Q=s(40141),z=s(10806),W=s(83379);class Z extends b.Component{constructor(e){super(e),this.onEntryPointClick=()=>{this.props.isStateless?this.props.onShow(this.buttonElement.getBoundingClientRect()):this.props.onToggleButtonState(this.props.id)}}componentDidUpdate(e,t){this.props.isActive&&!e.isActive&&this.buttonElement?this.props.onShow(this.buttonElement.getBoundingClientRect()):!this.props.isActive&&e.isActive&&this.props.onHide()}render(){let e=(0,Q.e)(),t=(0,f.AH)(this.props.isNoninteractive?P().nonInteractiveButton:P().button,W.customHeaderButton,this.props.isNoninteractive?e.nonInteractiveButton:e.headerButton,{[e.activeHeaderButton]:this.props.isActive});const{iconData:n}=this.props;return this.props.isNoninteractive?b.createElement(z.e,{controlID:this.props.id,isActive:this.props.isActive,controlElement:this.buttonElement},b.createElement("div",{className:W.customHeaderButtonWrapper},b.createElement("span",{className:(0,f.AH)(t),role:"presentation",id:`CustomHeader_${this.props.id}`,ref:e=>this.buttonElement=e,onClick:null,"aria-label":this.props.ariaLabel,style:I(n)?{fontFamily:n.iconFontFamily}:void 0,title:this.props.ariaLabel,"aria-expanded":this.props.isActive},I(n)?b.createElement(f.rP,{fontSize:"16",fontValue:n.iconFontName}):n.element))):b.createElement(z.e,{controlID:this.props.id,isActive:this.props.isActive,controlElement:this.buttonElement},b.createElement("div",{className:W.customHeaderButtonWrapper},b.createElement("button",{className:(0,f.AH)(t),type:"button",role:"button",id:`CustomHeader_${this.props.id}`,ref:e=>this.buttonElement=e,onClick:this.onEntryPointClick,"aria-label":this.props.ariaLabel,style:I(n)?{fontFamily:n.iconFontFamily}:void 0,title:this.props.ariaLabel,"aria-expanded":this.props.isActive},I(n)?b.createElement(f.rP,{fontSize:"16",fontValue:n.iconFontName}):n.element)))}}const K=(0,g.connect)(((e,t)=>Object.assign(Object.assign({},t),{isActive:!!e.extensibilityState&&t.id===e.extensibilityState.activeButtonId})),(e=>({onToggleButtonState:t=>{e((0,f.ad)(t))}})))(Z);let V=[];let q=(0,f.OU)();class G{AddOrUpdateCustomHeaderButton(...e){for(let t=0;te.id===n.id));o>=0?V=[...V.slice(0,o),n,...V.slice(o+1)]:V.push(n)}let n=t.getState().shellInitDataState;if(n.layout){const e=(0,r.YF)();e.DefaultLayoutState.CustomHeaderButtons=V,e.ConfigureCustomHeaderButtons(n.layout,V),(0,r.NP)().invoke("ShellLayoutUpdated",n.layout)}else{const e=[...V].reverse().map((e=>{var t;return b.createElement(K,{key:e.id,id:e.id,iconData:null!==(t=e.iconData)&&void 0!==t?t:{iconFontName:e.iconFontName,iconFontFamily:e.iconFontFamily},onHide:e.onHide,onShow:e.onShow,isStateless:e.isStateless,ariaLabel:"function"==typeof e.ariaLabel?e.ariaLabel():e.ariaLabel})})),n=document.getElementById("O365_CustomHeaderButtonsContainer");if(!n)return;n.style.height="48px",v.render(b.createElement(g.Provider,{store:t},b.createElement("div",{className:W.customHeaderButtonsContainer},e)),n)}}(...e)}AddOrUpdateCustomFlexpane(e,t){let n=(0,f.OU)();n.dispatch((0,_.Ig)(e.flexPaneID)),null!=n.getState().extensibilityState.customFlexPanes[e.flexPaneID]&&n.dispatch((0,R.rv)(e.flexPaneID)),n.dispatch((0,R.mA)(e,t))}UpdateButtonState(e,t){const n=(0,f.OU)(),o=n.getState().extensibilityState;o.activeButtonId!==e||t?o.activeButtonId!==e&&t&&n.dispatch((0,f.ad)(e)):n.dispatch((0,f.ad)(""))}SetCustomHeaderButtonBadgeValue(e,t){q.dispatch(function(e,t){return{type:F,buttonID:e,badgeValue:t}}(e,t))}SetCustomHeaderButtonBadgeColor(e,t){q.dispatch(function(e,t){return{type:N,buttonID:e,badgeColors:t}}(e,t))}SetCustomHeaderButtonBadgeLabel(e,t){q.dispatch({type:B,buttonID:e,badgeLabel:t})}SetCustomHeaderButtonBadgeCharacter(e,t){q.dispatch(function(e,t){return{type:H,buttonID:e,badgeCharacter:t}}(e,t))}}function J(){f.h5.register(U),function(){let e=new G,t=window.O365Shell.Extensibility;window.O365Shell.Extensibility=e,t.applyCalls(e)}();let e,t=(0,f.OU)();function n(){let n=t.getState();if(e!==n.extensibilityState.customFlexPaneHash){Object.keys(n.extensibilityState.customFlexPanes).forEach((e=>{if(!n.flexPaneState.registeredProviders.some((t=>t.key===e))){const o=n.extensibilityState.customFlexPanes[e],r=n.extensibilityState.customFlexpaneWidth?n.extensibilityState.customFlexpaneWidth:h.xk;t.dispatch((0,h.ZM)({component:A,btnId:o.triggerControlID,shellControlID:o.triggerControlID,key:e,width:r}))}}))}e=n.extensibilityState.customFlexPaneHash}n(),(0,r.NP)().invoke("LazyComponentLoaded",m.J,E),t.subscribe(n)}var Y=s(53512),X=s(99542),$=s(71936);class ee extends b.Component{render(){let e={controlID:this.props.id,isVisible:this.props.isAvailable,ariaLabel:O.D.FeatureFlags_Title,affordanceMenuItemText:O.D.FeatureFlags_Title,iconID:"FeatureFlagsLogo",iconFontSize:w.LV.toString(),isActive:this.props.isActive,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.props.onClick,onDimensionsChanged:this.props.controlDimensionsChanged};return 0===this.props.renderContext?b.createElement(a.hp,Object.assign({},e)):b.createElement(a.vO,Object.assign({},e))}}const te=(0,g.connect)(((e,t)=>({id:t&&t.id,isAvailable:!0,isActive:e.flexPaneState&&"FeatureFlags"===e.flexPaneState.activeProviderKey,controlDimensionsChanged:t.controlDimensionsChanged})),(e=>({onClick:(t,n)=>{t.stopPropagation(),n.onClick&&n.onClick(t),e((0,f.ad)(t.currentTarget&&t.currentTarget.id)),e((0,h.IZ)("FeatureFlags"))}})),((e,t,n)=>{let o=Object.assign(Object.assign({},n),e);return Object.assign(Object.assign(Object.assign({},o),t),{onClick:e=>t.onClick(e,o),onDimensionsChanged:()=>t.onDimensionsChanged(o)})}))(ee),ne="suiteux-mecontrol.UPDATE_WORKLOAD_FEATURE_FLAG_LIST";let oe={featureFlagsState:function(e,t){return e||(e={enabled:!1,workloadFeatureFlagList:{}}),t.type===ne?function(e,t){let n=t;return Object.assign(Object.assign({},e),{workloadFeatureFlagList:n.workloadFeatureFlagList})}(e,t):e}};class re{AddFeatureFlags(e){e?(0,f.OU)().dispatch(function(e){return{type:ne,workloadFeatureFlagList:e}}(e)):(0,r.tZ)().tag("FeatureFlags_Shim_FeatureFlags_Param_Invalid",6)}SubscribeToFeatureFlagStatusChange(e){return(0,r.NP)().subscribe("FeatureFlagChanged",e,!1)}}function ie(){f.h5.register(oe),function(){let e=new re,t=window.O365Shell.FeatureFlags;window.O365Shell.FeatureFlags=e,t.applyCalls(e)}(),(0,r.NP)().subscribe("ShellDataUpdated",ae,!0)}function ae(e,t){if(t.FeatureFlagsEnabled){const e=(0,Y._)((()=>s.e("featureflags").then(s.bind(s,72848)).then((e=>e.FeatureFlagsFlexPanePanelConnector))));let t=(0,r.GJ)().layout,n={component:e,key:"FeatureFlags",width:h.xk};if(t){(0,r.NP)().invoke("LazyComponentLoaded",$.p,te),n.nativeControlID="FeatureFlags"}else n.btnId=X.DP;(0,f.OU)().dispatch((0,h.ZM)(n))}}var se=s(82453),ce=s(94361),le=s(66164),ue=s(8428),de=s(98052),pe=s(85348),fe=s(83496);class he extends b.Component{componentDidMount(){this.props.isAvailable&&(0,r.tZ)().perfMarker("MyDayTimeToInteractive")}render(){let e={controlID:this.props.id,isVisible:this.props.isAvailable,ariaLabel:O.D.MyDay,affordanceMenuItemText:O.D.MyDay,iconID:"EventToDoLogo",iconFontSize:w.LV.toString(),isActive:this.props.isActive,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.props.onClick,onDimensionsChanged:this.props.controlDimensionsChanged};return 0===this.props.renderContext?b.createElement(fe.h,Object.assign({},e)):b.createElement(pe.v,Object.assign({},e))}}const me=(0,g.connect)(((e,t)=>{var n;return{isAvailable:e.shellInitDataState.clientData.OpxEnabled&&e.shellInitDataState.clientData.MyDayOpxEnabled,id:null==t?void 0:t.id,isActive:"MyDay"===(null===(n=e.flexPaneState)||void 0===n?void 0:n.activeProviderKey),controlDimensionsChanged:t.controlDimensionsChanged}}),(e=>({onClick:(t,n)=>{var o;t.stopPropagation(),(0,r.tZ)().click("MyDay","NavBar",null,null,`Active state: ${n.isActive}, Render context: ${n.renderContext}`),e((0,f.ad)(null===(o=t.currentTarget)||void 0===o?void 0:o.id)),e((0,_.IZ)("MyDay")),n.onClick&&n.onClick(t)}})),((e,t,n)=>{let o=Object.assign(Object.assign({},n),e);return Object.assign(Object.assign(Object.assign({},o),t),{onClick:e=>t.onClick(e,o),onDimensionsChanged:()=>t.onDimensionsChanged(o)})}))(he);function ge(e,t){if(t.OpxEnabled&&t.MyDayOpxEnabled&&!(0,le.bi)(t.WorkloadId,e.CurrentMainLinkElementID)){(0,r.NP)().unsubscribe("ShellDataUpdated",ge);const e=()=>Promise.all([s.e("plus"),s.e("myday")]).then(s.bind(s,74386));let t={component:(0,Y._)((()=>e().then((e=>e.MyDayFlexPaneConnector)))),key:"MyDay",width:ue.x};(0,r.NP)().invoke("LazyComponentLoaded",de.q,me),t.nativeControlID="MyDay",(0,se.O)().dispatch((0,_.ZM)(t))}}var be=s(36558);class ve extends b.Component{componentDidMount(){this.props.isAvailable&&(0,r.tZ)().perfMarker("HelpTimeToInteractive")}render(){let e={controlID:this.props.id,isVisible:this.props.isAvailable,ariaLabel:O.D.Help_Title,affordanceMenuItemText:O.D.Help,iconID:this.props.flipHelpIcon?"HelpMirrored":"Help",iconFontSize:w.LV.toString(),isActive:this.props.isActive,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.props.onClick,onDimensionsChanged:this.props.controlDimensionsChanged};return 0===this.props.renderContext?b.createElement(a.hp,Object.assign({},e)):b.createElement(a.vO,Object.assign({},e))}}const ye=(0,g.connect)(((e,t)=>{var n,o;return{isAvailable:!(null===(o=null===(n=e.shellInitDataState)||void 0===n?void 0:n.clientData)||void 0===o?void 0:o.HelpPaneDisabled),id:t&&t.id,isActive:e.flexPaneState&&"Help"===e.flexPaneState.activeProviderKey,flipHelpIcon:e.headerState&&e.headerState.flipHelpIcon,controlDimensionsChanged:t.controlDimensionsChanged}}),(e=>({onClick:(t,n)=>{t.stopPropagation(),(0,r.tZ)().click("Help","NavBar",null,null,`Active state: ${n.isActive}, Render context: ${n.renderContext}`),e((0,f.ad)(t&&t.currentTarget&&t.currentTarget.id));let o=(0,r.GJ)();!o||null!=o.OnHelpButtonClick&&o.OnHelpButtonClick()||e((0,h.IZ)("Help")),n.onClick&&n.onClick(t)}})),((e,t,n)=>{let o=Object.assign(Object.assign({},n),e);return Object.assign(Object.assign(Object.assign({},o),t),{onClick:e=>t.onClick(e,o),onDimensionsChanged:()=>t.onDimensionsChanged(o)})}))(ve);var xe=s(51545);let Ae=null;function Ce(e,t){let n;n=t.EnableVNextFeedback?(0,Y._)((()=>Ae().then((e=>e.FeedbackButtonPanelConnector)))):(0,Y._)((()=>Ae().then((e=>e.FeedbackFlexPaneConnector))));const o=(0,r.GJ)(),i=!(!o.feedbackUiType||(0,xe.m)((0,xe.k)(o.feedbackUiType)));(0,f.OU)().dispatch((0,h.ZM)({component:n,key:"Feedback",width:h.xk,hideFlexPane:i}))}var Se=s(21226);class we extends b.Component{componentDidMount(){this.props.isAvailable&&(0,r.tZ)().perfMarker("SettingsTimeToInteractive")}render(){let e={controlID:this.props.id,isVisible:this.props.isAvailable,ariaLabel:O.D.Settings,affordanceMenuItemText:O.D.Settings,iconID:"Settings",iconFontSize:w.LV.toString(),isActive:this.props.isActive,isDarkModeEnabled:this.props.isDarkModeEnabled,onClick:this.props.onClick,onDimensionsChanged:this.props.controlDimensionsChanged};return 0===this.props.renderContext?b.createElement(a.hp,Object.assign({},e)):b.createElement(a.vO,Object.assign({},e))}}var ke=s(92720);const Pe=(0,g.connect)(((e,t)=>{let n=!1;if(e.shellInitDataState.layout)if(e.shellInitDataState.clientData.SettingsPaneEnabled){n=(0,ke.S)(Object.assign(Object.assign({},e.shellInitDataState.clientData),{CurrentMainLinkElementID:e.shellInitDataState.navBarData.CurrentMainLinkElementID}),null,e.settingsFlexPaneState.workloadSettingLinks).length>0}else n=!1;return{isAvailable:n,id:t&&t.id,isActive:e.flexPaneState&&"Settings"===e.flexPaneState.activeProviderKey,controlDimensionsChanged:t.controlDimensionsChanged}}),(e=>({onClick:(t,n)=>{t.stopPropagation(),(0,r.tZ)().click("Settings","NavBar",null,null,`Active state: ${n.isActive}, Render context: ${n.renderContext}`),n.onClick&&n.onClick(t),e((0,f.ad)(t.currentTarget&&t.currentTarget.id)),e((0,h.IZ)("Settings"))}})),((e,t,n)=>{let o=Object.assign(Object.assign({},n),e);return Object.assign(Object.assign(Object.assign({},o),t),{onClick:e=>t.onClick(e,o),onDimensionsChanged:()=>t.onDimensionsChanged(o)})}))(we);var Oe=s(84107),Ie=s(1742),De=/d{1,4}|D{3,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|W{1,2}|[LlopSZN]|"[^"]*"|'[^']*'/g,Te=/\b(?:[A-Z]{1,3}[A-Z][TC])(?:[-+]\d{4})?|((?:Australian )?(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time)\b/g,Ee=/[^-+\dA-Z]/g;function Le(e,t,n,o){if(1!==arguments.length||"string"!=typeof e||/\d/.test(e)||(t=e,e=void 0),(e=e||0===e?e:new Date)instanceof Date||(e=new Date(e)),isNaN(e))throw TypeError("Invalid date");var r=(t=String(Me[t]||t||Me.default)).slice(0,4);"UTC:"!==r&&"GMT:"!==r||(t=t.slice(4),n=!0,"GMT:"===r&&(o=!0));var i=function(){return n?"getUTC":"get"},a=function(){return e[i()+"Date"]()},s=function(){return e[i()+"Day"]()},c=function(){return e[i()+"Month"]()},l=function(){return e[i()+"FullYear"]()},u=function(){return e[i()+"Hours"]()},d=function(){return e[i()+"Minutes"]()},p=function(){return e[i()+"Seconds"]()},f=function(){return e[i()+"Milliseconds"]()},h=function(){return n?0:e.getTimezoneOffset()},m=function(){return He(e)},g={d:function(){return a()},dd:function(){return Ne(a())},ddd:function(){return Fe.dayNames[s()]},DDD:function(){return Be({y:l(),m:c(),d:a(),_:i(),dayName:Fe.dayNames[s()],short:!0})},dddd:function(){return Fe.dayNames[s()+7]},DDDD:function(){return Be({y:l(),m:c(),d:a(),_:i(),dayName:Fe.dayNames[s()+7]})},m:function(){return c()+1},mm:function(){return Ne(c()+1)},mmm:function(){return Fe.monthNames[c()]},mmmm:function(){return Fe.monthNames[c()+12]},yy:function(){return String(l()).slice(2)},yyyy:function(){return Ne(l(),4)},h:function(){return u()%12||12},hh:function(){return Ne(u()%12||12)},H:function(){return u()},HH:function(){return Ne(u())},M:function(){return d()},MM:function(){return Ne(d())},s:function(){return p()},ss:function(){return Ne(p())},l:function(){return Ne(f(),3)},L:function(){return Ne(Math.floor(f()/10))},t:function(){return u()<12?Fe.timeNames[0]:Fe.timeNames[1]},tt:function(){return u()<12?Fe.timeNames[2]:Fe.timeNames[3]},T:function(){return u()<12?Fe.timeNames[4]:Fe.timeNames[5]},TT:function(){return u()<12?Fe.timeNames[6]:Fe.timeNames[7]},Z:function(){return o?"GMT":n?"UTC":Ue(e)},o:function(){return(h()>0?"-":"+")+Ne(100*Math.floor(Math.abs(h())/60)+Math.abs(h())%60,4)},p:function(){return(h()>0?"-":"+")+Ne(Math.floor(Math.abs(h())/60),2)+":"+Ne(Math.floor(Math.abs(h())%60),2)},S:function(){return["th","st","nd","rd"][a()%10>3?0:(a()%100-a()%10!=10)*a()%10]},W:function(){return m()},WW:function(){return Ne(m())},N:function(){return je(e)}};return t.replace(De,(function(e){return e in g?g[e]():e.slice(1,e.length-1)}))}var Me={default:"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",paddedShortDate:"mm/dd/yyyy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:sso",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",expiresHeaderFormat:"ddd, dd mmm yyyy HH:MM:ss Z"},Fe={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],timeNames:["a","p","am","pm","A","P","AM","PM"]},Ne=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return String(e).padStart(t,"0")},Be=function(e){var t=e.y,n=e.m,o=e.d,r=e._,i=e.dayName,a=e.short,s=void 0!==a&&a,c=new Date,l=new Date;l.setDate(l[r+"Date"]()-1);var u=new Date;u.setDate(u[r+"Date"]()+1);return c[r+"FullYear"]()===t&&c[r+"Month"]()===n&&c[r+"Date"]()===o?s?"Tdy":"Today":l[r+"FullYear"]()===t&&l[r+"Month"]()===n&&l[r+"Date"]()===o?s?"Ysd":"Yesterday":u[r+"FullYear"]()===t&&u[r+"Month"]()===n&&u[r+"Date"]()===o?s?"Tmw":"Tomorrow":i},He=function(e){var t=new Date(e.getFullYear(),e.getMonth(),e.getDate());t.setDate(t.getDate()-(t.getDay()+6)%7+3);var n=new Date(t.getFullYear(),0,4);n.setDate(n.getDate()-(n.getDay()+6)%7+3);var o=t.getTimezoneOffset()-n.getTimezoneOffset();t.setHours(t.getHours()-o);var r=(t-n)/6048e5;return 1+Math.floor(r)},je=function(e){var t=e.getDay();return 0===t&&(t=7),t},Ue=function(e){return(String(e).match(Te)||[""]).pop().replace(Ee,"").replace(/GMT\+0000/g,"UTC")},Re=s(87894),_e=s(6936);const Qe="UTC",ze="tzone://Microsoft/Utc";class We{constructor(){this.timeZones=null,this.timeZoneOffsets=[]}get isInitialized(){return null!=this.timeZones&&this.timeZoneOffsets.length>0}initializeTimeZoneConverter(e){this.timeZoneOffsets=e,this.timeZones={}}convert(e,t,n){if(null===this.timeZones)throw Error("LoadTimeZoneOffsets must be called before convert.");if(e===ze&&(e=Qe),t===ze&&(t=Qe),null==n||e===t)return n;let o=qe.parseISO8601DateTime(n),r=0;e===Qe?(r=this.findOffsetInUTC(t,o),o=o.addMinutes(r)):t===Qe?(r=this.findOffsetInLocal(e,o),o=o.addMinutes(0-r)):(r=this.findOffsetInLocal(e,o),o=o.addMinutes(0-r),r=this.findOffsetInUTC(t,o),o=o.addMinutes(r));let i=-1===n.indexOf(".")?qe.generateISO8601DateTimeString(o):qe.generateISO8601DateTimeMsString(o);if(t===Qe)i+="Z";else{let e=Math.abs(r),t=Math.floor(e/60),n=e%60;i+=(r<0?"-":"+")+(t<10?"0"+t:t.toString())+":"+(n<10?"0"+n:n.toString())}return i}findOffsetInLocal(e,t){let n=this.getTimeZoneRanges(e);if(null==n)throw Error("Unknown time zone specified: "+e);for(let e of n)if(t.compare(e.localStart)>=0&&t.compare(e.localEnd)<0)return e.offset;throw new Error("Could not find an offset for this time stamp")}findOffsetInUTC(e,t){let n=this.getTimeZoneRanges(e);if(null==n)throw Error("Unknown time zone specified: "+e);for(let e of n)if(t.compare(e.utcStart)>=0&&t.compare(e.utcEnd)<0)return e.offset;throw new Error("Could not find an offset for this time stamp")}ConvertDateTimeMembersTimeZone(e,t,n,o,r,i){throw new Error("Unimplemented.")}getTimeZoneRanges(e){let t=this.timeZones[e];return null==t&&(this.loadOffsetsForTimezone(e),t=this.timeZones[e]),t}loadOffsetsForTimezone(e){let t;for(let n of this.timeZoneOffsets)if(e===n.TimeZoneId){t=n.OffsetRanges;break}if(!t||0===t.length)return void(0,r.tZ)().tag("TimeZoneConverter_NoIncomingOffsetRanges",6,e);let n=t.map((e=>({utcStart:qe.parseISO8601DateTime(e.UtcTime),offset:e.Offset})));n.forEach(((e,t)=>{if(0===t?(e.utcStart=qe.MinValue,e.localStart=qe.MinValue):e.localStart=e.utcStart.addMinutes(e.offset),t+1===n.length)e.utcEnd=qe.MaxValue,e.localEnd=qe.MaxValue;else{let o=n[t+1];e.utcEnd=o.utcStart,e.localEnd=e.utcEnd.addMinutes(Math.max(e.offset,o.offset))}})),this.timeZones[e]=n}}const Ze={TimeFormat:"hh:mm tt",DateFormat:"MM/dd/yyyy",TimeZone:"Pacific Standard Time",UserCulture:"default",WeekStartDay:0,FirstWeekOfYear:0,get TimeZoneOffsets(){return[{TimeZoneId:this.TimeZone,OffsetRanges:[{UtcTime:"1970-01-01T00:00:00Z",Offset:-180}]}]}};class Ke{constructor(e){let t=e.UserOptions||{},n=t.MailboxTimeZoneOffset;this.timeFormat=t.TimeFormat||Ze.TimeFormat,this.dateFormat=t.DateFormat||Ze.DateFormat,this.timeZone=t.TimeZone||Ze.TimeZone,this.userCulture=null!=e.SessionSettings?e.SessionSettings.UserCulture:Ze.UserCulture,this.weekStartDay=null!=t.WeekStartDay?t.WeekStartDay:Ze.WeekStartDay,this.firstWeekOfYear=null!=t.FirstWeekOfYear?t.FirstWeekOfYear:Ze.FirstWeekOfYear,this.timeZoneConverter=new We,this.timeZoneConverter.initializeTimeZoneConverter(null!=n?n:Ze.TimeZoneOffsets)}static get Instance(){return null==Ke.instance&&(Ke.instance=new Ke({})),Ke.instance}static populate(e){Ke.instance=new Ke(e)}}const Ve=864e13;class qe{constructor(e,t,n,o=0,r=0,i=0,a=0,s=0){if(t<0||t>11||n<0||n>31||o<0||o>23||r<0||r>59||i<0||i>59||a<0||a>999)throw new Error("Date part out of range.");this.localTime=new Date(Date.UTC(e,t,n,o,r,i,a)),this.utcOffsetInMinutes=null==s?qe.timeZoneConverter.findOffsetInLocal(qe.timeZone,qe.fromNativeDateTime(this.localTime)):s,qe.throwIfDateOutOfRange(this)}get date(){return this.localTime.getUTCDate()}get month(){return this.localTime.getUTCMonth()}get year(){return this.localTime.getUTCFullYear()}get hour(){return this.localTime.getUTCHours()}get second(){return this.localTime.getUTCSeconds()}get minute(){return this.localTime.getUTCMinutes()}get millisecond(){return this.localTime.getUTCMilliseconds()}static get timeZone(){return Ke.Instance.timeZone}static get Now(){let e=qe.timeZoneConverter.convert(Qe,qe.timeZone,qe.generateISO8601DateTimeMsStringWithOffset(qe.UTCNow));return qe.parseISO8601DateTime(e)}static get timeZoneConverter(){return Ke.Instance.timeZoneConverter}static get UTCNow(){return qe.fromNativeDateTime(new Date).toUTC()}static get now(){let e=qe.timeZoneConverter.convert(Qe,qe.timeZone,qe.generateISO8601DateTimeMsStringWithOffset(qe.UTCNow));return qe.parseISO8601DateTime(e)}static fromNativeDateTime(e){return new qe(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds(),-e.getTimezoneOffset())}format(e){return Le(this.localTime,qe.getDateFormatMask(e),!0)}static parseISO8601DateTime(e=""){let t=qe.isoRegex.exec(e);if(null==t||15!==t.length)throw new Error((0,u.JT)("Unexpected datetime format (value: {0}).",e));let n=parseInt(t[1],10),o=parseInt(t[2],10),r=parseInt(t[3],10),i=0,a=0,s=0,c=0,l=0;return null!=t[5]&&null!=t[6]&&null!=t[7]&&(i=parseInt(t[5],10),a=parseInt(t[6],10),s=parseInt(t[7],10),null!=t[9]&&(c=parseInt(t[9],10))),null!=t[10]&&"Z"!==t[10].toUpperCase()&&(l+=60*parseInt(t[13],10),l+=parseInt(t[14],10),"-"===t[12]&&(l=-l)),new qe(n,o-1,r,i,a,s,c,l)}static generateISO8601DateTimeString(e){return qe.generateISO8601DateTimeMsString(e,!1)}static generateISO8601DateTimeMsString(e,t=!0){const n="yyyy-MM-dd'T'HH:mm:ss"+(t?".l":"");return e.format(n)}static generateISO8601DateTimeMsStringWithOffset(e){return qe.generateISO8601DateTimeMsString(e)+e.getUtcOffsetDisplayString()}getUtcOffsetDisplayString(){if(0===this.utcOffsetInMinutes)return"Z";const e=Math.floor(Math.abs(this.utcOffsetInMinutes)/60),t=Math.abs(this.utcOffsetInMinutes)%60,n=this.utcOffsetInMinutes<0?"-":"+";return(0,u.JT)("{0}{1}:{2}",n,Ge(e,2),Ge(t,2))}static areDatePartsEqual(e,t){return null===e&&null===t||null!==e&&null!=t&&0===e.compareDatePart(t)}compare(e){return Re.throwOnNullOrUndefined(e,"other"),this.localTime.getTime()-e.localTime.getTime()}clone(){let e=new qe(0,0,0,0,0,0,0,0);return e.localTime.setTime(this.localTime.getTime()),e.utcOffsetInMinutes=this.utcOffsetInMinutes,e}addMilliseconds(e){qe.throwIfNotNumber(e);let t=this.clone();const n=t.localTime.getTime()+e;return t.localTime.setTime(n),qe.throwIfDateOutOfRange(t),t}Subtract(e){return Re.throwOnNullOrUndefined(e,"value"),this.localTime.getTime()-e.localTime.getTime()}addSeconds(e){return qe.throwIfNotNumber(e),this.addMilliseconds(1e3*e)}addMinutes(e){return qe.throwIfNotNumber(e),this.addMilliseconds(e*_e.I9)}addHours(e){return qe.throwIfNotNumber(e),this.addMilliseconds(e*_e.Q)}addDays(e){return qe.throwIfNotNumber(e),this.addMilliseconds(e*_e.Gj)}toUTC(){if(0===this.utcOffsetInMinutes)return this;let e=this.addMinutes(-this.utcOffsetInMinutes);return e.utcOffsetInMinutes=0,e}getNativeDateTime(){return new Date(this.toUTC().getUTCMilliseconds())}getUTCMilliseconds(){return this.toUTC().localTime.getTime()}GetMilliseconds(){return this.localTime.getTime()}compareDatePart(e){return qe.getDatePartHashValue(this)-qe.getDatePartHashValue(e)}static throwIfNotNumber(e){if("number"!=typeof e)throw Error("Argument must be of type number, but is type "+typeof e)}static throwIfDateOutOfRange(e){if(!qe.isValidDate(e))throw new Error("The resulting DateTime is less than MinValue or greater than MaxValue")}static isValidDate(e){return null!=e&&!isNaN(e.localTime.getTime())&&e.localTime.getTime()>=-864e13&&e.localTime.getTime()<=Ve}static getDatePartHashValue(e){return e.date+(e.month<<5)+(e.year<<9)}static getDateFormatMask(e){let t=!1;return e.replace(/[mMtT']/g,(e=>{if(t)return t="'"!==e,e;switch(e){case"'":return t=!0,e;case"m":return"M";case"M":return"m";case"t":return"T";case"T":return"t";default:return e}}))}}function Ge(e,t){let n=e.toString();for(;n.length"edu"===e.toLowerCase())),showMonarchColorThemes:n&&n.ShowMonarchColorThemes},languageAndRegionCardState:{selectedLanguage:"",selectedDateFormat:"",selectedTimeFormat:"",selectedTimeZone:"",languageChoices:[],timeZoneChoices:[],dateFormatChoices:[],timeFormatChoices:[],savedLanguage:"",savedDateFormat:"",savedTimeFormat:"",savedTimeZone:""},aboutCardState:{correlationID:o&&o.correlationID?o.correlationID:O.D.NotAvailable,sessionID:o&&o.sessionID?o.sessionID:O.D.NotAvailable,version:(null==o?void 0:o.version)?o.version:O.D.NotAvailable},workloadData:n,workloadId:n&&n.WorkloadId?n.WorkloadId:"",expandO365Settings:!1,workloadSettingLinksTitle:o&&o.workloadSettingsSubLinksTitle||(null==t?void 0:t.CurrentWorkloadSettingsSubLinksTitle)||(null==n?void 0:n.AppHeaderLinkText),workloadSettingLinks:[...(null==t?void 0:t.CurrentWorkloadSettingsSubLinks)||[],...o&&o.workloadSettingsSubLinks||[]],cards:[]})}function $e(e){const t=-1!==e.indexOf("HH");return new qe(2018,8,1,t?21:9,5).format(e).replace("Sep",O.D.SeptemberAbbrev).replace("September",O.D.September)}const et={settingsFlexPaneState:function(e,t){if(!e){const n=t.shellInitData.shellInitDataState;e=Xe(null,n.navBarData,n.clientData,n.renderSettings)}switch(t.type){case f.l5:const n=t;return Xe(e,n.navBarData,n.shellClientData,n.renderSettings);case Ye.cj:return function(e,t){const n=t,o=(0,f.K$)(e.workloadSettingLinks,(e=>e.Id===n.newWorkloadSettingLink.Id));if(!(0,Oe.l)(n.newWorkloadSettingLink))return e;const r=o>=0?Object.assign(Object.assign({},e),{workloadSettingLinks:[...e.workloadSettingLinks.slice(0,o),n.newWorkloadSettingLink,...e.workloadSettingLinks.slice(o+1)]}):Object.assign(Object.assign({},e),{workloadSettingLinks:e.workloadSettingLinks.concat(n.newWorkloadSettingLink)});return r}(e,t);case Ye.XL:return function(e,t){const n=t,o=(0,f.K$)(e.workloadSettingLinks,(e=>e.Id===n.settingLinkID));if(o>=0)return Object.assign(Object.assign({},e),{workloadSettingLinks:[...e.workloadSettingLinks.slice(0,o),...e.workloadSettingLinks.slice(o+1)]});return e}(e,t);case Ye.Rq:return function(e,t){const n=t,o=n.newWorkloadSettingsLinks.filter((e=>(0,Oe.l)(e)));if(0===o.length)return e;return Object.assign(Object.assign({},e),{workloadSettingLinks:o})}(e,t);case Ye._f:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{cards:n.cardData})}(e,t);case f.BE:return function(e,t){const n=t,o=(0,r.Vz)().getUserPersonalizationAllowed(),i=(0,Je.cv)(n.themeData||[],e.themeCardState.selectedThemeId,e.themeCardState.preferOfficeTheme,o);return Object.assign(Object.assign({},e),{themeCardState:Object.assign(Object.assign({},e.themeCardState),{themeData:i})})}(e,t);case f.bS:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{themeCardState:Object.assign(Object.assign({},e.themeCardState),{selectedThemeId:n.themeInfo.ThemeId||Ie.ux,preferOfficeTheme:n.themeInfo.PreferOfficeTheme})})}(e,t);case Ye.Eh:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedLanguage:n.selectedLanguage,savedLanguage:n.selectedLanguage})})}(e,t);case Ye.T9:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{languageChoices:n.languageChoices.map((e=>({id:e.Locale,text:e.DisplayName,language:e.Locale})))})})}(e,t);case Ye.nf:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedLanguage:n.selectedLanguage})})}(e,t);case Ye.wS:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedTimeZone:n.timeZoneChoice,selectedDateFormat:n.dateFormatChoice,selectedTimeFormat:n.timeFormatChoice,savedTimeZone:n.timeZoneChoice,savedDateFormat:n.dateFormatChoice,savedTimeFormat:n.timeFormatChoice})})}(e,t);case Ye.Kt:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{timeZoneChoices:n.timeZoneChoices.map((e=>({id:e.alias,text:e.displayName})))})})}(e,t);case Ye.u4:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedTimeZone:n.selectedTimeZone})})}(e,t);case Ye.uT:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{dateFormatChoices:n.dateFormatChoices.map((e=>({id:e,text:$e(e)})))})})}(e,t);case Ye.Ul:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedDateFormat:n.selectedDateFormat})})}(e,t);case Ye.jj:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{timeFormatChoices:n.timeFormatChoices.map((e=>({id:e,text:$e(e)})))})})}(e,t);case Ye.nt:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},e.languageAndRegionCardState),{selectedTimeFormat:n.selectedTimeFormat})})}(e,t);case Ye.ar:return function(e){const t=e.languageAndRegionCardState;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},t),{savedLanguage:t.selectedLanguage,savedTimeZone:t.selectedTimeZone,savedDateFormat:t.selectedDateFormat,savedTimeFormat:t.selectedTimeFormat})})}(e);case Ye.Xu:return function(e){const t=e.languageAndRegionCardState;return Object.assign(Object.assign({},e),{languageAndRegionCardState:Object.assign(Object.assign({},t),{selectedLanguage:t.savedLanguage,selectedTimeZone:t.savedTimeZone,selectedDateFormat:t.savedDateFormat,selectedTimeFormat:t.savedTimeFormat})})}(e);case Ye.dE:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{parentCardId:n.cardId})}(e,t);case Ye.oc:return function(e,t){const n=t;return Object.assign(Object.assign({},e),{expandO365Settings:n.isExpanded})}(e,t);default:return e}}};var tt=s(33106);class nt{AddOrUpdateWorkloadSettingLink(e){(0,f.OU)().dispatch((0,tt.Xm)(e))}RemoveWorkloadSettingLink(e){(0,f.OU)().dispatch((0,tt.G4)(e))}SetWorkloadSettingsLinks(e){(0,f.OU)().dispatch((0,tt.S)(e))}}function ot(e,t){let n=(0,r.GJ)().layout;const o=(0,f.OU)().getState().settingsFlexPaneState.workloadSettingLinks;if(!n){let n=t.SettingsPaneEnabled&&(0,ke.S)(Object.assign(Object.assign({},t),{CurrentMainLinkElementID:e.CurrentMainLinkElementID}),null,o).length>0,r=document.getElementById(X.Xf);r&&n&&(r.style.display="block")}}function rt(){const e=(0,r.GJ)();if(e.disableSettings)return;f.h5.register(et),function(){let e=new nt,t=window.O365Shell.Settings;window.O365Shell.Settings=e,t.applyCalls(e)}();const t=(0,Y._)((()=>Promise.all([s.e("plus"),s.e("extraflexpane")]).then(s.bind(s,324)).then((e=>e.SettingsFlexPanePanelConnector))));(0,r.NP)().subscribe("ShellDataUpdated",ot,!0);let n=e.layout,o={component:t,key:"Settings",width:h.xk};if(n){(0,r.NP)().invoke("LazyComponentLoaded",Se.$,Pe),o.nativeControlID="SettingsIcon"}else o.btnId=X.Xf;(0,f.OU)().dispatch((0,h.ZM)(o))}let it;s.nc=window.oneShellUxNonce,function(){let e=(0,r.l3)();s.e=e.loadChunk.bind(e)}(),(0,c.IJ)(),setTimeout((()=>(0,a.Nv)()));let at=!1,st=(0,r.NP)(),ct=(0,r.GJ)();const lt=()=>{if(!at){at=!0;try{(0,i.l)()}catch(e){(0,r.tZ)().exception("Init_ECS_Failed",6,e)}(0,h.M8)(),function(){let e=(0,r.GJ)();if(e.disableHelp)return;Ae=()=>Promise.all([s.e("plus"),s.e("extraflexpane")]).then(s.bind(s,96510));let t=window.O365Shell.NFD;t.registerShimCallback&&t.registerShimCallback((()=>{Ae()}),["OpenHelp","OpenFeedback"]);let n={component:(0,Y._)((()=>Ae().then((e=>e.HelpFlexPanePanelConnector)))),key:"Help",width:h.xk,overrideOnClick:e.OnHelpButtonClick};e.layout?((0,r.NP)().invoke("LazyComponentLoaded",be.V,ye),n.nativeControlID="HelpIcon"):n.btnId=X.hl;(0,f.OU)().dispatch((0,h.ZM)(n)),(0,r.NP)().subscribe("ShellDataUpdated",Ce,!0)}(),rt(),ie(),function(){let e=(0,r.GJ)();e&&e.layout&&e.layout.centerCustomizationRegion&&(0,ce.mD)("MyDay",e.layout.centerCustomizationRegion.children)&&(0,r.NP)().subscribe("ShellDataUpdated",ge,!0)}(),J();try{(0,i.l)().getConfig().then((e=>{}))}catch(e){(0,r.tZ)().exception("ECS_Config_Fetch_Failed",6,e)}!function(){(0,e.__awaiter)(this,void 0,void 0,(function*(){try{if(ct&&ct.enableSearchUX&&!0===ct.enableSearchUX){const e=yield s.e("search").then(s.bind(s,40374)).catch((e=>{var t;o(18,null===(t=ct.initialRenderData)||void 0===t?void 0:t.WorkloadId,e.ResourceName,e.Details)}));e&&e.initSearch&&e.initSearch()}}catch(e){}}))}(),(0,t.Qg)(),it=s.e("plus").then(s.bind(s,70796)).catch((e=>{var t;o(16,null===(t=ct.initialRenderData)||void 0===t?void 0:t.WorkloadId,e.ResourceName,e.Details)})),p(),(0,Je.Gy)(),(0,r.tZ)().perfMarker("shell_core_executioncomplete"),st.unsubscribe("StringsLoaded",lt),st.unsubscribe("StringsLoadedFailed",lt)}};setTimeout((()=>{st.subscribe("StringsLoadedFailed",lt,!0),st.subscribe("StringsLoaded",lt,!0)})),s(48358)}(),c=s.O(c)}(),HighResolutionTimingSupported&&(shellPerformance.mark("shell_core_end"),shellPerformance.measure("shell_core","shell_core_start","shell_core_end")); \ No newline at end of file diff --git a/utils.js b/utils.js index ec046a4..6960de4 100644 --- a/utils.js +++ b/utils.js @@ -1,280 +1,16 @@ -// src/utils.ts -import { timeoutManager } from "./timeoutManager.js"; -var isServer = typeof window === "undefined" || "Deno" in globalThis; -function noop() { -} -function functionalUpdate(updater, input) { - return typeof updater === "function" ? updater(input) : updater; -} -function isValidTimeout(value) { - return typeof value === "number" && value >= 0 && value !== Infinity; -} -function timeUntilStale(updatedAt, staleTime) { - return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0); -} -function resolveStaleTime(staleTime, query) { - return typeof staleTime === "function" ? staleTime(query) : staleTime; -} -function resolveEnabled(enabled, query) { - return typeof enabled === "function" ? enabled(query) : enabled; -} -function matchQuery(filters, query) { - const { - type = "all", - exact, - fetchStatus, - predicate, - queryKey, - stale - } = filters; - if (queryKey) { - if (exact) { - if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) { - return false; - } - } else if (!partialMatchKey(query.queryKey, queryKey)) { - return false; +// Waits for condition to return true. If it returns false initially, this function creates a +// MutationObserver that calls body() whenever the contents of the component change. +export const observeMutationsUntilConditionMet = (element, condition, body) => { + if (condition()) { + body(); + } + else { + const mutationObserver = new MutationObserver(() => { + if (condition()) { + body(); + mutationObserver.disconnect(); + } + }); + mutationObserver.observe(element, { childList: true, subtree: true }); } - } - if (type !== "all") { - const isActive = query.isActive(); - if (type === "active" && !isActive) { - return false; - } - if (type === "inactive" && isActive) { - return false; - } - } - if (typeof stale === "boolean" && query.isStale() !== stale) { - return false; - } - if (fetchStatus && fetchStatus !== query.state.fetchStatus) { - return false; - } - if (predicate && !predicate(query)) { - return false; - } - return true; -} -function matchMutation(filters, mutation) { - const { exact, status, predicate, mutationKey } = filters; - if (mutationKey) { - if (!mutation.options.mutationKey) { - return false; - } - if (exact) { - if (hashKey(mutation.options.mutationKey) !== hashKey(mutationKey)) { - return false; - } - } else if (!partialMatchKey(mutation.options.mutationKey, mutationKey)) { - return false; - } - } - if (status && mutation.state.status !== status) { - return false; - } - if (predicate && !predicate(mutation)) { - return false; - } - return true; -} -function hashQueryKeyByOptions(queryKey, options) { - const hashFn = options?.queryKeyHashFn || hashKey; - return hashFn(queryKey); -} -function hashKey(queryKey) { - return JSON.stringify( - queryKey, - (_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => { - result[key] = val[key]; - return result; - }, {}) : val - ); -} -function partialMatchKey(a, b) { - if (a === b) { - return true; - } - if (typeof a !== typeof b) { - return false; - } - if (a && b && typeof a === "object" && typeof b === "object") { - return Object.keys(b).every((key) => partialMatchKey(a[key], b[key])); - } - return false; -} -var hasOwn = Object.prototype.hasOwnProperty; -function replaceEqualDeep(a, b) { - if (a === b) { - return a; - } - const array = isPlainArray(a) && isPlainArray(b); - if (!array && !(isPlainObject(a) && isPlainObject(b))) return b; - const aItems = array ? a : Object.keys(a); - const aSize = aItems.length; - const bItems = array ? b : Object.keys(b); - const bSize = bItems.length; - const copy = array ? new Array(bSize) : {}; - let equalItems = 0; - for (let i = 0; i < bSize; i++) { - const key = array ? i : bItems[i]; - const aItem = a[key]; - const bItem = b[key]; - if (aItem === bItem) { - copy[key] = aItem; - if (array ? i < aSize : hasOwn.call(a, key)) equalItems++; - continue; - } - if (aItem === null || bItem === null || typeof aItem !== "object" || typeof bItem !== "object") { - copy[key] = bItem; - continue; - } - const v = replaceEqualDeep(aItem, bItem); - copy[key] = v; - if (v === aItem) equalItems++; - } - return aSize === bSize && equalItems === aSize ? a : copy; -} -function shallowEqualObjects(a, b) { - if (!b || Object.keys(a).length !== Object.keys(b).length) { - return false; - } - for (const key in a) { - if (a[key] !== b[key]) { - return false; - } - } - return true; -} -function isPlainArray(value) { - return Array.isArray(value) && value.length === Object.keys(value).length; -} -function isPlainObject(o) { - if (!hasObjectPrototype(o)) { - return false; - } - const ctor = o.constructor; - if (ctor === void 0) { - return true; - } - const prot = ctor.prototype; - if (!hasObjectPrototype(prot)) { - return false; - } - if (!prot.hasOwnProperty("isPrototypeOf")) { - return false; - } - if (Object.getPrototypeOf(o) !== Object.prototype) { - return false; - } - return true; -} -function hasObjectPrototype(o) { - return Object.prototype.toString.call(o) === "[object Object]"; -} -function sleep(timeout) { - return new Promise((resolve) => { - timeoutManager.setTimeout(resolve, timeout); - }); -} -function replaceData(prevData, data, options) { - if (typeof options.structuralSharing === "function") { - return options.structuralSharing(prevData, data); - } else if (options.structuralSharing !== false) { - if (process.env.NODE_ENV !== "production") { - try { - return replaceEqualDeep(prevData, data); - } catch (error) { - console.error( - `Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}` - ); - throw error; - } - } - return replaceEqualDeep(prevData, data); - } - return data; -} -function keepPreviousData(previousData) { - return previousData; -} -function addToEnd(items, item, max = 0) { - const newItems = [...items, item]; - return max && newItems.length > max ? newItems.slice(1) : newItems; -} -function addToStart(items, item, max = 0) { - const newItems = [item, ...items]; - return max && newItems.length > max ? newItems.slice(0, -1) : newItems; -} -var skipToken = Symbol(); -function ensureQueryFn(options, fetchOptions) { - if (process.env.NODE_ENV !== "production") { - if (options.queryFn === skipToken) { - console.error( - `Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '${options.queryHash}'` - ); - } - } - if (!options.queryFn && fetchOptions?.initialPromise) { - return () => fetchOptions.initialPromise; - } - if (!options.queryFn || options.queryFn === skipToken) { - return () => Promise.reject(new Error(`Missing queryFn: '${options.queryHash}'`)); - } - return options.queryFn; -} -function shouldThrowError(throwOnError, params) { - if (typeof throwOnError === "function") { - return throwOnError(...params); - } - return !!throwOnError; -} -function addConsumeAwareSignal(object, getSignal, onCancelled) { - let consumed = false; - let signal; - Object.defineProperty(object, "signal", { - enumerable: true, - get: () => { - signal ??= getSignal(); - if (consumed) { - return signal; - } - consumed = true; - if (signal.aborted) { - onCancelled(); - } else { - signal.addEventListener("abort", onCancelled, { once: true }); - } - return signal; - } - }); - return object; -} -export { - addConsumeAwareSignal, - addToEnd, - addToStart, - ensureQueryFn, - functionalUpdate, - hashKey, - hashQueryKeyByOptions, - isPlainArray, - isPlainObject, - isServer, - isValidTimeout, - keepPreviousData, - matchMutation, - matchQuery, - noop, - partialMatchKey, - replaceData, - replaceEqualDeep, - resolveEnabled, - resolveStaleTime, - shallowEqualObjects, - shouldThrowError, - skipToken, - sleep, - timeUntilStale }; -//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/viewer.mjs b/viewer.mjs new file mode 100644 index 0000000..5e9469a --- /dev/null +++ b/viewer.mjs @@ -0,0 +1,16934 @@ +/** + * @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.445 + * pdfjsBuild = ec5330f78 + */ +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; + +;// ./web/pdfjs.js +const { + AbortException, + AnnotationEditorLayer, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationEditorUIManager, + AnnotationLayer, + AnnotationMode, + AnnotationType, + applyOpacity, + build, + ColorPicker, + createValidAbsoluteUrl, + CSSConstants, + DOMSVGFactory, + DrawLayer, + FeatureTest, + fetchData, + findContrastColor, + getDocument, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getRGB, + getUuid, + getXfaPageViewport, + GlobalWorkerOptions, + ImageKind, + InvalidPDFException, + isDataScheme, + isPdfFile, + isValidExplicitDest, + MathClamp, + noContextMenu, + normalizeUnicode, + OPS, + OutputScale, + PasswordResponses, + PDFDataRangeTransport, + PDFDateString, + PDFWorker, + PermissionFlag, + PixelsPerInch, + RenderingCancelledException, + renderRichText, + 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) { + if (scrollMatches) { + const elementWidth = element.getBoundingClientRect().width; + const padding = MathClamp((parent.clientWidth - elementWidth) / 2, 20, 400); + offsetX += spot.left - padding; + } else { + 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 = Math.fround; + +;// ./web/app_options.js +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: null, + 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: "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/pdf-alt-text", + 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 + }, + commentLearnMoreUrl: { + value: "https://support.mozilla.org/%LOCALE%/kb/view-pdf-files-firefox-or-choose-another-viewer#w_add-a-comment-to-a-pdf", + 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 + }, + enableOptimizedPartialRendering: { + value: false, + 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: "resource://pdf.js/web/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: "resource://pdf.js/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: false, + kind: OptionKind.API + OptionKind.VIEWER + OptionKind.PREFERENCE + }, + enableXfa: { + value: true, + kind: OptionKind.API + OptionKind.PREFERENCE + }, + fontExtraProperties: { + value: false, + kind: OptionKind.API + }, + iccUrl: { + value: "resource://pdf.js/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: "resource://pdf.js/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: "resource://pdf.js/web/wasm/", + kind: OptionKind.API + }, + workerPort: { + value: globalThis.pdfjsPreloadedWorker || null, + kind: OptionKind.WORKER + }, + workerSrc: { + value: "resource://pdf.js/build/pdf.worker.mjs", + kind: OptionKind.WORKER + } +}; +class AppOptions { + static eventBus; + static #opts = new Map(); + static { + for (const name in defaultOptions) { + this.#opts.set(name, defaultOptions[name].value); + } + } + 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) { + 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 + }); + } + goToXY(pageNumber, x, y, options = {}) { + this.pdfViewer.scrollPageIntoView({ + pageNumber, + destArray: [null, { + name: "XYZ" + }, x, y], + ignoreDestinationZoom: true, + ...options + }); + } + 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")); + } + if (!params.has("filename") || !params.has("filedest")) { + return; + } + hash = params.get("filedest"); + } + 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) { + super.dispatch(eventName, data); + if (this.#isInAutomation) { + const detail = Object.create(null); + if (data) { + for (const key in data) { + const value = data[key]; + if (key === "source") { + if (value === window || value === document) { + return; + } + continue; + } + detail[key] = value; + } + } + const event = new CustomEvent(eventName, { + bubbles: true, + cancelable: true, + detail + }); + document.dispatchEvent(event); + } + if (this.#globalEventNames?.has(eventName)) { + this.#externalServices.dispatchGlobalEvent({ + eventName, + detail: data + }); + } + } +} + +;// ./web/external_services.js +class BaseExternalServices { + updateFindControlState(data) {} + updateFindMatchesCount(data) {} + initPassiveLoading() {} + reportTelemetry(data) {} + reportText(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: "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/pdf-alt-text", + annotationEditorMode: 0, + annotationMode: 2, + capCanvasAreaFactor: 200, + commentLearnMoreUrl: "https://support.mozilla.org/%LOCALE%/kb/view-pdf-files-firefox-or-choose-another-viewer#w_add-a-comment-to-a-pdf", + cursorToolOnLoad: 0, + defaultZoomDelay: 400, + defaultZoomValue: "", + disablePageLabels: false, + enableAltText: false, + enableAltTextModelDownload: true, + enableAutoLinking: true, + enableComment: false, + enableGuessAltText: true, + enableHighlightFloatingButton: false, + enableNewAltTextWhenAddingImage: true, + enableOptimizedPartialRendering: false, + 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: false, + enableXfa: true + }); + #initializedPromise = null; + constructor() { + this.#initializedPromise = this._readFromStorage(this.#defaults).then(({ + browserPrefs, + prefs + }) => { + AppOptions.setAll({ + ...browserPrefs, + ...prefs + }, true); + }); + window.addEventListener("updatedPreference", async ({ + detail: { + name, + value + } + }) => { + await this.#initializedPromise; + AppOptions.setAll({ + [name]: value + }, true); + }); + } + async _writeToStorage(prefObj) { + throw new Error("Not implemented: _writeToStorage"); + } + async _readFromStorage(prefObj) { + throw new Error("Not implemented: _readFromStorage"); + } + async reset() { + throw new Error("Please use `about:config` to change preferences."); + } + async set(name, value) { + await this.#initializedPromise; + AppOptions.setAll({ + [name]: value + }, true); + await this._writeToStorage({ + [name]: AppOptions.get(name) + }); + } + async get(name) { + throw new Error("Not implemented: get"); + } + get initializedPromise() { + return this.#initializedPromise; + } +} + +;// ./web/l10n.js +class L10n { + #dir; + #elements; + #lang; + #l10n; + constructor({ + lang, + isRTL + }, l10n = null) { + this.#lang = L10n.#fixupLangCode(lang); + this.#l10n = l10n; + this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr"; + } + _setL10n(l10n) { + this.#l10n = l10n; + } + getLanguage() { + return this.#lang; + } + getDirection() { + return this.#dir; + } + async get(ids, args = null, fallback) { + if (Array.isArray(ids)) { + ids = ids.map(id => ({ + id + })); + const messages = await this.#l10n.formatMessages(ids); + return messages.map(message => message.value); + } + const messages = await this.#l10n.formatMessages([{ + id: ids, + args + }]); + return messages[0]?.value || fallback; + } + async translate(element) { + (this.#elements ||= new Set()).add(element); + try { + this.#l10n.connectRoot(element); + await this.#l10n.translateRoots(); + } catch {} + } + async translateOnce(element) { + try { + await this.#l10n.translateElements([element]); + } catch (ex) { + console.error("translateOnce:", ex); + } + } + async destroy() { + if (this.#elements) { + for (const element of this.#elements) { + this.#l10n.disconnectRoot(element); + } + this.#elements.clear(); + this.#elements = null; + } + this.#l10n.pauseObserving(); + } + pause() { + this.#l10n.pauseObserving(); + } + resume() { + this.#l10n.resumeObserving(); + } + static #fixupLangCode(langCode) { + langCode = langCode?.toLowerCase() || "en-us"; + const PARTIAL_LANG_CODES = { + en: "en-us", + es: "es-es", + fy: "fy-nl", + ga: "ga-ie", + gu: "gu-in", + hi: "hi-in", + hy: "hy-am", + nb: "nb-no", + ne: "ne-np", + nn: "nn-no", + pa: "pa-in", + pt: "pt-pt", + sv: "sv-se", + zh: "zh-cn" + }; + return PARTIAL_LANG_CODES[langCode] || langCode; + } + static #isRTL(lang) { + const shortCode = lang.split("-", 1)[0]; + return ["ar", "he", "fa", "ps", "ur"].includes(shortCode); + } +} +const GenericL10n = null; + +;// ./web/firefoxcom.js + + + + + + +let viewerApp = { + initialized: false +}; +function initCom(app) { + viewerApp = app; +} +class FirefoxCom { + static requestAsync(action, data) { + return new Promise(resolve => { + this.request(action, data, resolve); + }); + } + static request(action, data, callback = null) { + const request = document.createTextNode(""); + if (callback) { + request.addEventListener("pdf.js.response", event => { + const response = event.detail.response; + event.target.remove(); + callback(response); + }, { + once: true + }); + } + document.documentElement.append(request); + const sender = new CustomEvent("pdf.js.message", { + bubbles: true, + cancelable: false, + detail: { + action, + data, + responseExpected: !!callback + } + }); + request.dispatchEvent(sender); + } +} +class DownloadManager { + #openBlobUrls = new WeakMap(); + downloadData(data, filename, contentType) { + const blobUrl = URL.createObjectURL(new Blob([data], { + type: contentType + })); + FirefoxCom.request("download", { + blobUrl, + originalUrl: blobUrl, + filename, + isAttachment: true + }); + } + openOrDownloadData(data, filename, dest = null) { + const isPdfData = isPdfFile(filename); + const contentType = isPdfData ? "application/pdf" : ""; + if (isPdfData) { + let blobUrl = this.#openBlobUrls.get(data); + if (!blobUrl) { + blobUrl = URL.createObjectURL(new Blob([data], { + type: contentType + })); + this.#openBlobUrls.set(data, blobUrl); + } + let viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename); + if (dest) { + viewerUrl += `&filedest=${escape(dest)}`; + } + try { + window.open(viewerUrl); + return true; + } catch (ex) { + console.error("openOrDownloadData:", ex); + URL.revokeObjectURL(blobUrl); + this.#openBlobUrls.delete(data); + } + } + this.downloadData(data, filename, contentType); + return false; + } + download(data, url, filename) { + const blobUrl = data ? URL.createObjectURL(new Blob([data], { + type: "application/pdf" + })) : null; + FirefoxCom.request("download", { + blobUrl, + originalUrl: url, + filename + }); + } +} +class Preferences extends BasePreferences { + async _readFromStorage(prefObj) { + return FirefoxCom.requestAsync("getPreferences", prefObj); + } + async _writeToStorage(prefObj) { + return FirefoxCom.requestAsync("setPreferences", prefObj); + } +} +(function listenFindEvents() { + const events = ["find", "findagain", "findhighlightallchange", "findcasesensitivitychange", "findentirewordchange", "findbarclose", "finddiacriticmatchingchange"]; + const findLen = "find".length; + const handleEvent = function ({ + type, + detail + }) { + if (!viewerApp.initialized) { + return; + } + if (type === "findbarclose") { + viewerApp.eventBus.dispatch(type, { + source: window + }); + return; + } + viewerApp.eventBus.dispatch("find", { + source: window, + type: type.substring(findLen), + query: detail.query, + caseSensitive: !!detail.caseSensitive, + entireWord: !!detail.entireWord, + highlightAll: !!detail.highlightAll, + findPrevious: !!detail.findPrevious, + matchDiacritics: !!detail.matchDiacritics + }); + }; + for (const event of events) { + window.addEventListener(event, handleEvent); + } +})(); +(function listenZoomEvents() { + const events = ["zoomin", "zoomout", "zoomreset"]; + const handleEvent = function ({ + type, + detail + }) { + if (!viewerApp.initialized) { + return; + } + if (type === "zoomreset" && viewerApp.pdfViewer.currentScaleValue === DEFAULT_SCALE_VALUE) { + return; + } + viewerApp.eventBus.dispatch(type, { + source: window + }); + }; + for (const event of events) { + window.addEventListener(event, handleEvent); + } +})(); +(function listenSaveEvent() { + const handleEvent = function ({ + type, + detail + }) { + if (!viewerApp.initialized) { + return; + } + viewerApp.eventBus.dispatch("download", { + source: window + }); + }; + window.addEventListener("save", handleEvent); +})(); +(function listenEditingEvent() { + const handleEvent = function ({ + detail + }) { + if (!viewerApp.initialized) { + return; + } + viewerApp.eventBus.dispatch("editingaction", { + source: window, + name: detail.name + }); + }; + window.addEventListener("editingaction", handleEvent); +})(); +class FirefoxComDataRangeTransport extends PDFDataRangeTransport { + requestDataRange(begin, end) { + FirefoxCom.request("requestDataRange", { + begin, + end + }); + } + abort() { + FirefoxCom.request("abortLoading", null); + } +} +class FirefoxScripting { + static async createSandbox(data) { + const success = await FirefoxCom.requestAsync("createSandbox", data); + if (!success) { + throw new Error("Cannot create sandbox."); + } + } + static async dispatchEventInSandbox(event) { + FirefoxCom.request("dispatchEventInSandbox", event); + } + static async destroySandbox() { + FirefoxCom.request("destroySandbox", null); + } +} +class MLManager { + #abortSignal = null; + #enabled = null; + #eventBus = null; + #ready = null; + #requestResolvers = null; + hasProgress = false; + static #AI_ALT_TEXT_MODEL_NAME = "moz-image-to-text"; + constructor({ + altTextLearnMoreUrl, + enableGuessAltText, + enableAltTextModelDownload + }) { + this.altTextLearnMoreUrl = altTextLearnMoreUrl; + this.enableAltTextModelDownload = enableAltTextModelDownload; + this.enableGuessAltText = enableGuessAltText; + } + setEventBus(eventBus, abortSignal) { + this.#eventBus = eventBus; + this.#abortSignal = abortSignal; + eventBus._on("enablealttextmodeldownload", ({ + value + }) => { + if (this.enableAltTextModelDownload === value) { + return; + } + if (value) { + this.downloadModel("altText"); + } else { + this.deleteModel("altText"); + } + }, { + signal: abortSignal + }); + eventBus._on("enableguessalttext", ({ + value + }) => { + this.toggleService("altText", value); + }, { + signal: abortSignal + }); + } + async isEnabledFor(name) { + return this.enableGuessAltText && !!(await this.#enabled?.get(name)); + } + isReady(name) { + return this.#ready?.has(name) ?? false; + } + async deleteModel(name) { + if (name !== "altText" || !this.enableAltTextModelDownload) { + return; + } + this.enableAltTextModelDownload = false; + this.#ready?.delete(name); + this.#enabled?.delete(name); + await this.toggleService("altText", false); + await FirefoxCom.requestAsync("mlDelete", MLManager.#AI_ALT_TEXT_MODEL_NAME); + } + async loadModel(name) { + if (name === "altText" && this.enableAltTextModelDownload) { + await this.#loadAltTextEngine(false); + } + } + async downloadModel(name) { + if (name !== "altText" || this.enableAltTextModelDownload) { + return null; + } + this.enableAltTextModelDownload = true; + return this.#loadAltTextEngine(true); + } + async guess(data) { + if (data?.name !== "altText") { + return null; + } + const resolvers = this.#requestResolvers ||= new Set(); + const resolver = Promise.withResolvers(); + resolvers.add(resolver); + data.service = MLManager.#AI_ALT_TEXT_MODEL_NAME; + FirefoxCom.requestAsync("mlGuess", data).then(response => { + if (resolvers.has(resolver)) { + resolver.resolve(response); + resolvers.delete(resolver); + } + }).catch(reason => { + if (resolvers.has(resolver)) { + resolver.reject(reason); + resolvers.delete(resolver); + } + }); + return resolver.promise; + } + async #cancelAllRequests() { + if (!this.#requestResolvers) { + return; + } + for (const resolver of this.#requestResolvers) { + resolver.resolve({ + cancel: true + }); + } + this.#requestResolvers.clear(); + this.#requestResolvers = null; + } + async toggleService(name, enabled) { + if (name !== "altText" || this.enableGuessAltText === enabled) { + return; + } + this.enableGuessAltText = enabled; + if (enabled) { + if (this.enableAltTextModelDownload) { + await this.#loadAltTextEngine(false); + } + } else { + this.#cancelAllRequests(); + } + } + async #loadAltTextEngine(listenToProgress) { + if (this.#enabled?.has("altText")) { + return; + } + this.#ready ||= new Set(); + const promise = FirefoxCom.requestAsync("loadAIEngine", { + service: MLManager.#AI_ALT_TEXT_MODEL_NAME, + listenToProgress + }).then(ok => { + if (ok) { + this.#ready.add("altText"); + } + return ok; + }); + (this.#enabled ||= new Map()).set("altText", promise); + if (listenToProgress) { + const ac = new AbortController(); + const signal = AbortSignal.any([this.#abortSignal, ac.signal]); + this.hasProgress = true; + window.addEventListener("loadAIEngineProgress", ({ + detail + }) => { + this.#eventBus.dispatch("loadaiengineprogress", { + source: this, + detail + }); + if (detail.finished) { + ac.abort(); + this.hasProgress = false; + } + }, { + signal + }); + promise.then(ok => { + if (!ok) { + ac.abort(); + this.hasProgress = false; + } + }); + } + await promise; + } +} +class SignatureStorage { + #eventBus = null; + #signatures = null; + #signal = null; + constructor(eventBus, signal) { + this.#eventBus = eventBus; + this.#signal = signal; + } + #handleSignature(data) { + return FirefoxCom.requestAsync("handleSignature", data); + } + async getAll() { + if (this.#signal) { + window.addEventListener("storedSignaturesChanged", () => { + this.#signatures = null; + this.#eventBus?.dispatch("storedsignatureschanged", { + source: this + }); + }, { + signal: this.#signal + }); + this.#signal = null; + } + if (!this.#signatures) { + this.#signatures = new Map(); + const data = await this.#handleSignature({ + action: "get" + }); + if (data) { + for (const { + uuid, + description, + signatureData + } of data) { + this.#signatures.set(uuid, { + description, + signatureData + }); + } + } + } + return this.#signatures; + } + async isFull() { + return (await this.size()) === 5; + } + async size() { + return (await this.getAll()).size; + } + async create(data) { + if (await this.isFull()) { + return null; + } + const uuid = await this.#handleSignature({ + action: "create", + ...data + }); + if (!uuid) { + return null; + } + this.#signatures.set(uuid, data); + return uuid; + } + async delete(uuid) { + const signatures = await this.getAll(); + if (!signatures.has(uuid)) { + return false; + } + if (await this.#handleSignature({ + action: "delete", + uuid + })) { + signatures.delete(uuid); + return true; + } + return false; + } +} +class ExternalServices extends BaseExternalServices { + updateFindControlState(data) { + FirefoxCom.request("updateFindControlState", data); + } + updateFindMatchesCount(data) { + FirefoxCom.request("updateFindMatchesCount", data); + } + initPassiveLoading() { + let pdfDataRangeTransport; + window.addEventListener("message", function windowMessage(e) { + if (e.source !== null) { + console.warn("Rejected untrusted message from " + e.origin); + return; + } + const args = e.data; + if (typeof args !== "object" || !("pdfjsLoadAction" in args)) { + return; + } + switch (args.pdfjsLoadAction) { + case "supportsRangedLoading": + if (args.done && !args.data) { + viewerApp._documentError(null); + break; + } + pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename); + viewerApp.open({ + range: pdfDataRangeTransport + }); + break; + case "range": + pdfDataRangeTransport.onDataRange(args.begin, args.chunk); + break; + case "rangeProgress": + pdfDataRangeTransport.onDataProgress(args.loaded); + break; + case "progressiveRead": + pdfDataRangeTransport.onDataProgressiveRead(args.chunk); + pdfDataRangeTransport.onDataProgress(args.loaded, args.total); + break; + case "progressiveDone": + pdfDataRangeTransport?.onDataProgressiveDone(); + break; + case "progress": + viewerApp.progress(args.loaded / args.total); + break; + case "complete": + if (!args.data) { + viewerApp._documentError(null, { + message: args.errorCode + }); + break; + } + viewerApp.open({ + data: args.data, + filename: args.filename + }); + break; + } + }); + FirefoxCom.request("initPassiveLoading", null); + } + reportTelemetry(data) { + FirefoxCom.request("reportTelemetry", data); + } + reportText(data) { + FirefoxCom.request("reportText", data); + } + updateEditorStates(data) { + FirefoxCom.request("updateEditorStates", data); + } + async createL10n() { + await document.l10n.ready; + return new L10n(AppOptions.get("localeProperties"), document.l10n); + } + createScripting() { + return FirefoxScripting; + } + createSignatureStorage(eventBus, signal) { + return new SignatureStorage(eventBus, signal); + } + dispatchGlobalEvent(event) { + FirefoxCom.request("dispatchGlobalEvent", event); + } +} + +;// ./web/new_alt_text_manager.js + +class NewAltTextManager { + #boundCancel = this.#cancel.bind(this); + #createAutomaticallyButton; + #currentEditor = null; + #cancelButton; + #descriptionContainer; + #dialog; + #disclaimer; + #downloadModel; + #downloadModelDescription; + #eventBus; + #firstTime = false; + #guessedAltText; + #hasAI = null; + #isEditing = null; + #imagePreview; + #imageData; + #isAILoading = false; + #wasAILoading = false; + #learnMore; + #notNowButton; + #overlayManager; + #textarea; + #title; + #uiManager; + #previousAltText = null; + constructor({ + descriptionContainer, + dialog, + imagePreview, + cancelButton, + disclaimer, + notNowButton, + saveButton, + textarea, + learnMore, + errorCloseButton, + createAutomaticallyButton, + downloadModel, + downloadModelDescription, + title + }, overlayManager, eventBus) { + this.#cancelButton = cancelButton; + this.#createAutomaticallyButton = createAutomaticallyButton; + this.#descriptionContainer = descriptionContainer; + this.#dialog = dialog; + this.#disclaimer = disclaimer; + this.#notNowButton = notNowButton; + this.#imagePreview = imagePreview; + this.#textarea = textarea; + this.#learnMore = learnMore; + this.#title = title; + this.#downloadModel = downloadModel; + this.#downloadModelDescription = downloadModelDescription; + this.#overlayManager = overlayManager; + this.#eventBus = eventBus; + dialog.addEventListener("close", this.#close.bind(this)); + dialog.addEventListener("contextmenu", event => { + if (event.target !== this.#textarea) { + event.preventDefault(); + } + }); + cancelButton.addEventListener("click", this.#boundCancel); + notNowButton.addEventListener("click", this.#boundCancel); + saveButton.addEventListener("click", this.#save.bind(this)); + errorCloseButton.addEventListener("click", () => { + this.#toggleError(false); + }); + createAutomaticallyButton.addEventListener("click", async () => { + const checked = createAutomaticallyButton.getAttribute("aria-pressed") !== "true"; + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.alt_text.ai_generation_check", + data: { + status: checked + } + }); + if (this.#uiManager) { + this.#uiManager.setPreference("enableGuessAltText", checked); + await this.#uiManager.mlManager.toggleService("altText", checked); + } + this.#toggleGuessAltText(checked, false); + }); + textarea.addEventListener("focus", () => { + this.#wasAILoading = this.#isAILoading; + this.#toggleLoading(false); + this.#toggleTitleAndDisclaimer(); + }); + textarea.addEventListener("blur", () => { + if (!textarea.value) { + this.#toggleLoading(this.#wasAILoading); + } + this.#toggleTitleAndDisclaimer(); + }); + textarea.addEventListener("input", () => { + this.#toggleTitleAndDisclaimer(); + }); + textarea.addEventListener("keydown", e => { + if ((e.ctrlKey || e.metaKey) && e.key === "Enter" && !saveButton.disabled) { + this.#save(); + } + }); + eventBus._on("enableguessalttext", ({ + value + }) => { + this.#toggleGuessAltText(value, false); + }); + this.#overlayManager.register(dialog); + this.#learnMore.addEventListener("click", () => { + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.alt_text.info", + data: { + topic: "alt_text" + } + }); + }); + } + #toggleLoading(value) { + if (!this.#uiManager || this.#isAILoading === value) { + return; + } + this.#isAILoading = value; + this.#descriptionContainer.classList.toggle("loading", value); + } + #toggleError(value) { + if (!this.#uiManager) { + return; + } + this.#dialog.classList.toggle("error", value); + } + async #toggleGuessAltText(value, isInitial = false) { + if (!this.#uiManager) { + return; + } + this.#dialog.classList.toggle("aiDisabled", !value); + this.#createAutomaticallyButton.setAttribute("aria-pressed", value); + if (value) { + const { + altTextLearnMoreUrl + } = this.#uiManager.mlManager; + if (altTextLearnMoreUrl) { + this.#learnMore.href = altTextLearnMoreUrl; + } + this.#mlGuessAltText(isInitial); + } else { + this.#toggleLoading(false); + this.#isAILoading = false; + this.#toggleTitleAndDisclaimer(); + } + } + #toggleNotNow() { + this.#notNowButton.classList.toggle("hidden", !this.#firstTime); + this.#cancelButton.classList.toggle("hidden", this.#firstTime); + } + #toggleAI(value) { + if (!this.#uiManager || this.#hasAI === value) { + return; + } + this.#hasAI = value; + this.#dialog.classList.toggle("noAi", !value); + this.#toggleTitleAndDisclaimer(); + } + #toggleTitleAndDisclaimer() { + const visible = this.#isAILoading || this.#guessedAltText && this.#guessedAltText === this.#textarea.value; + this.#disclaimer.hidden = !visible; + const isEditing = this.#isAILoading || !!this.#textarea.value; + if (this.#isEditing === isEditing) { + return; + } + this.#isEditing = isEditing; + this.#title.setAttribute("data-l10n-id", isEditing ? "pdfjs-editor-new-alt-text-dialog-edit-label" : "pdfjs-editor-new-alt-text-dialog-add-label"); + } + async #mlGuessAltText(isInitial) { + if (this.#isAILoading) { + return; + } + if (this.#textarea.value) { + return; + } + if (isInitial && this.#previousAltText !== null) { + return; + } + this.#guessedAltText = this.#currentEditor.guessedAltText; + if (this.#previousAltText === null && this.#guessedAltText) { + this.#addAltText(this.#guessedAltText); + return; + } + this.#toggleLoading(true); + this.#toggleTitleAndDisclaimer(); + let hasError = false; + try { + const altText = await this.#currentEditor.mlGuessAltText(this.#imageData, false); + if (altText) { + this.#guessedAltText = altText; + this.#wasAILoading = this.#isAILoading; + if (this.#isAILoading) { + this.#addAltText(altText); + } + } + } catch (e) { + console.error(e); + hasError = true; + } + this.#toggleLoading(false); + this.#toggleTitleAndDisclaimer(); + if (hasError && this.#uiManager) { + this.#toggleError(true); + } + } + #addAltText(altText) { + if (!this.#uiManager || this.#textarea.value) { + return; + } + this.#textarea.value = altText; + this.#toggleTitleAndDisclaimer(); + } + #setProgress() { + this.#downloadModel.classList.toggle("hidden", false); + const callback = async ({ + detail: { + finished, + total, + totalLoaded + } + }) => { + const ONE_MEGA_BYTES = 1e6; + totalLoaded = Math.min(0.99 * total, totalLoaded); + const totalSize = this.#downloadModelDescription.ariaValueMax = Math.round(total / ONE_MEGA_BYTES); + const downloadedSize = this.#downloadModelDescription.ariaValueNow = Math.round(totalLoaded / ONE_MEGA_BYTES); + this.#downloadModelDescription.setAttribute("data-l10n-args", JSON.stringify({ + totalSize, + downloadedSize + })); + if (!finished) { + return; + } + this.#eventBus._off("loadaiengineprogress", callback); + this.#downloadModel.classList.toggle("hidden", true); + this.#toggleAI(true); + if (!this.#uiManager) { + return; + } + const { + mlManager + } = this.#uiManager; + mlManager.toggleService("altText", true); + this.#toggleGuessAltText(await mlManager.isEnabledFor("altText"), true); + }; + this.#eventBus._on("loadaiengineprogress", callback); + } + async editAltText(uiManager, editor, firstTime) { + if (this.#currentEditor || !editor) { + return; + } + if (firstTime && editor.hasAltTextData()) { + editor.altTextFinish(); + return; + } + this.#firstTime = firstTime; + let { + mlManager + } = uiManager; + let hasAI = !!mlManager; + this.#toggleTitleAndDisclaimer(); + if (mlManager && !mlManager.isReady("altText")) { + hasAI = false; + if (mlManager.hasProgress) { + this.#setProgress(); + } else { + mlManager = null; + } + } else { + this.#downloadModel.classList.toggle("hidden", true); + } + const isAltTextEnabledPromise = mlManager?.isEnabledFor("altText"); + this.#currentEditor = editor; + this.#uiManager = uiManager; + this.#uiManager.removeEditListeners(); + ({ + altText: this.#previousAltText + } = editor.altTextData); + this.#textarea.value = this.#previousAltText ?? ""; + const AI_MAX_IMAGE_DIMENSION = 224; + const MAX_PREVIEW_DIMENSION = 180; + let canvas, width, height; + if (mlManager) { + ({ + canvas, + width, + height, + imageData: this.#imageData + } = editor.copyCanvas(AI_MAX_IMAGE_DIMENSION, MAX_PREVIEW_DIMENSION, true)); + if (hasAI) { + this.#toggleGuessAltText(await isAltTextEnabledPromise, true); + } + } else { + ({ + canvas, + width, + height + } = editor.copyCanvas(AI_MAX_IMAGE_DIMENSION, MAX_PREVIEW_DIMENSION, false)); + } + canvas.setAttribute("role", "presentation"); + const { + style + } = canvas; + style.width = `${width}px`; + style.height = `${height}px`; + this.#imagePreview.append(canvas); + this.#toggleNotNow(); + this.#toggleAI(hasAI); + this.#toggleError(false); + try { + await this.#overlayManager.open(this.#dialog); + } catch (ex) { + this.#close(); + throw ex; + } + } + #cancel() { + this.#currentEditor.altTextData = { + cancel: true + }; + const altText = this.#textarea.value.trim(); + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.alt_text.dismiss", + data: { + alt_text_type: altText ? "present" : "empty", + flow: this.#firstTime ? "image_add" : "alt_text_edit" + } + }); + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.image_added", + data: { + alt_text_modal: true, + alt_text_type: "skipped" + } + }); + this.#finish(); + } + #finish() { + this.#overlayManager.closeIfActive(this.#dialog); + } + #close() { + const canvas = this.#imagePreview.firstElementChild; + canvas.remove(); + canvas.width = canvas.height = 0; + this.#imageData = null; + this.#toggleLoading(false); + this.#uiManager?.addEditListeners(); + this.#currentEditor.altTextFinish(); + this.#uiManager?.setSelected(this.#currentEditor); + this.#currentEditor = null; + this.#uiManager = null; + } + #extractWords(text) { + return new Set(text.toLowerCase().split(/[^\p{L}\p{N}]+/gu).filter(x => !!x)); + } + #save() { + const altText = this.#textarea.value.trim(); + this.#currentEditor.altTextData = { + altText, + decorative: false + }; + this.#currentEditor.altTextData.guessedAltText = this.#guessedAltText; + if (this.#guessedAltText && this.#guessedAltText !== altText) { + const guessedWords = this.#extractWords(this.#guessedAltText); + const words = this.#extractWords(altText); + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.alt_text.user_edit", + data: { + total_words: guessedWords.size, + words_removed: guessedWords.difference(words).size, + words_added: words.difference(guessedWords).size + } + }); + } + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.image_added", + data: { + alt_text_modal: true, + alt_text_type: altText ? "present" : "empty" + } + }); + this.#currentEditor._reportTelemetry({ + action: "pdfjs.image.alt_text.save", + data: { + alt_text_type: altText ? "present" : "empty", + flow: this.#firstTime ? "image_add" : "alt_text_edit" + } + }); + this.#finish(); + } + destroy() { + this.#uiManager = null; + this.#finish(); + } +} +class ImageAltTextSettings { + #aiModelSettings; + #createModelButton; + #downloadModelButton; + #dialog; + #eventBus; + #mlManager; + #overlayManager; + #showAltTextDialogButton; + constructor({ + dialog, + createModelButton, + aiModelSettings, + learnMore, + closeButton, + deleteModelButton, + downloadModelButton, + showAltTextDialogButton + }, overlayManager, eventBus, mlManager) { + this.#dialog = dialog; + this.#aiModelSettings = aiModelSettings; + this.#createModelButton = createModelButton; + this.#downloadModelButton = downloadModelButton; + this.#showAltTextDialogButton = showAltTextDialogButton; + this.#overlayManager = overlayManager; + this.#eventBus = eventBus; + this.#mlManager = mlManager; + const { + altTextLearnMoreUrl + } = mlManager; + if (altTextLearnMoreUrl) { + learnMore.href = altTextLearnMoreUrl; + } + dialog.addEventListener("contextmenu", noContextMenu); + createModelButton.addEventListener("click", async e => { + const checked = this.#togglePref("enableGuessAltText", e); + await mlManager.toggleService("altText", checked); + this.#reportTelemetry({ + type: "stamp", + action: "pdfjs.image.alt_text.settings_ai_generation_check", + data: { + status: checked + } + }); + }); + showAltTextDialogButton.addEventListener("click", e => { + const checked = this.#togglePref("enableNewAltTextWhenAddingImage", e); + this.#reportTelemetry({ + type: "stamp", + action: "pdfjs.image.alt_text.settings_edit_alt_text_check", + data: { + status: checked + } + }); + }); + deleteModelButton.addEventListener("click", this.#delete.bind(this, true)); + downloadModelButton.addEventListener("click", this.#download.bind(this, true)); + closeButton.addEventListener("click", this.#finish.bind(this)); + learnMore.addEventListener("click", () => { + this.#reportTelemetry({ + type: "stamp", + action: "pdfjs.image.alt_text.info", + data: { + topic: "ai_generation" + } + }); + }); + eventBus._on("enablealttextmodeldownload", ({ + value + }) => { + if (value) { + this.#download(false); + } else { + this.#delete(false); + } + }); + this.#overlayManager.register(dialog); + } + #reportTelemetry(data) { + this.#eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data + } + }); + } + async #download(isFromUI = false) { + if (isFromUI) { + this.#downloadModelButton.disabled = true; + const span = this.#downloadModelButton.firstElementChild; + span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-downloading-model-button"); + await this.#mlManager.downloadModel("altText"); + span.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-settings-download-model-button"); + this.#createModelButton.disabled = false; + this.#setPref("enableGuessAltText", true); + this.#mlManager.toggleService("altText", true); + this.#setPref("enableAltTextModelDownload", true); + this.#downloadModelButton.disabled = false; + } + this.#aiModelSettings.classList.toggle("download", false); + this.#createModelButton.setAttribute("aria-pressed", true); + } + async #delete(isFromUI = false) { + if (isFromUI) { + await this.#mlManager.deleteModel("altText"); + this.#setPref("enableGuessAltText", false); + this.#setPref("enableAltTextModelDownload", false); + } + this.#aiModelSettings.classList.toggle("download", true); + this.#createModelButton.disabled = true; + this.#createModelButton.setAttribute("aria-pressed", false); + } + async open({ + enableGuessAltText, + enableNewAltTextWhenAddingImage + }) { + const { + enableAltTextModelDownload + } = this.#mlManager; + this.#createModelButton.disabled = !enableAltTextModelDownload; + this.#createModelButton.setAttribute("aria-pressed", enableAltTextModelDownload && enableGuessAltText); + this.#showAltTextDialogButton.setAttribute("aria-pressed", enableNewAltTextWhenAddingImage); + this.#aiModelSettings.classList.toggle("download", !enableAltTextModelDownload); + await this.#overlayManager.open(this.#dialog); + this.#reportTelemetry({ + type: "stamp", + action: "pdfjs.image.alt_text.settings_displayed" + }); + } + #togglePref(name, { + target + }) { + const checked = target.getAttribute("aria-pressed") !== "true"; + this.#setPref(name, checked); + target.setAttribute("aria-pressed", checked); + return checked; + } + #setPref(name, value) { + this.#eventBus.dispatch("setpreference", { + source: this, + name, + value + }); + } + #finish() { + this.#overlayManager.closeIfActive(this.#dialog); + } +} + +;// ./web/alt_text_manager.js + +class AltTextManager { + #clickAC = null; + #currentEditor = null; + #cancelButton; + #dialog; + #eventBus; + #hasUsedPointer = false; + #optionDescription; + #optionDecorative; + #overlayManager; + #saveButton; + #textarea; + #uiManager; + #previousAltText = null; + #resizeAC = null; + #svgElement = null; + #rectElement = null; + #container; + #telemetryData = null; + constructor({ + dialog, + optionDescription, + optionDecorative, + textarea, + cancelButton, + saveButton + }, container, overlayManager, eventBus) { + this.#dialog = dialog; + this.#optionDescription = optionDescription; + this.#optionDecorative = optionDecorative; + this.#textarea = textarea; + this.#cancelButton = cancelButton; + this.#saveButton = saveButton; + this.#overlayManager = overlayManager; + this.#eventBus = eventBus; + this.#container = container; + const onUpdateUIState = this.#updateUIState.bind(this); + dialog.addEventListener("close", this.#close.bind(this)); + dialog.addEventListener("contextmenu", event => { + if (event.target !== this.#textarea) { + event.preventDefault(); + } + }); + cancelButton.addEventListener("click", this.#finish.bind(this)); + saveButton.addEventListener("click", this.#save.bind(this)); + optionDescription.addEventListener("change", onUpdateUIState); + optionDecorative.addEventListener("change", onUpdateUIState); + textarea.addEventListener("keydown", e => { + if ((e.ctrlKey || e.metaKey) && e.key === "Enter" && !saveButton.disabled) { + this.#save(); + } + }); + this.#overlayManager.register(dialog); + } + #createSVGElement() { + if (this.#svgElement) { + return; + } + const svgFactory = new DOMSVGFactory(); + const svg = this.#svgElement = svgFactory.createElement("svg"); + svg.setAttribute("width", "0"); + svg.setAttribute("height", "0"); + const defs = svgFactory.createElement("defs"); + svg.append(defs); + const mask = svgFactory.createElement("mask"); + defs.append(mask); + mask.setAttribute("id", "alttext-manager-mask"); + mask.setAttribute("maskContentUnits", "objectBoundingBox"); + let rect = svgFactory.createElement("rect"); + mask.append(rect); + rect.setAttribute("fill", "white"); + rect.setAttribute("width", "1"); + rect.setAttribute("height", "1"); + rect.setAttribute("x", "0"); + rect.setAttribute("y", "0"); + rect = this.#rectElement = svgFactory.createElement("rect"); + mask.append(rect); + rect.setAttribute("fill", "black"); + this.#dialog.append(svg); + } + async editAltText(uiManager, editor) { + if (this.#currentEditor || !editor) { + return; + } + this.#createSVGElement(); + this.#hasUsedPointer = false; + this.#clickAC = new AbortController(); + const clickOpts = { + signal: this.#clickAC.signal + }, + onClick = this.#onClick.bind(this); + for (const element of [this.#optionDescription, this.#optionDecorative, this.#textarea, this.#saveButton, this.#cancelButton]) { + element.addEventListener("click", onClick, clickOpts); + } + const { + altText, + decorative + } = editor.altTextData; + if (decorative === true) { + this.#optionDecorative.checked = true; + this.#optionDescription.checked = false; + } else { + this.#optionDecorative.checked = false; + this.#optionDescription.checked = true; + } + this.#previousAltText = this.#textarea.value = altText?.trim() || ""; + this.#updateUIState(); + this.#currentEditor = editor; + this.#uiManager = uiManager; + this.#uiManager.removeEditListeners(); + this.#resizeAC = new AbortController(); + this.#eventBus._on("resize", this.#setPosition.bind(this), { + signal: this.#resizeAC.signal + }); + try { + await this.#overlayManager.open(this.#dialog); + this.#setPosition(); + } catch (ex) { + this.#close(); + throw ex; + } + } + #setPosition() { + if (!this.#currentEditor) { + return; + } + const dialog = this.#dialog; + const { + style + } = dialog; + const { + x: containerX, + y: containerY, + width: containerW, + height: containerH + } = this.#container.getBoundingClientRect(); + const { + innerWidth: windowW, + innerHeight: windowH + } = window; + const { + width: dialogW, + height: dialogH + } = dialog.getBoundingClientRect(); + const { + x, + y, + width, + height + } = this.#currentEditor.getClientDimensions(); + const MARGIN = 10; + const isLTR = this.#uiManager.direction === "ltr"; + const xs = Math.max(x, containerX); + const xe = Math.min(x + width, containerX + containerW); + const ys = Math.max(y, containerY); + const ye = Math.min(y + height, containerY + containerH); + this.#rectElement.setAttribute("width", `${(xe - xs) / windowW}`); + this.#rectElement.setAttribute("height", `${(ye - ys) / windowH}`); + this.#rectElement.setAttribute("x", `${xs / windowW}`); + this.#rectElement.setAttribute("y", `${ys / windowH}`); + let left = null; + let top = Math.max(y, 0); + top += Math.min(windowH - (top + dialogH), 0); + if (isLTR) { + if (x + width + MARGIN + dialogW < windowW) { + left = x + width + MARGIN; + } else if (x > dialogW + MARGIN) { + left = x - dialogW - MARGIN; + } + } else if (x > dialogW + MARGIN) { + left = x - dialogW - MARGIN; + } else if (x + width + MARGIN + dialogW < windowW) { + left = x + width + MARGIN; + } + if (left === null) { + top = null; + left = Math.max(x, 0); + left += Math.min(windowW - (left + dialogW), 0); + if (y > dialogH + MARGIN) { + top = y - dialogH - MARGIN; + } else if (y + height + MARGIN + dialogH < windowH) { + top = y + height + MARGIN; + } + } + if (top !== null) { + dialog.classList.add("positioned"); + if (isLTR) { + style.left = `${left}px`; + } else { + style.right = `${windowW - left - dialogW}px`; + } + style.top = `${top}px`; + } else { + dialog.classList.remove("positioned"); + style.left = ""; + style.top = ""; + } + } + #finish() { + this.#overlayManager.closeIfActive(this.#dialog); + } + #close() { + this.#currentEditor._reportTelemetry(this.#telemetryData || { + action: "alt_text_cancel", + alt_text_keyboard: !this.#hasUsedPointer + }); + this.#telemetryData = null; + this.#removeOnClickListeners(); + this.#uiManager?.addEditListeners(); + this.#resizeAC?.abort(); + this.#resizeAC = null; + this.#currentEditor.altTextFinish(); + this.#currentEditor = null; + this.#uiManager = null; + } + #updateUIState() { + this.#textarea.disabled = this.#optionDecorative.checked; + } + #save() { + const altText = this.#textarea.value.trim(); + const decorative = this.#optionDecorative.checked; + this.#currentEditor.altTextData = { + altText, + decorative + }; + this.#telemetryData = { + action: "alt_text_save", + alt_text_description: !!altText, + alt_text_edit: !!this.#previousAltText && this.#previousAltText !== altText, + alt_text_decorative: decorative, + alt_text_keyboard: !this.#hasUsedPointer + }; + this.#finish(); + } + #onClick(evt) { + if (evt.detail === 0) { + return; + } + this.#hasUsedPointer = true; + this.#removeOnClickListeners(); + } + #removeOnClickListeners() { + this.#clickAC?.abort(); + this.#clickAC = null; + } + destroy() { + this.#uiManager = null; + this.#finish(); + this.#svgElement?.remove(); + this.#svgElement = this.#rectElement = null; + } +} + +;// ./web/annotation_editor_params.js + +class AnnotationEditorParams { + constructor(options, eventBus) { + this.eventBus = eventBus; + this.#bindListeners(options); + } + #bindListeners({ + editorFreeTextFontSize, + editorFreeTextColor, + editorInkColor, + editorInkThickness, + editorInkOpacity, + editorStampAddImage, + editorFreeHighlightThickness, + editorHighlightShowAll, + editorSignatureAddSignature + }) { + const { + eventBus + } = this; + const dispatchEvent = (typeStr, value) => { + eventBus.dispatch("switchannotationeditorparams", { + source: this, + type: AnnotationEditorParamsType[typeStr], + value + }); + }; + editorFreeTextFontSize.addEventListener("input", function () { + dispatchEvent("FREETEXT_SIZE", this.valueAsNumber); + }); + editorFreeTextColor.addEventListener("input", function () { + dispatchEvent("FREETEXT_COLOR", this.value); + }); + editorInkColor.addEventListener("input", function () { + dispatchEvent("INK_COLOR", this.value); + }); + editorInkThickness.addEventListener("input", function () { + dispatchEvent("INK_THICKNESS", this.valueAsNumber); + }); + editorInkOpacity.addEventListener("input", function () { + dispatchEvent("INK_OPACITY", this.valueAsNumber); + }); + editorStampAddImage.addEventListener("click", () => { + eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data: { + action: "pdfjs.image.add_image_click" + } + } + }); + dispatchEvent("CREATE"); + }); + editorFreeHighlightThickness.addEventListener("input", function () { + dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber); + }); + editorHighlightShowAll.addEventListener("click", function () { + const checked = this.getAttribute("aria-pressed") === "true"; + this.setAttribute("aria-pressed", !checked); + dispatchEvent("HIGHLIGHT_SHOW_ALL", !checked); + }); + editorSignatureAddSignature.addEventListener("click", () => { + dispatchEvent("CREATE"); + }); + eventBus._on("annotationeditorparamschanged", evt => { + for (const [type, value] of evt.details) { + switch (type) { + case AnnotationEditorParamsType.FREETEXT_SIZE: + editorFreeTextFontSize.value = value; + break; + case AnnotationEditorParamsType.FREETEXT_COLOR: + editorFreeTextColor.value = value; + break; + case AnnotationEditorParamsType.INK_COLOR: + editorInkColor.value = value; + break; + case AnnotationEditorParamsType.INK_THICKNESS: + editorInkThickness.value = value; + break; + case AnnotationEditorParamsType.INK_OPACITY: + editorInkOpacity.value = value; + break; + case AnnotationEditorParamsType.HIGHLIGHT_COLOR: + eventBus.dispatch("mainhighlightcolorpickerupdatecolor", { + source: this, + value + }); + break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + editorFreeHighlightThickness.value = value; + break; + case AnnotationEditorParamsType.HIGHLIGHT_FREE: + editorFreeHighlightThickness.disabled = !value; + break; + case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL: + editorHighlightShowAll.setAttribute("aria-pressed", value); + break; + } + } + }); + } +} + +;// ./web/caret_browsing.js +const PRECISION = 1e-1; +class CaretBrowsingMode { + #mainContainer; + #toolBarHeight = 0; + #viewerContainer; + constructor(abortSignal, mainContainer, viewerContainer, toolbarContainer) { + this.#mainContainer = mainContainer; + this.#viewerContainer = viewerContainer; + if (!toolbarContainer) { + return; + } + this.#toolBarHeight = toolbarContainer.getBoundingClientRect().height; + const toolbarObserver = new ResizeObserver(entries => { + for (const entry of entries) { + if (entry.target === toolbarContainer) { + this.#toolBarHeight = Math.floor(entry.borderBoxSize[0].blockSize); + break; + } + } + }); + toolbarObserver.observe(toolbarContainer); + abortSignal.addEventListener("abort", () => toolbarObserver.disconnect(), { + once: true + }); + } + #isOnSameLine(rect1, rect2) { + const top1 = rect1.y; + const bot1 = rect1.bottom; + const mid1 = rect1.y + rect1.height / 2; + const top2 = rect2.y; + const bot2 = rect2.bottom; + const mid2 = rect2.y + rect2.height / 2; + return top1 <= mid2 && mid2 <= bot1 || top2 <= mid1 && mid1 <= bot2; + } + #isUnderOver(rect, x, y, isUp) { + const midY = rect.y + rect.height / 2; + return (isUp ? y >= midY : y <= midY) && rect.x - PRECISION <= x && x <= rect.right + PRECISION; + } + #isVisible(rect) { + return rect.top >= this.#toolBarHeight && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth); + } + #getCaretPosition(selection, isUp) { + const { + focusNode, + focusOffset + } = selection; + const range = document.createRange(); + range.setStart(focusNode, focusOffset); + range.setEnd(focusNode, focusOffset); + const rect = range.getBoundingClientRect(); + return [rect.x, isUp ? rect.top : rect.bottom]; + } + static #caretPositionFromPoint(x, y) { + return document.caretPositionFromPoint(x, y); + } + #setCaretPositionHelper(selection, caretX, select, element, rect) { + rect ||= element.getBoundingClientRect(); + if (caretX <= rect.x + PRECISION) { + if (select) { + selection.extend(element.firstChild, 0); + } else { + selection.setPosition(element.firstChild, 0); + } + return; + } + if (rect.right - PRECISION <= caretX) { + const { + lastChild + } = element; + if (select) { + selection.extend(lastChild, lastChild.length); + } else { + selection.setPosition(lastChild, lastChild.length); + } + return; + } + const midY = rect.y + rect.height / 2; + let caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY); + let parentElement = caretPosition.offsetNode?.parentElement; + if (parentElement && parentElement !== element) { + const elementsAtPoint = document.elementsFromPoint(caretX, midY); + const savedVisibilities = []; + for (const el of elementsAtPoint) { + if (el === element) { + break; + } + const { + style + } = el; + savedVisibilities.push([el, style.visibility]); + style.visibility = "hidden"; + } + caretPosition = CaretBrowsingMode.#caretPositionFromPoint(caretX, midY); + parentElement = caretPosition.offsetNode?.parentElement; + for (const [el, visibility] of savedVisibilities) { + el.style.visibility = visibility; + } + } + if (parentElement !== element) { + if (select) { + selection.extend(element.firstChild, 0); + } else { + selection.setPosition(element.firstChild, 0); + } + return; + } + if (select) { + selection.extend(caretPosition.offsetNode, caretPosition.offset); + } else { + selection.setPosition(caretPosition.offsetNode, caretPosition.offset); + } + } + #setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX) { + if (this.#isVisible(newLineElementRect)) { + this.#setCaretPositionHelper(selection, caretX, select, newLineElement, newLineElementRect); + return; + } + this.#mainContainer.addEventListener("scrollend", this.#setCaretPositionHelper.bind(this, selection, caretX, select, newLineElement, null), { + once: true + }); + newLineElement.scrollIntoView(); + } + #getNodeOnNextPage(textLayer, isUp) { + while (true) { + const page = textLayer.closest(".page"); + const pageNumber = parseInt(page.getAttribute("data-page-number")); + const nextPage = isUp ? pageNumber - 1 : pageNumber + 1; + textLayer = this.#viewerContainer.querySelector(`.page[data-page-number="${nextPage}"] .textLayer`); + if (!textLayer) { + return null; + } + const walker = document.createTreeWalker(textLayer, NodeFilter.SHOW_TEXT); + const node = isUp ? walker.lastChild() : walker.firstChild(); + if (node) { + return node; + } + } + } + moveCaret(isUp, select) { + const selection = document.getSelection(); + if (selection.rangeCount === 0) { + return; + } + const { + focusNode + } = selection; + const focusElement = focusNode.nodeType !== Node.ELEMENT_NODE ? focusNode.parentElement : focusNode; + const root = focusElement.closest(".textLayer"); + if (!root) { + return; + } + const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT); + walker.currentNode = focusNode; + const focusRect = focusElement.getBoundingClientRect(); + let newLineElement = null; + const nodeIterator = (isUp ? walker.previousSibling : walker.nextSibling).bind(walker); + while (nodeIterator()) { + const element = walker.currentNode.parentElement; + if (!this.#isOnSameLine(focusRect, element.getBoundingClientRect())) { + newLineElement = element; + break; + } + } + if (!newLineElement) { + const node = this.#getNodeOnNextPage(root, isUp); + if (!node) { + return; + } + if (select) { + const lastNode = (isUp ? walker.firstChild() : walker.lastChild()) || focusNode; + selection.extend(lastNode, isUp ? 0 : lastNode.length); + const range = document.createRange(); + range.setStart(node, isUp ? node.length : 0); + range.setEnd(node, isUp ? node.length : 0); + selection.addRange(range); + return; + } + const [caretX] = this.#getCaretPosition(selection, isUp); + const { + parentElement + } = node; + this.#setCaretPosition(select, selection, parentElement, parentElement.getBoundingClientRect(), caretX); + return; + } + const [caretX, caretY] = this.#getCaretPosition(selection, isUp); + const newLineElementRect = newLineElement.getBoundingClientRect(); + if (this.#isUnderOver(newLineElementRect, caretX, caretY, isUp)) { + this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX); + return; + } + while (nodeIterator()) { + const element = walker.currentNode.parentElement; + const elementRect = element.getBoundingClientRect(); + if (!this.#isOnSameLine(newLineElementRect, elementRect)) { + break; + } + if (this.#isUnderOver(elementRect, caretX, caretY, isUp)) { + this.#setCaretPosition(select, selection, element, elementRect, caretX); + return; + } + } + this.#setCaretPosition(select, selection, newLineElement, newLineElementRect, caretX); + } +} + +;// ./web/sidebar.js + +class Sidebar { + #minWidth = 0; + #maxWidth = 0; + #initialWidth = 0; + #width = 0; + #coefficient; + #visible = false; + constructor({ + sidebar, + resizer, + toggleButton + }, ltr, isResizerOnTheLeft) { + this._sidebar = sidebar; + this.#coefficient = ltr === isResizerOnTheLeft ? -1 : 1; + const style = window.getComputedStyle(sidebar); + this.#minWidth = parseFloat(style.getPropertyValue("--sidebar-min-width")); + this.#maxWidth = parseFloat(style.getPropertyValue("--sidebar-max-width")); + this.#initialWidth = this.#width = parseFloat(style.getPropertyValue("--sidebar-width")); + this.#makeSidebarResizable(resizer, isResizerOnTheLeft); + toggleButton.addEventListener("click", this.toggle.bind(this)); + sidebar.hidden = true; + } + #makeSidebarResizable(resizer, isResizerOnTheLeft) { + resizer.ariaValueMin = this.#minWidth; + resizer.ariaValueMax = this.#maxWidth; + resizer.ariaValueNow = this.#width; + let pointerMoveAC; + const cancelResize = () => { + this.#width = MathClamp(this.#width, this.#minWidth, this.#maxWidth); + this._sidebar.classList.remove("resizing"); + pointerMoveAC?.abort(); + pointerMoveAC = null; + }; + resizer.addEventListener("pointerdown", e => { + if (pointerMoveAC) { + cancelResize(); + return; + } + const { + clientX + } = e; + stopEvent(e); + let prevX = clientX; + pointerMoveAC = new AbortController(); + const { + signal + } = pointerMoveAC; + const sidebar = this._sidebar; + const sidebarStyle = sidebar.style; + sidebar.classList.add("resizing"); + const parentStyle = sidebar.parentElement.style; + parentStyle.minWidth = 0; + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + window.addEventListener("pointermove", ev => { + if (!pointerMoveAC) { + return; + } + stopEvent(ev); + const { + clientX: x + } = ev; + this.#setNewWidth(x - prevX, parentStyle, resizer, sidebarStyle, isResizerOnTheLeft, false); + prevX = x; + }, { + signal, + capture: true + }); + window.addEventListener("blur", cancelResize, { + signal + }); + window.addEventListener("pointerup", ev => { + if (pointerMoveAC) { + cancelResize(); + stopEvent(ev); + } + }, { + signal + }); + }); + resizer.addEventListener("keydown", e => { + const { + key + } = e; + const isArrowLeft = key === "ArrowLeft"; + if (isArrowLeft || key === "ArrowRight") { + const base = e.ctrlKey || e.metaKey ? 10 : 1; + const dx = base * (isArrowLeft ? -1 : 1); + this.#setNewWidth(dx, this._sidebar.parentElement.style, resizer, this._sidebar.style, isResizerOnTheLeft, true); + stopEvent(e); + } + }); + } + #setNewWidth(dx, parentStyle, resizer, sidebarStyle, isResizerOnTheLeft, isFromKeyboard) { + let newWidth = this.#width + this.#coefficient * dx; + if (!isFromKeyboard) { + this.#width = newWidth; + } + if ((newWidth > this.#maxWidth || newWidth < this.#minWidth) && (this.#width === this.#maxWidth || this.#width === this.#minWidth)) { + return; + } + newWidth = MathClamp(newWidth, this.#minWidth, this.#maxWidth); + if (isFromKeyboard) { + this.#width = newWidth; + } + resizer.ariaValueNow = Math.round(newWidth); + sidebarStyle.width = `${newWidth.toFixed(3)}px`; + if (isResizerOnTheLeft) { + parentStyle.insetInlineStart = `${(this.#initialWidth - newWidth).toFixed(3)}px`; + } + } + toggle() { + this._sidebar.hidden = !(this.#visible = !this.#visible); + } +} + +;// ./web/comment_manager.js + + + +class CommentManager { + #dialog; + #popup; + #sidebar; + static #hasForcedColors = null; + constructor(commentDialog, sidebar, eventBus, linkService, overlayManager, ltr, hasForcedColors) { + const dateFormat = new Intl.DateTimeFormat(undefined, { + dateStyle: "long" + }); + this.dialogElement = commentDialog.dialog; + this.#dialog = new CommentDialog(commentDialog, overlayManager, eventBus, ltr); + this.#popup = new CommentPopup(eventBus, dateFormat, ltr, this.dialogElement); + this.#sidebar = new CommentSidebar(sidebar, eventBus, linkService, this.#popup, dateFormat, ltr); + this.#popup.sidebar = this.#sidebar; + CommentManager.#hasForcedColors = hasForcedColors; + } + setSidebarUiManager(uiManager) { + this.#sidebar.setUIManager(uiManager); + } + showSidebar(annotations) { + this.#sidebar.show(annotations); + } + hideSidebar() { + this.#sidebar.hide(); + } + removeComments(ids) { + this.#sidebar.removeComments(ids); + } + selectComment(id) { + this.#sidebar.selectComment(null, id); + } + addComment(annotation) { + this.#sidebar.addComment(annotation); + } + updateComment(annotation) { + this.#sidebar.updateComment(annotation); + } + toggleCommentPopup(editor, isSelected, visibility, isEditable) { + if (isSelected) { + this.selectComment(editor.uid); + } + this.#popup.toggle(editor, isSelected, visibility, isEditable); + } + destroyPopup() { + this.#popup.destroy(); + } + updatePopupColor(editor) { + this.#popup.updateColor(editor); + } + showDialog(uiManager, editor, posX, posY, options) { + return this.#dialog.open(uiManager, editor, posX, posY, options); + } + makeCommentColor(color, opacity) { + return CommentManager._makeCommentColor(color, opacity); + } + static _makeCommentColor(color, opacity) { + return this.#hasForcedColors ? null : findContrastColor(applyOpacity(...color, opacity ?? 1), CSSConstants.commentForegroundColor); + } + destroy() { + this.#dialog.destroy(); + this.#sidebar.hide(); + this.#popup.destroy(); + } +} +class CommentSidebar extends Sidebar { + #annotations = null; + #eventBus; + #boundCommentClick = this.#commentClick.bind(this); + #boundCommentKeydown = this.#commentKeydown.bind(this); + #closeButton; + #commentsList; + #commentCount; + #dateFormat; + #sidebarTitle; + #learnMoreUrl; + #linkService; + #popup; + #elementsToAnnotations = null; + #idsToElements = null; + #uiManager = null; + constructor({ + learnMoreUrl, + sidebar, + sidebarResizer, + commentsList, + commentCount, + sidebarTitle, + closeButton, + commentToolbarButton + }, eventBus, linkService, popup, dateFormat, ltr) { + super({ + sidebar, + resizer: sidebarResizer, + toggleButton: commentToolbarButton + }, ltr, true); + this.#sidebarTitle = sidebarTitle; + this.#commentsList = commentsList; + this.#commentCount = commentCount; + this.#learnMoreUrl = learnMoreUrl; + this.#linkService = linkService; + this.#closeButton = closeButton; + this.#popup = popup; + this.#dateFormat = dateFormat; + this.#eventBus = eventBus; + closeButton.addEventListener("click", () => { + eventBus.dispatch("switchannotationeditormode", { + source: this, + mode: AnnotationEditorType.NONE + }); + }); + const keyDownCallback = e => { + if (e.key === "ArrowDown" || e.key === "Home" || e.key === "F6") { + this.#commentsList.firstElementChild.focus(); + stopEvent(e); + } else if (e.key === "ArrowUp" || e.key === "End") { + this.#commentsList.lastElementChild.focus(); + stopEvent(e); + } + }; + commentToolbarButton.addEventListener("keydown", keyDownCallback); + sidebar.addEventListener("keydown", keyDownCallback); + } + setUIManager(uiManager) { + this.#uiManager = uiManager; + } + show(annotations) { + this.#elementsToAnnotations = new WeakMap(); + this.#idsToElements = new Map(); + this.#annotations = annotations; + annotations.sort(this.#sortComments.bind(this)); + if (annotations.length !== 0) { + const fragment = document.createDocumentFragment(); + for (const annotation of annotations) { + fragment.append(this.#createCommentElement(annotation)); + } + this.#setCommentsCount(fragment); + this.#commentsList.append(fragment); + } else { + this.#setCommentsCount(); + } + this._sidebar.hidden = false; + this.#eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "commentSidebar", + data: { + numberOfAnnotations: annotations.length + } + } + }); + } + hide() { + this._sidebar.hidden = true; + this.#commentsList.replaceChildren(); + this.#elementsToAnnotations = null; + this.#idsToElements = null; + this.#annotations = null; + } + removeComments(ids) { + if (ids.length === 0 || !this.#idsToElements) { + return; + } + if (new Set(this.#idsToElements.keys()).difference(new Set(ids)).size === 0) { + this.#removeAll(); + return; + } + for (const id of ids) { + this.#removeComment(id); + } + } + focusComment(id) { + const element = this.#idsToElements.get(id); + if (!element) { + return; + } + this._sidebar.scrollTop = element.offsetTop - this._sidebar.offsetTop; + for (const el of this.#commentsList.children) { + el.classList.toggle("selected", el === element); + } + } + updateComment(annotation) { + if (!this.#idsToElements) { + return; + } + const { + id, + creationDate, + modificationDate, + richText, + contentsObj, + popupRef + } = annotation; + if (!popupRef || !richText && !contentsObj?.str) { + this.#removeComment(id); + } + const element = this.#idsToElements.get(id); + if (!element) { + return; + } + const prevAnnotation = this.#elementsToAnnotations.get(element); + let index = binarySearchFirstItem(this.#annotations, a => this.#sortComments(a, prevAnnotation) >= 0); + if (index >= this.#annotations.length) { + return; + } + this.#setDate(element.firstElementChild, modificationDate || creationDate); + this.#setText(element.lastElementChild, richText, contentsObj); + this.#annotations.splice(index, 1); + index = binarySearchFirstItem(this.#annotations, a => this.#sortComments(a, annotation) >= 0); + this.#annotations.splice(index, 0, annotation); + if (index >= this.#commentsList.children.length) { + this.#commentsList.append(element); + } else { + this.#commentsList.insertBefore(element, this.#commentsList.children[index]); + } + } + #removeComment(id) { + const element = this.#idsToElements?.get(id); + if (!element) { + return; + } + const annotation = this.#elementsToAnnotations.get(element); + const index = binarySearchFirstItem(this.#annotations, a => this.#sortComments(a, annotation) >= 0); + if (index >= this.#annotations.length) { + return; + } + this.#annotations.splice(index, 1); + element.remove(); + this.#idsToElements.delete(id); + this.#setCommentsCount(); + } + #removeAll() { + this.#commentsList.replaceChildren(); + this.#elementsToAnnotations = new WeakMap(); + this.#idsToElements.clear(); + this.#annotations.length = 0; + this.#setCommentsCount(); + } + selectComment(element, id = null) { + if (!this.#idsToElements) { + return; + } + const hasNoElement = !element; + element ||= this.#idsToElements.get(id); + for (const el of this.#commentsList.children) { + el.classList.toggle("selected", el === element); + } + if (hasNoElement) { + element?.scrollIntoView({ + behavior: "instant", + block: "center" + }); + } + } + addComment(annotation) { + if (this.#idsToElements?.has(annotation.id)) { + return; + } + const { + popupRef, + contentsObj + } = annotation; + if (!popupRef || !contentsObj?.str) { + return; + } + const commentItem = this.#createCommentElement(annotation); + if (this.#annotations.length === 0) { + this.#commentsList.replaceChildren(commentItem); + this.#annotations.push(annotation); + this.#setCommentsCount(); + return; + } + const index = binarySearchFirstItem(this.#annotations, a => this.#sortComments(a, annotation) >= 0); + this.#annotations.splice(index, 0, annotation); + if (index >= this.#commentsList.children.length) { + this.#commentsList.append(commentItem); + } else { + this.#commentsList.insertBefore(commentItem, this.#commentsList.children[index]); + } + this.#setCommentsCount(); + } + #setCommentsCount(container = this.#commentsList) { + const count = this.#idsToElements.size; + this.#sidebarTitle.setAttribute("data-l10n-args", JSON.stringify({ + count + })); + this.#commentCount.textContent = count; + if (count === 0) { + container.append(this.#createZeroCommentElement()); + } + } + #createZeroCommentElement() { + const commentItem = document.createElement("li"); + commentItem.classList.add("sidebarComment", "noComments"); + const textDiv = document.createElement("div"); + textDiv.className = "sidebarCommentText"; + textDiv.setAttribute("data-l10n-id", "pdfjs-editor-comments-sidebar-no-comments1"); + commentItem.append(textDiv); + if (this.#learnMoreUrl) { + const a = document.createElement("a"); + a.setAttribute("data-l10n-id", "pdfjs-editor-comments-sidebar-no-comments-link"); + a.href = this.#learnMoreUrl; + a.target = "_blank"; + a.rel = "noopener noreferrer"; + commentItem.append(a); + } + return commentItem; + } + #setDate(element, date) { + date = PDFDateString.toDateObject(date); + element.dateTime = date.toISOString(); + element.textContent = this.#dateFormat.format(date); + } + #setText(element, richText, contentsObj) { + element.replaceChildren(); + const html = richText?.str && (!contentsObj?.str || richText.str === contentsObj.str) ? richText.html : contentsObj?.str; + renderRichText({ + html, + dir: contentsObj?.dir || "auto", + className: "richText" + }, element); + } + #createCommentElement(annotation) { + const { + id, + creationDate, + modificationDate, + richText, + contentsObj, + color, + opacity + } = annotation; + const commentItem = document.createElement("li"); + commentItem.role = "button"; + commentItem.className = "sidebarComment"; + commentItem.tabIndex = -1; + commentItem.style.backgroundColor = color && CommentManager._makeCommentColor(color, opacity) || ""; + const dateDiv = document.createElement("time"); + this.#setDate(dateDiv, modificationDate || creationDate); + const textDiv = document.createElement("div"); + textDiv.className = "sidebarCommentText"; + this.#setText(textDiv, richText, contentsObj); + commentItem.append(dateDiv, textDiv); + commentItem.addEventListener("click", this.#boundCommentClick); + commentItem.addEventListener("keydown", this.#boundCommentKeydown); + this.#elementsToAnnotations.set(commentItem, annotation); + this.#idsToElements.set(id, commentItem); + return commentItem; + } + async #commentClick({ + currentTarget + }) { + if (currentTarget.classList.contains("selected")) { + currentTarget.classList.remove("selected"); + this.#popup._hide(); + return; + } + const annotation = this.#elementsToAnnotations.get(currentTarget); + if (!annotation) { + return; + } + this.#popup._hide(); + const { + id, + pageIndex, + rect + } = annotation; + const pageNumber = pageIndex + 1; + const pageVisiblePromise = this.#uiManager?.waitForEditorsRendered(pageNumber); + this.#linkService?.goToXY(pageNumber, rect[0], rect[3], { + center: "both" + }); + this.selectComment(currentTarget); + await pageVisiblePromise; + this.#uiManager?.selectComment(pageIndex, id); + } + #commentKeydown(e) { + const { + key, + currentTarget + } = e; + switch (key) { + case "ArrowDown": + (currentTarget.nextElementSibling || this.#commentsList.firstElementChild).focus(); + stopEvent(e); + break; + case "ArrowUp": + (currentTarget.previousElementSibling || this.#commentsList.lastElementChild).focus(); + stopEvent(e); + break; + case "Home": + this.#commentsList.firstElementChild.focus(); + stopEvent(e); + break; + case "End": + this.#commentsList.lastElementChild.focus(); + stopEvent(e); + break; + case "Enter": + case " ": + this.#commentClick(e); + stopEvent(e); + break; + case "ShiftTab": + this.#closeButton.focus(); + stopEvent(e); + break; + } + } + #sortComments(a, b) { + const dateA = PDFDateString.toDateObject(a.modificationDate || a.creationDate); + const dateB = PDFDateString.toDateObject(b.modificationDate || b.creationDate); + if (dateA !== dateB) { + if (dateA !== null && dateB !== null) { + return dateB - dateA; + } + return dateA !== null ? -1 : 1; + } + if (a.pageIndex !== b.pageIndex) { + return a.pageIndex - b.pageIndex; + } + if (a.rect[3] !== b.rect[3]) { + return b.rect[3] - a.rect[3]; + } + if (a.rect[0] !== b.rect[0]) { + return a.rect[0] - b.rect[0]; + } + if (a.rect[1] !== b.rect[1]) { + return b.rect[1] - a.rect[1]; + } + if (a.rect[2] !== b.rect[2]) { + return a.rect[2] - b.rect[2]; + } + return a.id.localeCompare(b.id); + } +} +class CommentDialog { + #dialog; + #editor; + #overlayManager; + #previousText = ""; + #commentText = ""; + #textInput; + #title; + #saveButton; + #uiManager; + #prevDragX = 0; + #prevDragY = 0; + #dialogX = 0; + #dialogY = 0; + #isLTR; + #eventBus; + constructor({ + dialog, + toolbar, + title, + textInput, + cancelButton, + saveButton + }, overlayManager, eventBus, ltr) { + this.#dialog = dialog; + this.#textInput = textInput; + this.#overlayManager = overlayManager; + this.#eventBus = eventBus; + this.#saveButton = saveButton; + this.#title = title; + this.#isLTR = ltr; + const finishBound = this.#finish.bind(this); + dialog.addEventListener("close", finishBound); + dialog.addEventListener("contextmenu", e => { + if (e.target !== this.#textInput) { + e.preventDefault(); + } + }); + cancelButton.addEventListener("click", finishBound); + saveButton.addEventListener("click", this.#save.bind(this)); + textInput.addEventListener("input", () => { + saveButton.disabled = textInput.value === this.#previousText; + }); + textInput.addEventListener("keydown", e => { + if ((e.ctrlKey || e.metaKey) && e.key === "Enter" && !saveButton.disabled) { + this.#save(); + } + }); + let pointerMoveAC; + const cancelDrag = () => { + dialog.classList.remove("dragging"); + pointerMoveAC?.abort(); + pointerMoveAC = null; + }; + toolbar.addEventListener("pointerdown", e => { + if (pointerMoveAC) { + cancelDrag(); + return; + } + const { + clientX, + clientY + } = e; + stopEvent(e); + this.#prevDragX = clientX; + this.#prevDragY = clientY; + pointerMoveAC = new AbortController(); + const { + signal + } = pointerMoveAC; + const { + innerHeight, + innerWidth + } = window; + dialog.classList.add("dragging"); + window.addEventListener("pointermove", ev => { + if (!pointerMoveAC) { + return; + } + const { + clientX: x, + clientY: y + } = ev; + this.#setPosition(this.#dialogX + (x - this.#prevDragX) / innerWidth, this.#dialogY + (y - this.#prevDragY) / innerHeight); + this.#prevDragX = x; + this.#prevDragY = y; + stopEvent(ev); + }, { + signal + }); + window.addEventListener("blur", cancelDrag, { + signal + }); + window.addEventListener("pointerup", ev => { + if (pointerMoveAC) { + cancelDrag(); + stopEvent(ev); + } + }, { + signal + }); + }); + overlayManager.register(dialog); + } + async open(uiManager, editor, posX, posY, options) { + if (editor) { + this.#uiManager = uiManager; + this.#editor = editor; + } + const { + contentsObj: { + str + }, + color, + opacity + } = editor.getData(); + const { + style: dialogStyle + } = this.#dialog; + if (color) { + dialogStyle.backgroundColor = CommentManager._makeCommentColor(color, opacity); + dialogStyle.borderColor = Util.makeHexColor(...color); + } else { + dialogStyle.backgroundColor = dialogStyle.borderColor = ""; + } + this.#commentText = str || ""; + const textInput = this.#textInput; + textInput.value = this.#previousText = this.#commentText; + if (str) { + this.#title.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-dialog-title-when-editing"); + this.#saveButton.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-dialog-save-button-when-editing"); + } else { + this.#title.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-dialog-title-when-adding"); + this.#saveButton.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-dialog-save-button-when-adding"); + } + if (options?.height) { + textInput.style.height = `${options.height}px`; + } + this.#uiManager?.removeEditListeners(); + this.#saveButton.disabled = true; + const parentDimensions = options?.parentDimensions; + const { + innerHeight, + innerWidth + } = window; + if (editor.hasDefaultPopupPosition()) { + const { + dialogWidth, + dialogHeight + } = this._dialogDimensions; + if (parentDimensions) { + if (this.#isLTR && posX + dialogWidth > Math.min(parentDimensions.x + parentDimensions.width, innerWidth)) { + const buttonWidth = this.#editor.commentButtonWidth; + posX -= dialogWidth - buttonWidth * parentDimensions.width; + } else if (!this.#isLTR) { + const buttonWidth = this.#editor.commentButtonWidth * parentDimensions.width; + if (posX - dialogWidth < Math.max(0, parentDimensions.x)) { + posX = Math.max(0, posX); + } else { + posX -= dialogWidth - buttonWidth; + } + } + } + const height = Math.max(dialogHeight, options?.height || 0); + if (posY + height > innerHeight) { + posY = innerHeight - height; + } + if (posY < 0) { + posY = 0; + } + } + posX = MathClamp(posX / innerWidth, 0, 1); + posY = MathClamp(posY / innerHeight, 0, 1); + this.#setPosition(posX, posY); + await this.#overlayManager.open(this.#dialog); + textInput.focus(); + } + async #save() { + this.#editor.comment = this.#textInput.value; + this.#finish(); + } + get _dialogDimensions() { + const dialog = this.#dialog; + const { + style + } = dialog; + style.opacity = "0"; + style.display = "block"; + const { + width, + height + } = dialog.getBoundingClientRect(); + style.opacity = style.display = ""; + return shadow(this, "_dialogDimensions", { + dialogWidth: width, + dialogHeight: height + }); + } + #setPosition(x, y) { + this.#dialogX = x; + this.#dialogY = y; + const { + style + } = this.#dialog; + style.left = `${100 * x}%`; + style.top = `${100 * y}%`; + } + #finish() { + if (!this.#editor) { + return; + } + const edited = this.#textInput.value !== this.#commentText; + this.#eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "comment", + data: { + edited + } + } + }); + this.#editor?.focusCommentButton(); + this.#editor = null; + this.#textInput.value = this.#previousText = this.#commentText = ""; + this.#overlayManager.closeIfActive(this.#dialog); + this.#textInput.style.height = ""; + this.#uiManager?.addEditListeners(); + this.#uiManager = null; + } + destroy() { + this.#uiManager = null; + this.#editor = null; + this.#finish(); + } +} +class CommentPopup { + #buttonsContainer = null; + #eventBus; + #commentDialog; + #dateFormat; + #editor = null; + #isLTR; + #container = null; + #text = null; + #time = null; + #prevDragX = 0; + #prevDragY = 0; + #posX = 0; + #posY = 0; + #previousFocusedElement = null; + #selected = false; + #visible = false; + constructor(eventBus, dateFormat, ltr, commentDialog) { + this.#eventBus = eventBus; + this.#dateFormat = dateFormat; + this.#isLTR = ltr; + this.#commentDialog = commentDialog; + this.sidebar = null; + } + get _popupWidth() { + const container = this.#createPopup(); + const { + style + } = container; + style.opacity = "0"; + style.display = "block"; + document.body.append(container); + const width = container.getBoundingClientRect().width; + container.remove(); + style.opacity = style.display = ""; + return shadow(this, "_popupWidth", width); + } + #createPopup() { + if (this.#container) { + return this.#container; + } + const container = this.#container = document.createElement("div"); + container.className = "commentPopup"; + container.id = "commentPopup"; + container.tabIndex = -1; + container.role = "dialog"; + container.ariaModal = "false"; + container.addEventListener("contextmenu", noContextMenu); + container.addEventListener("keydown", e => { + if (e.key === "Escape") { + this.toggle(this.#editor, true, false); + this.#previousFocusedElement?.focus(); + stopEvent(e); + } + }); + container.addEventListener("click", () => { + container.focus(); + }); + const top = document.createElement("div"); + top.className = "commentPopupTop"; + const time = this.#time = document.createElement("time"); + time.className = "commentPopupTime"; + const buttons = this.#buttonsContainer = document.createElement("div"); + buttons.className = "commentPopupButtons"; + const edit = document.createElement("button"); + edit.classList.add("commentPopupEdit", "toolbarButton"); + edit.tabIndex = 0; + edit.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-popup-button"); + edit.ariaHasPopup = "dialog"; + edit.ariaControlsElements = [this.#commentDialog]; + const editLabel = document.createElement("span"); + editLabel.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-popup-button-label"); + edit.append(editLabel); + edit.addEventListener("click", () => { + const editor = this.#editor; + const height = parseFloat(getComputedStyle(this.#text).height); + this.toggle(editor, true, false); + editor.editComment({ + height + }); + }); + edit.addEventListener("contextmenu", noContextMenu); + const del = document.createElement("button"); + del.classList.add("commentPopupDelete", "toolbarButton"); + del.tabIndex = 0; + del.setAttribute("data-l10n-id", "pdfjs-editor-delete-comment-popup-button"); + const delLabel = document.createElement("span"); + delLabel.setAttribute("data-l10n-id", "pdfjs-editor-delete-comment-popup-button-label"); + del.append(delLabel); + del.addEventListener("click", () => { + this.#eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "comment", + data: { + deleted: true + } + } + }); + this.#editor.comment = null; + this.#editor.focus(); + this.destroy(); + }); + del.addEventListener("contextmenu", noContextMenu); + buttons.append(edit, del); + top.append(time, buttons); + const separator = document.createElement("hr"); + const text = this.#text = document.createElement("div"); + text.className = "commentPopupText"; + container.append(top, separator, text); + let pointerMoveAC; + const cancelDrag = () => { + container.classList.remove("dragging"); + pointerMoveAC?.abort(); + pointerMoveAC = null; + }; + top.addEventListener("pointerdown", e => { + if (pointerMoveAC) { + cancelDrag(); + return; + } + const { + target, + clientX, + clientY + } = e; + if (buttons.contains(target)) { + return; + } + stopEvent(e); + const { + width: parentWidth, + height: parentHeight + } = this.#editor.parentBoundingClientRect; + this.#prevDragX = clientX; + this.#prevDragY = clientY; + pointerMoveAC = new AbortController(); + const { + signal + } = pointerMoveAC; + container.classList.add("dragging"); + window.addEventListener("pointermove", ev => { + if (!pointerMoveAC) { + return; + } + const { + clientX: x, + clientY: y + } = ev; + this.#setPosition(this.#posX + (x - this.#prevDragX) / parentWidth, this.#posY + (y - this.#prevDragY) / parentHeight, false); + this.#prevDragX = x; + this.#prevDragY = y; + stopEvent(ev); + }, { + signal + }); + window.addEventListener("blur", cancelDrag, { + signal + }); + window.addEventListener("pointerup", ev => { + if (pointerMoveAC) { + cancelDrag(); + stopEvent(ev); + } + }, { + signal + }); + }); + return container; + } + updateColor(editor) { + if (this.#editor !== editor || !this.#visible) { + return; + } + const { + color, + opacity + } = editor.getData(); + this.#container.style.backgroundColor = color && CommentManager._makeCommentColor(color, opacity) || ""; + } + _hide(editor) { + const container = this.#createPopup(); + container.classList.toggle("hidden", true); + container.classList.toggle("selected", false); + (editor || this.#editor)?.setCommentButtonStates({ + selected: false, + hasPopup: false + }); + this.#editor = null; + this.#selected = false; + this.#visible = false; + this.#text.replaceChildren(); + this.sidebar.selectComment(null); + } + toggle(editor, isSelected, visibility = undefined, isEditable = true) { + if (!editor) { + this.destroy(); + return; + } + if (isSelected) { + visibility ??= this.#editor === editor ? !this.#selected || !this.#visible : true; + } else { + if (this.#selected) { + return; + } + visibility ??= !this.#visible; + } + if (!visibility) { + this._hide(editor); + return; + } + this.#visible = true; + if (this.#editor !== editor) { + this.#editor?.setCommentButtonStates({ + selected: false, + hasPopup: false + }); + } + const container = this.#createPopup(); + this.#buttonsContainer.classList.toggle("hidden", !isEditable); + container.classList.toggle("hidden", false); + container.classList.toggle("selected", isSelected); + this.#selected = isSelected; + this.#editor = editor; + editor.setCommentButtonStates({ + selected: isSelected, + hasPopup: true + }); + const { + contentsObj, + richText, + creationDate, + modificationDate, + color, + opacity + } = editor.getData(); + container.style.backgroundColor = color && CommentManager._makeCommentColor(color, opacity) || ""; + this.#text.replaceChildren(); + const html = richText?.str && (!contentsObj?.str || richText.str === contentsObj.str) ? richText.html : contentsObj?.str; + if (html) { + renderRichText({ + html, + dir: contentsObj?.dir || "auto", + className: "richText" + }, this.#text); + } + this.#time.textContent = this.#dateFormat.format(PDFDateString.toDateObject(modificationDate || creationDate)); + this.#setPosition(...editor.commentPopupPosition, editor.hasDefaultPopupPosition()); + editor.elementBeforePopup.after(container); + container.addEventListener("focus", ({ + relatedTarget + }) => { + this.#previousFocusedElement = relatedTarget; + }, { + once: true + }); + if (isSelected) { + setTimeout(() => container.focus(), 0); + } + } + #setPosition(x, y, correctPosition) { + if (!correctPosition) { + this.#editor.commentPopupPosition = [x, y]; + } else { + const parentRect = this.#editor.parentBoundingClientRect; + const widthRatio = this._popupWidth / parentRect.width; + if (this.#isLTR && x + widthRatio > 1 || !this.#isLTR && x - widthRatio >= 0) { + const buttonWidth = this.#editor.commentButtonWidth; + x -= widthRatio - buttonWidth; + } + const margin = 0.01; + if (this.#isLTR) { + x = Math.max(x, -parentRect.x / parentRect.width + margin); + } else { + x = Math.min(x, (window.innerWidth - parentRect.x) / parentRect.width - widthRatio - margin); + } + } + this.#posX = x; + this.#posY = y; + const { + style + } = this.#container; + style.left = `${100 * x}%`; + style.top = `${100 * y}%`; + } + destroy() { + this._hide(); + this.#container?.remove(); + this.#container = this.#text = this.#time = null; + this.#prevDragX = this.#prevDragY = Infinity; + this.#posX = this.#posY = 0; + this.#previousFocusedElement = null; + } +} + +;// ./web/editor_undo_bar.js + +class EditorUndoBar { + #closeButton = null; + #container; + #eventBus = null; + #focusTimeout = null; + #initController = null; + isOpen = false; + #message; + #showController = null; + #undoButton; + static #l10nMessages = Object.freeze({ + highlight: "pdfjs-editor-undo-bar-message-highlight", + freetext: "pdfjs-editor-undo-bar-message-freetext", + stamp: "pdfjs-editor-undo-bar-message-stamp", + ink: "pdfjs-editor-undo-bar-message-ink", + signature: "pdfjs-editor-undo-bar-message-signature", + _multiple: "pdfjs-editor-undo-bar-message-multiple" + }); + constructor({ + container, + message, + undoButton, + closeButton + }, eventBus) { + this.#container = container; + this.#message = message; + this.#undoButton = undoButton; + this.#closeButton = closeButton; + this.#eventBus = eventBus; + } + destroy() { + this.#initController?.abort(); + this.#initController = null; + this.hide(); + } + show(undoAction, messageData) { + if (!this.#initController) { + this.#initController = new AbortController(); + const opts = { + signal: this.#initController.signal + }; + const boundHide = this.hide.bind(this); + this.#container.addEventListener("contextmenu", noContextMenu, opts); + this.#closeButton.addEventListener("click", boundHide, opts); + this.#eventBus._on("beforeprint", boundHide, opts); + this.#eventBus._on("download", boundHide, opts); + } + this.hide(); + if (typeof messageData === "string") { + this.#message.setAttribute("data-l10n-id", EditorUndoBar.#l10nMessages[messageData]); + } else { + this.#message.setAttribute("data-l10n-id", EditorUndoBar.#l10nMessages._multiple); + this.#message.setAttribute("data-l10n-args", JSON.stringify({ + count: messageData + })); + } + this.isOpen = true; + this.#container.hidden = false; + this.#showController = new AbortController(); + this.#undoButton.addEventListener("click", () => { + undoAction(); + this.hide(); + }, { + signal: this.#showController.signal + }); + this.#focusTimeout = setTimeout(() => { + this.#container.focus(); + this.#focusTimeout = null; + }, 100); + } + hide() { + if (!this.isOpen) { + return; + } + this.isOpen = false; + this.#container.hidden = true; + this.#showController?.abort(); + this.#showController = null; + if (this.#focusTimeout) { + clearTimeout(this.#focusTimeout); + this.#focusTimeout = null; + } + } +} + +;// ./web/overlay_manager.js +class OverlayManager { + #overlays = new WeakMap(); + #active = null; + get active() { + return this.#active; + } + async register(dialog, canForceClose = false) { + if (typeof dialog !== "object") { + throw new Error("Not enough parameters."); + } else if (this.#overlays.has(dialog)) { + throw new Error("The overlay is already registered."); + } + this.#overlays.set(dialog, { + canForceClose + }); + dialog.addEventListener("cancel", ({ + target + }) => { + if (this.#active === target) { + this.#active = null; + } + }); + } + async open(dialog) { + if (!this.#overlays.has(dialog)) { + throw new Error("The overlay does not exist."); + } else if (this.#active) { + if (this.#active === dialog) { + throw new Error("The overlay is already active."); + } else if (this.#overlays.get(dialog).canForceClose) { + await this.close(); + } else { + throw new Error("Another overlay is currently active."); + } + } + this.#active = dialog; + dialog.showModal(); + } + async close(dialog = this.#active) { + if (!this.#overlays.has(dialog)) { + throw new Error("The overlay does not exist."); + } else if (!this.#active) { + throw new Error("The overlay is currently not active."); + } else if (this.#active !== dialog) { + throw new Error("Another overlay is currently active."); + } + dialog.close(); + this.#active = null; + } + async closeIfActive(dialog) { + if (this.#active === dialog) { + await this.close(dialog); + } + } +} + +;// ./web/password_prompt.js + +class PasswordPrompt { + #activeCapability = null; + #updateCallback = null; + #reason = null; + constructor(options, overlayManager, isViewerEmbedded = false) { + this.dialog = options.dialog; + this.label = options.label; + this.input = options.input; + this.submitButton = options.submitButton; + this.cancelButton = options.cancelButton; + this.overlayManager = overlayManager; + this._isViewerEmbedded = isViewerEmbedded; + this.submitButton.addEventListener("click", this.#verify.bind(this)); + this.cancelButton.addEventListener("click", this.close.bind(this)); + this.input.addEventListener("keydown", e => { + if (e.keyCode === 13) { + this.#verify(); + } + }); + this.overlayManager.register(this.dialog, true); + this.dialog.addEventListener("close", this.#cancel.bind(this)); + } + async open() { + await this.#activeCapability?.promise; + this.#activeCapability = Promise.withResolvers(); + try { + await this.overlayManager.open(this.dialog); + } catch (ex) { + this.#activeCapability.resolve(); + throw ex; + } + const passwordIncorrect = this.#reason === PasswordResponses.INCORRECT_PASSWORD; + if (!this._isViewerEmbedded || passwordIncorrect) { + this.input.focus(); + } + this.label.setAttribute("data-l10n-id", passwordIncorrect ? "pdfjs-password-invalid" : "pdfjs-password-label"); + } + async close() { + this.overlayManager.closeIfActive(this.dialog); + } + #verify() { + const password = this.input.value; + if (password?.length > 0) { + this.#invokeCallback(password); + } + } + #cancel() { + this.#invokeCallback(new Error("PasswordPrompt cancelled.")); + this.#activeCapability.resolve(); + } + #invokeCallback(password) { + if (!this.#updateCallback) { + return; + } + this.close(); + this.input.value = ""; + this.#updateCallback(password); + this.#updateCallback = null; + } + async setUpdateCallback(updateCallback, reason) { + if (this.#activeCapability) { + await this.#activeCapability.promise; + } + this.#updateCallback = updateCallback; + this.#reason = reason; + } +} + +;// ./web/base_tree_viewer.js + +const TREEITEM_OFFSET_TOP = -100; +const TREEITEM_SELECTED_CLASS = "selected"; +class BaseTreeViewer { + constructor(options) { + this.container = options.container; + this.eventBus = options.eventBus; + this._l10n = options.l10n; + this.reset(); + } + reset() { + this._pdfDocument = null; + this._lastToggleIsShow = true; + this._currentTreeItem = null; + this.container.textContent = ""; + this.container.classList.remove("treeWithDeepNesting"); + } + _dispatchEvent(count) { + throw new Error("Not implemented: _dispatchEvent"); + } + _bindLink(element, params) { + throw new Error("Not implemented: _bindLink"); + } + _normalizeTextContent(str) { + return removeNullCharacters(str, true) || "\u2013"; + } + _addToggleButton(div, hidden = false) { + const toggler = document.createElement("div"); + toggler.className = "treeItemToggler"; + if (hidden) { + toggler.classList.add("treeItemsHidden"); + } + toggler.onclick = evt => { + evt.stopPropagation(); + toggler.classList.toggle("treeItemsHidden"); + if (evt.shiftKey) { + const shouldShowAll = !toggler.classList.contains("treeItemsHidden"); + this._toggleTreeItem(div, shouldShowAll); + } + }; + div.prepend(toggler); + } + _toggleTreeItem(root, show = false) { + this._l10n.pause(); + this._lastToggleIsShow = show; + for (const toggler of root.querySelectorAll(".treeItemToggler")) { + toggler.classList.toggle("treeItemsHidden", !show); + } + this._l10n.resume(); + } + _toggleAllTreeItems() { + this._toggleTreeItem(this.container, !this._lastToggleIsShow); + } + _finishRendering(fragment, count, hasAnyNesting = false) { + if (hasAnyNesting) { + this.container.classList.add("treeWithDeepNesting"); + this._lastToggleIsShow = !fragment.querySelector(".treeItemsHidden"); + } + this._l10n.pause(); + this.container.append(fragment); + this._l10n.resume(); + this._dispatchEvent(count); + } + render(params) { + throw new Error("Not implemented: render"); + } + _updateCurrentTreeItem(treeItem = null) { + if (this._currentTreeItem) { + this._currentTreeItem.classList.remove(TREEITEM_SELECTED_CLASS); + this._currentTreeItem = null; + } + if (treeItem) { + treeItem.classList.add(TREEITEM_SELECTED_CLASS); + this._currentTreeItem = treeItem; + } + } + _scrollToCurrentTreeItem(treeItem) { + if (!treeItem) { + return; + } + this._l10n.pause(); + let currentNode = treeItem.parentNode; + while (currentNode && currentNode !== this.container) { + if (currentNode.classList.contains("treeItem")) { + const toggler = currentNode.firstElementChild; + toggler?.classList.remove("treeItemsHidden"); + } + currentNode = currentNode.parentNode; + } + this._l10n.resume(); + this._updateCurrentTreeItem(treeItem); + this.container.scrollTo(treeItem.offsetLeft, treeItem.offsetTop + TREEITEM_OFFSET_TOP); + } +} + +;// ./web/pdf_attachment_viewer.js + + +class PDFAttachmentViewer extends BaseTreeViewer { + constructor(options) { + super(options); + this.downloadManager = options.downloadManager; + this.eventBus._on("fileattachmentannotation", this.#appendAttachment.bind(this)); + } + reset(keepRenderedCapability = false) { + super.reset(); + this._attachments = null; + if (!keepRenderedCapability) { + this._renderedCapability = Promise.withResolvers(); + } + this._pendingDispatchEvent = false; + } + async _dispatchEvent(attachmentsCount) { + this._renderedCapability.resolve(); + if (attachmentsCount === 0 && !this._pendingDispatchEvent) { + this._pendingDispatchEvent = true; + await waitOnEventOrTimeout({ + target: this.eventBus, + name: "annotationlayerrendered", + delay: 1000 + }); + if (!this._pendingDispatchEvent) { + return; + } + } + this._pendingDispatchEvent = false; + this.eventBus.dispatch("attachmentsloaded", { + source: this, + attachmentsCount + }); + } + _bindLink(element, { + content, + description, + filename + }) { + if (description) { + element.title = description; + } + element.onclick = () => { + this.downloadManager.openOrDownloadData(content, filename); + return false; + }; + } + render({ + attachments, + keepRenderedCapability = false + }) { + if (this._attachments) { + this.reset(keepRenderedCapability); + } + this._attachments = attachments || null; + if (!attachments) { + this._dispatchEvent(0); + return; + } + const fragment = document.createDocumentFragment(); + let attachmentsCount = 0; + for (const name in attachments) { + const item = attachments[name]; + const div = document.createElement("div"); + div.className = "treeItem"; + const element = document.createElement("a"); + this._bindLink(element, item); + element.textContent = this._normalizeTextContent(item.filename); + div.append(element); + fragment.append(div); + attachmentsCount++; + } + this._finishRendering(fragment, attachmentsCount); + } + #appendAttachment(item) { + const renderedPromise = this._renderedCapability.promise; + renderedPromise.then(() => { + if (renderedPromise !== this._renderedCapability.promise) { + return; + } + const attachments = this._attachments || Object.create(null); + for (const name in attachments) { + if (item.filename === name) { + return; + } + } + attachments[item.filename] = item; + this.render({ + attachments, + keepRenderedCapability: true + }); + }); + } +} + +;// ./web/grab_to_pan.js + +const CSS_CLASS_GRAB = "grab-to-pan-grab"; +class GrabToPan { + #activateAC = null; + #mouseDownAC = null; + #scrollAC = null; + constructor({ + element + }) { + this.element = element; + this.document = element.ownerDocument; + const overlay = this.overlay = document.createElement("div"); + overlay.className = "grab-to-pan-grabbing"; + } + activate() { + if (!this.#activateAC) { + this.#activateAC = new AbortController(); + this.element.addEventListener("mousedown", this.#onMouseDown.bind(this), { + capture: true, + signal: this.#activateAC.signal + }); + this.element.classList.add(CSS_CLASS_GRAB); + } + } + deactivate() { + if (this.#activateAC) { + this.#activateAC.abort(); + this.#activateAC = null; + this.#endPan(); + this.element.classList.remove(CSS_CLASS_GRAB); + } + } + toggle() { + if (this.#activateAC) { + this.deactivate(); + } else { + this.activate(); + } + } + ignoreTarget(node) { + return node.matches("a[href], a[href] *, input, textarea, button, button *, select, option"); + } + #onMouseDown(event) { + if (event.button !== 0 || this.ignoreTarget(event.target)) { + return; + } + if (event.originalTarget) { + try { + event.originalTarget.tagName; + } catch { + return; + } + } + this.scrollLeftStart = this.element.scrollLeft; + this.scrollTopStart = this.element.scrollTop; + this.clientXStart = event.clientX; + this.clientYStart = event.clientY; + this.#mouseDownAC = new AbortController(); + const boundEndPan = this.#endPan.bind(this), + mouseOpts = { + capture: true, + signal: this.#mouseDownAC.signal + }; + this.document.addEventListener("mousemove", this.#onMouseMove.bind(this), mouseOpts); + this.document.addEventListener("mouseup", boundEndPan, mouseOpts); + this.#scrollAC = new AbortController(); + this.element.addEventListener("scroll", boundEndPan, { + capture: true, + signal: this.#scrollAC.signal + }); + stopEvent(event); + const focusedElement = document.activeElement; + if (focusedElement && !focusedElement.contains(event.target)) { + focusedElement.blur(); + } + } + #onMouseMove(event) { + this.#scrollAC?.abort(); + this.#scrollAC = null; + if (!(event.buttons & 1)) { + this.#endPan(); + return; + } + const xDiff = event.clientX - this.clientXStart; + const yDiff = event.clientY - this.clientYStart; + this.element.scrollTo({ + top: this.scrollTopStart - yDiff, + left: this.scrollLeftStart - xDiff, + behavior: "instant" + }); + if (!this.overlay.parentNode) { + document.body.append(this.overlay); + } + } + #endPan() { + this.#mouseDownAC?.abort(); + this.#mouseDownAC = null; + this.#scrollAC?.abort(); + this.#scrollAC = null; + this.overlay.remove(); + } +} + +;// ./web/pdf_cursor_tools.js + + + +class PDFCursorTools { + #active = CursorTool.SELECT; + #prevActive = null; + constructor({ + container, + eventBus, + cursorToolOnLoad = CursorTool.SELECT + }) { + this.container = container; + this.eventBus = eventBus; + this.#addEventListeners(); + Promise.resolve().then(() => { + this.switchTool(cursorToolOnLoad); + }); + } + get activeTool() { + return this.#active; + } + switchTool(tool) { + if (this.#prevActive !== null) { + return; + } + this.#switchTool(tool); + } + #switchTool(tool, disabled = false) { + if (tool === this.#active) { + if (this.#prevActive !== null) { + this.eventBus.dispatch("cursortoolchanged", { + source: this, + tool, + disabled + }); + } + return; + } + const disableActiveTool = () => { + switch (this.#active) { + case CursorTool.SELECT: + break; + case CursorTool.HAND: + this._handTool.deactivate(); + break; + case CursorTool.ZOOM: + } + }; + switch (tool) { + case CursorTool.SELECT: + disableActiveTool(); + break; + case CursorTool.HAND: + disableActiveTool(); + this._handTool.activate(); + break; + case CursorTool.ZOOM: + default: + console.error(`switchTool: "${tool}" is an unsupported value.`); + return; + } + this.#active = tool; + this.eventBus.dispatch("cursortoolchanged", { + source: this, + tool, + disabled + }); + } + #addEventListeners() { + this.eventBus._on("switchcursortool", evt => { + if (!evt.reset) { + this.switchTool(evt.tool); + } else if (this.#prevActive !== null) { + annotationEditorMode = AnnotationEditorType.NONE; + presentationModeState = PresentationModeState.NORMAL; + enableActive(); + } + }); + let annotationEditorMode = AnnotationEditorType.NONE, + presentationModeState = PresentationModeState.NORMAL; + const disableActive = () => { + this.#prevActive ??= this.#active; + this.#switchTool(CursorTool.SELECT, true); + }; + const enableActive = () => { + if (this.#prevActive !== null && annotationEditorMode === AnnotationEditorType.NONE && presentationModeState === PresentationModeState.NORMAL) { + this.#switchTool(this.#prevActive); + this.#prevActive = null; + } + }; + this.eventBus._on("annotationeditormodechanged", ({ + mode + }) => { + annotationEditorMode = mode; + if (mode === AnnotationEditorType.NONE) { + enableActive(); + } else { + disableActive(); + } + }); + this.eventBus._on("presentationmodechanged", ({ + state + }) => { + presentationModeState = state; + if (state === PresentationModeState.NORMAL) { + enableActive(); + } else if (state === PresentationModeState.FULLSCREEN) { + disableActive(); + } + }); + } + get _handTool() { + return shadow(this, "_handTool", new GrabToPan({ + element: this.container + })); + } +} + +;// ./web/pdf_document_properties.js + + +const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"]; +const US_PAGE_NAMES = { + "8.5x11": "pdfjs-document-properties-page-size-name-letter", + "8.5x14": "pdfjs-document-properties-page-size-name-legal" +}; +const METRIC_PAGE_NAMES = { + "297x420": "pdfjs-document-properties-page-size-name-a-three", + "210x297": "pdfjs-document-properties-page-size-name-a-four" +}; +function getPageName(size, isPortrait, pageNames) { + const width = isPortrait ? size.width : size.height; + const height = isPortrait ? size.height : size.width; + return pageNames[`${width}x${height}`]; +} +class PDFDocumentProperties { + #fieldData = null; + constructor({ + dialog, + fields, + closeButton + }, overlayManager, eventBus, l10n, fileNameLookup, titleLookup) { + this.dialog = dialog; + this.fields = fields; + this.overlayManager = overlayManager; + this.l10n = l10n; + this._fileNameLookup = fileNameLookup; + this._titleLookup = titleLookup; + this.#reset(); + closeButton.addEventListener("click", this.close.bind(this)); + this.overlayManager.register(this.dialog); + eventBus._on("pagechanging", evt => { + this._currentPageNumber = evt.pageNumber; + }); + eventBus._on("rotationchanging", evt => { + this._pagesRotation = evt.pagesRotation; + }); + } + async open() { + await Promise.all([this.overlayManager.open(this.dialog), this._dataAvailableCapability.promise]); + const currentPageNumber = this._currentPageNumber; + const pagesRotation = this._pagesRotation; + if (this.#fieldData && currentPageNumber === this.#fieldData._currentPageNumber && pagesRotation === this.#fieldData._pagesRotation) { + this.#updateUI(); + return; + } + const [{ + info, + metadata, + contentLength + }, pdfPage] = await Promise.all([this.pdfDocument.getMetadata(), this.pdfDocument.getPage(currentPageNumber)]); + const [fileName, fileSize, title, creationDate, modificationDate, pageSize, isLinearized] = await Promise.all([this._fileNameLookup(), this.#parseFileSize(contentLength), this._titleLookup(), this.#parseDate(metadata?.get("xmp:createdate"), info.CreationDate), this.#parseDate(metadata?.get("xmp:modifydate"), info.ModDate), this.#parsePageSize(getPageSizeInches(pdfPage), pagesRotation), this.#parseLinearization(info.IsLinearized)]); + this.#fieldData = Object.freeze({ + fileName, + fileSize, + title, + author: metadata?.get("dc:creator")?.join("\n") || info.Author, + subject: metadata?.get("dc:subject")?.join("\n") || info.Subject, + keywords: metadata?.get("pdf:keywords") || info.Keywords, + creationDate, + modificationDate, + creator: metadata?.get("xmp:creatortool") || info.Creator, + producer: metadata?.get("pdf:producer") || info.Producer, + version: info.PDFFormatVersion, + pageCount: this.pdfDocument.numPages, + pageSize, + linearized: isLinearized, + _currentPageNumber: currentPageNumber, + _pagesRotation: pagesRotation + }); + this.#updateUI(); + const { + length + } = await this.pdfDocument.getDownloadInfo(); + if (contentLength === length) { + return; + } + const data = Object.assign(Object.create(null), this.#fieldData); + data.fileSize = await this.#parseFileSize(length); + this.#fieldData = Object.freeze(data); + this.#updateUI(); + } + async close() { + this.overlayManager.close(this.dialog); + } + setDocument(pdfDocument) { + if (this.pdfDocument) { + this.#reset(); + this.#updateUI(); + } + if (!pdfDocument) { + return; + } + this.pdfDocument = pdfDocument; + this._dataAvailableCapability.resolve(); + } + #reset() { + this.pdfDocument = null; + this.#fieldData = null; + this._dataAvailableCapability = Promise.withResolvers(); + this._currentPageNumber = 1; + this._pagesRotation = 0; + } + #updateUI() { + if (this.#fieldData && this.overlayManager.active !== this.dialog) { + return; + } + for (const id in this.fields) { + const content = this.#fieldData?.[id]; + this.fields[id].textContent = content || content === 0 ? content : "-"; + } + } + async #parseFileSize(b = 0) { + const kb = b / 1024, + mb = kb / 1024; + return kb ? this.l10n.get(mb >= 1 ? "pdfjs-document-properties-size-mb" : "pdfjs-document-properties-size-kb", { + mb, + kb, + b + }) : undefined; + } + async #parsePageSize(pageSizeInches, pagesRotation) { + if (!pageSizeInches) { + return undefined; + } + if (pagesRotation % 180 !== 0) { + pageSizeInches = { + width: pageSizeInches.height, + height: pageSizeInches.width + }; + } + const isPortrait = isPortraitOrientation(pageSizeInches), + nonMetric = NON_METRIC_LOCALES.includes(this.l10n.getLanguage()); + let sizeInches = { + width: Math.round(pageSizeInches.width * 100) / 100, + height: Math.round(pageSizeInches.height * 100) / 100 + }; + let sizeMillimeters = { + width: Math.round(pageSizeInches.width * 25.4 * 10) / 10, + height: Math.round(pageSizeInches.height * 25.4 * 10) / 10 + }; + let nameId = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES); + if (!nameId && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) { + const exactMillimeters = { + width: pageSizeInches.width * 25.4, + height: pageSizeInches.height * 25.4 + }; + const intMillimeters = { + width: Math.round(sizeMillimeters.width), + height: Math.round(sizeMillimeters.height) + }; + if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) { + nameId = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES); + if (nameId) { + sizeInches = { + width: Math.round(intMillimeters.width / 25.4 * 100) / 100, + height: Math.round(intMillimeters.height / 25.4 * 100) / 100 + }; + sizeMillimeters = intMillimeters; + } + } + } + const [{ + width, + height + }, 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")]); + return this.l10n.get(name ? "pdfjs-document-properties-page-size-dimension-name-string" : "pdfjs-document-properties-page-size-dimension-string", { + width, + height, + unit, + name, + orientation + }); + } + async #parseDate(metadataDate, infoDate) { + const dateObj = Date.parse(metadataDate) || PDFDateString.toDateObject(infoDate); + return dateObj ? this.l10n.get("pdfjs-document-properties-date-time-string", { + dateObj: dateObj.valueOf() + }) : undefined; + } + #parseLinearization(isLinearized) { + return this.l10n.get(isLinearized ? "pdfjs-document-properties-linearized-yes" : "pdfjs-document-properties-linearized-no"); + } +} + +;// ./web/pdf_find_utils.js + +const CharacterType = { + SPACE: 0, + ALPHA_LETTER: 1, + PUNCT: 2, + HAN_LETTER: 3, + KATAKANA_LETTER: 4, + HIRAGANA_LETTER: 5, + HALFWIDTH_KATAKANA_LETTER: 6, + THAI_LETTER: 7 +}; +function isAlphabeticalScript(charCode) { + return charCode < 0x2e80; +} +function isAscii(charCode) { + return (charCode & 0xff80) === 0; +} +function isAsciiAlpha(charCode) { + return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a; +} +function isAsciiDigit(charCode) { + return charCode >= 0x30 && charCode <= 0x39; +} +function isAsciiSpace(charCode) { + return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a; +} +function isHan(charCode) { + return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff; +} +function isKatakana(charCode) { + return charCode >= 0x30a0 && charCode <= 0x30ff; +} +function isHiragana(charCode) { + return charCode >= 0x3040 && charCode <= 0x309f; +} +function isHalfwidthKatakana(charCode) { + return charCode >= 0xff60 && charCode <= 0xff9f; +} +function isThai(charCode) { + return (charCode & 0xff80) === 0x0e00; +} +function getCharacterType(charCode) { + if (isAlphabeticalScript(charCode)) { + if (isAscii(charCode)) { + if (isAsciiSpace(charCode)) { + return CharacterType.SPACE; + } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) { + return CharacterType.ALPHA_LETTER; + } + return CharacterType.PUNCT; + } else if (isThai(charCode)) { + return CharacterType.THAI_LETTER; + } else if (charCode === 0xa0) { + return CharacterType.SPACE; + } + return CharacterType.ALPHA_LETTER; + } + if (isHan(charCode)) { + return CharacterType.HAN_LETTER; + } else if (isKatakana(charCode)) { + return CharacterType.KATAKANA_LETTER; + } else if (isHiragana(charCode)) { + return CharacterType.HIRAGANA_LETTER; + } else if (isHalfwidthKatakana(charCode)) { + return CharacterType.HALFWIDTH_KATAKANA_LETTER; + } + return CharacterType.ALPHA_LETTER; +} +let NormalizeWithNFKC; +function getNormalizeWithNFKC() { + NormalizeWithNFKC ||= `\xA0¨ª¯²-µ¸-º¼-¾IJ-ijĿ-ŀʼnſDŽ-njDZ-dzʰ-ʸ˘-ËË -ˤʹͺ;΄-΅·Ï-ϖϰ-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-à§à§Ÿà¨³à¨¶à©™-ਜ਼ਫ਼ଡ଼-à­à¸³àº³à»œ-à»à¼Œà½ƒà½à½’བྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-áµáµ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-á¿á¿‰á¿‹á¿-á¿á¿“á¿›á¿-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾â‡-â‰â—âŸâ°-â±â´-₎â‚-ₜ₨℀-℃℅-ℇ℉-â„“â„•-â„–â„™-â„â„ -™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-â…‰â…-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕ 〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇ã‰-㉾㊀-ã¿êšœ-êšê°êŸ±-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-ï¨ï¨ï¨’凞-羽蘒諸逸-都飯-ï©­ï©°-龎ff-stﬓ-ﬗï¬ï¬Ÿ-זּטּ-לּמּנּ-ï­ï­ƒ-ï­„ï­†-ﮱﯓ-ï´½ïµ-ï¶ï¶’-ﷇﷰ-ï·¼ï¸-︙︰-﹄﹇-ï¹’ï¹”-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼï¼-하-ᅦᅧ-ï¿ï¿’-ᅲᅳ-ᅵ¢-₩`; + return NormalizeWithNFKC; +} + +;// ./web/pdf_find_controller.js + + +const FindState = { + FOUND: 0, + NOT_FOUND: 1, + WRAPPED: 2, + PENDING: 3 +}; +const FIND_TIMEOUT = 250; +const MATCH_SCROLL_OFFSET_TOP = -50; +const CHARACTERS_TO_NORMALIZE = { + "\u2010": "-", + "\u2018": "'", + "\u2019": "'", + "\u201A": "'", + "\u201B": "'", + "\u201C": '"', + "\u201D": '"', + "\u201E": '"', + "\u201F": '"', + "\u00BC": "1/4", + "\u00BD": "1/2", + "\u00BE": "3/4" +}; +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]); +let DIACRITICS_EXCEPTION_STR; +const DIACRITICS_REG_EXP = /\p{M}+/gu; +const SPECIAL_CHARS_REG_EXP = /([*+^${}()|[\]\\])|(\p{P}+)|(\s+)|(\p{M})|(\p{L})/gu; +const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u; +const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u; +const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g; +const SYLLABLES_LENGTHS = new Map(); +const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]"; +const NFKC_CHARS_TO_NORMALIZE = new Map(); +let noSyllablesRegExp = null; +let withSyllablesRegExp = null; +function normalize(text, options = {}) { + const syllablePositions = []; + let m; + while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) { + let { + index + } = m; + for (const char of m[0]) { + let len = SYLLABLES_LENGTHS.get(char); + if (!len) { + len = char.normalize("NFD").length; + SYLLABLES_LENGTHS.set(char, len); + } + syllablePositions.push([len, index++]); + } + } + const hasSyllables = syllablePositions.length > 0; + const ignoreDashEOL = options.ignoreDashEOL ?? false; + let normalizationRegex; + if (!hasSyllables && noSyllablesRegExp) { + normalizationRegex = noSyllablesRegExp; + } else if (hasSyllables && withSyllablesRegExp) { + normalizationRegex = withSyllablesRegExp; + } else { + const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join(""); + const toNormalizeWithNFKC = getNormalizeWithNFKC(); + const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])"; + const HKDiacritics = "(?:\u3099|\u309A)"; + const BrokenWord = `\\p{Ll}-\\n(?=\\p{Ll})|\\p{Lu}-\\n(?=\\p{L})`; + const regexps = [`[${replace}]`, `[${toNormalizeWithNFKC}]`, `${HKDiacritics}\\n`, "\\p{M}+(?:-\\n)?", `${BrokenWord}`, "\\S-\\n", `${CJK}\\n`, "\\n", hasSyllables ? FIRST_CHAR_SYLLABLES_REG_EXP : "\\u0000"]; + normalizationRegex = new RegExp(regexps.map(r => `(${r})`).join("|"), "gum"); + if (hasSyllables) { + withSyllablesRegExp = normalizationRegex; + } else { + noSyllablesRegExp = normalizationRegex; + } + } + const rawDiacriticsPositions = []; + while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) { + rawDiacriticsPositions.push([m[0].length, m.index]); + } + let normalized = text.normalize("NFD"); + const positions = [0, 0]; + let rawDiacriticsIndex = 0; + let syllableIndex = 0; + let shift = 0; + let shiftOrigin = 0; + let eol = 0; + let hasDiacritics = false; + normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, p9, i) => { + i -= shiftOrigin; + if (p1) { + const replacement = CHARACTERS_TO_NORMALIZE[p1]; + const jj = replacement.length; + for (let j = 1; j < jj; j++) { + positions.push(i - shift + j, shift - j); + } + shift -= jj - 1; + return replacement; + } + if (p2) { + let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2); + if (!replacement) { + replacement = p2.normalize("NFKC"); + NFKC_CHARS_TO_NORMALIZE.set(p2, replacement); + } + const jj = replacement.length; + for (let j = 1; j < jj; j++) { + positions.push(i - shift + j, shift - j); + } + shift -= jj - 1; + return replacement; + } + if (p3) { + hasDiacritics = true; + if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) { + ++rawDiacriticsIndex; + } else { + positions.push(i - 1 - shift + 1, shift - 1); + shift -= 1; + shiftOrigin += 1; + } + positions.push(i - shift + 1, shift); + shiftOrigin += 1; + eol += 1; + return p3.charAt(0); + } + if (p4) { + const hasTrailingDashEOL = p4.endsWith("\n"); + const len = hasTrailingDashEOL ? p4.length - 2 : p4.length; + hasDiacritics = true; + let jj = len; + if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) { + jj -= rawDiacriticsPositions[rawDiacriticsIndex][0]; + ++rawDiacriticsIndex; + } + for (let j = 1; j <= jj; j++) { + positions.push(i - 1 - shift + j, shift - j); + } + shift -= jj; + shiftOrigin += jj; + if (hasTrailingDashEOL) { + i += len - 1; + positions.push(i - shift + 1, 1 + shift); + shift += 1; + shiftOrigin += 1; + eol += 1; + return p4.slice(0, len); + } + return p4; + } + if (p5) { + if (ignoreDashEOL) { + shiftOrigin += 1; + eol += 1; + return p5.slice(0, -1); + } + const len = p5.length - 2; + positions.push(i - shift + len, 1 + shift); + shift += 1; + shiftOrigin += 1; + eol += 1; + return p5.slice(0, -2); + } + if (p6) { + shiftOrigin += 1; + eol += 1; + return p6.slice(0, -1); + } + if (p7) { + const len = p7.length - 1; + positions.push(i - shift + len, shift); + shiftOrigin += 1; + eol += 1; + return p7.slice(0, -1); + } + if (p8) { + positions.push(i - shift + 1, shift - 1); + shift -= 1; + shiftOrigin += 1; + eol += 1; + return " "; + } + if (i + eol === syllablePositions[syllableIndex]?.[1]) { + const newCharLen = syllablePositions[syllableIndex][0] - 1; + ++syllableIndex; + for (let j = 1; j <= newCharLen; j++) { + positions.push(i - (shift - j), shift - j); + } + shift -= newCharLen; + shiftOrigin += newCharLen; + } + return p9; + }); + positions.push(normalized.length, shift); + const starts = new Uint32Array(positions.length >> 1); + const shifts = new Int32Array(positions.length >> 1); + for (let i = 0, ii = positions.length; i < ii; i += 2) { + starts[i >> 1] = positions[i]; + shifts[i >> 1] = positions[i + 1]; + } + return [normalized, [starts, shifts], hasDiacritics]; +} +function getOriginalIndex(diffs, pos, len) { + if (!diffs) { + return [pos, len]; + } + const [starts, shifts] = diffs; + const start = pos; + const end = pos + len - 1; + let i = binarySearchFirstItem(starts, x => x >= start); + if (starts[i] > start) { + --i; + } + let j = binarySearchFirstItem(starts, x => x >= end, i); + if (starts[j] > end) { + --j; + } + const oldStart = start + shifts[i]; + const oldEnd = end + shifts[j]; + const oldLen = oldEnd + 1 - oldStart; + return [oldStart, oldLen]; +} +class PDFFindController { + #state = null; + #updateMatchesCountOnProgress = true; + #visitedPagesCount = 0; + constructor({ + linkService, + eventBus, + updateMatchesCountOnProgress = true + }) { + this._linkService = linkService; + this._eventBus = eventBus; + this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress; + this.onIsPageVisible = null; + this.#reset(); + eventBus._on("find", this.#onFind.bind(this)); + eventBus._on("findbarclose", this.#onFindBarClose.bind(this)); + } + get highlightMatches() { + return this._highlightMatches; + } + get pageMatches() { + return this._pageMatches; + } + get pageMatchesLength() { + return this._pageMatchesLength; + } + get selected() { + return this._selected; + } + get state() { + return this.#state; + } + setDocument(pdfDocument) { + if (this._pdfDocument) { + this.#reset(); + } + if (!pdfDocument) { + return; + } + this._pdfDocument = pdfDocument; + this._firstPageCapability.resolve(); + } + #onFind(state) { + if (!state) { + return; + } + const pdfDocument = this._pdfDocument; + const { + type + } = state; + if (this.#state === null || this.#shouldDirtyMatch(state)) { + this._dirtyMatch = true; + } + this.#state = state; + if (type !== "highlightallchange") { + this.#updateUIState(FindState.PENDING); + } + this._firstPageCapability.promise.then(() => { + if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) { + return; + } + this.#extractText(); + const findbarClosed = !this._highlightMatches; + const pendingTimeout = !!this._findTimeout; + if (this._findTimeout) { + clearTimeout(this._findTimeout); + this._findTimeout = null; + } + if (!type) { + this._findTimeout = setTimeout(() => { + this.#nextMatch(); + this._findTimeout = null; + }, FIND_TIMEOUT); + } else if (this._dirtyMatch) { + this.#nextMatch(); + } else if (type === "again") { + this.#nextMatch(); + if (findbarClosed && this.#state.highlightAll) { + this.#updateAllPages(); + } + } else if (type === "highlightallchange") { + if (pendingTimeout) { + this.#nextMatch(); + } else { + this._highlightMatches = true; + } + this.#updateAllPages(); + } else { + this.#nextMatch(); + } + }); + } + scrollMatchIntoView({ + element = null, + selectedLeft = 0, + pageIndex = -1, + matchIndex = -1 + }) { + if (!this._scrollMatches || !element) { + return; + } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) { + return; + } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) { + return; + } + this._scrollMatches = false; + const spot = { + top: MATCH_SCROLL_OFFSET_TOP, + left: selectedLeft + }; + scrollIntoView(element, spot, true); + } + #reset() { + this._highlightMatches = false; + this._scrollMatches = false; + this._pdfDocument = null; + this._pageMatches = []; + this._pageMatchesLength = []; + this.#visitedPagesCount = 0; + this.#state = null; + this._selected = { + pageIdx: -1, + matchIdx: -1 + }; + this._offset = { + pageIdx: null, + matchIdx: null, + wrapped: false + }; + this._extractTextPromises = []; + this._pageContents = []; + this._pageDiffs = []; + this._hasDiacritics = []; + this._matchesCountTotal = 0; + this._pagesToSearch = null; + this._pendingFindMatches = new Set(); + this._resumePageIdx = null; + this._dirtyMatch = false; + clearTimeout(this._findTimeout); + this._findTimeout = null; + this._firstPageCapability = Promise.withResolvers(); + } + get #query() { + const { + query + } = this.#state; + if (typeof query === "string") { + if (query !== this._rawQuery) { + this._rawQuery = query; + [this._normalizedQuery] = normalize(query); + } + return this._normalizedQuery; + } + return (query || []).filter(q => !!q).map(q => normalize(q)[0]); + } + #shouldDirtyMatch(state) { + const newQuery = state.query, + prevQuery = this.#state.query; + const newType = typeof newQuery, + prevType = typeof prevQuery; + if (newType !== prevType) { + return true; + } + if (newType === "string") { + if (newQuery !== prevQuery) { + return true; + } + } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) { + return true; + } + switch (state.type) { + case "again": + const pageNumber = this._selected.pageIdx + 1; + const linkService = this._linkService; + return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true); + case "highlightallchange": + return false; + } + return true; + } + #isEntireWord(content, startIdx, length) { + let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP); + if (match) { + const first = content.charCodeAt(startIdx); + const limit = match[1].charCodeAt(0); + if (getCharacterType(first) === getCharacterType(limit)) { + return false; + } + } + match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP); + if (match) { + const last = content.charCodeAt(startIdx + length - 1); + const limit = match[1].charCodeAt(0); + if (getCharacterType(last) === getCharacterType(limit)) { + return false; + } + } + return true; + } + #convertToRegExpString(query, hasDiacritics) { + const { + matchDiacritics + } = this.#state; + let isUnicode = false; + const addExtraWhitespaces = (original, fixed) => { + if (original === query) { + return fixed; + } + if (query.startsWith(original)) { + return `${fixed}[ ]*`; + } + if (query.endsWith(original)) { + return `[ ]*${fixed}`; + } + return `[ ]*${fixed}[ ]*`; + }; + query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => { + if (p1) { + return addExtraWhitespaces(p1, `\\${p1}`); + } + if (p2) { + return addExtraWhitespaces(p2, p2.replaceAll(/[.?]/g, "\\$&")); + } + if (p3) { + return "[ ]+"; + } + if (matchDiacritics) { + return p4 || p5; + } + if (p4) { + return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : ""; + } + if (hasDiacritics) { + isUnicode = true; + return `${p5}\\p{M}*`; + } + return p5; + }); + const trailingSpaces = "[ ]*"; + if (query.endsWith(trailingSpaces)) { + query = query.slice(0, query.length - trailingSpaces.length); + } + if (matchDiacritics) { + if (hasDiacritics) { + DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION); + isUnicode = true; + query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`; + } + } + return [isUnicode, query]; + } + #calculateMatch(pageIndex) { + if (!this.#state) { + return; + } + const query = this.#query; + if (query.length === 0) { + return; + } + const pageContent = this._pageContents[pageIndex]; + const matcherResult = this.match(query, pageContent, pageIndex); + const matches = this._pageMatches[pageIndex] = []; + const matchesLength = this._pageMatchesLength[pageIndex] = []; + const diffs = this._pageDiffs[pageIndex]; + matcherResult?.forEach(({ + index, + length + }) => { + const [matchPos, matchLen] = getOriginalIndex(diffs, index, length); + if (matchLen) { + matches.push(matchPos); + matchesLength.push(matchLen); + } + }); + if (this.#state.highlightAll) { + this.#updatePage(pageIndex); + } + if (this._resumePageIdx === pageIndex) { + this._resumePageIdx = null; + this.#nextPageMatch(); + } + const pageMatchesCount = matches.length; + this._matchesCountTotal += pageMatchesCount; + if (this.#updateMatchesCountOnProgress) { + if (pageMatchesCount > 0) { + this.#updateUIResultsCount(); + } + } else if (++this.#visitedPagesCount === this._linkService.pagesCount) { + this.#updateUIResultsCount(); + } + } + match(query, pageContent, pageIndex) { + const hasDiacritics = this._hasDiacritics[pageIndex]; + let isUnicode = false; + if (typeof query === "string") { + [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics); + } else { + query = query.sort().reverse().map(q => { + const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics); + isUnicode ||= isUnicodePart; + return `(${queryPart})`; + }).join("|"); + } + if (!query) { + return undefined; + } + const { + caseSensitive, + entireWord + } = this.#state; + const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`; + query = new RegExp(query, flags); + const matches = []; + let match; + while ((match = query.exec(pageContent)) !== null) { + if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) { + continue; + } + matches.push({ + index: match.index, + length: match[0].length + }); + } + return matches; + } + #extractText() { + if (this._extractTextPromises.length > 0) { + return; + } + let deferred = Promise.resolve(); + const textOptions = { + disableNormalization: true + }; + const pdfDoc = this._pdfDocument; + for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) { + const { + promise, + resolve + } = Promise.withResolvers(); + this._extractTextPromises[i] = promise; + deferred = deferred.then(async () => { + if (pdfDoc !== this._pdfDocument) { + resolve(); + return; + } + await pdfDoc.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => { + const strBuf = []; + for (const textItem of textContent.items) { + strBuf.push(textItem.str); + if (textItem.hasEOL) { + strBuf.push("\n"); + } + } + [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join("")); + resolve(); + }, reason => { + console.error(`Unable to get text content for page ${i + 1}`, reason); + this._pageContents[i] = ""; + this._pageDiffs[i] = null; + this._hasDiacritics[i] = false; + resolve(); + }); + }); + } + } + #updatePage(index) { + if (this._scrollMatches && this._selected.pageIdx === index) { + this._linkService.page = index + 1; + } + this._eventBus.dispatch("updatetextlayermatches", { + source: this, + pageIndex: index + }); + } + #updateAllPages() { + this._eventBus.dispatch("updatetextlayermatches", { + source: this, + pageIndex: -1 + }); + } + #nextMatch() { + const previous = this.#state.findPrevious; + const currentPageIndex = this._linkService.page - 1; + const numPages = this._linkService.pagesCount; + this._highlightMatches = true; + if (this._dirtyMatch) { + this._dirtyMatch = false; + this._selected.pageIdx = this._selected.matchIdx = -1; + this._offset.pageIdx = currentPageIndex; + this._offset.matchIdx = null; + this._offset.wrapped = false; + this._resumePageIdx = null; + this._pageMatches.length = 0; + this._pageMatchesLength.length = 0; + this.#visitedPagesCount = 0; + this._matchesCountTotal = 0; + this.#updateAllPages(); + for (let i = 0; i < numPages; i++) { + if (this._pendingFindMatches.has(i)) { + continue; + } + this._pendingFindMatches.add(i); + this._extractTextPromises[i].then(() => { + this._pendingFindMatches.delete(i); + this.#calculateMatch(i); + }); + } + } + const query = this.#query; + if (query.length === 0) { + this.#updateUIState(FindState.FOUND); + return; + } + if (this._resumePageIdx) { + return; + } + const offset = this._offset; + this._pagesToSearch = numPages; + if (offset.matchIdx !== null) { + const numPageMatches = this._pageMatches[offset.pageIdx].length; + if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) { + offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1; + this.#updateMatch(true); + return; + } + this.#advanceOffsetPage(previous); + } + this.#nextPageMatch(); + } + #matchesReady(matches) { + const offset = this._offset; + const numMatches = matches.length; + const previous = this.#state.findPrevious; + if (numMatches) { + offset.matchIdx = previous ? numMatches - 1 : 0; + this.#updateMatch(true); + return true; + } + this.#advanceOffsetPage(previous); + if (offset.wrapped) { + offset.matchIdx = null; + if (this._pagesToSearch < 0) { + this.#updateMatch(false); + return true; + } + } + return false; + } + #nextPageMatch() { + if (this._resumePageIdx !== null) { + console.error("There can only be one pending page."); + } + let matches = null; + do { + const pageIdx = this._offset.pageIdx; + matches = this._pageMatches[pageIdx]; + if (!matches) { + this._resumePageIdx = pageIdx; + break; + } + } while (!this.#matchesReady(matches)); + } + #advanceOffsetPage(previous) { + const offset = this._offset; + const numPages = this._linkService.pagesCount; + offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1; + offset.matchIdx = null; + this._pagesToSearch--; + if (offset.pageIdx >= numPages || offset.pageIdx < 0) { + offset.pageIdx = previous ? numPages - 1 : 0; + offset.wrapped = true; + } + } + #updateMatch(found = false) { + let state = FindState.NOT_FOUND; + const wrapped = this._offset.wrapped; + this._offset.wrapped = false; + if (found) { + const previousPage = this._selected.pageIdx; + this._selected.pageIdx = this._offset.pageIdx; + this._selected.matchIdx = this._offset.matchIdx; + state = wrapped ? FindState.WRAPPED : FindState.FOUND; + if (previousPage !== -1 && previousPage !== this._selected.pageIdx) { + this.#updatePage(previousPage); + } + } + this.#updateUIState(state, this.#state.findPrevious); + if (this._selected.pageIdx !== -1) { + this._scrollMatches = true; + this.#updatePage(this._selected.pageIdx); + } + } + #onFindBarClose(evt) { + const pdfDocument = this._pdfDocument; + this._firstPageCapability.promise.then(() => { + if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) { + return; + } + if (this._findTimeout) { + clearTimeout(this._findTimeout); + this._findTimeout = null; + } + if (this._resumePageIdx) { + this._resumePageIdx = null; + this._dirtyMatch = true; + } + this.#updateUIState(FindState.FOUND); + this._highlightMatches = false; + this.#updateAllPages(); + }); + } + #requestMatchesCount() { + const { + pageIdx, + matchIdx + } = this._selected; + let current = 0, + total = this._matchesCountTotal; + if (matchIdx !== -1) { + for (let i = 0; i < pageIdx; i++) { + current += this._pageMatches[i]?.length || 0; + } + current += matchIdx + 1; + } + if (current < 1 || current > total) { + current = total = 0; + } + return { + current, + total + }; + } + #updateUIResultsCount() { + this._eventBus.dispatch("updatefindmatchescount", { + source: this, + matchesCount: this.#requestMatchesCount() + }); + } + #updateUIState(state, previous = false) { + if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) { + return; + } + this._eventBus.dispatch("updatefindcontrolstate", { + source: this, + state, + previous, + entireWord: this.#state?.entireWord ?? null, + matchesCount: this.#requestMatchesCount(), + rawQuery: this.#state?.query ?? null + }); + } +} + +;// ./web/pdf_find_bar.js + + +const MATCHES_COUNT_LIMIT = 1000; +class PDFFindBar { + #mainContainer; + #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this)); + constructor(options, mainContainer, eventBus) { + this.opened = false; + this.bar = options.bar; + this.toggleButton = options.toggleButton; + this.findField = options.findField; + this.highlightAll = options.highlightAllCheckbox; + this.caseSensitive = options.caseSensitiveCheckbox; + this.matchDiacritics = options.matchDiacriticsCheckbox; + this.entireWord = options.entireWordCheckbox; + this.findMsg = options.findMsg; + this.findResultsCount = options.findResultsCount; + this.findPreviousButton = options.findPreviousButton; + this.findNextButton = options.findNextButton; + this.eventBus = eventBus; + this.#mainContainer = mainContainer; + const checkedInputs = new Map([[this.highlightAll, "highlightallchange"], [this.caseSensitive, "casesensitivitychange"], [this.entireWord, "entirewordchange"], [this.matchDiacritics, "diacriticmatchingchange"]]); + this.toggleButton.addEventListener("click", () => { + this.toggle(); + }); + this.findField.addEventListener("input", () => { + this.dispatchEvent(""); + }); + this.bar.addEventListener("keydown", ({ + keyCode, + shiftKey, + target + }) => { + switch (keyCode) { + case 13: + if (target === this.findField) { + this.dispatchEvent("again", shiftKey); + } else if (checkedInputs.has(target)) { + target.checked = !target.checked; + this.dispatchEvent(checkedInputs.get(target)); + } + break; + case 27: + this.close(); + break; + } + }); + this.findPreviousButton.addEventListener("click", () => { + this.dispatchEvent("again", true); + }); + this.findNextButton.addEventListener("click", () => { + this.dispatchEvent("again", false); + }); + for (const [elem, evtName] of checkedInputs) { + elem.addEventListener("click", () => { + this.dispatchEvent(evtName); + }); + } + } + reset() { + this.updateUIState(); + } + dispatchEvent(type, findPrev = false) { + this.eventBus.dispatch("find", { + source: this, + type, + query: this.findField.value, + caseSensitive: this.caseSensitive.checked, + entireWord: this.entireWord.checked, + highlightAll: this.highlightAll.checked, + findPrevious: findPrev, + matchDiacritics: this.matchDiacritics.checked + }); + } + updateUIState(state, previous, matchesCount) { + const { + findField, + findMsg + } = this; + let findMsgId = "", + status = ""; + switch (state) { + case FindState.FOUND: + break; + case FindState.PENDING: + status = "pending"; + break; + case FindState.NOT_FOUND: + findMsgId = "pdfjs-find-not-found"; + status = "notFound"; + break; + case FindState.WRAPPED: + findMsgId = previous ? "pdfjs-find-reached-top" : "pdfjs-find-reached-bottom"; + break; + } + findField.setAttribute("data-status", status); + findField.setAttribute("aria-invalid", state === FindState.NOT_FOUND); + findMsg.setAttribute("data-status", status); + if (findMsgId) { + findMsg.setAttribute("data-l10n-id", findMsgId); + } else { + findMsg.removeAttribute("data-l10n-id"); + findMsg.textContent = ""; + } + this.updateResultsCount(matchesCount); + } + updateResultsCount({ + current = 0, + total = 0 + } = {}) { + const { + findResultsCount + } = this; + if (total > 0) { + const limit = MATCHES_COUNT_LIMIT; + findResultsCount.setAttribute("data-l10n-id", total > limit ? "pdfjs-find-match-count-limit" : "pdfjs-find-match-count"); + findResultsCount.setAttribute("data-l10n-args", JSON.stringify({ + limit, + current, + total + })); + } else { + findResultsCount.removeAttribute("data-l10n-id"); + findResultsCount.textContent = ""; + } + } + open() { + if (!this.opened) { + this.#resizeObserver.observe(this.#mainContainer); + this.#resizeObserver.observe(this.bar); + this.opened = true; + toggleExpandedBtn(this.toggleButton, true, this.bar); + } + this.findField.select(); + this.findField.focus(); + } + close() { + if (!this.opened) { + return; + } + this.#resizeObserver.disconnect(); + this.opened = false; + toggleExpandedBtn(this.toggleButton, false, this.bar); + this.eventBus.dispatch("findbarclose", { + source: this + }); + } + toggle() { + if (this.opened) { + this.close(); + } else { + this.open(); + } + } + #resizeObserverCallback() { + const { + bar + } = this; + bar.classList.remove("wrapContainers"); + const findbarHeight = bar.clientHeight; + const inputContainerHeight = bar.firstElementChild.clientHeight; + if (findbarHeight > inputContainerHeight) { + bar.classList.add("wrapContainers"); + } + } +} + +;// ./web/pdf_history.js + + + +const HASH_CHANGE_TIMEOUT = 1000; +const POSITION_UPDATED_THRESHOLD = 50; +const UPDATE_VIEWAREA_TIMEOUT = 1000; +function getCurrentHash() { + return document.location.hash; +} +class PDFHistory { + #eventAbortController = null; + constructor({ + linkService, + eventBus + }) { + this.linkService = linkService; + this.eventBus = eventBus; + this._initialized = false; + this._fingerprint = ""; + this.reset(); + this.eventBus._on("pagesinit", () => { + this._isPagesLoaded = false; + this.eventBus._on("pagesloaded", evt => { + this._isPagesLoaded = !!evt.pagesCount; + }, { + once: true + }); + }); + } + initialize({ + fingerprint, + resetHistory = false, + updateUrl = false + }) { + if (!fingerprint || typeof fingerprint !== "string") { + console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.'); + return; + } + if (this._initialized) { + this.reset(); + } + const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint; + this._fingerprint = fingerprint; + this._updateUrl = updateUrl === true; + this._initialized = true; + this.#bindEvents(); + const state = window.history.state; + this._popStateInProgress = false; + this._blockHashChange = 0; + this._currentHash = getCurrentHash(); + this._numPositionUpdates = 0; + this._uid = this._maxUid = 0; + this._destination = null; + this._position = null; + if (!this.#isValidState(state, true) || resetHistory) { + const { + hash, + page, + rotation + } = this.#parseCurrentHash(true); + if (!hash || reInitialized || resetHistory) { + this.#pushOrReplaceState(null, true); + return; + } + this.#pushOrReplaceState({ + hash, + page, + rotation + }, true); + return; + } + const destination = state.destination; + this.#updateInternalState(destination, state.uid, true); + if (destination.rotation !== undefined) { + this._initialRotation = destination.rotation; + } + if (destination.dest) { + this._initialBookmark = JSON.stringify(destination.dest); + this._destination.page = null; + } else if (destination.hash) { + this._initialBookmark = destination.hash; + } else if (destination.page) { + this._initialBookmark = `page=${destination.page}`; + } + } + reset() { + if (this._initialized) { + this.#pageHide(); + this._initialized = false; + this.#unbindEvents(); + } + if (this._updateViewareaTimeout) { + clearTimeout(this._updateViewareaTimeout); + this._updateViewareaTimeout = null; + } + this._initialBookmark = null; + this._initialRotation = null; + } + push({ + namedDest = null, + explicitDest, + pageNumber + }) { + if (!this._initialized) { + return; + } + if (namedDest && typeof namedDest !== "string") { + console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`); + return; + } else if (!Array.isArray(explicitDest)) { + console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`); + return; + } else if (!this.#isValidPage(pageNumber)) { + if (pageNumber !== null || this._destination) { + console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`); + return; + } + } + const hash = namedDest || JSON.stringify(explicitDest); + if (!hash) { + return; + } + let forceReplace = false; + if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) { + if (this._destination.page) { + return; + } + forceReplace = true; + } + if (this._popStateInProgress && !forceReplace) { + return; + } + this.#pushOrReplaceState({ + dest: explicitDest, + hash, + page: pageNumber, + rotation: this.linkService.rotation + }, forceReplace); + if (!this._popStateInProgress) { + this._popStateInProgress = true; + Promise.resolve().then(() => { + this._popStateInProgress = false; + }); + } + } + pushPage(pageNumber) { + if (!this._initialized) { + return; + } + if (!this.#isValidPage(pageNumber)) { + console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`); + return; + } + if (this._destination?.page === pageNumber) { + return; + } + if (this._popStateInProgress) { + return; + } + this.#pushOrReplaceState({ + dest: null, + hash: `page=${pageNumber}`, + page: pageNumber, + rotation: this.linkService.rotation + }); + if (!this._popStateInProgress) { + this._popStateInProgress = true; + Promise.resolve().then(() => { + this._popStateInProgress = false; + }); + } + } + pushCurrentPosition() { + if (!this._initialized || this._popStateInProgress) { + return; + } + this.#tryPushCurrentPosition(); + } + back() { + if (!this._initialized || this._popStateInProgress) { + return; + } + const state = window.history.state; + if (this.#isValidState(state) && state.uid > 0) { + window.history.back(); + } + } + forward() { + if (!this._initialized || this._popStateInProgress) { + return; + } + const state = window.history.state; + if (this.#isValidState(state) && state.uid < this._maxUid) { + window.history.forward(); + } + } + get popStateInProgress() { + return this._initialized && (this._popStateInProgress || this._blockHashChange > 0); + } + get initialBookmark() { + return this._initialized ? this._initialBookmark : null; + } + get initialRotation() { + return this._initialized ? this._initialRotation : null; + } + #pushOrReplaceState(destination, forceReplace = false) { + const shouldReplace = forceReplace || !this._destination; + const newState = { + fingerprint: this._fingerprint, + uid: shouldReplace ? this._uid : this._uid + 1, + destination + }; + this.#updateInternalState(destination, newState.uid); + let newUrl; + if (this._updateUrl && destination?.hash) { + const { + href, + protocol + } = document.location; + if (protocol !== "file:") { + newUrl = updateUrlHash(href, destination.hash); + } + } + if (shouldReplace) { + window.history.replaceState(newState, "", newUrl); + } else { + window.history.pushState(newState, "", newUrl); + } + } + #tryPushCurrentPosition(temporary = false) { + if (!this._position) { + return; + } + let position = this._position; + if (temporary) { + position = Object.assign(Object.create(null), this._position); + position.temporary = true; + } + if (!this._destination) { + this.#pushOrReplaceState(position); + return; + } + if (this._destination.temporary) { + this.#pushOrReplaceState(position, true); + return; + } + if (this._destination.hash === position.hash) { + return; + } + if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) { + return; + } + let forceReplace = false; + if (this._destination.page >= position.first && this._destination.page <= position.page) { + if (this._destination.dest !== undefined || !this._destination.first) { + return; + } + forceReplace = true; + } + this.#pushOrReplaceState(position, forceReplace); + } + #isValidPage(val) { + return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount; + } + #isValidState(state, checkReload = false) { + if (!state) { + return false; + } + if (state.fingerprint !== this._fingerprint) { + if (checkReload) { + if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) { + return false; + } + const [perfEntry] = performance.getEntriesByType("navigation"); + if (perfEntry?.type !== "reload") { + return false; + } + } else { + return false; + } + } + if (!Number.isInteger(state.uid) || state.uid < 0) { + return false; + } + if (state.destination === null || typeof state.destination !== "object") { + return false; + } + return true; + } + #updateInternalState(destination, uid, removeTemporary = false) { + if (this._updateViewareaTimeout) { + clearTimeout(this._updateViewareaTimeout); + this._updateViewareaTimeout = null; + } + if (removeTemporary && destination?.temporary) { + delete destination.temporary; + } + this._destination = destination; + this._uid = uid; + this._maxUid = Math.max(this._maxUid, uid); + this._numPositionUpdates = 0; + } + #parseCurrentHash(checkNameddest = false) { + const hash = unescape(getCurrentHash()).substring(1); + const params = parseQueryString(hash); + const nameddest = params.get("nameddest") || ""; + let page = params.get("page") | 0; + if (!this.#isValidPage(page) || checkNameddest && nameddest.length > 0) { + page = null; + } + return { + hash, + page, + rotation: this.linkService.rotation + }; + } + #updateViewarea({ + location + }) { + if (this._updateViewareaTimeout) { + clearTimeout(this._updateViewareaTimeout); + this._updateViewareaTimeout = null; + } + this._position = { + hash: location.pdfOpenParams.substring(1), + page: this.linkService.page, + first: location.pageNumber, + rotation: location.rotation + }; + if (this._popStateInProgress) { + return; + } + if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) { + this._numPositionUpdates++; + } + if (UPDATE_VIEWAREA_TIMEOUT > 0) { + this._updateViewareaTimeout = setTimeout(() => { + if (!this._popStateInProgress) { + this.#tryPushCurrentPosition(true); + } + this._updateViewareaTimeout = null; + }, UPDATE_VIEWAREA_TIMEOUT); + } + } + #popState({ + state + }) { + const newHash = getCurrentHash(), + hashChanged = this._currentHash !== newHash; + this._currentHash = newHash; + if (!state) { + this._uid++; + const { + hash, + page, + rotation + } = this.#parseCurrentHash(); + this.#pushOrReplaceState({ + hash, + page, + rotation + }, true); + return; + } + if (!this.#isValidState(state)) { + return; + } + this._popStateInProgress = true; + if (hashChanged) { + this._blockHashChange++; + waitOnEventOrTimeout({ + target: window, + name: "hashchange", + delay: HASH_CHANGE_TIMEOUT + }).then(() => { + this._blockHashChange--; + }); + } + const destination = state.destination; + this.#updateInternalState(destination, state.uid, true); + if (isValidRotation(destination.rotation)) { + this.linkService.rotation = destination.rotation; + } + if (destination.dest) { + this.linkService.goToDestination(destination.dest); + } else if (destination.hash) { + this.linkService.setHash(destination.hash); + } else if (destination.page) { + this.linkService.page = destination.page; + } + Promise.resolve().then(() => { + this._popStateInProgress = false; + }); + } + #pageHide() { + if (!this._destination || this._destination.temporary) { + this.#tryPushCurrentPosition(); + } + } + #bindEvents() { + if (this.#eventAbortController) { + return; + } + this.#eventAbortController = new AbortController(); + const { + signal + } = this.#eventAbortController; + this.eventBus._on("updateviewarea", this.#updateViewarea.bind(this), { + signal + }); + window.addEventListener("popstate", this.#popState.bind(this), { + signal + }); + window.addEventListener("pagehide", this.#pageHide.bind(this), { + signal + }); + } + #unbindEvents() { + this.#eventAbortController?.abort(); + this.#eventAbortController = null; + } +} +function isDestHashesEqual(destHash, pushHash) { + if (typeof destHash !== "string" || typeof pushHash !== "string") { + return false; + } + if (destHash === pushHash) { + return true; + } + const nameddest = parseQueryString(destHash).get("nameddest"); + if (nameddest === pushHash) { + return true; + } + return false; +} +function isDestArraysEqual(firstDest, secondDest) { + function isEntryEqual(first, second) { + if (typeof first !== typeof second) { + return false; + } + if (Array.isArray(first) || Array.isArray(second)) { + return false; + } + if (first !== null && typeof first === "object" && second !== null) { + if (Object.keys(first).length !== Object.keys(second).length) { + return false; + } + for (const key in first) { + if (!isEntryEqual(first[key], second[key])) { + return false; + } + } + return true; + } + return first === second || Number.isNaN(first) && Number.isNaN(second); + } + if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) { + return false; + } + if (firstDest.length !== secondDest.length) { + return false; + } + for (let i = 0, ii = firstDest.length; i < ii; i++) { + if (!isEntryEqual(firstDest[i], secondDest[i])) { + return false; + } + } + return true; +} + +;// ./web/pdf_layer_viewer.js + +class PDFLayerViewer extends BaseTreeViewer { + constructor(options) { + super(options); + this.eventBus._on("optionalcontentconfigchanged", evt => { + this.#updateLayers(evt.promise); + }); + this.eventBus._on("resetlayers", () => { + this.#updateLayers(); + }); + this.eventBus._on("togglelayerstree", this._toggleAllTreeItems.bind(this)); + } + reset() { + super.reset(); + this._optionalContentConfig = null; + this._optionalContentVisibility?.clear(); + this._optionalContentVisibility = null; + } + _dispatchEvent(layersCount) { + this.eventBus.dispatch("layersloaded", { + source: this, + layersCount + }); + } + _bindLink(element, { + groupId, + input + }) { + const setVisibility = () => { + const visible = input.checked; + this._optionalContentConfig.setVisibility(groupId, visible); + const cached = this._optionalContentVisibility.get(groupId); + if (cached) { + cached.visible = visible; + } + this.eventBus.dispatch("optionalcontentconfig", { + source: this, + promise: Promise.resolve(this._optionalContentConfig) + }); + }; + element.onclick = evt => { + if (evt.target === input) { + setVisibility(); + return true; + } else if (evt.target !== element) { + return true; + } + input.checked = !input.checked; + setVisibility(); + return false; + }; + } + _setNestedName(element, { + name = null + }) { + if (typeof name === "string") { + element.textContent = this._normalizeTextContent(name); + return; + } + element.setAttribute("data-l10n-id", "pdfjs-additional-layers"); + element.style.fontStyle = "italic"; + this._l10n.translateOnce(element); + } + _addToggleButton(div, { + name = null + }) { + super._addToggleButton(div, name === null); + } + _toggleAllTreeItems() { + if (!this._optionalContentConfig) { + return; + } + super._toggleAllTreeItems(); + } + render({ + optionalContentConfig, + pdfDocument + }) { + if (this._optionalContentConfig) { + this.reset(); + } + this._optionalContentConfig = optionalContentConfig || null; + this._pdfDocument = pdfDocument || null; + const groups = optionalContentConfig?.getOrder(); + if (!groups) { + this._dispatchEvent(0); + return; + } + this._optionalContentVisibility = new Map(); + const fragment = document.createDocumentFragment(), + queue = [{ + parent: fragment, + groups + }]; + let layersCount = 0, + hasAnyNesting = false; + while (queue.length > 0) { + const levelData = queue.shift(); + for (const groupId of levelData.groups) { + const div = document.createElement("div"); + div.className = "treeItem"; + const element = document.createElement("a"); + div.append(element); + if (typeof groupId === "object") { + hasAnyNesting = true; + this._addToggleButton(div, groupId); + this._setNestedName(element, groupId); + const itemsDiv = document.createElement("div"); + itemsDiv.className = "treeItems"; + div.append(itemsDiv); + queue.push({ + parent: itemsDiv, + groups: groupId.order + }); + } else { + const group = optionalContentConfig.getGroup(groupId); + const input = document.createElement("input"); + this._bindLink(element, { + groupId, + input + }); + input.type = "checkbox"; + input.checked = group.visible; + this._optionalContentVisibility.set(groupId, { + input, + visible: input.checked + }); + const label = document.createElement("label"); + label.textContent = this._normalizeTextContent(group.name); + label.append(input); + element.append(label); + layersCount++; + } + levelData.parent.append(div); + } + } + this._finishRendering(fragment, layersCount, hasAnyNesting); + } + async #updateLayers(promise = null) { + if (!this._optionalContentConfig) { + return; + } + const pdfDocument = this._pdfDocument; + const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig({ + intent: "display" + })); + if (pdfDocument !== this._pdfDocument) { + return; + } + if (promise) { + for (const [groupId, cached] of this._optionalContentVisibility) { + const group = optionalContentConfig.getGroup(groupId); + if (group && cached.visible !== group.visible) { + cached.input.checked = cached.visible = !cached.visible; + } + } + return; + } + this.eventBus.dispatch("optionalcontentconfig", { + source: this, + promise: Promise.resolve(optionalContentConfig) + }); + this.render({ + optionalContentConfig, + pdfDocument: this._pdfDocument + }); + } +} + +;// ./web/pdf_outline_viewer.js + + +class PDFOutlineViewer extends BaseTreeViewer { + constructor(options) { + super(options); + this.linkService = options.linkService; + this.downloadManager = options.downloadManager; + this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this)); + this.eventBus._on("currentoutlineitem", this._currentOutlineItem.bind(this)); + this.eventBus._on("pagechanging", evt => { + this._currentPageNumber = evt.pageNumber; + }); + this.eventBus._on("pagesloaded", evt => { + this._isPagesLoaded = !!evt.pagesCount; + this._currentOutlineItemCapability?.resolve(this._isPagesLoaded); + }); + this.eventBus._on("sidebarviewchanged", evt => { + this._sidebarView = evt.view; + }); + } + reset() { + super.reset(); + this._outline = null; + this._pageNumberToDestHashCapability = null; + this._currentPageNumber = 1; + this._isPagesLoaded = null; + this._currentOutlineItemCapability?.resolve(false); + this._currentOutlineItemCapability = null; + } + _dispatchEvent(outlineCount) { + this._currentOutlineItemCapability = Promise.withResolvers(); + if (outlineCount === 0 || this._pdfDocument?.loadingParams.disableAutoFetch) { + this._currentOutlineItemCapability.resolve(false); + } else if (this._isPagesLoaded !== null) { + this._currentOutlineItemCapability.resolve(this._isPagesLoaded); + } + this.eventBus.dispatch("outlineloaded", { + source: this, + outlineCount, + currentOutlineItemPromise: this._currentOutlineItemCapability.promise + }); + } + _bindLink(element, { + url, + newWindow, + action, + attachment, + dest, + setOCGState + }) { + const { + linkService + } = this; + if (url) { + linkService.addLinkAttributes(element, url, newWindow); + return; + } + if (action) { + element.href = linkService.getAnchorUrl(""); + element.onclick = () => { + linkService.executeNamedAction(action); + return false; + }; + return; + } + if (attachment) { + element.href = linkService.getAnchorUrl(""); + element.onclick = () => { + this.downloadManager.openOrDownloadData(attachment.content, attachment.filename); + return false; + }; + return; + } + if (setOCGState) { + element.href = linkService.getAnchorUrl(""); + element.onclick = () => { + linkService.executeSetOCGState(setOCGState); + return false; + }; + return; + } + element.href = linkService.getDestinationHash(dest); + element.onclick = evt => { + this._updateCurrentTreeItem(evt.target.parentNode); + if (dest) { + linkService.goToDestination(dest); + } + return false; + }; + } + _setStyles(element, { + bold, + italic + }) { + if (bold) { + element.style.fontWeight = "bold"; + } + if (italic) { + element.style.fontStyle = "italic"; + } + } + _addToggleButton(div, { + count, + items + }) { + let hidden = false; + if (count < 0) { + let totalCount = items.length; + if (totalCount > 0) { + const queue = [...items]; + while (queue.length > 0) { + const { + count: nestedCount, + items: nestedItems + } = queue.shift(); + if (nestedCount > 0 && nestedItems.length > 0) { + totalCount += nestedItems.length; + queue.push(...nestedItems); + } + } + } + if (Math.abs(count) === totalCount) { + hidden = true; + } + } + super._addToggleButton(div, hidden); + } + _toggleAllTreeItems() { + if (!this._outline) { + return; + } + super._toggleAllTreeItems(); + } + render({ + outline, + pdfDocument + }) { + if (this._outline) { + this.reset(); + } + this._outline = outline || null; + this._pdfDocument = pdfDocument || null; + if (!outline) { + this._dispatchEvent(0); + return; + } + const fragment = document.createDocumentFragment(); + const queue = [{ + parent: fragment, + items: outline + }]; + let outlineCount = 0, + hasAnyNesting = false; + while (queue.length > 0) { + const levelData = queue.shift(); + for (const item of levelData.items) { + const div = document.createElement("div"); + div.className = "treeItem"; + const element = document.createElement("a"); + this._bindLink(element, item); + this._setStyles(element, item); + element.textContent = this._normalizeTextContent(item.title); + div.append(element); + if (item.items.length > 0) { + hasAnyNesting = true; + this._addToggleButton(div, item); + const itemsDiv = document.createElement("div"); + itemsDiv.className = "treeItems"; + div.append(itemsDiv); + queue.push({ + parent: itemsDiv, + items: item.items + }); + } + levelData.parent.append(div); + outlineCount++; + } + } + this._finishRendering(fragment, outlineCount, hasAnyNesting); + } + async _currentOutlineItem() { + if (!this._isPagesLoaded) { + throw new Error("_currentOutlineItem: All pages have not been loaded."); + } + if (!this._outline || !this._pdfDocument) { + return; + } + const pageNumberToDestHash = await this._getPageNumberToDestHash(this._pdfDocument); + if (!pageNumberToDestHash) { + return; + } + this._updateCurrentTreeItem(null); + if (this._sidebarView !== SidebarView.OUTLINE) { + return; + } + for (let i = this._currentPageNumber; i > 0; i--) { + const destHash = pageNumberToDestHash.get(i); + if (!destHash) { + continue; + } + const linkElement = this.container.querySelector(`a[href="${destHash}"]`); + if (!linkElement) { + continue; + } + this._scrollToCurrentTreeItem(linkElement.parentNode); + break; + } + } + async _getPageNumberToDestHash(pdfDocument) { + if (this._pageNumberToDestHashCapability) { + return this._pageNumberToDestHashCapability.promise; + } + this._pageNumberToDestHashCapability = Promise.withResolvers(); + const pageNumberToDestHash = new Map(), + pageNumberNesting = new Map(); + const queue = [{ + nesting: 0, + items: this._outline + }]; + while (queue.length > 0) { + const levelData = queue.shift(), + currentNesting = levelData.nesting; + for (const { + dest, + items + } of levelData.items) { + let explicitDest, pageNumber; + if (typeof dest === "string") { + explicitDest = await pdfDocument.getDestination(dest); + if (pdfDocument !== this._pdfDocument) { + return null; + } + } else { + explicitDest = dest; + } + if (Array.isArray(explicitDest)) { + const [destRef] = explicitDest; + if (destRef && typeof destRef === "object") { + pageNumber = pdfDocument.cachedPageNumber(destRef); + } else if (Number.isInteger(destRef)) { + pageNumber = destRef + 1; + } + if (Number.isInteger(pageNumber) && (!pageNumberToDestHash.has(pageNumber) || currentNesting > pageNumberNesting.get(pageNumber))) { + const destHash = this.linkService.getDestinationHash(dest); + pageNumberToDestHash.set(pageNumber, destHash); + pageNumberNesting.set(pageNumber, currentNesting); + } + } + if (items.length > 0) { + queue.push({ + nesting: currentNesting + 1, + items + }); + } + } + } + this._pageNumberToDestHashCapability.resolve(pageNumberToDestHash.size > 0 ? pageNumberToDestHash : null); + return this._pageNumberToDestHashCapability.promise; + } +} + +;// ./web/pdf_presentation_mode.js + + +const DELAY_BEFORE_HIDING_CONTROLS = 3000; +const ACTIVE_SELECTOR = "pdfPresentationMode"; +const CONTROLS_SELECTOR = "pdfPresentationModeControls"; +const MOUSE_SCROLL_COOLDOWN_TIME = 50; +const PAGE_SWITCH_THRESHOLD = 0.1; +const SWIPE_MIN_DISTANCE_THRESHOLD = 50; +const SWIPE_ANGLE_THRESHOLD = Math.PI / 6; +class PDFPresentationMode { + #state = PresentationModeState.UNKNOWN; + #args = null; + #fullscreenChangeAbortController = null; + #windowAbortController = null; + constructor({ + container, + pdfViewer, + eventBus + }) { + this.container = container; + this.pdfViewer = pdfViewer; + this.eventBus = eventBus; + this.contextMenuOpen = false; + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; + this.touchSwipeState = null; + } + async request() { + const { + container, + pdfViewer + } = this; + if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) { + return false; + } + this.#addFullscreenChangeListeners(); + this.#notifyStateChange(PresentationModeState.CHANGING); + const promise = container.requestFullscreen(); + this.#args = { + pageNumber: pdfViewer.currentPageNumber, + scaleValue: pdfViewer.currentScaleValue, + scrollMode: pdfViewer.scrollMode, + spreadMode: null, + annotationEditorMode: null + }; + if (pdfViewer.spreadMode !== SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) { + console.warn("Ignoring Spread modes when entering PresentationMode, " + "since the document may contain varying page sizes."); + this.#args.spreadMode = pdfViewer.spreadMode; + } + if (pdfViewer.annotationEditorMode !== AnnotationEditorType.DISABLE) { + this.#args.annotationEditorMode = pdfViewer.annotationEditorMode; + } + try { + await promise; + pdfViewer.focus(); + return true; + } catch { + this.#removeFullscreenChangeListeners(); + this.#notifyStateChange(PresentationModeState.NORMAL); + } + return false; + } + get active() { + return this.#state === PresentationModeState.CHANGING || this.#state === PresentationModeState.FULLSCREEN; + } + #mouseWheel(evt) { + if (!this.active) { + return; + } + evt.preventDefault(); + const delta = normalizeWheelEventDelta(evt); + const currentTime = Date.now(); + const storedTime = this.mouseScrollTimeStamp; + if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) { + return; + } + if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) { + this.#resetMouseScrollState(); + } + this.mouseScrollDelta += delta; + if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) { + const totalDelta = this.mouseScrollDelta; + this.#resetMouseScrollState(); + const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage(); + if (success) { + this.mouseScrollTimeStamp = currentTime; + } + } + } + #notifyStateChange(state) { + this.#state = state; + this.eventBus.dispatch("presentationmodechanged", { + source: this, + state + }); + } + #enter() { + this.#notifyStateChange(PresentationModeState.FULLSCREEN); + this.container.classList.add(ACTIVE_SELECTOR); + setTimeout(() => { + this.pdfViewer.scrollMode = ScrollMode.PAGE; + if (this.#args.spreadMode !== null) { + this.pdfViewer.spreadMode = SpreadMode.NONE; + } + this.pdfViewer.currentPageNumber = this.#args.pageNumber; + this.pdfViewer.currentScaleValue = "page-fit"; + if (this.#args.annotationEditorMode !== null) { + this.pdfViewer.annotationEditorMode = { + mode: AnnotationEditorType.NONE + }; + } + }, 0); + this.#addWindowListeners(); + this.#showControls(); + this.contextMenuOpen = false; + document.getSelection().empty(); + } + #exit() { + const pageNumber = this.pdfViewer.currentPageNumber; + this.container.classList.remove(ACTIVE_SELECTOR); + setTimeout(() => { + this.#removeFullscreenChangeListeners(); + this.#notifyStateChange(PresentationModeState.NORMAL); + this.pdfViewer.scrollMode = this.#args.scrollMode; + if (this.#args.spreadMode !== null) { + this.pdfViewer.spreadMode = this.#args.spreadMode; + } + this.pdfViewer.currentScaleValue = this.#args.scaleValue; + this.pdfViewer.currentPageNumber = pageNumber; + if (this.#args.annotationEditorMode !== null) { + this.pdfViewer.annotationEditorMode = { + mode: this.#args.annotationEditorMode + }; + } + this.#args = null; + }, 0); + this.#removeWindowListeners(); + this.#hideControls(); + this.#resetMouseScrollState(); + this.contextMenuOpen = false; + } + #mouseDown(evt) { + if (this.contextMenuOpen) { + this.contextMenuOpen = false; + evt.preventDefault(); + return; + } + if (evt.button !== 0) { + return; + } + if (evt.target.href && evt.target.parentNode?.hasAttribute("data-internal-link")) { + return; + } + evt.preventDefault(); + if (evt.shiftKey) { + this.pdfViewer.previousPage(); + } else { + this.pdfViewer.nextPage(); + } + } + #contextMenu() { + this.contextMenuOpen = true; + } + #showControls() { + if (this.controlsTimeout) { + clearTimeout(this.controlsTimeout); + } else { + this.container.classList.add(CONTROLS_SELECTOR); + } + this.controlsTimeout = setTimeout(() => { + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + }, DELAY_BEFORE_HIDING_CONTROLS); + } + #hideControls() { + if (!this.controlsTimeout) { + return; + } + clearTimeout(this.controlsTimeout); + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + } + #resetMouseScrollState() { + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; + } + #touchSwipe(evt) { + if (!this.active) { + return; + } + if (evt.touches.length > 1) { + this.touchSwipeState = null; + return; + } + switch (evt.type) { + case "touchstart": + this.touchSwipeState = { + startX: evt.touches[0].pageX, + startY: evt.touches[0].pageY, + endX: evt.touches[0].pageX, + endY: evt.touches[0].pageY + }; + break; + case "touchmove": + if (this.touchSwipeState === null) { + return; + } + this.touchSwipeState.endX = evt.touches[0].pageX; + this.touchSwipeState.endY = evt.touches[0].pageY; + evt.preventDefault(); + break; + case "touchend": + if (this.touchSwipeState === null) { + return; + } + let delta = 0; + const dx = this.touchSwipeState.endX - this.touchSwipeState.startX; + const dy = this.touchSwipeState.endY - this.touchSwipeState.startY; + const absAngle = Math.abs(Math.atan2(dy, dx)); + if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) { + delta = dx; + } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) { + delta = dy; + } + if (delta > 0) { + this.pdfViewer.previousPage(); + } else if (delta < 0) { + this.pdfViewer.nextPage(); + } + break; + } + } + #addWindowListeners() { + if (this.#windowAbortController) { + return; + } + this.#windowAbortController = new AbortController(); + const { + signal + } = this.#windowAbortController; + const touchSwipeBind = this.#touchSwipe.bind(this); + window.addEventListener("mousemove", this.#showControls.bind(this), { + signal + }); + window.addEventListener("mousedown", this.#mouseDown.bind(this), { + signal + }); + window.addEventListener("wheel", this.#mouseWheel.bind(this), { + passive: false, + signal + }); + window.addEventListener("keydown", this.#resetMouseScrollState.bind(this), { + signal + }); + window.addEventListener("contextmenu", this.#contextMenu.bind(this), { + signal + }); + window.addEventListener("touchstart", touchSwipeBind, { + signal + }); + window.addEventListener("touchmove", touchSwipeBind, { + signal + }); + window.addEventListener("touchend", touchSwipeBind, { + signal + }); + } + #removeWindowListeners() { + this.#windowAbortController?.abort(); + this.#windowAbortController = null; + } + #addFullscreenChangeListeners() { + if (this.#fullscreenChangeAbortController) { + return; + } + this.#fullscreenChangeAbortController = new AbortController(); + window.addEventListener("fullscreenchange", () => { + if (document.fullscreenElement) { + this.#enter(); + } else { + this.#exit(); + } + }, { + signal: this.#fullscreenChangeAbortController.signal + }); + } + #removeFullscreenChangeListeners() { + this.#fullscreenChangeAbortController?.abort(); + this.#fullscreenChangeAbortController = null; + } +} + +;// ./web/xfa_layer_builder.js + +class XfaLayerBuilder { + constructor({ + pdfPage, + annotationStorage = null, + linkService, + xfaHtml = null + }) { + this.pdfPage = pdfPage; + this.annotationStorage = annotationStorage; + this.linkService = linkService; + this.xfaHtml = xfaHtml; + this.div = null; + this._cancelled = false; + } + async render({ + viewport, + intent = "display" + }) { + if (intent === "print") { + const parameters = { + viewport: viewport.clone({ + dontFlip: true + }), + div: this.div, + xfaHtml: this.xfaHtml, + annotationStorage: this.annotationStorage, + linkService: this.linkService, + intent + }; + this.div = document.createElement("div"); + parameters.div = this.div; + return XfaLayer.render(parameters); + } + const xfaHtml = await this.pdfPage.getXfa(); + if (this._cancelled || !xfaHtml) { + return { + textDivs: [] + }; + } + const parameters = { + viewport: viewport.clone({ + dontFlip: true + }), + div: this.div, + xfaHtml, + annotationStorage: this.annotationStorage, + linkService: this.linkService, + intent + }; + if (this.div) { + return XfaLayer.update(parameters); + } + this.div = document.createElement("div"); + parameters.div = this.div; + return XfaLayer.render(parameters); + } + cancel() { + this._cancelled = true; + } + hide() { + if (!this.div) { + return; + } + this.div.hidden = true; + } +} + +;// ./web/print_utils.js + + + +function getXfaHtmlForPrinting(printContainer, pdfDocument) { + const xfaHtml = pdfDocument.allXfaHtml; + const linkService = new SimpleLinkService(); + const scale = Math.round(PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100; + for (const xfaPage of xfaHtml.children) { + const page = document.createElement("div"); + page.className = "xfaPrintedPage"; + printContainer.append(page); + const builder = new XfaLayerBuilder({ + pdfPage: null, + annotationStorage: pdfDocument.annotationStorage, + linkService, + xfaHtml: xfaPage + }); + const viewport = getXfaPageViewport(xfaPage, { + scale + }); + builder.render({ + viewport, + intent: "print" + }); + page.append(builder.div); + } +} + +;// ./web/firefox_print_service.js + + +function composePage(pdfDocument, pageNumber, size, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) { + const canvas = document.createElement("canvas"); + const PRINT_UNITS = printResolution / PixelsPerInch.PDF; + canvas.width = Math.floor(size.width * PRINT_UNITS); + canvas.height = Math.floor(size.height * PRINT_UNITS); + const canvasWrapper = document.createElement("div"); + canvasWrapper.className = "printedPage"; + canvasWrapper.append(canvas); + printContainer.append(canvasWrapper); + let currentRenderTask = null; + canvas.mozPrintCallback = function (obj) { + const ctx = obj.context; + ctx.save(); + ctx.fillStyle = "rgb(255, 255, 255)"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.restore(); + let thisRenderTask = null; + Promise.all([pdfDocument.getPage(pageNumber), printAnnotationStoragePromise]).then(function ([pdfPage, printAnnotationStorage]) { + if (currentRenderTask) { + currentRenderTask.cancel(); + currentRenderTask = null; + } + const renderContext = { + canvasContext: ctx, + canvas: null, + transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0], + viewport: pdfPage.getViewport({ + scale: 1, + rotation: size.rotation + }), + intent: "print", + annotationMode: AnnotationMode.ENABLE_STORAGE, + optionalContentConfigPromise, + printAnnotationStorage + }; + currentRenderTask = thisRenderTask = pdfPage.render(renderContext); + return thisRenderTask.promise; + }).then(function () { + if (currentRenderTask === thisRenderTask) { + currentRenderTask = null; + } + obj.done(); + }, function (reason) { + if (!(reason instanceof RenderingCancelledException)) { + console.error(reason); + } + if (currentRenderTask === thisRenderTask) { + currentRenderTask.cancel(); + currentRenderTask = null; + } + if ("abort" in obj) { + obj.abort(); + } else { + obj.done(); + } + }); + }; +} +class FirefoxPrintService { + constructor({ + pdfDocument, + pagesOverview, + printContainer, + printResolution, + printAnnotationStoragePromise = null + }) { + this.pdfDocument = pdfDocument; + this.pagesOverview = pagesOverview; + this.printContainer = printContainer; + this._printResolution = printResolution || 150; + this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ + intent: "print" + }); + this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve(); + } + layout() { + const { + pdfDocument, + pagesOverview, + printContainer, + _printResolution, + _optionalContentConfigPromise, + _printAnnotationStoragePromise + } = this; + const body = document.querySelector("body"); + body.setAttribute("data-pdfjsprinting", true); + const { + width, + height + } = this.pagesOverview[0]; + const hasEqualPageSizes = this.pagesOverview.every(size => size.width === width && size.height === height); + if (!hasEqualPageSizes) { + console.warn("Not all pages have the same size. The printed result may be incorrect!"); + } + this.pageStyleSheet = document.createElement("style"); + this.pageStyleSheet.textContent = `@page { size: ${width}pt ${height}pt;}`; + body.append(this.pageStyleSheet); + if (pdfDocument.isPureXfa) { + getXfaHtmlForPrinting(printContainer, pdfDocument); + return; + } + for (let i = 0, ii = pagesOverview.length; i < ii; ++i) { + composePage(pdfDocument, i + 1, pagesOverview[i], printContainer, _printResolution, _optionalContentConfigPromise, _printAnnotationStoragePromise); + } + } + destroy() { + this.printContainer.textContent = ""; + const body = document.querySelector("body"); + body.removeAttribute("data-pdfjsprinting"); + if (this.pageStyleSheet) { + this.pageStyleSheet.remove(); + this.pageStyleSheet = null; + } + } +} +class PDFPrintServiceFactory { + static get supportsPrinting() { + const canvas = document.createElement("canvas"); + return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas); + } + static createPrintService(params) { + return new FirefoxPrintService(params); + } +} + +;// ./web/pdf_rendering_queue.js + + +const CLEANUP_TIMEOUT = 30000; +class PDFRenderingQueue { + constructor() { + this.pdfViewer = null; + this.pdfThumbnailViewer = null; + this.onIdle = null; + this.highestPriorityPage = null; + this.idleTimeout = null; + this.printing = false; + this.isThumbnailViewEnabled = false; + } + setViewer(pdfViewer) { + this.pdfViewer = pdfViewer; + } + setThumbnailViewer(pdfThumbnailViewer) { + this.pdfThumbnailViewer = pdfThumbnailViewer; + } + isHighestPriority(view) { + return this.highestPriorityPage === view.renderingId; + } + renderHighestPriority(currentlyVisiblePages) { + if (this.idleTimeout) { + clearTimeout(this.idleTimeout); + this.idleTimeout = null; + } + if (this.pdfViewer.forceRendering(currentlyVisiblePages)) { + return; + } + if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) { + return; + } + if (this.printing) { + return; + } + if (this.onIdle) { + this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT); + } + } + getHighestPriority(visible, views, scrolledDown, preRenderExtra = false, ignoreDetailViews = false) { + const visibleViews = visible.views, + numVisible = visibleViews.length; + if (numVisible === 0) { + return null; + } + for (let i = 0; i < numVisible; i++) { + const view = visibleViews[i].view; + if (!this.isViewFinished(view)) { + return view; + } + } + if (!ignoreDetailViews) { + for (let i = 0; i < numVisible; i++) { + const { + detailView + } = visibleViews[i].view; + if (detailView && !this.isViewFinished(detailView)) { + return detailView; + } + } + } + const firstId = visible.first.id, + lastId = visible.last.id; + if (lastId - firstId + 1 > numVisible) { + const visibleIds = visible.ids; + for (let i = 1, ii = lastId - firstId; i < ii; i++) { + const holeId = scrolledDown ? firstId + i : lastId - i; + if (visibleIds.has(holeId)) { + continue; + } + const holeView = views[holeId - 1]; + if (!this.isViewFinished(holeView)) { + return holeView; + } + } + } + let preRenderIndex = scrolledDown ? lastId : firstId - 2; + let preRenderView = views[preRenderIndex]; + if (preRenderView && !this.isViewFinished(preRenderView)) { + return preRenderView; + } + if (preRenderExtra) { + preRenderIndex += scrolledDown ? 1 : -1; + preRenderView = views[preRenderIndex]; + if (preRenderView && !this.isViewFinished(preRenderView)) { + return preRenderView; + } + } + return null; + } + isViewFinished(view) { + return view.renderingState === RenderingStates.FINISHED; + } + renderView(view) { + switch (view.renderingState) { + case RenderingStates.FINISHED: + return false; + case RenderingStates.PAUSED: + this.highestPriorityPage = view.renderingId; + view.resume(); + break; + case RenderingStates.RUNNING: + this.highestPriorityPage = view.renderingId; + break; + case RenderingStates.INITIAL: + this.highestPriorityPage = view.renderingId; + view.draw().finally(() => { + this.renderHighestPriority(); + }).catch(reason => { + if (reason instanceof RenderingCancelledException) { + return; + } + console.error("renderView:", reason); + }); + break; + } + return true; + } +} + +;// ./web/pdf_scripting_manager.js + + +class PDFScriptingManager { + #closeCapability = null; + #destroyCapability = null; + #docProperties = null; + #eventAbortController = null; + #eventBus = null; + #externalServices = null; + #pdfDocument = null; + #pdfViewer = null; + #ready = false; + #scripting = null; + #willPrintCapability = null; + constructor({ + eventBus, + externalServices = null, + docProperties = null + }) { + this.#eventBus = eventBus; + this.#externalServices = externalServices; + this.#docProperties = docProperties; + } + setViewer(pdfViewer) { + this.#pdfViewer = pdfViewer; + } + async setDocument(pdfDocument) { + if (this.#pdfDocument) { + await this.#destroyScripting(); + } + this.#pdfDocument = pdfDocument; + if (!pdfDocument) { + return; + } + const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]); + if (!objects && !docActions) { + await this.#destroyScripting(); + return; + } + if (pdfDocument !== this.#pdfDocument) { + return; + } + try { + this.#scripting = this.#initScripting(); + } catch (error) { + console.error("setDocument:", error); + await this.#destroyScripting(); + return; + } + const eventBus = this.#eventBus; + this.#eventAbortController = new AbortController(); + const { + signal + } = this.#eventAbortController; + eventBus._on("updatefromsandbox", event => { + if (event?.source === window) { + this.#updateFromSandbox(event.detail); + } + }, { + signal + }); + eventBus._on("dispatcheventinsandbox", event => { + this.#scripting?.dispatchEventInSandbox(event.detail); + }, { + signal + }); + eventBus._on("pagechanging", ({ + pageNumber, + previous + }) => { + if (pageNumber === previous) { + return; + } + this.#dispatchPageClose(previous); + this.#dispatchPageOpen(pageNumber); + }, { + signal + }); + eventBus._on("pagerendered", ({ + pageNumber + }) => { + if (!this._pageOpenPending.has(pageNumber)) { + return; + } + if (pageNumber !== this.#pdfViewer.currentPageNumber) { + return; + } + this.#dispatchPageOpen(pageNumber); + }, { + signal + }); + eventBus._on("pagesdestroy", async () => { + await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber); + await this.#scripting?.dispatchEventInSandbox({ + id: "doc", + name: "WillClose" + }); + this.#closeCapability?.resolve(); + }, { + signal + }); + try { + const docProperties = await this.#docProperties(pdfDocument); + if (pdfDocument !== this.#pdfDocument) { + return; + } + await this.#scripting.createSandbox({ + objects, + calculationOrder, + appInfo: { + platform: navigator.platform, + language: navigator.language + }, + docInfo: { + ...docProperties, + actions: docActions + } + }); + eventBus.dispatch("sandboxcreated", { + source: this + }); + } catch (error) { + console.error("setDocument:", error); + await this.#destroyScripting(); + return; + } + await this.#scripting?.dispatchEventInSandbox({ + id: "doc", + name: "Open" + }); + await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true); + Promise.resolve().then(() => { + if (pdfDocument === this.#pdfDocument) { + this.#ready = true; + } + }); + } + async dispatchWillSave() { + return this.#scripting?.dispatchEventInSandbox({ + id: "doc", + name: "WillSave" + }); + } + async dispatchDidSave() { + return this.#scripting?.dispatchEventInSandbox({ + id: "doc", + name: "DidSave" + }); + } + async dispatchWillPrint() { + if (!this.#scripting) { + return; + } + await this.#willPrintCapability?.promise; + this.#willPrintCapability = Promise.withResolvers(); + try { + await this.#scripting.dispatchEventInSandbox({ + id: "doc", + name: "WillPrint" + }); + } catch (ex) { + this.#willPrintCapability.resolve(); + this.#willPrintCapability = null; + throw ex; + } + await this.#willPrintCapability.promise; + } + async dispatchDidPrint() { + return this.#scripting?.dispatchEventInSandbox({ + id: "doc", + name: "DidPrint" + }); + } + get destroyPromise() { + return this.#destroyCapability?.promise || null; + } + get ready() { + return this.#ready; + } + get _pageOpenPending() { + return shadow(this, "_pageOpenPending", new Set()); + } + get _visitedPages() { + return shadow(this, "_visitedPages", new Map()); + } + async #updateFromSandbox(detail) { + const pdfViewer = this.#pdfViewer; + const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode; + const { + id, + siblings, + command, + value + } = detail; + if (!id) { + switch (command) { + case "clear": + console.clear(); + break; + case "error": + console.error(value); + break; + case "layout": + if (!isInPresentationMode) { + const modes = apiPageLayoutToViewerModes(value); + pdfViewer.spreadMode = modes.spreadMode; + } + break; + case "page-num": + pdfViewer.currentPageNumber = value + 1; + break; + case "print": + await pdfViewer.pagesPromise; + this.#eventBus.dispatch("print", { + source: this + }); + break; + case "println": + console.log(value); + break; + case "zoom": + if (!isInPresentationMode) { + pdfViewer.currentScaleValue = value; + } + break; + case "SaveAs": + this.#eventBus.dispatch("download", { + source: this + }); + break; + case "FirstPage": + pdfViewer.currentPageNumber = 1; + break; + case "LastPage": + pdfViewer.currentPageNumber = pdfViewer.pagesCount; + break; + case "NextPage": + pdfViewer.nextPage(); + break; + case "PrevPage": + pdfViewer.previousPage(); + break; + case "ZoomViewIn": + if (!isInPresentationMode) { + pdfViewer.increaseScale(); + } + break; + case "ZoomViewOut": + if (!isInPresentationMode) { + pdfViewer.decreaseScale(); + } + break; + case "WillPrintFinished": + this.#willPrintCapability?.resolve(); + this.#willPrintCapability = null; + break; + } + return; + } + if (isInPresentationMode && detail.focus) { + return; + } + delete detail.id; + delete detail.siblings; + const ids = siblings ? [id, ...siblings] : [id]; + for (const elementId of ids) { + const element = document.querySelector(`[data-element-id="${elementId}"]`); + if (element) { + element.dispatchEvent(new CustomEvent("updatefromsandbox", { + detail + })); + } else { + this.#pdfDocument?.annotationStorage.setValue(elementId, detail); + } + } + } + async #dispatchPageOpen(pageNumber, initialize = false) { + const pdfDocument = this.#pdfDocument, + visitedPages = this._visitedPages; + if (initialize) { + this.#closeCapability = Promise.withResolvers(); + } + if (!this.#closeCapability) { + return; + } + const pageView = this.#pdfViewer.getPageView(pageNumber - 1); + if (pageView?.renderingState !== RenderingStates.FINISHED) { + this._pageOpenPending.add(pageNumber); + return; + } + this._pageOpenPending.delete(pageNumber); + const actionsPromise = (async () => { + const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null); + if (pdfDocument !== this.#pdfDocument) { + return; + } + await this.#scripting?.dispatchEventInSandbox({ + id: "page", + name: "PageOpen", + pageNumber, + actions + }); + })(); + visitedPages.set(pageNumber, actionsPromise); + } + async #dispatchPageClose(pageNumber) { + const pdfDocument = this.#pdfDocument, + visitedPages = this._visitedPages; + if (!this.#closeCapability) { + return; + } + if (this._pageOpenPending.has(pageNumber)) { + return; + } + const actionsPromise = visitedPages.get(pageNumber); + if (!actionsPromise) { + return; + } + visitedPages.set(pageNumber, null); + await actionsPromise; + if (pdfDocument !== this.#pdfDocument) { + return; + } + await this.#scripting?.dispatchEventInSandbox({ + id: "page", + name: "PageClose", + pageNumber + }); + } + #initScripting() { + this.#destroyCapability = Promise.withResolvers(); + if (this.#scripting) { + throw new Error("#initScripting: Scripting already exists."); + } + return this.#externalServices.createScripting(); + } + async #destroyScripting() { + if (!this.#scripting) { + this.#pdfDocument = null; + this.#destroyCapability?.resolve(); + return; + } + if (this.#closeCapability) { + await Promise.race([this.#closeCapability.promise, new Promise(resolve => { + setTimeout(resolve, 1000); + })]).catch(() => {}); + this.#closeCapability = null; + } + this.#pdfDocument = null; + try { + await this.#scripting.destroySandbox(); + } catch {} + this.#willPrintCapability?.reject(new Error("Scripting destroyed.")); + this.#willPrintCapability = null; + this.#eventAbortController?.abort(); + this.#eventAbortController = null; + this._pageOpenPending.clear(); + this._visitedPages.clear(); + this.#scripting = null; + this.#ready = false; + this.#destroyCapability?.resolve(); + } +} + +;// ./web/pdf_sidebar.js + +const SIDEBAR_WIDTH_VAR = "--sidebar-width"; +const SIDEBAR_MIN_WIDTH = 200; +const SIDEBAR_RESIZING_CLASS = "sidebarResizing"; +const UI_NOTIFICATION_CLASS = "pdfSidebarNotification"; +class PDFSidebar { + #isRTL = false; + #mouseAC = null; + #outerContainerWidth = null; + #width = null; + constructor({ + elements, + eventBus, + l10n + }) { + this.isOpen = false; + this.active = SidebarView.THUMBS; + this.isInitialViewSet = false; + this.isInitialEventDispatched = false; + this.onToggled = null; + this.onUpdateThumbnails = null; + this.outerContainer = elements.outerContainer; + this.sidebarContainer = elements.sidebarContainer; + this.toggleButton = elements.toggleButton; + this.resizer = elements.resizer; + this.thumbnailButton = elements.thumbnailButton; + this.outlineButton = elements.outlineButton; + this.attachmentsButton = elements.attachmentsButton; + this.layersButton = elements.layersButton; + this.thumbnailView = elements.thumbnailView; + this.outlineView = elements.outlineView; + this.attachmentsView = elements.attachmentsView; + this.layersView = elements.layersView; + this._currentOutlineItemButton = elements.currentOutlineItemButton; + this.eventBus = eventBus; + this.#isRTL = l10n.getDirection() === "rtl"; + this.#addEventListeners(); + } + reset() { + this.isInitialViewSet = false; + this.isInitialEventDispatched = false; + this.#hideUINotification(true); + this.switchView(SidebarView.THUMBS); + this.outlineButton.disabled = false; + this.attachmentsButton.disabled = false; + this.layersButton.disabled = false; + this._currentOutlineItemButton.disabled = true; + } + get visibleView() { + return this.isOpen ? this.active : SidebarView.NONE; + } + setInitialView(view = SidebarView.NONE) { + if (this.isInitialViewSet) { + return; + } + this.isInitialViewSet = true; + if (view === SidebarView.NONE || view === SidebarView.UNKNOWN) { + this.#dispatchEvent(); + return; + } + this.switchView(view, true); + if (!this.isInitialEventDispatched) { + this.#dispatchEvent(); + } + } + switchView(view, forceOpen = false) { + const isViewChanged = view !== this.active; + let forceRendering = false; + switch (view) { + case SidebarView.NONE: + if (this.isOpen) { + this.close(); + } + return; + case SidebarView.THUMBS: + if (this.isOpen && isViewChanged) { + forceRendering = true; + } + break; + case SidebarView.OUTLINE: + if (this.outlineButton.disabled) { + return; + } + break; + case SidebarView.ATTACHMENTS: + if (this.attachmentsButton.disabled) { + return; + } + break; + case SidebarView.LAYERS: + if (this.layersButton.disabled) { + return; + } + break; + default: + console.error(`PDFSidebar.switchView: "${view}" is not a valid view.`); + return; + } + this.active = view; + toggleCheckedBtn(this.thumbnailButton, view === SidebarView.THUMBS, this.thumbnailView); + toggleCheckedBtn(this.outlineButton, view === SidebarView.OUTLINE, this.outlineView); + toggleCheckedBtn(this.attachmentsButton, view === SidebarView.ATTACHMENTS, this.attachmentsView); + toggleCheckedBtn(this.layersButton, view === SidebarView.LAYERS, this.layersView); + if (forceOpen && !this.isOpen) { + this.open(); + return; + } + if (forceRendering) { + this.onUpdateThumbnails(); + this.onToggled(); + } + if (isViewChanged) { + this.#dispatchEvent(); + } + } + open() { + if (this.isOpen) { + return; + } + this.isOpen = true; + toggleExpandedBtn(this.toggleButton, true); + this.outerContainer.classList.add("sidebarMoving", "sidebarOpen"); + if (this.active === SidebarView.THUMBS) { + this.onUpdateThumbnails(); + } + this.onToggled(); + this.#dispatchEvent(); + this.#hideUINotification(); + } + close(evt = null) { + if (!this.isOpen) { + return; + } + this.isOpen = false; + toggleExpandedBtn(this.toggleButton, false); + this.outerContainer.classList.add("sidebarMoving"); + this.outerContainer.classList.remove("sidebarOpen"); + this.onToggled(); + this.#dispatchEvent(); + if (evt?.detail > 0) { + this.toggleButton.blur(); + } + } + toggle(evt = null) { + if (this.isOpen) { + this.close(evt); + } else { + this.open(); + } + } + #dispatchEvent() { + if (this.isInitialViewSet) { + this.isInitialEventDispatched ||= true; + } + this.eventBus.dispatch("sidebarviewchanged", { + source: this, + view: this.visibleView + }); + } + #showUINotification() { + this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-notification-button"); + if (!this.isOpen) { + this.toggleButton.classList.add(UI_NOTIFICATION_CLASS); + } + } + #hideUINotification(reset = false) { + if (this.isOpen || reset) { + this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS); + } + if (reset) { + this.toggleButton.setAttribute("data-l10n-id", "pdfjs-toggle-sidebar-button"); + } + } + #addEventListeners() { + const { + eventBus, + outerContainer + } = this; + this.sidebarContainer.addEventListener("transitionend", evt => { + if (evt.target === this.sidebarContainer) { + outerContainer.classList.remove("sidebarMoving"); + eventBus.dispatch("resize", { + source: this + }); + } + }); + this.toggleButton.addEventListener("click", evt => { + this.toggle(evt); + }); + this.thumbnailButton.addEventListener("click", () => { + this.switchView(SidebarView.THUMBS); + }); + this.outlineButton.addEventListener("click", () => { + this.switchView(SidebarView.OUTLINE); + }); + this.outlineButton.addEventListener("dblclick", () => { + eventBus.dispatch("toggleoutlinetree", { + source: this + }); + }); + this.attachmentsButton.addEventListener("click", () => { + this.switchView(SidebarView.ATTACHMENTS); + }); + this.layersButton.addEventListener("click", () => { + this.switchView(SidebarView.LAYERS); + }); + this.layersButton.addEventListener("dblclick", () => { + eventBus.dispatch("resetlayers", { + source: this + }); + }); + this._currentOutlineItemButton.addEventListener("click", () => { + eventBus.dispatch("currentoutlineitem", { + source: this + }); + }); + const onTreeLoaded = (count, button, view) => { + button.disabled = !count; + if (count) { + this.#showUINotification(); + } else if (this.active === view) { + this.switchView(SidebarView.THUMBS); + } + }; + eventBus._on("outlineloaded", evt => { + onTreeLoaded(evt.outlineCount, this.outlineButton, SidebarView.OUTLINE); + evt.currentOutlineItemPromise.then(enabled => { + if (!this.isInitialViewSet) { + return; + } + this._currentOutlineItemButton.disabled = !enabled; + }); + }); + eventBus._on("attachmentsloaded", evt => { + onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, SidebarView.ATTACHMENTS); + }); + eventBus._on("layersloaded", evt => { + onTreeLoaded(evt.layersCount, this.layersButton, SidebarView.LAYERS); + }); + eventBus._on("presentationmodechanged", evt => { + if (evt.state === PresentationModeState.NORMAL && this.visibleView === SidebarView.THUMBS) { + this.onUpdateThumbnails(); + } + }); + this.resizer.addEventListener("mousedown", evt => { + if (evt.button !== 0) { + return; + } + outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); + this.#mouseAC = new AbortController(); + const opts = { + signal: this.#mouseAC.signal + }; + window.addEventListener("mousemove", this.#mouseMove.bind(this), opts); + window.addEventListener("mouseup", this.#mouseUp.bind(this), opts); + window.addEventListener("blur", this.#mouseUp.bind(this), opts); + }); + eventBus._on("resize", evt => { + if (evt.source !== window) { + return; + } + this.#outerContainerWidth = null; + if (!this.#width) { + return; + } + if (!this.isOpen) { + this.#updateWidth(this.#width); + return; + } + outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); + const updated = this.#updateWidth(this.#width); + Promise.resolve().then(() => { + outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); + if (updated) { + eventBus.dispatch("resize", { + source: this + }); + } + }); + }); + } + get outerContainerWidth() { + return this.#outerContainerWidth ||= this.outerContainer.clientWidth; + } + #updateWidth(width = 0) { + const maxWidth = Math.floor(this.outerContainerWidth / 2); + if (width > maxWidth) { + width = maxWidth; + } + if (width < SIDEBAR_MIN_WIDTH) { + width = SIDEBAR_MIN_WIDTH; + } + if (width === this.#width) { + return false; + } + this.#width = width; + docStyle.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`); + return true; + } + #mouseMove(evt) { + let width = evt.clientX; + if (this.#isRTL) { + width = this.outerContainerWidth - width; + } + this.#updateWidth(width); + } + #mouseUp(evt) { + this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); + this.eventBus.dispatch("resize", { + source: this + }); + this.#mouseAC?.abort(); + this.#mouseAC = null; + } +} + +;// ./web/pdf_text_extractor.js +class PdfTextExtractor { + #pdfViewer; + #externalServices; + #textPromise; + #pendingRequests = new Set(); + constructor(externalServices) { + this.#externalServices = externalServices; + window.addEventListener("requestTextContent", ({ + detail + }) => { + this.extractTextContent(detail.requestId); + }); + } + setViewer(pdfViewer) { + this.#pdfViewer = pdfViewer; + if (this.#pdfViewer && this.#pendingRequests.size) { + for (const pendingRequest of this.#pendingRequests) { + this.extractTextContent(pendingRequest); + } + this.#pendingRequests.clear(); + } + } + async extractTextContent(requestId) { + if (!this.#pdfViewer) { + this.#pendingRequests.add(requestId); + return; + } + if (!this.#textPromise) { + const textPromise = this.#textPromise = this.#pdfViewer.getAllText(); + textPromise.then(() => { + setTimeout(() => { + if (this.#textPromise === textPromise) { + this.#textPromise = null; + } + }, 5000); + }); + } + this.#externalServices.reportText({ + text: await this.#textPromise, + requestId + }); + } +} + +;// ./web/pdf_thumbnail_view.js + + + +const DRAW_UPSCALE_FACTOR = 2; +const MAX_NUM_SCALING_STEPS = 3; +const THUMBNAIL_WIDTH = 98; +function zeroCanvas(c) { + c.width = 0; + c.height = 0; +} +class TempImageFactory { + static #tempCanvas = null; + static getCanvas(width, height) { + const tempCanvas = this.#tempCanvas ||= document.createElement("canvas"); + tempCanvas.width = width; + tempCanvas.height = height; + const ctx = tempCanvas.getContext("2d", { + alpha: false + }); + ctx.save(); + ctx.fillStyle = "rgb(255, 255, 255)"; + ctx.fillRect(0, 0, width, height); + ctx.restore(); + return [tempCanvas, tempCanvas.getContext("2d")]; + } + static destroyCanvas() { + if (this.#tempCanvas) { + zeroCanvas(this.#tempCanvas); + } + this.#tempCanvas = null; + } +} +class PDFThumbnailView { + constructor({ + container, + eventBus, + id, + defaultViewport, + optionalContentConfigPromise, + linkService, + renderingQueue, + maxCanvasPixels, + maxCanvasDim, + pageColors + }) { + this.id = id; + this.renderingId = "thumbnail" + id; + this.pageLabel = null; + this.pdfPage = null; + this.rotation = 0; + this.viewport = defaultViewport; + this.pdfPageRotate = defaultViewport.rotation; + this._optionalContentConfigPromise = optionalContentConfigPromise || null; + this.maxCanvasPixels = maxCanvasPixels ?? AppOptions.get("maxCanvasPixels"); + this.maxCanvasDim = maxCanvasDim || AppOptions.get("maxCanvasDim"); + this.pageColors = pageColors || null; + this.eventBus = eventBus; + this.linkService = linkService; + this.renderingQueue = renderingQueue; + this.renderTask = null; + this.renderingState = RenderingStates.INITIAL; + this.resume = null; + const anchor = document.createElement("a"); + anchor.href = linkService.getAnchorUrl("#page=" + id); + anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title"); + anchor.setAttribute("data-l10n-args", this.#pageL10nArgs); + anchor.onclick = function () { + linkService.goToPage(id); + return false; + }; + this.anchor = anchor; + const div = document.createElement("div"); + div.className = "thumbnail"; + div.setAttribute("data-page-number", this.id); + this.div = div; + this.#updateDims(); + const img = document.createElement("div"); + img.className = "thumbnailImage"; + this._placeholderImg = img; + div.append(img); + anchor.append(div); + container.append(anchor); + } + #updateDims() { + const { + width, + height + } = this.viewport; + const ratio = width / height; + this.canvasWidth = THUMBNAIL_WIDTH; + this.canvasHeight = this.canvasWidth / ratio | 0; + this.scale = this.canvasWidth / width; + const { + style + } = this.div; + style.setProperty("--thumbnail-width", `${this.canvasWidth}px`); + style.setProperty("--thumbnail-height", `${this.canvasHeight}px`); + } + setPdfPage(pdfPage) { + this.pdfPage = pdfPage; + this.pdfPageRotate = pdfPage.rotate; + const totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = pdfPage.getViewport({ + scale: 1, + rotation: totalRotation + }); + this.reset(); + } + reset() { + this.cancelRendering(); + this.renderingState = RenderingStates.INITIAL; + this.div.removeAttribute("data-loaded"); + this.image?.replaceWith(this._placeholderImg); + this.#updateDims(); + if (this.image) { + this.image.removeAttribute("src"); + delete this.image; + } + } + update({ + rotation = null + }) { + if (typeof rotation === "number") { + this.rotation = rotation; + } + const totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = this.viewport.clone({ + scale: 1, + rotation: totalRotation + }); + this.reset(); + } + cancelRendering() { + if (this.renderTask) { + this.renderTask.cancel(); + this.renderTask = null; + } + this.resume = null; + } + #getPageDrawContext(upscaleFactor = 1) { + const canvas = document.createElement("canvas"); + const outputScale = new OutputScale(); + const width = upscaleFactor * this.canvasWidth, + height = upscaleFactor * this.canvasHeight; + outputScale.limitCanvas(width, height, this.maxCanvasPixels, this.maxCanvasDim); + canvas.width = width * outputScale.sx | 0; + canvas.height = height * outputScale.sy | 0; + const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null; + return { + canvas, + transform + }; + } + #convertCanvasToImage(canvas) { + if (this.renderingState !== RenderingStates.FINISHED) { + throw new Error("#convertCanvasToImage: Rendering has not finished."); + } + const reducedCanvas = this.#reduceImage(canvas); + const image = document.createElement("img"); + image.className = "thumbnailImage"; + image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas"); + image.setAttribute("data-l10n-args", this.#pageL10nArgs); + image.src = reducedCanvas.toDataURL(); + this.image = image; + this.div.setAttribute("data-loaded", true); + this._placeholderImg.replaceWith(image); + zeroCanvas(reducedCanvas); + } + async draw() { + if (this.renderingState !== RenderingStates.INITIAL) { + console.error("Must be in new state before drawing"); + return; + } + const { + pageColors, + pdfPage + } = this; + if (!pdfPage) { + this.renderingState = RenderingStates.FINISHED; + throw new Error("pdfPage is not loaded"); + } + this.renderingState = RenderingStates.RUNNING; + const { + canvas, + transform + } = this.#getPageDrawContext(DRAW_UPSCALE_FACTOR); + const drawViewport = this.viewport.clone({ + scale: DRAW_UPSCALE_FACTOR * this.scale + }); + const renderContinueCallback = cont => { + if (!this.renderingQueue.isHighestPriority(this)) { + this.renderingState = RenderingStates.PAUSED; + this.resume = () => { + this.renderingState = RenderingStates.RUNNING; + cont(); + }; + return; + } + cont(); + }; + const renderContext = { + canvas, + transform, + viewport: drawViewport, + optionalContentConfigPromise: this._optionalContentConfigPromise, + pageColors + }; + const renderTask = this.renderTask = pdfPage.render(renderContext); + renderTask.onContinue = renderContinueCallback; + let error = null; + try { + await renderTask.promise; + } catch (e) { + if (e instanceof RenderingCancelledException) { + zeroCanvas(canvas); + return; + } + error = e; + } finally { + if (renderTask === this.renderTask) { + this.renderTask = null; + } + } + this.renderingState = RenderingStates.FINISHED; + this.#convertCanvasToImage(canvas); + zeroCanvas(canvas); + this.eventBus.dispatch("thumbnailrendered", { + source: this, + pageNumber: this.id, + pdfPage + }); + if (error) { + throw error; + } + } + setImage(pageView) { + if (this.renderingState !== RenderingStates.INITIAL) { + return; + } + const { + thumbnailCanvas: canvas, + pdfPage, + scale + } = pageView; + if (!canvas) { + return; + } + if (!this.pdfPage) { + this.setPdfPage(pdfPage); + } + if (scale < this.scale) { + return; + } + this.renderingState = RenderingStates.FINISHED; + this.#convertCanvasToImage(canvas); + } + #getReducedImageDims(canvas) { + const width = canvas.width << MAX_NUM_SCALING_STEPS, + height = canvas.height << MAX_NUM_SCALING_STEPS; + const outputScale = new OutputScale(); + outputScale.sx = outputScale.sy = 1; + outputScale.limitCanvas(width, height, this.maxCanvasPixels, this.maxCanvasDim); + return [width * outputScale.sx | 0, height * outputScale.sy | 0]; + } + #reduceImage(img) { + const { + canvas + } = this.#getPageDrawContext(1); + const ctx = canvas.getContext("2d", { + alpha: false, + willReadFrequently: false + }); + if (img.width <= 2 * canvas.width) { + ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); + return canvas; + } + let [reducedWidth, reducedHeight] = this.#getReducedImageDims(canvas); + const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight); + while (reducedWidth > img.width || reducedHeight > img.height) { + reducedWidth >>= 1; + reducedHeight >>= 1; + } + reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight); + while (reducedWidth > 2 * canvas.width) { + reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1); + reducedWidth >>= 1; + reducedHeight >>= 1; + } + ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height); + return canvas; + } + get #pageL10nArgs() { + return JSON.stringify({ + page: this.pageLabel ?? this.id + }); + } + setPageLabel(label) { + this.pageLabel = typeof label === "string" ? label : null; + this.anchor.setAttribute("data-l10n-args", this.#pageL10nArgs); + if (this.renderingState !== RenderingStates.FINISHED) { + return; + } + this.image?.setAttribute("data-l10n-args", this.#pageL10nArgs); + } +} + +;// ./web/pdf_thumbnail_viewer.js + + +const THUMBNAIL_SCROLL_MARGIN = -19; +const THUMBNAIL_SELECTED_CLASS = "selected"; +class PDFThumbnailViewer { + constructor({ + container, + eventBus, + linkService, + renderingQueue, + maxCanvasPixels, + maxCanvasDim, + pageColors, + abortSignal, + enableHWA + }) { + this.container = container; + this.eventBus = eventBus; + this.linkService = linkService; + this.renderingQueue = renderingQueue; + this.maxCanvasPixels = maxCanvasPixels; + this.maxCanvasDim = maxCanvasDim; + this.pageColors = pageColors || null; + this.enableHWA = enableHWA || false; + this.scroll = watchScroll(this.container, this.#scrollUpdated.bind(this), abortSignal); + this.#resetView(); + } + #scrollUpdated() { + this.renderingQueue.renderHighestPriority(); + } + getThumbnail(index) { + return this._thumbnails[index]; + } + #getVisibleThumbs() { + return getVisibleElements({ + scrollEl: this.container, + views: this._thumbnails + }); + } + scrollThumbnailIntoView(pageNumber) { + if (!this.pdfDocument) { + return; + } + const thumbnailView = this._thumbnails[pageNumber - 1]; + if (!thumbnailView) { + console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.'); + return; + } + if (pageNumber !== this._currentPageNumber) { + const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1]; + prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS); + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); + } + const { + first, + last, + views + } = this.#getVisibleThumbs(); + if (views.length > 0) { + let shouldScroll = false; + if (pageNumber <= first.id || pageNumber >= last.id) { + shouldScroll = true; + } else { + for (const { + id, + percent + } of views) { + if (id !== pageNumber) { + continue; + } + shouldScroll = percent < 100; + break; + } + } + if (shouldScroll) { + scrollIntoView(thumbnailView.div, { + top: THUMBNAIL_SCROLL_MARGIN + }); + } + } + this._currentPageNumber = pageNumber; + } + get pagesRotation() { + return this._pagesRotation; + } + set pagesRotation(rotation) { + if (!isValidRotation(rotation)) { + throw new Error("Invalid thumbnails rotation angle."); + } + if (!this.pdfDocument) { + return; + } + if (this._pagesRotation === rotation) { + return; + } + this._pagesRotation = rotation; + const updateArgs = { + rotation + }; + for (const thumbnail of this._thumbnails) { + thumbnail.update(updateArgs); + } + } + cleanup() { + for (const thumbnail of this._thumbnails) { + if (thumbnail.renderingState !== RenderingStates.FINISHED) { + thumbnail.reset(); + } + } + TempImageFactory.destroyCanvas(); + } + #resetView() { + this._thumbnails = []; + this._currentPageNumber = 1; + this._pageLabels = null; + this._pagesRotation = 0; + this.container.textContent = ""; + } + setDocument(pdfDocument) { + if (this.pdfDocument) { + this.#cancelRendering(); + this.#resetView(); + } + this.pdfDocument = pdfDocument; + if (!pdfDocument) { + return; + } + const firstPagePromise = pdfDocument.getPage(1); + const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ + intent: "display" + }); + firstPagePromise.then(firstPdfPage => { + const pagesCount = pdfDocument.numPages; + const viewport = firstPdfPage.getViewport({ + scale: 1 + }); + for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { + const thumbnail = new PDFThumbnailView({ + container: this.container, + eventBus: this.eventBus, + id: pageNum, + defaultViewport: viewport.clone(), + optionalContentConfigPromise, + linkService: this.linkService, + renderingQueue: this.renderingQueue, + maxCanvasPixels: this.maxCanvasPixels, + maxCanvasDim: this.maxCanvasDim, + pageColors: this.pageColors, + enableHWA: this.enableHWA + }); + this._thumbnails.push(thumbnail); + } + this._thumbnails[0]?.setPdfPage(firstPdfPage); + const thumbnailView = this._thumbnails[this._currentPageNumber - 1]; + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); + }).catch(reason => { + console.error("Unable to initialize thumbnail viewer", reason); + }); + } + #cancelRendering() { + for (const thumbnail of this._thumbnails) { + thumbnail.cancelRendering(); + } + } + setPageLabels(labels) { + if (!this.pdfDocument) { + return; + } + if (!labels) { + this._pageLabels = null; + } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) { + this._pageLabels = null; + console.error("PDFThumbnailViewer_setPageLabels: Invalid page labels."); + } else { + this._pageLabels = labels; + } + for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { + this._thumbnails[i].setPageLabel(this._pageLabels?.[i] ?? null); + } + } + async #ensurePdfPageLoaded(thumbView) { + if (thumbView.pdfPage) { + return thumbView.pdfPage; + } + try { + const pdfPage = await this.pdfDocument.getPage(thumbView.id); + if (!thumbView.pdfPage) { + thumbView.setPdfPage(pdfPage); + } + return pdfPage; + } catch (reason) { + console.error("Unable to get page for thumb view", reason); + return null; + } + } + #getScrollAhead(visible) { + if (visible.first?.id === 1) { + return true; + } else if (visible.last?.id === this._thumbnails.length) { + return false; + } + return this.scroll.down; + } + forceRendering() { + const visibleThumbs = this.#getVisibleThumbs(); + const scrollAhead = this.#getScrollAhead(visibleThumbs); + const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead, false, true); + if (thumbView) { + this.#ensurePdfPageLoaded(thumbView).then(() => { + this.renderingQueue.renderView(thumbView); + }); + return true; + } + return false; + } +} + +;// ./web/annotation_editor_layer_builder.js + + +class AnnotationEditorLayerBuilder { + #annotationLayer = null; + #drawLayer = null; + #onAppend = null; + #structTreeLayer = null; + #textLayer = null; + #uiManager; + constructor(options) { + this.pdfPage = options.pdfPage; + this.accessibilityManager = options.accessibilityManager; + this.l10n = options.l10n; + this.annotationEditorLayer = null; + this.div = null; + this._cancelled = false; + this.#uiManager = options.uiManager; + this.#annotationLayer = options.annotationLayer || null; + this.#textLayer = options.textLayer || null; + this.#drawLayer = options.drawLayer || null; + this.#onAppend = options.onAppend || null; + this.#structTreeLayer = options.structTreeLayer || null; + } + async render({ + viewport, + intent = "display" + }) { + if (intent !== "display") { + return; + } + if (this._cancelled) { + return; + } + const clonedViewport = viewport.clone({ + dontFlip: true + }); + if (this.div) { + this.annotationEditorLayer.update({ + viewport: clonedViewport + }); + this.show(); + return; + } + const div = this.div = document.createElement("div"); + div.className = "annotationEditorLayer"; + div.hidden = true; + div.dir = this.#uiManager.direction; + this.#onAppend?.(div); + this.annotationEditorLayer = new AnnotationEditorLayer({ + uiManager: this.#uiManager, + div, + structTreeLayer: this.#structTreeLayer, + accessibilityManager: this.accessibilityManager, + pageIndex: this.pdfPage.pageNumber - 1, + l10n: this.l10n, + viewport: clonedViewport, + annotationLayer: this.#annotationLayer, + textLayer: this.#textLayer, + drawLayer: this.#drawLayer + }); + const parameters = { + viewport: clonedViewport, + div, + annotations: null, + intent + }; + this.annotationEditorLayer.render(parameters); + this.show(); + } + cancel() { + this._cancelled = true; + if (!this.div) { + return; + } + this.annotationEditorLayer.destroy(); + } + hide() { + if (!this.div) { + return; + } + this.annotationEditorLayer.pause(true); + this.div.hidden = true; + } + show() { + if (!this.div || this.annotationEditorLayer.isInvisible) { + return; + } + this.div.hidden = false; + this.annotationEditorLayer.pause(false); + } +} + +;// ./web/annotation_layer_builder.js + + +class AnnotationLayerBuilder { + #annotations = null; + #commentManager = null; + #externalHide = false; + #onAppend = null; + #eventAbortController = null; + #linksInjected = false; + constructor({ + pdfPage, + linkService, + downloadManager, + annotationStorage = null, + imageResourcesPath = "", + renderForms = true, + enableComment = false, + commentManager = null, + enableScripting = false, + hasJSActionsPromise = null, + fieldObjectsPromise = null, + annotationCanvasMap = null, + accessibilityManager = null, + annotationEditorUIManager = null, + onAppend = null + }) { + this.pdfPage = pdfPage; + this.linkService = linkService; + this.downloadManager = downloadManager; + this.imageResourcesPath = imageResourcesPath; + this.renderForms = renderForms; + this.annotationStorage = annotationStorage; + this.enableComment = enableComment; + this.#commentManager = commentManager; + this.enableScripting = enableScripting; + this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false); + this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null); + this._annotationCanvasMap = annotationCanvasMap; + this._accessibilityManager = accessibilityManager; + this._annotationEditorUIManager = annotationEditorUIManager; + this.#onAppend = onAppend; + this.annotationLayer = null; + this.div = null; + this._cancelled = false; + this._eventBus = linkService.eventBus; + } + async render({ + viewport, + intent = "display", + structTreeLayer = null + }) { + if (this.div) { + if (this._cancelled || !this.annotationLayer) { + return; + } + this.annotationLayer.update({ + viewport: viewport.clone({ + dontFlip: true + }) + }); + return; + } + const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({ + intent + }), this._hasJSActionsPromise, this._fieldObjectsPromise]); + if (this._cancelled) { + return; + } + const div = this.div = document.createElement("div"); + div.className = "annotationLayer"; + this.#onAppend?.(div); + this.#initAnnotationLayer(viewport, structTreeLayer); + if (annotations.length === 0) { + this.#annotations = annotations; + setLayerDimensions(this.div, viewport); + return; + } + await this.annotationLayer.render({ + annotations, + imageResourcesPath: this.imageResourcesPath, + renderForms: this.renderForms, + downloadManager: this.downloadManager, + enableComment: this.enableComment, + enableScripting: this.enableScripting, + hasJSActions, + fieldObjects + }); + this.#annotations = annotations; + if (this.linkService.isInPresentationMode) { + this.#updatePresentationModeState(PresentationModeState.FULLSCREEN); + } + if (!this.#eventAbortController) { + this.#eventAbortController = new AbortController(); + this._eventBus?._on("presentationmodechanged", evt => { + this.#updatePresentationModeState(evt.state); + }, { + signal: this.#eventAbortController.signal + }); + } + } + #initAnnotationLayer(viewport, structTreeLayer) { + this.annotationLayer = new AnnotationLayer({ + div: this.div, + accessibilityManager: this._accessibilityManager, + annotationCanvasMap: this._annotationCanvasMap, + annotationEditorUIManager: this._annotationEditorUIManager, + annotationStorage: this.annotationStorage, + page: this.pdfPage, + viewport: viewport.clone({ + dontFlip: true + }), + structTreeLayer, + commentManager: this.#commentManager, + linkService: this.linkService + }); + } + cancel() { + this._cancelled = true; + this.#eventAbortController?.abort(); + this.#eventAbortController = null; + } + hide(internal = false) { + this.#externalHide = !internal; + if (!this.div) { + return; + } + this.div.hidden = true; + } + hasEditableAnnotations() { + return !!this.annotationLayer?.hasEditableAnnotations(); + } + async injectLinkAnnotations(inferredLinks) { + if (this.#annotations === null) { + throw new Error("`render` method must be called before `injectLinkAnnotations`."); + } + if (this._cancelled || this.#linksInjected) { + return; + } + this.#linksInjected = true; + const newLinks = this.#annotations.length ? this.#checkInferredLinks(inferredLinks) : inferredLinks; + if (!newLinks.length) { + return; + } + await this.annotationLayer.addLinkAnnotations(newLinks); + if (!this.#externalHide) { + this.div.hidden = false; + } + } + #updatePresentationModeState(state) { + if (!this.div) { + return; + } + let disableFormElements = false; + switch (state) { + case PresentationModeState.FULLSCREEN: + disableFormElements = true; + break; + case PresentationModeState.NORMAL: + break; + default: + return; + } + for (const section of this.div.childNodes) { + if (section.hasAttribute("data-internal-link")) { + continue; + } + section.inert = disableFormElements; + } + } + #checkInferredLinks(inferredLinks) { + function annotationRects(annot) { + if (!annot.quadPoints) { + return [annot.rect]; + } + const rects = []; + for (let i = 2, ii = annot.quadPoints.length; i < ii; i += 8) { + const trX = annot.quadPoints[i]; + const trY = annot.quadPoints[i + 1]; + const blX = annot.quadPoints[i + 2]; + const blY = annot.quadPoints[i + 3]; + rects.push([blX, blY, trX, trY]); + } + return rects; + } + function intersectAnnotations(annot1, annot2) { + const intersections = []; + const annot1Rects = annotationRects(annot1); + const annot2Rects = annotationRects(annot2); + for (const rect1 of annot1Rects) { + for (const rect2 of annot2Rects) { + const intersection = Util.intersect(rect1, rect2); + if (intersection) { + intersections.push(intersection); + } + } + } + return intersections; + } + function areaRects(rects) { + let totalArea = 0; + for (const rect of rects) { + totalArea += Math.abs((rect[2] - rect[0]) * (rect[3] - rect[1])); + } + return totalArea; + } + return inferredLinks.filter(link => { + let linkAreaRects; + for (const annotation of this.#annotations) { + if (annotation.annotationType !== AnnotationType.LINK || !annotation.url) { + continue; + } + const intersections = intersectAnnotations(annotation, link); + if (intersections.length === 0) { + continue; + } + linkAreaRects ??= areaRects(annotationRects(link)); + if (areaRects(intersections) / linkAreaRects > 0.5) { + return false; + } + } + return true; + }); + } +} + +;// ./web/autolinker.js + + +function DOMRectToPDF({ + width, + height, + left, + top +}, pdfPageView) { + if (width === 0 || height === 0) { + return null; + } + const pageBox = pdfPageView.textLayer.div.getBoundingClientRect(); + const bottomLeft = pdfPageView.getPagePoint(left - pageBox.left, top - pageBox.top); + const topRight = pdfPageView.getPagePoint(left - pageBox.left + width, top - pageBox.top + height); + return Util.normalizeRect([bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]); +} +function calculateLinkPosition(range, pdfPageView) { + const rangeRects = range.getClientRects(); + if (rangeRects.length === 1) { + return { + rect: DOMRectToPDF(rangeRects[0], pdfPageView) + }; + } + const rect = [Infinity, Infinity, -Infinity, -Infinity]; + const quadPoints = []; + let i = 0; + for (const domRect of rangeRects) { + const normalized = DOMRectToPDF(domRect, pdfPageView); + if (normalized === null) { + continue; + } + quadPoints[i] = quadPoints[i + 4] = normalized[0]; + quadPoints[i + 1] = quadPoints[i + 3] = normalized[3]; + quadPoints[i + 2] = quadPoints[i + 6] = normalized[2]; + quadPoints[i + 5] = quadPoints[i + 7] = normalized[1]; + Util.rectBoundingBox(...normalized, rect); + i += 8; + } + return { + quadPoints, + rect + }; +} +function textPosition(container, offset) { + let currentContainer = container; + do { + if (currentContainer.nodeType === Node.TEXT_NODE) { + const currentLength = currentContainer.textContent.length; + if (offset <= currentLength) { + return [currentContainer, offset]; + } + offset -= currentLength; + } else if (currentContainer.firstChild) { + currentContainer = currentContainer.firstChild; + continue; + } + while (!currentContainer.nextSibling && currentContainer !== container) { + currentContainer = currentContainer.parentNode; + } + if (currentContainer !== container) { + currentContainer = currentContainer.nextSibling; + } + } while (currentContainer !== container); + throw new Error("Offset is bigger than container's contents length."); +} +function createLinkAnnotation({ + url, + index, + length +}, pdfPageView, id) { + const highlighter = pdfPageView._textHighlighter; + const [{ + begin, + end + }] = highlighter._convertMatches([index], [length]); + const range = new Range(); + range.setStart(...textPosition(highlighter.textDivs[begin.divIdx], begin.offset)); + range.setEnd(...textPosition(highlighter.textDivs[end.divIdx], end.offset)); + return { + id: `inferred_link_${id}`, + unsafeUrl: url, + url, + annotationType: AnnotationType.LINK, + rotation: 0, + ...calculateLinkPosition(range, pdfPageView), + borderStyle: null + }; +} +class Autolinker { + static #index = 0; + static #regex; + static findLinks(text) { + this.#regex ??= /\b(?:https?:\/\/|mailto:|www\.)(?:[\S--[\p{P}<>]]|\/|[\S--[\[\]]]+[\S--[\p{P}<>]])+|\b[\S--[@\p{Ps}\p{Pe}<>]]+@([\S--[\p{P}<>]]+(?:\.[\S--[\p{P}<>]]+)+)/gmv; + const [normalizedText, diffs] = normalize(text, { + ignoreDashEOL: true + }); + const matches = normalizedText.matchAll(this.#regex); + const links = []; + for (const match of matches) { + const [url, emailDomain] = match; + let raw; + if (url.startsWith("www.") || url.startsWith("http://") || url.startsWith("https://")) { + raw = url; + } else if (URL.canParse(`http://${emailDomain}`)) { + raw = url.startsWith("mailto:") ? url : `mailto:${url}`; + } else { + continue; + } + const absoluteURL = createValidAbsoluteUrl(raw, null, { + addDefaultProtocol: true + }); + if (absoluteURL) { + const [index, length] = getOriginalIndex(diffs, match.index, url.length); + links.push({ + url: absoluteURL.href, + index, + length + }); + } + } + return links; + } + static processLinks(pdfPageView) { + return this.findLinks(pdfPageView._textHighlighter.textContentItemsStr.join("\n")).map(link => createLinkAnnotation(link, pdfPageView, this.#index++)); + } +} + +;// ./web/base_pdf_page_view.js + + +class BasePDFPageView { + #loadingId = null; + #minDurationToUpdateCanvas = 0; + #renderError = null; + #renderingState = RenderingStates.INITIAL; + #showCanvas = null; + #startTime = 0; + #tempCanvas = null; + canvas = null; + div = null; + enableOptimizedPartialRendering = false; + eventBus = null; + id = null; + pageColors = null; + recordedBBoxes = null; + renderingQueue = null; + renderTask = null; + resume = null; + constructor(options) { + this.eventBus = options.eventBus; + this.id = options.id; + this.pageColors = options.pageColors || null; + this.renderingQueue = options.renderingQueue; + this.enableOptimizedPartialRendering = options.enableOptimizedPartialRendering ?? false; + this.#minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500; + } + get renderingState() { + return this.#renderingState; + } + set renderingState(state) { + if (state === this.#renderingState) { + return; + } + this.#renderingState = state; + if (this.#loadingId) { + clearTimeout(this.#loadingId); + this.#loadingId = null; + } + switch (state) { + case RenderingStates.PAUSED: + this.div.classList.remove("loading"); + this.#startTime = 0; + this.#showCanvas?.(false); + break; + case RenderingStates.RUNNING: + this.div.classList.add("loadingIcon"); + this.#loadingId = setTimeout(() => { + this.div.classList.add("loading"); + this.#loadingId = null; + }, 0); + this.#startTime = Date.now(); + break; + case RenderingStates.INITIAL: + case RenderingStates.FINISHED: + this.div.classList.remove("loadingIcon", "loading"); + this.#startTime = 0; + break; + } + } + _createCanvas(onShow, hideUntilComplete = false) { + const { + pageColors + } = this; + const hasHCM = !!(pageColors?.background && pageColors?.foreground); + const prevCanvas = this.canvas; + const updateOnFirstShow = !prevCanvas && !hasHCM && !hideUntilComplete; + let canvas = this.canvas = document.createElement("canvas"); + this.#showCanvas = isLastShow => { + if (updateOnFirstShow) { + let tempCanvas = this.#tempCanvas; + if (!isLastShow && this.#minDurationToUpdateCanvas > 0) { + if (Date.now() - this.#startTime < this.#minDurationToUpdateCanvas) { + return; + } + if (!tempCanvas) { + tempCanvas = this.#tempCanvas = canvas; + canvas = this.canvas = canvas.cloneNode(false); + onShow(canvas); + } + } + if (tempCanvas) { + const ctx = canvas.getContext("2d", { + alpha: false + }); + ctx.drawImage(tempCanvas, 0, 0); + if (isLastShow) { + this.#resetTempCanvas(); + } else { + this.#startTime = Date.now(); + } + return; + } + onShow(canvas); + this.#showCanvas = null; + return; + } + if (!isLastShow) { + return; + } + if (prevCanvas) { + prevCanvas.replaceWith(canvas); + prevCanvas.width = prevCanvas.height = 0; + } else { + onShow(canvas); + } + }; + return { + canvas, + prevCanvas + }; + } + #renderContinueCallback = cont => { + this.#showCanvas?.(false); + if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) { + this.renderingState = RenderingStates.PAUSED; + this.resume = () => { + this.renderingState = RenderingStates.RUNNING; + cont(); + }; + return; + } + cont(); + }; + _resetCanvas() { + const { + canvas + } = this; + if (!canvas) { + return; + } + canvas.remove(); + canvas.width = canvas.height = 0; + this.canvas = null; + this.#resetTempCanvas(); + } + #resetTempCanvas() { + if (this.#tempCanvas) { + this.#tempCanvas.width = this.#tempCanvas.height = 0; + this.#tempCanvas = null; + } + } + async _drawCanvas(options, onCancel, onFinish) { + const renderTask = this.renderTask = this.pdfPage.render(options); + renderTask.onContinue = this.#renderContinueCallback; + renderTask.onError = error => { + if (error instanceof RenderingCancelledException) { + onCancel(); + this.#renderError = null; + } + }; + let error = null; + try { + await renderTask.promise; + this.#showCanvas?.(true); + } catch (e) { + if (e instanceof RenderingCancelledException) { + return; + } + error = e; + this.#showCanvas?.(true); + } finally { + this.#renderError = error; + if (renderTask === this.renderTask) { + this.renderTask = null; + if (this.enableOptimizedPartialRendering) { + this.recordedBBoxes ??= renderTask.recordedBBoxes; + } + } + } + this.renderingState = RenderingStates.FINISHED; + onFinish(renderTask); + if (error) { + throw error; + } + } + cancelRendering({ + cancelExtraDelay = 0 + } = {}) { + if (this.renderTask) { + this.renderTask.cancel(cancelExtraDelay); + this.renderTask = null; + } + this.resume = null; + } + dispatchPageRender() { + this.eventBus.dispatch("pagerender", { + source: this, + pageNumber: this.id + }); + } + dispatchPageRendered(cssTransform, isDetailView) { + this.eventBus.dispatch("pagerendered", { + source: this, + pageNumber: this.id, + cssTransform, + isDetailView, + timestamp: performance.now(), + error: this.#renderError + }); + } +} + +;// ./web/draw_layer_builder.js + +class DrawLayerBuilder { + #drawLayer = null; + constructor(options) { + this.pageIndex = options.pageIndex; + } + async render({ + intent = "display" + }) { + if (intent !== "display" || this.#drawLayer || this._cancelled) { + return; + } + this.#drawLayer = new DrawLayer({ + pageIndex: this.pageIndex + }); + } + cancel() { + this._cancelled = true; + if (!this.#drawLayer) { + return; + } + this.#drawLayer.destroy(); + this.#drawLayer = null; + } + setParent(parent) { + this.#drawLayer?.setParent(parent); + } + getDrawLayer() { + return this.#drawLayer; + } +} + +;// ./web/pdf_page_detail_view.js + + + +class PDFPageDetailView extends BasePDFPageView { + #detailArea = null; + renderingCancelled = false; + constructor({ + pageView + }) { + super(pageView); + this.pageView = pageView; + this.renderingId = "detail" + this.id; + this.div = pageView.div; + } + setPdfPage(pdfPage) { + this.pageView.setPdfPage(pdfPage); + } + get pdfPage() { + return this.pageView.pdfPage; + } + get renderingState() { + return super.renderingState; + } + set renderingState(value) { + this.renderingCancelled = false; + super.renderingState = value; + } + reset({ + keepCanvas = false + } = {}) { + const renderingCancelled = this.renderingCancelled || this.renderingState === RenderingStates.RUNNING || this.renderingState === RenderingStates.PAUSED; + this.cancelRendering(); + this.renderingState = RenderingStates.INITIAL; + this.renderingCancelled = renderingCancelled; + if (!keepCanvas) { + this._resetCanvas(); + } + } + #shouldRenderDifferentArea(visibleArea) { + if (!this.#detailArea) { + return true; + } + const minDetailX = this.#detailArea.minX; + const minDetailY = this.#detailArea.minY; + const maxDetailX = this.#detailArea.width + minDetailX; + const maxDetailY = this.#detailArea.height + minDetailY; + if (visibleArea.minX < minDetailX || visibleArea.minY < minDetailY || visibleArea.maxX > maxDetailX || visibleArea.maxY > maxDetailY) { + return true; + } + const { + width: maxWidth, + height: maxHeight, + scale + } = this.pageView.viewport; + if (this.#detailArea.scale !== scale) { + return true; + } + const paddingLeftSize = visibleArea.minX - minDetailX; + const paddingRightSize = maxDetailX - visibleArea.maxX; + const paddingTopSize = visibleArea.minY - minDetailY; + const paddingBottomSize = maxDetailY - visibleArea.maxY; + const MOVEMENT_THRESHOLD = 0.5; + const ratio = (1 + MOVEMENT_THRESHOLD) / MOVEMENT_THRESHOLD; + if (minDetailX > 0 && paddingRightSize / paddingLeftSize > ratio || maxDetailX < maxWidth && paddingLeftSize / paddingRightSize > ratio || minDetailY > 0 && paddingBottomSize / paddingTopSize > ratio || maxDetailY < maxHeight && paddingTopSize / paddingBottomSize > ratio) { + return true; + } + return false; + } + update({ + visibleArea = null, + underlyingViewUpdated = false + } = {}) { + if (underlyingViewUpdated) { + this.cancelRendering(); + this.renderingState = RenderingStates.INITIAL; + return; + } + if (!this.#shouldRenderDifferentArea(visibleArea)) { + return; + } + const { + viewport, + maxCanvasPixels, + capCanvasAreaFactor + } = this.pageView; + const visibleWidth = visibleArea.maxX - visibleArea.minX; + const visibleHeight = visibleArea.maxY - visibleArea.minY; + const visiblePixels = visibleWidth * visibleHeight * OutputScale.pixelRatio ** 2; + const maxDetailToVisibleLinearRatio = Math.sqrt(OutputScale.capPixels(maxCanvasPixels, capCanvasAreaFactor) / visiblePixels); + const maxOverflowScale = (maxDetailToVisibleLinearRatio - 1) / 2; + let overflowScale = Math.min(1, maxOverflowScale); + if (overflowScale < 0) { + overflowScale = 0; + } + const overflowWidth = visibleWidth * overflowScale; + const overflowHeight = visibleHeight * overflowScale; + const minX = Math.max(0, visibleArea.minX - overflowWidth); + const maxX = Math.min(viewport.width, visibleArea.maxX + overflowWidth); + const minY = Math.max(0, visibleArea.minY - overflowHeight); + const maxY = Math.min(viewport.height, visibleArea.maxY + overflowHeight); + const width = maxX - minX; + const height = maxY - minY; + this.#detailArea = { + minX, + minY, + width, + height, + scale: viewport.scale + }; + this.reset({ + keepCanvas: true + }); + } + _getRenderingContext(canvas, transform) { + const baseContext = this.pageView._getRenderingContext(canvas, transform, false); + const recordedBBoxes = this.pdfPage.recordedBBoxes; + if (!recordedBBoxes || !this.enableOptimizedPartialRendering) { + return baseContext; + } + const { + viewport: { + width: vWidth, + height: vHeight + } + } = this.pageView; + const { + width: aWidth, + height: aHeight, + minX: aMinX, + minY: aMinY + } = this.#detailArea; + const detailMinX = aMinX / vWidth; + const detailMinY = aMinY / vHeight; + const detailMaxX = (aMinX + aWidth) / vWidth; + const detailMaxY = (aMinY + aHeight) / vHeight; + return { + ...baseContext, + operationsFilter(index) { + if (recordedBBoxes.isEmpty(index)) { + return false; + } + return recordedBBoxes.minX(index) <= detailMaxX && recordedBBoxes.maxX(index) >= detailMinX && recordedBBoxes.minY(index) <= detailMaxY && recordedBBoxes.maxY(index) >= detailMinY; + } + }; + } + async draw() { + if (this.pageView.detailView !== this) { + return undefined; + } + const hideUntilComplete = this.pageView.renderingState === RenderingStates.FINISHED || this.renderingState === RenderingStates.FINISHED; + if (this.renderingState !== RenderingStates.INITIAL) { + console.error("Must be in new state before drawing"); + this.reset(); + } + const { + div, + pdfPage, + viewport + } = this.pageView; + if (!pdfPage) { + this.renderingState = RenderingStates.FINISHED; + throw new Error("pdfPage is not loaded"); + } + this.renderingState = RenderingStates.RUNNING; + const canvasWrapper = this.pageView._ensureCanvasWrapper(); + const { + canvas, + prevCanvas + } = this._createCanvas(newCanvas => { + if (canvasWrapper.firstElementChild?.tagName === "CANVAS") { + canvasWrapper.firstElementChild.after(newCanvas); + } else { + canvasWrapper.prepend(newCanvas); + } + }, hideUntilComplete); + canvas.ariaHidden = true; + if (this.enableOptimizedPartialRendering) { + canvas.className = "detailView"; + } + const { + width, + height + } = viewport; + const area = this.#detailArea; + const { + pixelRatio + } = OutputScale; + const transform = [pixelRatio, 0, 0, pixelRatio, -area.minX * pixelRatio, -area.minY * pixelRatio]; + canvas.width = area.width * pixelRatio; + canvas.height = area.height * pixelRatio; + const { + style + } = canvas; + style.width = `${area.width * 100 / width}%`; + style.height = `${area.height * 100 / height}%`; + style.top = `${area.minY * 100 / height}%`; + style.left = `${area.minX * 100 / width}%`; + const renderingPromise = this._drawCanvas(this._getRenderingContext(canvas, transform), () => { + this.canvas?.remove(); + this.canvas = prevCanvas; + }, () => { + this.dispatchPageRendered(false, true); + }); + div.setAttribute("data-loaded", true); + this.dispatchPageRender(); + return renderingPromise; + } +} + +;// ./web/struct_tree_layer_builder.js + + +const PDF_ROLE_TO_HTML_ROLE = { + Document: null, + DocumentFragment: null, + Part: "group", + Sect: "group", + Div: "group", + Aside: "note", + NonStruct: "none", + P: null, + H: "heading", + Title: null, + FENote: "note", + Sub: "group", + Lbl: null, + Span: null, + Em: null, + Strong: null, + Link: "link", + Annot: "note", + Form: "form", + Ruby: null, + RB: null, + RT: null, + RP: null, + Warichu: null, + WT: null, + WP: null, + L: "list", + LI: "listitem", + LBody: null, + Table: "table", + TR: "row", + TH: "columnheader", + TD: "cell", + THead: "columnheader", + TBody: null, + TFoot: null, + Caption: null, + Figure: "figure", + Formula: null, + Artifact: null +}; +const MathMLElements = new Set(["math", "merror", "mfrac", "mi", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mprescripts", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "semantics"]); +const MathMLNamespace = "http://www.w3.org/1998/Math/MathML"; +class MathMLSanitizer { + static get sanitizer() { + return shadow(this, "sanitizer", FeatureTest.isSanitizerSupported ? new Sanitizer({ + elements: [...MathMLElements].map(name => ({ + name, + namespace: MathMLNamespace + })), + replaceWithChildrenElements: [{ + name: "maction", + namespace: MathMLNamespace + }], + attributes: ["dir", "displaystyle", "mathbackground", "mathcolor", "mathsize", "scriptlevel", "encoding", "display", "linethickness", "intent", "arg", "form", "fence", "separator", "lspace", "rspace", "stretchy", "symmetric", "maxsize", "minsize", "largeop", "movablelimits", "width", "height", "depth", "voffset", "accent", "accentunder", "columnspan", "rowspan"], + comments: false + }) : null); + } +} +const HEADING_PATTERN = /^H(\d+)$/; +class StructTreeLayerBuilder { + #promise; + #treeDom = null; + #treePromise; + #elementAttributes = new Map(); + #rawDims; + #elementsToAddToTextLayer = null; + constructor(pdfPage, rawDims) { + this.#promise = pdfPage.getStructTree(); + this.#rawDims = rawDims; + } + async render() { + if (this.#treePromise) { + return this.#treePromise; + } + const { + promise, + resolve, + reject + } = Promise.withResolvers(); + this.#treePromise = promise; + try { + this.#treeDom = this.#walk(await this.#promise); + } catch (ex) { + reject(ex); + } + this.#promise = null; + this.#treeDom?.classList.add("structTree"); + resolve(this.#treeDom); + return promise; + } + async getAriaAttributes(annotationId) { + try { + await this.render(); + return this.#elementAttributes.get(annotationId); + } catch {} + return null; + } + hide() { + if (this.#treeDom && !this.#treeDom.hidden) { + this.#treeDom.hidden = true; + } + } + show() { + if (this.#treeDom?.hidden) { + this.#treeDom.hidden = false; + } + } + #setAttributes(structElement, htmlElement) { + const { + alt, + id, + lang + } = structElement; + if (alt !== undefined) { + let added = false; + const label = removeNullCharacters(alt); + for (const child of structElement.children) { + if (child.type === "annotation") { + let attrs = this.#elementAttributes.get(child.id); + if (!attrs) { + attrs = new Map(); + this.#elementAttributes.set(child.id, attrs); + } + attrs.set("aria-label", label); + added = true; + } + } + if (!added) { + htmlElement.setAttribute("aria-label", label); + } + } + if (id !== undefined) { + htmlElement.setAttribute("aria-owns", id); + } + if (lang !== undefined) { + htmlElement.setAttribute("lang", removeNullCharacters(lang, true)); + } + } + #addImageInTextLayer(node, element) { + const { + alt, + bbox, + children + } = node; + const child = children?.[0]; + if (!this.#rawDims || !alt || !bbox || child?.type !== "content") { + return false; + } + const { + id + } = child; + if (!id) { + return false; + } + element.setAttribute("aria-owns", id); + const img = document.createElement("span"); + (this.#elementsToAddToTextLayer ||= new Map()).set(id, img); + img.setAttribute("role", "img"); + img.setAttribute("aria-label", removeNullCharacters(alt)); + const { + pageHeight, + pageX, + pageY + } = this.#rawDims; + const calc = "calc(var(--total-scale-factor) *"; + const { + style + } = img; + style.width = `${calc}${bbox[2] - bbox[0]}px)`; + style.height = `${calc}${bbox[3] - bbox[1]}px)`; + style.left = `${calc}${bbox[0] - pageX}px)`; + style.top = `${calc}${pageHeight - bbox[3] + pageY}px)`; + return true; + } + addElementsToTextLayer() { + if (!this.#elementsToAddToTextLayer) { + return; + } + for (const [id, img] of this.#elementsToAddToTextLayer) { + document.getElementById(id)?.append(img); + } + this.#elementsToAddToTextLayer.clear(); + this.#elementsToAddToTextLayer = null; + } + #walk(node) { + if (!node) { + return null; + } + let element; + if ("role" in node) { + const { + role + } = node; + element = MathMLElements.has(role) ? document.createElementNS(MathMLNamespace, role) : document.createElement("span"); + const match = role.match(HEADING_PATTERN); + if (match) { + element.setAttribute("role", "heading"); + element.setAttribute("aria-level", match[1]); + } else if (PDF_ROLE_TO_HTML_ROLE[role]) { + element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]); + } + if (role === "Figure" && this.#addImageInTextLayer(node, element)) { + return element; + } + if (role === "Formula") { + if (node.mathML && MathMLSanitizer.sanitizer) { + element.setHTML(node.mathML, { + sanitizer: MathMLSanitizer.sanitizer + }); + } + if (!node.mathML && node.children.length === 1 && node.children[0].role !== "math") { + element = document.createElementNS(MathMLNamespace, "math"); + } + } + } + element ||= document.createElement("span"); + this.#setAttributes(node, element); + if (node.children) { + if (node.children.length === 1 && "id" in node.children[0]) { + this.#setAttributes(node.children[0], element); + } else { + for (const kid of node.children) { + element.append(this.#walk(kid)); + } + } + } + return element; + } +} + +;// ./web/text_accessibility.js + +class TextAccessibilityManager { + #enabled = false; + #textChildren = null; + #textNodes = new Map(); + #waitingElements = new Map(); + setTextMapping(textDivs) { + this.#textChildren = textDivs; + } + static #compareElementPositions(e1, e2) { + const rect1 = e1.getBoundingClientRect(); + const rect2 = e2.getBoundingClientRect(); + if (rect1.width === 0 && rect1.height === 0) { + return +1; + } + if (rect2.width === 0 && rect2.height === 0) { + return -1; + } + const top1 = rect1.y; + const bot1 = rect1.y + rect1.height; + const mid1 = rect1.y + rect1.height / 2; + const top2 = rect2.y; + const bot2 = rect2.y + rect2.height; + const mid2 = rect2.y + rect2.height / 2; + if (mid1 <= top2 && mid2 >= bot1) { + return -1; + } + if (mid2 <= top1 && mid1 >= bot2) { + return +1; + } + const centerX1 = rect1.x + rect1.width / 2; + const centerX2 = rect2.x + rect2.width / 2; + return centerX1 - centerX2; + } + enable() { + if (this.#enabled) { + throw new Error("TextAccessibilityManager is already enabled."); + } + if (!this.#textChildren) { + throw new Error("Text divs and strings have not been set."); + } + this.#enabled = true; + this.#textChildren = this.#textChildren.slice(); + this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions); + if (this.#textNodes.size > 0) { + const textChildren = this.#textChildren; + for (const [id, nodeIndex] of this.#textNodes) { + const element = document.getElementById(id); + if (!element) { + this.#textNodes.delete(id); + continue; + } + this.#addIdToAriaOwns(id, textChildren[nodeIndex]); + } + } + for (const [element, isRemovable] of this.#waitingElements) { + this.addPointerInTextLayer(element, isRemovable); + } + this.#waitingElements.clear(); + } + disable() { + if (!this.#enabled) { + return; + } + this.#waitingElements.clear(); + this.#textChildren = null; + this.#enabled = false; + } + removePointerInTextLayer(element) { + if (!this.#enabled) { + this.#waitingElements.delete(element); + return; + } + const children = this.#textChildren; + if (!children || children.length === 0) { + return; + } + const { + id + } = element; + const nodeIndex = this.#textNodes.get(id); + if (nodeIndex === undefined) { + return; + } + const node = children[nodeIndex]; + this.#textNodes.delete(id); + let owns = node.getAttribute("aria-owns"); + if (owns?.includes(id)) { + owns = owns.split(" ").filter(x => x !== id).join(" "); + if (owns) { + node.setAttribute("aria-owns", owns); + } else { + node.removeAttribute("aria-owns"); + node.setAttribute("role", "presentation"); + } + } + } + #addIdToAriaOwns(id, node) { + const owns = node.getAttribute("aria-owns"); + if (!owns?.includes(id)) { + node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id); + } + node.removeAttribute("role"); + } + addPointerInTextLayer(element, isRemovable) { + const { + id + } = element; + if (!id) { + return null; + } + if (!this.#enabled) { + this.#waitingElements.set(element, isRemovable); + return null; + } + if (isRemovable) { + this.removePointerInTextLayer(element); + } + const children = this.#textChildren; + if (!children || children.length === 0) { + return null; + } + const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0); + const nodeIndex = Math.max(0, index - 1); + const child = children[nodeIndex]; + this.#addIdToAriaOwns(id, child); + this.#textNodes.set(id, nodeIndex); + const parent = child.parentNode; + return parent?.classList.contains("markedContent") ? parent.id : null; + } + moveElementInDOM(container, element, contentElement, isRemovable) { + const id = this.addPointerInTextLayer(contentElement, isRemovable); + if (!container.hasChildNodes()) { + container.append(element); + return id; + } + const children = Array.from(container.childNodes).filter(node => node !== element); + if (children.length === 0) { + return id; + } + const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0); + if (index === 0) { + children[0].before(element); + } else { + children[index - 1].after(element); + } + return id; + } +} + +;// ./web/text_highlighter.js +class TextHighlighter { + #eventAbortController = null; + constructor({ + findController, + eventBus, + pageIndex + }) { + this.findController = findController; + this.matches = []; + this.eventBus = eventBus; + this.pageIdx = pageIndex; + this.textDivs = null; + this.textContentItemsStr = null; + this.enabled = false; + } + setTextMapping(divs, texts) { + this.textDivs = divs; + this.textContentItemsStr = texts; + } + enable() { + if (!this.textDivs || !this.textContentItemsStr) { + throw new Error("Text divs and strings have not been set."); + } + if (this.enabled) { + throw new Error("TextHighlighter is already enabled."); + } + this.enabled = true; + if (!this.#eventAbortController) { + this.#eventAbortController = new AbortController(); + this.eventBus._on("updatetextlayermatches", evt => { + if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) { + this._updateMatches(); + } + }, { + signal: this.#eventAbortController.signal + }); + } + this._updateMatches(); + } + disable() { + if (!this.enabled) { + return; + } + this.enabled = false; + this.#eventAbortController?.abort(); + this.#eventAbortController = null; + this._updateMatches(true); + } + _convertMatches(matches, matchesLength) { + if (!matches) { + return []; + } + const { + textContentItemsStr + } = this; + let i = 0, + iIndex = 0; + const end = textContentItemsStr.length - 1; + const result = []; + for (let m = 0, mm = matches.length; m < mm; m++) { + let matchIdx = matches[m]; + while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) { + iIndex += textContentItemsStr[i].length; + i++; + } + if (i === textContentItemsStr.length) { + console.error("Could not find a matching mapping"); + } + const match = { + begin: { + divIdx: i, + offset: matchIdx - iIndex + } + }; + matchIdx += matchesLength[m]; + while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) { + iIndex += textContentItemsStr[i].length; + i++; + } + match.end = { + divIdx: i, + offset: matchIdx - iIndex + }; + result.push(match); + } + return result; + } + _renderMatches(matches) { + if (matches.length === 0) { + return; + } + const { + findController, + pageIdx + } = this; + const { + textContentItemsStr, + textDivs + } = this; + const isSelectedPage = pageIdx === findController.selected.pageIdx; + const selectedMatchIdx = findController.selected.matchIdx; + const highlightAll = findController.state.highlightAll; + let prevEnd = null; + const infinity = { + divIdx: -1, + offset: undefined + }; + function beginText(begin, className) { + const divIdx = begin.divIdx; + textDivs[divIdx].textContent = ""; + return appendTextToDiv(divIdx, 0, begin.offset, className); + } + function appendTextToDiv(divIdx, fromOffset, toOffset, className) { + let div = textDivs[divIdx]; + if (div.nodeType === Node.TEXT_NODE) { + const span = document.createElement("span"); + div.before(span); + span.append(div); + textDivs[divIdx] = span; + div = span; + } + const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset); + const node = document.createTextNode(content); + if (className) { + const span = document.createElement("span"); + span.className = `${className} appended`; + span.append(node); + div.append(span); + if (className.includes("selected")) { + const { + left + } = span.getClientRects()[0]; + const parentLeft = div.getBoundingClientRect().left; + return left - parentLeft; + } + return 0; + } + div.append(node); + return 0; + } + let i0 = selectedMatchIdx, + i1 = i0 + 1; + if (highlightAll) { + i0 = 0; + i1 = matches.length; + } else if (!isSelectedPage) { + return; + } + let lastDivIdx = -1; + let lastOffset = -1; + for (let i = i0; i < i1; i++) { + const match = matches[i]; + const begin = match.begin; + if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) { + continue; + } + lastDivIdx = begin.divIdx; + lastOffset = begin.offset; + const end = match.end; + const isSelected = isSelectedPage && i === selectedMatchIdx; + const highlightSuffix = isSelected ? " selected" : ""; + let selectedLeft = 0; + if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { + if (prevEnd !== null) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + beginText(begin); + } else { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset); + } + if (begin.divIdx === end.divIdx) { + selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix); + } else { + selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix); + for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) { + textDivs[n0].className = "highlight middle" + highlightSuffix; + } + beginText(end, "highlight end" + highlightSuffix); + } + prevEnd = end; + if (isSelected) { + findController.scrollMatchIntoView({ + element: textDivs[begin.divIdx], + selectedLeft, + pageIndex: pageIdx, + matchIndex: selectedMatchIdx + }); + } + } + if (prevEnd) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + } + _updateMatches(reset = false) { + if (!this.enabled && !reset) { + return; + } + const { + findController, + matches, + pageIdx + } = this; + const { + textContentItemsStr, + textDivs + } = this; + let clearedUntilDivIdx = -1; + for (const match of matches) { + const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); + for (let n = begin, end = match.end.divIdx; n <= end; n++) { + const div = textDivs[n]; + div.textContent = textContentItemsStr[n]; + div.className = ""; + } + clearedUntilDivIdx = match.end.divIdx + 1; + } + if (!findController?.highlightMatches || reset) { + return; + } + const pageMatches = findController.pageMatches[pageIdx] || null; + const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null; + this.matches = this._convertMatches(pageMatches, pageMatchesLength); + this._renderMatches(this.matches); + } +} + +;// ./web/text_layer_builder.js + + +class TextLayerBuilder { + #enablePermissions = false; + #onAppend = null; + #renderingDone = false; + #textLayer = null; + static #textLayers = new Map(); + static #selectionChangeAbortController = null; + constructor({ + pdfPage, + highlighter = null, + accessibilityManager = null, + enablePermissions = false, + onAppend = null + }) { + this.pdfPage = pdfPage; + this.highlighter = highlighter; + this.accessibilityManager = accessibilityManager; + this.#enablePermissions = enablePermissions === true; + this.#onAppend = onAppend; + this.div = document.createElement("div"); + this.div.tabIndex = 0; + this.div.className = "textLayer"; + } + async render({ + viewport, + textContentParams = null + }) { + if (this.#renderingDone && this.#textLayer) { + this.#textLayer.update({ + viewport, + onBefore: this.hide.bind(this) + }); + this.show(); + return; + } + this.cancel(); + this.#textLayer = new TextLayer({ + textContentSource: this.pdfPage.streamTextContent(textContentParams || { + includeMarkedContent: true, + disableNormalization: true + }), + container: this.div, + viewport + }); + const { + textDivs, + textContentItemsStr + } = this.#textLayer; + this.highlighter?.setTextMapping(textDivs, textContentItemsStr); + this.accessibilityManager?.setTextMapping(textDivs); + await this.#textLayer.render(); + this.#renderingDone = true; + const endOfContent = document.createElement("div"); + endOfContent.className = "endOfContent"; + this.div.append(endOfContent); + this.#bindMouse(endOfContent); + this.#onAppend?.(this.div); + this.highlighter?.enable(); + this.accessibilityManager?.enable(); + } + hide() { + if (!this.div.hidden && this.#renderingDone) { + this.highlighter?.disable(); + this.div.hidden = true; + } + } + show() { + if (this.div.hidden && this.#renderingDone) { + this.div.hidden = false; + this.highlighter?.enable(); + } + } + cancel() { + this.#textLayer?.cancel(); + this.#textLayer = null; + this.highlighter?.disable(); + this.accessibilityManager?.disable(); + TextLayerBuilder.#removeGlobalSelectionListener(this.div); + } + #bindMouse(end) { + const { + div + } = this; + div.addEventListener("mousedown", () => { + div.classList.add("selecting"); + }); + div.addEventListener("copy", event => { + if (!this.#enablePermissions) { + const selection = document.getSelection(); + event.clipboardData.setData("text/plain", removeNullCharacters(normalizeUnicode(selection.toString()))); + } + stopEvent(event); + }); + TextLayerBuilder.#textLayers.set(div, end); + TextLayerBuilder.#enableGlobalSelectionListener(); + } + static #removeGlobalSelectionListener(textLayerDiv) { + this.#textLayers.delete(textLayerDiv); + if (this.#textLayers.size === 0) { + this.#selectionChangeAbortController?.abort(); + this.#selectionChangeAbortController = null; + } + } + static #enableGlobalSelectionListener() { + if (this.#selectionChangeAbortController) { + return; + } + this.#selectionChangeAbortController = new AbortController(); + const { + signal + } = this.#selectionChangeAbortController; + const reset = (end, textLayer) => { + textLayer.classList.remove("selecting"); + }; + let isPointerDown = false; + document.addEventListener("pointerdown", () => { + isPointerDown = true; + }, { + signal + }); + document.addEventListener("pointerup", () => { + isPointerDown = false; + this.#textLayers.forEach(reset); + }, { + signal + }); + window.addEventListener("blur", () => { + isPointerDown = false; + this.#textLayers.forEach(reset); + }, { + signal + }); + document.addEventListener("keyup", () => { + if (!isPointerDown) { + this.#textLayers.forEach(reset); + } + }, { + signal + }); + document.addEventListener("selectionchange", () => { + const selection = document.getSelection(); + if (selection.rangeCount === 0) { + this.#textLayers.forEach(reset); + return; + } + const activeTextLayers = new Set(); + for (let i = 0; i < selection.rangeCount; i++) { + const range = selection.getRangeAt(i); + for (const textLayerDiv of this.#textLayers.keys()) { + if (!activeTextLayers.has(textLayerDiv) && range.intersectsNode(textLayerDiv)) { + activeTextLayers.add(textLayerDiv); + } + } + } + for (const [textLayerDiv, endDiv] of this.#textLayers) { + if (activeTextLayers.has(textLayerDiv)) { + textLayerDiv.classList.add("selecting"); + } else { + reset(endDiv, textLayerDiv); + } + } + }, { + signal + }); + } +} + +;// ./web/pdf_page_view.js + + + + + + + + + + + + + + + + +const DEFAULT_LAYER_PROPERTIES = null; +const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]); +class PDFPageView extends BasePDFPageView { + #annotationMode = AnnotationMode.ENABLE_FORMS; + #canvasWrapper = null; + #commentManager = null; + #enableAutoLinking = true; + #hasRestrictedScaling = false; + #isEditing = false; + #layerProperties = null; + #needsRestrictedScaling = false; + #originalViewport = null; + #previousRotation = null; + #scaleRoundX = 1; + #scaleRoundY = 1; + #textLayerMode = TextLayerMode.ENABLE; + #userUnit = 1; + #useThumbnailCanvas = { + directDrawing: true, + initialOptionalContent: true, + regularAnnotations: true + }; + #layers = [null, null, null, null]; + constructor(options) { + super(options); + const container = options.container; + const defaultViewport = options.defaultViewport; + this.renderingId = "page" + this.id; + this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES; + this.pdfPage = null; + this.pageLabel = null; + this.rotation = 0; + this.scale = options.scale || DEFAULT_SCALE; + this.viewport = defaultViewport; + this.pdfPageRotate = defaultViewport.rotation; + this._optionalContentConfigPromise = options.optionalContentConfigPromise || null; + this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE; + this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS; + this.imageResourcesPath = options.imageResourcesPath || ""; + this.enableDetailCanvas = options.enableDetailCanvas ?? true; + this.maxCanvasPixels = options.maxCanvasPixels ?? AppOptions.get("maxCanvasPixels"); + this.maxCanvasDim = options.maxCanvasDim || AppOptions.get("maxCanvasDim"); + this.capCanvasAreaFactor = options.capCanvasAreaFactor ?? AppOptions.get("capCanvasAreaFactor"); + this.#enableAutoLinking = options.enableAutoLinking !== false; + this.#commentManager = options.commentManager || null; + this.l10n = options.l10n; + this._annotationCanvasMap = null; + this.annotationLayer = null; + this.annotationEditorLayer = null; + this.textLayer = null; + this.xfaLayer = null; + this.structTreeLayer = null; + this.drawLayer = null; + this.detailView = null; + const div = document.createElement("div"); + div.className = "page"; + div.setAttribute("data-page-number", this.id); + div.setAttribute("role", "region"); + div.setAttribute("data-l10n-id", "pdfjs-page-landmark"); + div.setAttribute("data-l10n-args", JSON.stringify({ + page: this.id + })); + this.div = div; + this.#setDimensions(); + container?.append(div); + } + #addLayer(div, name) { + const pos = LAYERS_ORDER.get(name); + const oldDiv = this.#layers[pos]; + this.#layers[pos] = div; + if (oldDiv) { + oldDiv.replaceWith(div); + return; + } + for (let i = pos - 1; i >= 0; i--) { + const layer = this.#layers[i]; + if (layer) { + layer.after(div); + return; + } + } + this.div.prepend(div); + } + #setDimensions() { + const { + div, + viewport + } = this; + if (viewport.userUnit !== this.#userUnit) { + if (viewport.userUnit !== 1) { + div.style.setProperty("--user-unit", viewport.userUnit); + } else { + div.style.removeProperty("--user-unit"); + } + this.#userUnit = viewport.userUnit; + } + if (this.pdfPage) { + if (this.#previousRotation === viewport.rotation) { + return; + } + this.#previousRotation = viewport.rotation; + } + setLayerDimensions(div, viewport, true, false); + } + setPdfPage(pdfPage) { + this.pdfPage = pdfPage; + this.pdfPageRotate = pdfPage.rotate; + const totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = pdfPage.getViewport({ + scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS, + rotation: totalRotation + }); + this.#setDimensions(); + this.reset(); + } + destroy() { + this.reset(); + this.pdfPage?.cleanup(); + } + hasEditableAnnotations() { + return !!this.annotationLayer?.hasEditableAnnotations(); + } + get _textHighlighter() { + return shadow(this, "_textHighlighter", new TextHighlighter({ + pageIndex: this.id - 1, + eventBus: this.eventBus, + findController: this.#layerProperties.findController + })); + } + #dispatchLayerRendered(name, error) { + this.eventBus.dispatch(name, { + source: this, + pageNumber: this.id, + error + }); + } + async #renderAnnotationLayer() { + let error = null; + try { + await this.annotationLayer.render({ + viewport: this.viewport, + intent: "display", + structTreeLayer: this.structTreeLayer + }); + } catch (ex) { + console.error("#renderAnnotationLayer:", ex); + error = ex; + } finally { + this.#dispatchLayerRendered("annotationlayerrendered", error); + } + } + async #renderAnnotationEditorLayer() { + let error = null; + try { + await this.annotationEditorLayer.render({ + viewport: this.viewport, + intent: "display" + }); + } catch (ex) { + console.error("#renderAnnotationEditorLayer:", ex); + error = ex; + } finally { + this.#dispatchLayerRendered("annotationeditorlayerrendered", error); + } + } + async #renderDrawLayer() { + try { + await this.drawLayer.render({ + intent: "display" + }); + } catch (ex) { + console.error("#renderDrawLayer:", ex); + } + } + async #renderXfaLayer() { + let error = null; + try { + const result = await this.xfaLayer.render({ + viewport: this.viewport, + intent: "display" + }); + if (result?.textDivs && this._textHighlighter) { + this.#buildXfaTextContentItems(result.textDivs); + } + } catch (ex) { + console.error("#renderXfaLayer:", ex); + error = ex; + } finally { + if (this.xfaLayer?.div) { + this.l10n.pause(); + this.#addLayer(this.xfaLayer.div, "xfaLayer"); + this.l10n.resume(); + } + this.#dispatchLayerRendered("xfalayerrendered", error); + } + } + async #renderTextLayer() { + if (!this.textLayer) { + return; + } + let error = null; + try { + await this.textLayer.render({ + viewport: this.viewport + }); + } catch (ex) { + if (ex instanceof AbortException) { + return; + } + console.error("#renderTextLayer:", ex); + error = ex; + } + this.#dispatchLayerRendered("textlayerrendered", error); + this.#renderStructTreeLayer(); + } + async #renderStructTreeLayer() { + if (!this.textLayer) { + return; + } + const treeDom = await this.structTreeLayer?.render(); + if (treeDom) { + this.l10n.pause(); + this.structTreeLayer?.addElementsToTextLayer(); + if (this.canvas && treeDom.parentNode !== this.canvas) { + this.canvas.append(treeDom); + } + this.l10n.resume(); + } + this.structTreeLayer?.show(); + } + async #buildXfaTextContentItems(textDivs) { + const text = await this.pdfPage.getTextContent(); + const items = []; + for (const item of text.items) { + items.push(item.str); + } + this._textHighlighter.setTextMapping(textDivs, items); + this._textHighlighter.enable(); + } + async #injectLinkAnnotations(textLayerPromise) { + let error = null; + try { + await textLayerPromise; + if (!this.annotationLayer) { + return; + } + await this.annotationLayer.injectLinkAnnotations(Autolinker.processLinks(this)); + } catch (ex) { + console.error("#injectLinkAnnotations:", ex); + error = ex; + } + } + _resetCanvas() { + super._resetCanvas(); + this.#originalViewport = null; + } + reset({ + keepAnnotationLayer = false, + keepAnnotationEditorLayer = false, + keepXfaLayer = false, + keepTextLayer = false, + keepCanvasWrapper = false, + preserveDetailViewState = false + } = {}) { + const keepPdfBugGroups = this.pdfPage?._pdfBug ?? false; + this.cancelRendering({ + keepAnnotationLayer, + keepAnnotationEditorLayer, + keepXfaLayer, + keepTextLayer + }); + this.renderingState = RenderingStates.INITIAL; + const div = this.div; + const childNodes = div.childNodes, + annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null, + annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null, + xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null, + textLayerNode = keepTextLayer && this.textLayer?.div || null, + canvasWrapperNode = keepCanvasWrapper && this.#canvasWrapper || null; + for (let i = childNodes.length - 1; i >= 0; i--) { + const node = childNodes[i]; + switch (node) { + case annotationLayerNode: + case annotationEditorLayerNode: + case xfaLayerNode: + case textLayerNode: + case canvasWrapperNode: + continue; + } + if (keepPdfBugGroups && node.classList.contains("pdfBugGroupsLayer")) { + continue; + } + node.remove(); + const layerIndex = this.#layers.indexOf(node); + if (layerIndex >= 0) { + this.#layers[layerIndex] = null; + } + } + div.removeAttribute("data-loaded"); + if (annotationLayerNode) { + this.annotationLayer.hide(); + } + if (annotationEditorLayerNode) { + this.annotationEditorLayer.hide(); + } + if (xfaLayerNode) { + this.xfaLayer.hide(); + } + if (textLayerNode) { + this.textLayer.hide(); + } + this.structTreeLayer?.hide(); + if (!keepCanvasWrapper && this.#canvasWrapper) { + this.#canvasWrapper = null; + this._resetCanvas(); + } + if (!preserveDetailViewState) { + this.detailView?.reset({ + keepCanvas: keepCanvasWrapper + }); + if (!keepCanvasWrapper) { + this.detailView = null; + } + } + } + toggleEditingMode(isEditing) { + this.#isEditing = isEditing; + if (!this.hasEditableAnnotations()) { + return; + } + this.reset({ + keepAnnotationLayer: true, + keepAnnotationEditorLayer: true, + keepXfaLayer: true, + keepTextLayer: true, + keepCanvasWrapper: true + }); + } + updateVisibleArea(visibleArea) { + if (this.enableDetailCanvas) { + if (this.#needsRestrictedScaling && this.maxCanvasPixels > 0 && visibleArea) { + this.detailView ??= new PDFPageDetailView({ + pageView: this, + enableOptimizedPartialRendering: this.enableOptimizedPartialRendering + }); + this.detailView.update({ + visibleArea + }); + } else if (this.detailView) { + this.detailView.reset(); + this.detailView = null; + } + } + } + update({ + scale = 0, + rotation = null, + optionalContentConfigPromise = null, + drawingDelay = -1 + }) { + this.scale = scale || this.scale; + if (typeof rotation === "number") { + this.rotation = rotation; + } + if (optionalContentConfigPromise instanceof Promise) { + this._optionalContentConfigPromise = optionalContentConfigPromise; + optionalContentConfigPromise.then(optionalContentConfig => { + if (optionalContentConfigPromise !== this._optionalContentConfigPromise) { + return; + } + this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility; + }); + } + this.#useThumbnailCanvas.directDrawing = true; + const totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = this.viewport.clone({ + scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS, + rotation: totalRotation + }); + this.#setDimensions(); + this.#computeScale(); + if (this.canvas) { + const onlyCssZoom = this.#hasRestrictedScaling && this.#needsRestrictedScaling; + const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000; + if (postponeDrawing || onlyCssZoom) { + if (postponeDrawing && !onlyCssZoom && this.renderingState !== RenderingStates.FINISHED) { + this.cancelRendering({ + keepAnnotationLayer: true, + keepAnnotationEditorLayer: true, + keepXfaLayer: true, + keepTextLayer: true, + cancelExtraDelay: drawingDelay + }); + this.renderingState = RenderingStates.FINISHED; + this.#useThumbnailCanvas.directDrawing = false; + } + this.cssTransform({ + redrawAnnotationLayer: true, + redrawAnnotationEditorLayer: true, + redrawXfaLayer: true, + redrawTextLayer: !postponeDrawing, + hideTextLayer: postponeDrawing + }); + if (!postponeDrawing) { + this.detailView?.update({ + underlyingViewUpdated: true + }); + this.dispatchPageRendered(true, false); + } + return; + } + } + this.cssTransform({}); + this.reset({ + keepAnnotationLayer: true, + keepAnnotationEditorLayer: true, + keepXfaLayer: true, + keepTextLayer: true, + keepCanvasWrapper: true, + preserveDetailViewState: true + }); + this.detailView?.update({ + underlyingViewUpdated: true + }); + } + #computeScale() { + const { + width, + height + } = this.viewport; + const outputScale = this.outputScale = new OutputScale(); + this.#needsRestrictedScaling = outputScale.limitCanvas(width, height, this.maxCanvasPixels, this.maxCanvasDim, this.capCanvasAreaFactor); + if (this.#needsRestrictedScaling && this.enableDetailCanvas) { + const factor = this.enableOptimizedPartialRendering ? 4 : 2; + outputScale.sx /= factor; + outputScale.sy /= factor; + } + } + cancelRendering({ + keepAnnotationLayer = false, + keepAnnotationEditorLayer = false, + keepXfaLayer = false, + keepTextLayer = false, + cancelExtraDelay = 0 + } = {}) { + super.cancelRendering({ + cancelExtraDelay + }); + if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) { + this.textLayer.cancel(); + this.textLayer = null; + } + if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) { + this.annotationLayer.cancel(); + this.annotationLayer = null; + this._annotationCanvasMap = null; + } + if (this.structTreeLayer && !this.textLayer) { + this.structTreeLayer = null; + } + if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) { + if (this.drawLayer) { + this.drawLayer.cancel(); + this.drawLayer = null; + } + this.annotationEditorLayer.cancel(); + this.annotationEditorLayer = null; + } + if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) { + this.xfaLayer.cancel(); + this.xfaLayer = null; + this._textHighlighter?.disable(); + } + } + cssTransform({ + redrawAnnotationLayer = false, + redrawAnnotationEditorLayer = false, + redrawXfaLayer = false, + redrawTextLayer = false, + hideTextLayer = false + }) { + const { + canvas + } = this; + if (!canvas) { + return; + } + const originalViewport = this.#originalViewport; + if (this.viewport !== originalViewport) { + const relativeRotation = (360 + this.viewport.rotation - originalViewport.rotation) % 360; + if (relativeRotation === 90 || relativeRotation === 270) { + const { + width, + height + } = this.viewport; + const scaleX = height / width; + const scaleY = width / height; + canvas.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX},${scaleY})`; + } else { + canvas.style.transform = relativeRotation === 0 ? "" : `rotate(${relativeRotation}deg)`; + } + } + if (redrawAnnotationLayer && this.annotationLayer) { + this.#renderAnnotationLayer(); + } + if (redrawAnnotationEditorLayer && this.annotationEditorLayer) { + if (this.drawLayer) { + this.#renderDrawLayer(); + } + this.#renderAnnotationEditorLayer(); + } + if (redrawXfaLayer && this.xfaLayer) { + this.#renderXfaLayer(); + } + if (this.textLayer) { + if (hideTextLayer) { + this.textLayer.hide(); + this.structTreeLayer?.hide(); + } else if (redrawTextLayer) { + this.#renderTextLayer(); + } + } + } + get width() { + return this.viewport.width; + } + get height() { + return this.viewport.height; + } + getPagePoint(x, y) { + return this.viewport.convertToPdfPoint(x, y); + } + _ensureCanvasWrapper() { + let canvasWrapper = this.#canvasWrapper; + if (!canvasWrapper) { + canvasWrapper = this.#canvasWrapper = document.createElement("div"); + canvasWrapper.classList.add("canvasWrapper"); + this.#addLayer(canvasWrapper, "canvasWrapper"); + } + return canvasWrapper; + } + _getRenderingContext(canvas, transform, recordOperations) { + return { + canvas, + transform, + viewport: this.viewport, + annotationMode: this.#annotationMode, + optionalContentConfigPromise: this._optionalContentConfigPromise, + annotationCanvasMap: this._annotationCanvasMap, + pageColors: this.pageColors, + isEditing: this.#isEditing, + recordOperations + }; + } + async draw() { + if (this.renderingState !== RenderingStates.INITIAL) { + console.error("Must be in new state before drawing"); + this.reset(); + } + const { + div, + l10n, + pdfPage, + viewport + } = this; + if (!pdfPage) { + this.renderingState = RenderingStates.FINISHED; + throw new Error("pdfPage is not loaded"); + } + this.renderingState = RenderingStates.RUNNING; + const canvasWrapper = this._ensureCanvasWrapper(); + if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) { + this._accessibilityManager ||= new TextAccessibilityManager(); + this.textLayer = new TextLayerBuilder({ + pdfPage, + highlighter: this._textHighlighter, + accessibilityManager: this._accessibilityManager, + enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS, + onAppend: textLayerDiv => { + this.l10n.pause(); + this.#addLayer(textLayerDiv, "textLayer"); + this.l10n.resume(); + } + }); + } + if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) { + const { + annotationStorage, + annotationEditorUIManager, + downloadManager, + enableComment, + enableScripting, + fieldObjectsPromise, + hasJSActionsPromise, + linkService + } = this.#layerProperties; + this._annotationCanvasMap ||= new Map(); + this.annotationLayer = new AnnotationLayerBuilder({ + pdfPage, + annotationStorage, + imageResourcesPath: this.imageResourcesPath, + renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS, + linkService, + downloadManager, + enableComment, + enableScripting, + hasJSActionsPromise, + fieldObjectsPromise, + annotationCanvasMap: this._annotationCanvasMap, + accessibilityManager: this._accessibilityManager, + annotationEditorUIManager, + commentManager: this.#commentManager, + onAppend: annotationLayerDiv => { + this.#addLayer(annotationLayerDiv, "annotationLayer"); + } + }); + } + const { + width, + height + } = viewport; + this.#originalViewport = viewport; + const { + canvas, + prevCanvas + } = this._createCanvas(newCanvas => { + canvasWrapper.prepend(newCanvas); + }); + canvas.setAttribute("role", "presentation"); + if (!this.outputScale) { + this.#computeScale(); + } + const { + outputScale + } = this; + this.#hasRestrictedScaling = this.#needsRestrictedScaling; + const sfx = approximateFraction(outputScale.sx); + const sfy = approximateFraction(outputScale.sy); + const canvasWidth = canvas.width = floorToDivide(calcRound(width * outputScale.sx), sfx[0]); + const canvasHeight = canvas.height = floorToDivide(calcRound(height * outputScale.sy), sfy[0]); + const pageWidth = floorToDivide(calcRound(width), sfx[1]); + const pageHeight = floorToDivide(calcRound(height), sfy[1]); + outputScale.sx = canvasWidth / pageWidth; + outputScale.sy = canvasHeight / pageHeight; + if (this.#scaleRoundX !== sfx[1]) { + div.style.setProperty("--scale-round-x", `${sfx[1]}px`); + this.#scaleRoundX = sfx[1]; + } + if (this.#scaleRoundY !== sfy[1]) { + div.style.setProperty("--scale-round-y", `${sfy[1]}px`); + this.#scaleRoundY = sfy[1]; + } + const recordBBoxes = this.enableOptimizedPartialRendering && this.#hasRestrictedScaling && !this.recordedBBoxes; + const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null; + const resultPromise = this._drawCanvas(this._getRenderingContext(canvas, transform, recordBBoxes), () => { + prevCanvas?.remove(); + this._resetCanvas(); + }, renderTask => { + this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots; + this.dispatchPageRendered(false, false); + }).then(async () => { + if (this.renderingState !== RenderingStates.FINISHED) { + return; + } + this.structTreeLayer ||= new StructTreeLayerBuilder(pdfPage, viewport.rawDims); + const textLayerPromise = this.#renderTextLayer(); + if (this.annotationLayer) { + await this.#renderAnnotationLayer(); + if (this.#enableAutoLinking && this.annotationLayer && this.textLayer) { + await this.#injectLinkAnnotations(textLayerPromise); + } + } + const { + annotationEditorUIManager + } = this.#layerProperties; + if (!annotationEditorUIManager) { + return; + } + this.drawLayer ||= new DrawLayerBuilder({ + pageIndex: this.id + }); + await this.#renderDrawLayer(); + this.drawLayer.setParent(canvasWrapper); + if (this.annotationLayer || this.#annotationMode === AnnotationMode.DISABLE) { + this.annotationEditorLayer ||= new AnnotationEditorLayerBuilder({ + uiManager: annotationEditorUIManager, + pdfPage, + l10n, + structTreeLayer: this.structTreeLayer, + accessibilityManager: this._accessibilityManager, + annotationLayer: this.annotationLayer?.annotationLayer, + textLayer: this.textLayer, + drawLayer: this.drawLayer.getDrawLayer(), + onAppend: annotationEditorLayerDiv => { + this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer"); + } + }); + this.#renderAnnotationEditorLayer(); + } + }); + if (pdfPage.isPureXfa) { + if (!this.xfaLayer) { + const { + annotationStorage, + linkService + } = this.#layerProperties; + this.xfaLayer = new XfaLayerBuilder({ + pdfPage, + annotationStorage, + linkService + }); + } + this.#renderXfaLayer(); + } + div.setAttribute("data-loaded", true); + this.dispatchPageRender(); + return resultPromise; + } + setPageLabel(label) { + this.pageLabel = typeof label === "string" ? label : null; + this.div.setAttribute("data-l10n-args", JSON.stringify({ + page: this.pageLabel ?? this.id + })); + if (this.pageLabel !== null) { + this.div.setAttribute("data-page-label", this.pageLabel); + } else { + this.div.removeAttribute("data-page-label"); + } + } + get thumbnailCanvas() { + const { + directDrawing, + initialOptionalContent, + regularAnnotations + } = this.#useThumbnailCanvas; + return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null; + } +} + +;// ./web/pdf_viewer.js + + + + + + +const DEFAULT_CACHE_SIZE = 10; +const PagesCountLimit = { + FORCE_SCROLL_MODE_PAGE: 10000, + FORCE_LAZY_PAGE_INIT: 5000, + PAUSE_EAGER_PAGE_INIT: 250 +}; +function isValidAnnotationEditorMode(mode) { + return Object.values(AnnotationEditorType).includes(mode) && mode !== AnnotationEditorType.DISABLE; +} +class PDFPageViewBuffer { + #buf = new Set(); + #size = 0; + constructor(size) { + this.#size = size; + } + push(view) { + const buf = this.#buf; + if (buf.has(view)) { + buf.delete(view); + } + buf.add(view); + if (buf.size > this.#size) { + this.#destroyFirstView(); + } + } + resize(newSize, idsToKeep = null) { + this.#size = newSize; + const buf = this.#buf; + if (idsToKeep) { + const ii = buf.size; + let i = 1; + for (const view of buf) { + if (idsToKeep.has(view.id)) { + buf.delete(view); + buf.add(view); + } + if (++i > ii) { + break; + } + } + } + while (buf.size > this.#size) { + this.#destroyFirstView(); + } + } + has(view) { + return this.#buf.has(view); + } + [Symbol.iterator]() { + return this.#buf.keys(); + } + #destroyFirstView() { + const firstView = this.#buf.keys().next().value; + firstView?.destroy(); + this.#buf.delete(firstView); + } +} +class PDFViewer { + #buffer = null; + #altTextManager = null; + #annotationEditorHighlightColors = null; + #annotationEditorMode = AnnotationEditorType.NONE; + #annotationEditorUIManager = null; + #annotationMode = AnnotationMode.ENABLE_FORMS; + #commentManager = null; + #containerTopLeft = null; + #editorUndoBar = null; + #enableHWA = false; + #enableHighlightFloatingButton = false; + #enablePermissions = false; + #enableUpdatedAddImage = false; + #enableNewAltTextWhenAddingImage = false; + #enableAutoLinking = true; + #eventAbortController = null; + #minDurationToUpdateCanvas = 0; + #mlManager = null; + #printingAllowed = true; + #scrollTimeoutId = null; + #switchAnnotationEditorModeAC = null; + #switchAnnotationEditorModeTimeoutId = null; + #getAllTextInProgress = false; + #hiddenCopyElement = null; + #interruptCopyCondition = false; + #previousContainerHeight = 0; + #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this)); + #scrollModePageState = null; + #scaleTimeoutId = null; + #signatureManager = null; + #supportsPinchToZoom = true; + #textLayerMode = TextLayerMode.ENABLE; + #viewerAlert = null; + constructor(options) { + const viewerVersion = "5.4.445"; + if (version !== viewerVersion) { + throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); + } + this.container = options.container; + this.viewer = options.viewer || options.container.firstElementChild; + this.#viewerAlert = options.viewerAlert || null; + this.#resizeObserver.observe(this.container); + this.eventBus = options.eventBus; + this.linkService = options.linkService || new SimpleLinkService(); + this.downloadManager = options.downloadManager || null; + this.findController = options.findController || null; + this.#altTextManager = options.altTextManager || null; + this.#commentManager = options.commentManager || null; + this.#signatureManager = options.signatureManager || null; + this.#editorUndoBar = options.editorUndoBar || null; + if (this.findController) { + this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber); + } + this._scriptingManager = options.scriptingManager || null; + this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE; + this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS; + this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE; + this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null; + this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true; + this.#enableUpdatedAddImage = options.enableUpdatedAddImage === true; + this.#enableNewAltTextWhenAddingImage = options.enableNewAltTextWhenAddingImage === true; + this.imageResourcesPath = options.imageResourcesPath || ""; + this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; + this.maxCanvasPixels = options.maxCanvasPixels; + this.maxCanvasDim = options.maxCanvasDim; + this.capCanvasAreaFactor = options.capCanvasAreaFactor; + this.enableDetailCanvas = options.enableDetailCanvas ?? true; + this.enableOptimizedPartialRendering = options.enableOptimizedPartialRendering ?? false; + this.l10n = options.l10n; + this.#enablePermissions = options.enablePermissions || false; + this.pageColors = options.pageColors || null; + this.#mlManager = options.mlManager || null; + this.#enableHWA = options.enableHWA || false; + this.#supportsPinchToZoom = options.supportsPinchToZoom !== false; + this.#enableAutoLinking = options.enableAutoLinking !== false; + this.#minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500; + this.defaultRenderingQueue = !options.renderingQueue; + this.renderingQueue = options.renderingQueue; + const { + abortSignal + } = options; + abortSignal?.addEventListener("abort", () => { + this.#resizeObserver.disconnect(); + this.#resizeObserver = null; + }, { + once: true + }); + this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this), abortSignal); + this.presentationModeState = PresentationModeState.UNKNOWN; + this._resetView(); + this.#updateContainerHeightCss(); + this.eventBus._on("thumbnailrendered", ({ + pageNumber, + pdfPage + }) => { + const pageView = this._pages[pageNumber - 1]; + if (!this.#buffer.has(pageView)) { + pdfPage?.cleanup(); + } + }); + } + get printingAllowed() { + return this.#printingAllowed; + } + get pagesCount() { + return this._pages.length; + } + getPageView(index) { + return this._pages[index]; + } + getCachedPageViews() { + return new Set(this.#buffer); + } + get pageViewsReady() { + return this._pages.every(pageView => pageView?.pdfPage); + } + get renderForms() { + return this.#annotationMode === AnnotationMode.ENABLE_FORMS; + } + get enableScripting() { + return !!this._scriptingManager; + } + get currentPageNumber() { + return this._currentPageNumber; + } + set currentPageNumber(val) { + if (!Number.isInteger(val)) { + throw new Error("Invalid page number."); + } + if (!this.pdfDocument) { + return; + } + if (!this._setCurrentPageNumber(val, true)) { + console.error(`currentPageNumber: "${val}" is not a valid page.`); + } + } + _setCurrentPageNumber(val, resetCurrentPageView = false) { + if (this._currentPageNumber === val) { + if (resetCurrentPageView) { + this.#resetCurrentPageView(); + } + return true; + } + if (!(0 < val && val <= this.pagesCount)) { + return false; + } + const previous = this._currentPageNumber; + this._currentPageNumber = val; + this.eventBus.dispatch("pagechanging", { + source: this, + pageNumber: val, + pageLabel: this._pageLabels?.[val - 1] ?? null, + previous + }); + if (resetCurrentPageView) { + this.#resetCurrentPageView(); + } + return true; + } + get currentPageLabel() { + return this._pageLabels?.[this._currentPageNumber - 1] ?? null; + } + set currentPageLabel(val) { + if (!this.pdfDocument) { + return; + } + let page = val | 0; + if (this._pageLabels) { + const i = this._pageLabels.indexOf(val); + if (i >= 0) { + page = i + 1; + } + } + if (!this._setCurrentPageNumber(page, true)) { + console.error(`currentPageLabel: "${val}" is not a valid page.`); + } + } + get currentScale() { + return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE; + } + set currentScale(val) { + if (isNaN(val)) { + throw new Error("Invalid numeric scale."); + } + if (!this.pdfDocument) { + return; + } + this.#setScale(val, { + noScroll: false + }); + } + get currentScaleValue() { + return this._currentScaleValue; + } + set currentScaleValue(val) { + if (!this.pdfDocument) { + return; + } + this.#setScale(val, { + noScroll: false + }); + } + get pagesRotation() { + return this._pagesRotation; + } + set pagesRotation(rotation) { + if (!isValidRotation(rotation)) { + throw new Error("Invalid pages rotation angle."); + } + if (!this.pdfDocument) { + return; + } + rotation %= 360; + if (rotation < 0) { + rotation += 360; + } + if (this._pagesRotation === rotation) { + return; + } + this._pagesRotation = rotation; + const pageNumber = this._currentPageNumber; + this.refresh(true, { + rotation + }); + if (this._currentScaleValue) { + this.#setScale(this._currentScaleValue, { + noScroll: true + }); + } + this.eventBus.dispatch("rotationchanging", { + source: this, + pagesRotation: rotation, + pageNumber + }); + if (this.defaultRenderingQueue) { + this.update(); + } + } + get firstPagePromise() { + return this.pdfDocument ? this._firstPageCapability.promise : null; + } + get onePageRendered() { + return this.pdfDocument ? this._onePageRenderedCapability.promise : null; + } + get pagesPromise() { + return this.pdfDocument ? this._pagesCapability.promise : null; + } + get _layerProperties() { + const self = this; + return shadow(this, "_layerProperties", { + get annotationEditorUIManager() { + return self.#annotationEditorUIManager; + }, + get annotationStorage() { + return self.pdfDocument?.annotationStorage; + }, + get downloadManager() { + return self.downloadManager; + }, + get enableComment() { + return !!self.#commentManager; + }, + get enableScripting() { + return !!self._scriptingManager; + }, + get fieldObjectsPromise() { + return self.pdfDocument?.getFieldObjects(); + }, + get findController() { + return self.findController; + }, + get hasJSActionsPromise() { + return self.pdfDocument?.hasJSActions(); + }, + get linkService() { + return self.linkService; + } + }); + } + #initializePermissions(permissions) { + const params = { + annotationEditorMode: this.#annotationEditorMode, + annotationMode: this.#annotationMode, + textLayerMode: this.#textLayerMode + }; + if (!permissions) { + this.#printingAllowed = true; + this.eventBus.dispatch("printingallowed", { + source: this, + isAllowed: this.#printingAllowed + }); + return params; + } + this.#printingAllowed = permissions.includes(PermissionFlag.PRINT_HIGH_QUALITY) || permissions.includes(PermissionFlag.PRINT); + this.eventBus.dispatch("printingallowed", { + source: this, + isAllowed: this.#printingAllowed + }); + if (!permissions.includes(PermissionFlag.COPY) && this.#textLayerMode === TextLayerMode.ENABLE) { + params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS; + } + if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) { + params.annotationEditorMode = AnnotationEditorType.DISABLE; + } + if (!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === AnnotationMode.ENABLE_FORMS) { + params.annotationMode = AnnotationMode.ENABLE; + } + return params; + } + async #onePageRenderedOrForceFetch(signal) { + if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) { + return; + } + const hiddenCapability = Promise.withResolvers(), + ac = new AbortController(); + document.addEventListener("visibilitychange", () => { + if (document.visibilityState === "hidden") { + hiddenCapability.resolve(); + } + }, { + signal: AbortSignal.any([signal, ac.signal]) + }); + await Promise.race([this._onePageRenderedCapability.promise, hiddenCapability.promise]); + ac.abort(); + } + async getAllText() { + const texts = []; + const buffer = []; + for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) { + if (this.#interruptCopyCondition) { + return null; + } + buffer.length = 0; + const page = await this.pdfDocument.getPage(pageNum); + const { + items + } = await page.getTextContent(); + for (const item of items) { + if (item.str) { + buffer.push(item.str); + } + if (item.hasEOL) { + buffer.push("\n"); + } + } + texts.push(removeNullCharacters(buffer.join(""))); + } + return texts.join("\n"); + } + #copyCallback(textLayerMode, event) { + const selection = document.getSelection(); + const { + focusNode, + anchorNode + } = selection; + if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) { + if (this.#getAllTextInProgress || textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) { + stopEvent(event); + return; + } + this.#getAllTextInProgress = true; + const { + classList + } = this.viewer; + classList.add("copyAll"); + const ac = new AbortController(); + window.addEventListener("keydown", ev => this.#interruptCopyCondition = ev.key === "Escape", { + signal: ac.signal + }); + this.getAllText().then(async text => { + if (text !== null) { + await navigator.clipboard.writeText(text); + } + }).catch(reason => { + console.warn(`Something goes wrong when extracting the text: ${reason.message}`); + }).finally(() => { + this.#getAllTextInProgress = false; + this.#interruptCopyCondition = false; + ac.abort(); + classList.remove("copyAll"); + }); + stopEvent(event); + } + } + setDocument(pdfDocument) { + if (this.pdfDocument) { + this.eventBus.dispatch("pagesdestroy", { + source: this + }); + this._cancelRendering(); + this._resetView(); + this.findController?.setDocument(null); + this._scriptingManager?.setDocument(null); + this.#annotationEditorUIManager?.destroy(); + this.#annotationEditorUIManager = null; + this.#annotationEditorMode = AnnotationEditorType.NONE; + this.#printingAllowed = true; + } + this.pdfDocument = pdfDocument; + if (!pdfDocument) { + return; + } + const pagesCount = pdfDocument.numPages; + const firstPagePromise = pdfDocument.getPage(1); + const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({ + intent: "display" + }); + const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve(); + const { + eventBus, + pageColors, + viewer + } = this; + this.#eventAbortController = new AbortController(); + const { + signal + } = this.#eventAbortController; + if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) { + console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document."); + const mode = this._scrollMode = ScrollMode.PAGE; + eventBus.dispatch("scrollmodechanged", { + source: this, + mode + }); + } + this._pagesCapability.promise.then(() => { + eventBus.dispatch("pagesloaded", { + source: this, + pagesCount + }); + }, () => {}); + const onBeforeDraw = evt => { + const pageView = this._pages[evt.pageNumber - 1]; + if (!pageView) { + return; + } + this.#buffer.push(pageView); + }; + eventBus._on("pagerender", onBeforeDraw, { + signal + }); + const onAfterDraw = evt => { + if (evt.cssTransform || evt.isDetailView) { + return; + } + this._onePageRenderedCapability.resolve({ + timestamp: evt.timestamp + }); + eventBus._off("pagerendered", onAfterDraw); + }; + eventBus._on("pagerendered", onAfterDraw, { + signal + }); + Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => { + if (pdfDocument !== this.pdfDocument) { + return; + } + this._firstPageCapability.resolve(firstPdfPage); + this._optionalContentConfigPromise = optionalContentConfigPromise; + const { + annotationEditorMode, + annotationMode, + textLayerMode + } = this.#initializePermissions(permissions); + if (textLayerMode !== TextLayerMode.DISABLE) { + const element = this.#hiddenCopyElement = document.createElement("div"); + element.id = "hiddenCopyElement"; + viewer.before(element); + } + if (annotationEditorMode !== AnnotationEditorType.DISABLE) { + const mode = annotationEditorMode; + if (pdfDocument.isPureXfa) { + console.warn("Warning: XFA-editing is not implemented."); + } else if (isValidAnnotationEditorMode(mode)) { + this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, viewer, this.#viewerAlert, this.#altTextManager, this.#commentManager, this.#signatureManager, eventBus, pdfDocument, pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#enableUpdatedAddImage, this.#enableNewAltTextWhenAddingImage, this.#mlManager, this.#editorUndoBar, this.#supportsPinchToZoom); + eventBus.dispatch("annotationeditoruimanager", { + source: this, + uiManager: this.#annotationEditorUIManager + }); + if (mode !== AnnotationEditorType.NONE) { + this.#preloadEditingData(mode); + this.#annotationEditorUIManager.updateMode(mode); + } + } else { + console.error(`Invalid AnnotationEditor mode: ${mode}`); + } + } + const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : viewer; + const scale = this.currentScale; + const viewport = firstPdfPage.getViewport({ + scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS + }); + viewer.style.setProperty("--scale-factor", viewport.scale); + if (pageColors?.background) { + viewer.style.setProperty("--page-bg-color", pageColors.background); + } + if (pageColors?.foreground === "CanvasText" || pageColors?.background === "Canvas") { + viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight")); + viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText")); + } + for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { + const pageView = new PDFPageView({ + container: viewerElement, + eventBus, + id: pageNum, + scale, + defaultViewport: viewport.clone(), + optionalContentConfigPromise, + renderingQueue: this.renderingQueue, + textLayerMode, + annotationMode, + imageResourcesPath: this.imageResourcesPath, + maxCanvasPixels: this.maxCanvasPixels, + maxCanvasDim: this.maxCanvasDim, + capCanvasAreaFactor: this.capCanvasAreaFactor, + enableDetailCanvas: this.enableDetailCanvas, + enableOptimizedPartialRendering: this.enableOptimizedPartialRendering, + pageColors, + l10n: this.l10n, + layerProperties: this._layerProperties, + enableHWA: this.#enableHWA, + enableAutoLinking: this.#enableAutoLinking, + minDurationToUpdateCanvas: this.#minDurationToUpdateCanvas, + commentManager: this.#commentManager + }); + this._pages.push(pageView); + } + this._pages[0]?.setPdfPage(firstPdfPage); + if (this._scrollMode === ScrollMode.PAGE) { + this.#ensurePageViewVisible(); + } else if (this._spreadMode !== SpreadMode.NONE) { + this._updateSpreadMode(); + } + eventBus._on("annotationeditorlayerrendered", evt => { + if (this.#annotationEditorUIManager) { + eventBus.dispatch("annotationeditormodechanged", { + source: this, + mode: this.#annotationEditorMode + }); + } + }, { + once: true, + signal + }); + this.#onePageRenderedOrForceFetch(signal).then(async () => { + if (pdfDocument !== this.pdfDocument) { + return; + } + this.findController?.setDocument(pdfDocument); + this._scriptingManager?.setDocument(pdfDocument); + if (this.#hiddenCopyElement) { + document.addEventListener("copy", this.#copyCallback.bind(this, textLayerMode), { + signal + }); + } + if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) { + this._pagesCapability.resolve(); + return; + } + let getPagesLeft = pagesCount - 1; + if (getPagesLeft <= 0) { + this._pagesCapability.resolve(); + return; + } + for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) { + const promise = pdfDocument.getPage(pageNum).then(pdfPage => { + const pageView = this._pages[pageNum - 1]; + if (!pageView.pdfPage) { + pageView.setPdfPage(pdfPage); + } + if (--getPagesLeft === 0) { + this._pagesCapability.resolve(); + } + }, reason => { + console.error(`Unable to get page ${pageNum} to initialize viewer`, reason); + if (--getPagesLeft === 0) { + this._pagesCapability.resolve(); + } + }); + if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) { + await promise; + } + } + }); + eventBus.dispatch("pagesinit", { + source: this + }); + pdfDocument.getMetadata().then(({ + info + }) => { + if (pdfDocument !== this.pdfDocument) { + return; + } + if (info.Language) { + viewer.lang = info.Language; + } + }); + if (this.defaultRenderingQueue) { + this.update(); + } + }).catch(reason => { + console.error("Unable to initialize viewer", reason); + this._pagesCapability.reject(reason); + }); + } + setPageLabels(labels) { + if (!this.pdfDocument) { + return; + } + if (!labels) { + this._pageLabels = null; + } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) { + this._pageLabels = null; + console.error(`setPageLabels: Invalid page labels.`); + } else { + this._pageLabels = labels; + } + for (let i = 0, ii = this._pages.length; i < ii; i++) { + this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null); + } + } + _resetView() { + this._pages = []; + this._currentPageNumber = 1; + this._currentScale = UNKNOWN_SCALE; + this._currentScaleValue = null; + this._pageLabels = null; + this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE); + this._location = null; + this._pagesRotation = 0; + this._optionalContentConfigPromise = null; + this._firstPageCapability = Promise.withResolvers(); + this._onePageRenderedCapability = Promise.withResolvers(); + this._pagesCapability = Promise.withResolvers(); + this._scrollMode = ScrollMode.VERTICAL; + this._previousScrollMode = ScrollMode.UNKNOWN; + this._spreadMode = SpreadMode.NONE; + this.#scrollModePageState = { + previousPageNumber: 1, + scrollDown: true, + pages: [] + }; + this.#eventAbortController?.abort(); + this.#eventAbortController = null; + this.viewer.textContent = ""; + this._updateScrollMode(); + this.viewer.removeAttribute("lang"); + this.#hiddenCopyElement?.remove(); + this.#hiddenCopyElement = null; + this.#cleanupTimeouts(); + this.#cleanupSwitchAnnotationEditorMode(); + } + #ensurePageViewVisible() { + if (this._scrollMode !== ScrollMode.PAGE) { + throw new Error("#ensurePageViewVisible: Invalid scrollMode value."); + } + const pageNumber = this._currentPageNumber, + state = this.#scrollModePageState, + viewer = this.viewer; + viewer.textContent = ""; + state.pages.length = 0; + if (this._spreadMode === SpreadMode.NONE && !this.isInPresentationMode) { + const pageView = this._pages[pageNumber - 1]; + viewer.append(pageView.div); + state.pages.push(pageView); + } else { + const pageIndexSet = new Set(), + parity = this._spreadMode - 1; + if (parity === -1) { + pageIndexSet.add(pageNumber - 1); + } else if (pageNumber % 2 !== parity) { + pageIndexSet.add(pageNumber - 1); + pageIndexSet.add(pageNumber); + } else { + pageIndexSet.add(pageNumber - 2); + pageIndexSet.add(pageNumber - 1); + } + const spread = document.createElement("div"); + spread.className = "spread"; + if (this.isInPresentationMode) { + const dummyPage = document.createElement("div"); + dummyPage.className = "dummyPage"; + spread.append(dummyPage); + } + for (const i of pageIndexSet) { + const pageView = this._pages[i]; + if (!pageView) { + continue; + } + spread.append(pageView.div); + state.pages.push(pageView); + } + viewer.append(spread); + } + state.scrollDown = pageNumber >= state.previousPageNumber; + state.previousPageNumber = pageNumber; + } + _scrollUpdate() { + if (this.pagesCount === 0) { + return; + } + if (this.#scrollTimeoutId) { + clearTimeout(this.#scrollTimeoutId); + } + this.#scrollTimeoutId = setTimeout(() => { + this.#scrollTimeoutId = null; + this.update(); + }, 100); + this.update(); + } + #scrollIntoView(pageView, pageSpot = null) { + const { + div, + id + } = pageView; + if (this._currentPageNumber !== id) { + this._setCurrentPageNumber(id); + } + if (this._scrollMode === ScrollMode.PAGE) { + this.#ensurePageViewVisible(); + this.update(); + } + if (!pageSpot && !this.isInPresentationMode) { + const left = div.offsetLeft + div.clientLeft, + right = left + div.clientWidth; + const { + scrollLeft, + clientWidth + } = this.container; + if (this._scrollMode === ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) { + pageSpot = { + left: 0, + top: 0 + }; + } + } + scrollIntoView(div, pageSpot); + if (!this._currentScaleValue && this._location) { + this._location = null; + } + } + #isSameScale(newScale) { + return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15; + } + #setScaleUpdatePages(newScale, newValue, { + noScroll = false, + preset = false, + drawingDelay = -1, + origin = null + }) { + this._currentScaleValue = newValue.toString(); + if (this.#isSameScale(newScale)) { + if (preset) { + this.eventBus.dispatch("scalechanging", { + source: this, + scale: newScale, + presetValue: newValue + }); + } + return; + } + this.viewer.style.setProperty("--scale-factor", newScale * PixelsPerInch.PDF_TO_CSS_UNITS); + const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000; + this.refresh(true, { + scale: newScale, + drawingDelay: postponeDrawing ? drawingDelay : -1 + }); + if (postponeDrawing) { + this.#scaleTimeoutId = setTimeout(() => { + this.#scaleTimeoutId = null; + this.refresh(); + }, drawingDelay); + } + const previousScale = this._currentScale; + this._currentScale = newScale; + if (!noScroll) { + let page = this._currentPageNumber, + dest; + if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) { + page = this._location.pageNumber; + dest = [null, { + name: "XYZ" + }, this._location.left, this._location.top, null]; + } + this.scrollPageIntoView({ + pageNumber: page, + destArray: dest, + allowNegativeOffset: true + }); + if (Array.isArray(origin)) { + const scaleDiff = newScale / previousScale - 1; + const [top, left] = this.containerTopLeft; + this.container.scrollLeft += (origin[0] - left) * scaleDiff; + this.container.scrollTop += (origin[1] - top) * scaleDiff; + } + } + this.eventBus.dispatch("scalechanging", { + source: this, + scale: newScale, + presetValue: preset ? newValue : undefined + }); + if (this.defaultRenderingQueue) { + this.update(); + } + } + get #pageWidthScaleFactor() { + if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL) { + return 2; + } + return 1; + } + #setScale(value, options) { + let scale = parseFloat(value); + if (scale > 0) { + options.preset = false; + this.#setScaleUpdatePages(scale, value, options); + } else { + const currentPage = this._pages[this._currentPageNumber - 1]; + if (!currentPage) { + return; + } + let hPadding = SCROLLBAR_PADDING, + vPadding = VERTICAL_PADDING; + if (this.isInPresentationMode) { + hPadding = vPadding = 4; + if (this._spreadMode !== SpreadMode.NONE) { + hPadding *= 2; + } + } else if (this._scrollMode === ScrollMode.HORIZONTAL) { + [hPadding, vPadding] = [vPadding, hPadding]; + } + const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor; + const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale; + switch (value) { + case "page-actual": + scale = 1; + break; + case "page-width": + scale = pageWidthScale; + break; + case "page-height": + scale = pageHeightScale; + break; + case "page-fit": + scale = Math.min(pageWidthScale, pageHeightScale); + break; + case "auto": + const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale); + scale = Math.min(MAX_AUTO_SCALE, horizontalScale); + break; + default: + console.error(`#setScale: "${value}" is an unknown zoom value.`); + return; + } + options.preset = true; + this.#setScaleUpdatePages(scale, value, options); + } + } + #resetCurrentPageView() { + const pageView = this._pages[this._currentPageNumber - 1]; + if (this.isInPresentationMode) { + this.#setScale(this._currentScaleValue, { + noScroll: true + }); + } + this.#scrollIntoView(pageView); + } + pageLabelToPageNumber(label) { + if (!this._pageLabels) { + return null; + } + const i = this._pageLabels.indexOf(label); + if (i < 0) { + return null; + } + return i + 1; + } + scrollPageIntoView({ + pageNumber, + destArray = null, + allowNegativeOffset = false, + ignoreDestinationZoom = false, + center = null + }) { + if (!this.pdfDocument) { + return; + } + const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1]; + if (!pageView) { + console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`); + return; + } + if (this.isInPresentationMode || !destArray) { + this._setCurrentPageNumber(pageNumber, true); + return; + } + let x = 0, + y = 0; + let width = 0, + height = 0, + widthScale, + heightScale; + const changeOrientation = pageView.rotation % 180 !== 0; + const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS; + const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS; + let scale = 0; + switch (destArray[1].name) { + case "XYZ": + x = destArray[2]; + y = destArray[3]; + scale = destArray[4]; + x = x !== null ? x : 0; + y = y !== null ? y : pageHeight; + break; + case "Fit": + case "FitB": + scale = "page-fit"; + break; + case "FitH": + case "FitBH": + y = destArray[2]; + scale = "page-width"; + if (y === null && this._location) { + x = this._location.left; + y = this._location.top; + } else if (typeof y !== "number" || y < 0) { + y = pageHeight; + } + break; + case "FitV": + case "FitBV": + x = destArray[2]; + width = pageWidth; + height = pageHeight; + scale = "page-height"; + break; + case "FitR": + x = destArray[2]; + y = destArray[3]; + width = destArray[4] - x; + height = destArray[5] - y; + let hPadding = SCROLLBAR_PADDING, + vPadding = VERTICAL_PADDING; + widthScale = (this.container.clientWidth - hPadding) / width / PixelsPerInch.PDF_TO_CSS_UNITS; + heightScale = (this.container.clientHeight - vPadding) / height / PixelsPerInch.PDF_TO_CSS_UNITS; + scale = Math.min(Math.abs(widthScale), Math.abs(heightScale)); + break; + default: + console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`); + return; + } + if (!ignoreDestinationZoom) { + if (scale && scale !== this._currentScale) { + this.currentScaleValue = scale; + } else if (this._currentScale === UNKNOWN_SCALE) { + this.currentScaleValue = DEFAULT_SCALE_VALUE; + } + } + if (scale === "page-fit" && !destArray[4]) { + this.#scrollIntoView(pageView); + return; + } + const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)]; + let left = Math.min(boundingRect[0][0], boundingRect[1][0]); + let top = Math.min(boundingRect[0][1], boundingRect[1][1]); + if (center) { + if (center === "both" || center === "vertical") { + top -= (this.container.clientHeight - Math.abs(boundingRect[1][1] - boundingRect[0][1])) / 2; + } + if (center === "both" || center === "horizontal") { + left -= (this.container.clientWidth - Math.abs(boundingRect[1][0] - boundingRect[0][0])) / 2; + } + } else if (!allowNegativeOffset) { + left = Math.max(left, 0); + top = Math.max(top, 0); + } + this.#scrollIntoView(pageView, { + left, + top + }); + } + _updateLocation(firstPage) { + const currentScale = this._currentScale; + const currentScaleValue = this._currentScaleValue; + const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue; + const pageNumber = firstPage.id; + const currentPageView = this._pages[pageNumber - 1]; + const container = this.container; + const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y); + const intLeft = Math.round(topLeft[0]); + const intTop = Math.round(topLeft[1]); + let pdfOpenParams = `#page=${pageNumber}`; + if (!this.isInPresentationMode) { + pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`; + } + this._location = { + pageNumber, + scale: normalizedScaleValue, + top: intTop, + left: intLeft, + rotation: this._pagesRotation, + pdfOpenParams + }; + } + update() { + const visible = this._getVisiblePages(); + const visiblePages = visible.views, + numVisiblePages = visiblePages.length; + if (numVisiblePages === 0) { + return; + } + const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1); + this.#buffer.resize(newCacheSize, visible.ids); + for (const { + view, + visibleArea + } of visiblePages) { + view.updateVisibleArea(visibleArea); + } + for (const view of this.#buffer) { + if (!visible.ids.has(view.id)) { + view.updateVisibleArea(null); + } + } + this.renderingQueue.renderHighestPriority(visible); + const isSimpleLayout = this._spreadMode === SpreadMode.NONE && (this._scrollMode === ScrollMode.PAGE || this._scrollMode === ScrollMode.VERTICAL); + const currentId = this._currentPageNumber; + let stillFullyVisible = false; + for (const page of visiblePages) { + if (page.percent < 100) { + break; + } + if (page.id === currentId && isSimpleLayout) { + stillFullyVisible = true; + break; + } + } + this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id); + this._updateLocation(visible.first); + this.eventBus.dispatch("updateviewarea", { + source: this, + location: this._location + }); + } + #switchToEditAnnotationMode() { + const visible = this._getVisiblePages(); + const pagesToRefresh = []; + const { + ids, + views + } = visible; + for (const page of views) { + const { + view + } = page; + if (!view.hasEditableAnnotations()) { + ids.delete(view.id); + continue; + } + pagesToRefresh.push(page); + } + if (pagesToRefresh.length === 0) { + return null; + } + this.renderingQueue.renderHighestPriority({ + first: pagesToRefresh[0], + last: pagesToRefresh.at(-1), + views: pagesToRefresh, + ids + }); + return ids; + } + containsElement(element) { + return this.container.contains(element); + } + focus() { + this.container.focus(); + } + get _isContainerRtl() { + return getComputedStyle(this.container).direction === "rtl"; + } + get isInPresentationMode() { + return this.presentationModeState === PresentationModeState.FULLSCREEN; + } + get isChangingPresentationMode() { + return this.presentationModeState === PresentationModeState.CHANGING; + } + get isHorizontalScrollbarEnabled() { + return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth; + } + get isVerticalScrollbarEnabled() { + return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight; + } + _getVisiblePages() { + const views = this._scrollMode === ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages, + horizontal = this._scrollMode === ScrollMode.HORIZONTAL, + rtl = horizontal && this._isContainerRtl; + return getVisibleElements({ + scrollEl: this.container, + views, + sortByVisibility: true, + horizontal, + rtl + }); + } + cleanup() { + for (const pageView of this._pages) { + if (pageView.renderingState !== RenderingStates.FINISHED) { + pageView.reset(); + } + } + } + _cancelRendering() { + for (const pageView of this._pages) { + pageView.cancelRendering(); + } + } + async #ensurePdfPageLoaded(pageView) { + if (pageView.pdfPage) { + return pageView.pdfPage; + } + try { + const pdfPage = await this.pdfDocument.getPage(pageView.id); + if (!pageView.pdfPage) { + pageView.setPdfPage(pdfPage); + } + return pdfPage; + } catch (reason) { + console.error("Unable to get page for page view", reason); + return null; + } + } + #getScrollAhead(visible) { + if (visible.first?.id === 1) { + return true; + } else if (visible.last?.id === this.pagesCount) { + return false; + } + switch (this._scrollMode) { + case ScrollMode.PAGE: + return this.#scrollModePageState.scrollDown; + case ScrollMode.HORIZONTAL: + return this.scroll.right; + } + return this.scroll.down; + } + forceRendering(currentlyVisiblePages) { + const visiblePages = currentlyVisiblePages || this._getVisiblePages(); + const scrollAhead = this.#getScrollAhead(visiblePages); + const preRenderExtra = this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL; + const ignoreDetailViews = this.#scaleTimeoutId !== null || this.#scrollTimeoutId !== null && visiblePages.views.some(page => page.detailView?.renderingCancelled); + const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra, ignoreDetailViews); + if (pageView) { + this.#ensurePdfPageLoaded(pageView).then(() => { + this.renderingQueue.renderView(pageView); + }); + return true; + } + return false; + } + get hasEqualPageSizes() { + const firstPageView = this._pages[0]; + for (let i = 1, ii = this._pages.length; i < ii; ++i) { + const pageView = this._pages[i]; + if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) { + return false; + } + } + return true; + } + getPagesOverview() { + let initialOrientation; + return this._pages.map(pageView => { + const viewport = pageView.pdfPage.getViewport({ + scale: 1 + }); + const orientation = isPortraitOrientation(viewport); + if (initialOrientation === undefined) { + initialOrientation = orientation; + } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) { + return { + width: viewport.height, + height: viewport.width, + rotation: (viewport.rotation - 90) % 360 + }; + } + return { + width: viewport.width, + height: viewport.height, + rotation: viewport.rotation + }; + }); + } + get optionalContentConfigPromise() { + if (!this.pdfDocument) { + return Promise.resolve(null); + } + if (!this._optionalContentConfigPromise) { + console.error("optionalContentConfigPromise: Not initialized yet."); + return this.pdfDocument.getOptionalContentConfig({ + intent: "display" + }); + } + return this._optionalContentConfigPromise; + } + set optionalContentConfigPromise(promise) { + if (!(promise instanceof Promise)) { + throw new Error(`Invalid optionalContentConfigPromise: ${promise}`); + } + if (!this.pdfDocument) { + return; + } + if (!this._optionalContentConfigPromise) { + return; + } + this._optionalContentConfigPromise = promise; + this.refresh(false, { + optionalContentConfigPromise: promise + }); + this.eventBus.dispatch("optionalcontentconfigchanged", { + source: this, + promise + }); + } + get scrollMode() { + return this._scrollMode; + } + set scrollMode(mode) { + if (this._scrollMode === mode) { + return; + } + if (!isValidScrollMode(mode)) { + throw new Error(`Invalid scroll mode: ${mode}`); + } + if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) { + return; + } + this._previousScrollMode = this._scrollMode; + this._scrollMode = mode; + this.eventBus.dispatch("scrollmodechanged", { + source: this, + mode + }); + this._updateScrollMode(this._currentPageNumber); + } + _updateScrollMode(pageNumber = null) { + const scrollMode = this._scrollMode, + viewer = this.viewer; + viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL); + viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED); + if (!this.pdfDocument || !pageNumber) { + return; + } + if (scrollMode === ScrollMode.PAGE) { + this.#ensurePageViewVisible(); + } else if (this._previousScrollMode === ScrollMode.PAGE) { + this._updateSpreadMode(); + } + if (this._currentScaleValue && isNaN(this._currentScaleValue)) { + this.#setScale(this._currentScaleValue, { + noScroll: true + }); + } + this._setCurrentPageNumber(pageNumber, true); + this.update(); + } + get spreadMode() { + return this._spreadMode; + } + set spreadMode(mode) { + if (this._spreadMode === mode) { + return; + } + if (!isValidSpreadMode(mode)) { + throw new Error(`Invalid spread mode: ${mode}`); + } + this._spreadMode = mode; + this.eventBus.dispatch("spreadmodechanged", { + source: this, + mode + }); + this._updateSpreadMode(this._currentPageNumber); + } + _updateSpreadMode(pageNumber = null) { + if (!this.pdfDocument) { + return; + } + const viewer = this.viewer, + pages = this._pages; + if (this._scrollMode === ScrollMode.PAGE) { + this.#ensurePageViewVisible(); + } else { + viewer.textContent = ""; + if (this._spreadMode === SpreadMode.NONE) { + for (const pageView of this._pages) { + viewer.append(pageView.div); + } + } else { + const parity = this._spreadMode - 1; + let spread = null; + for (let i = 0, ii = pages.length; i < ii; ++i) { + if (spread === null) { + spread = document.createElement("div"); + spread.className = "spread"; + viewer.append(spread); + } else if (i % 2 === parity) { + spread = spread.cloneNode(false); + viewer.append(spread); + } + spread.append(pages[i].div); + } + } + } + if (!pageNumber) { + return; + } + if (this._currentScaleValue && isNaN(this._currentScaleValue)) { + this.#setScale(this._currentScaleValue, { + noScroll: true + }); + } + this._setCurrentPageNumber(pageNumber, true); + this.update(); + } + _getPageAdvance(currentPageNumber, previous = false) { + switch (this._scrollMode) { + case ScrollMode.WRAPPED: + { + const { + views + } = this._getVisiblePages(), + pageLayout = new Map(); + for (const { + id, + y, + percent, + widthPercent + } of views) { + if (percent === 0 || widthPercent < 100) { + continue; + } + let yArray = pageLayout.get(y); + if (!yArray) { + pageLayout.set(y, yArray ||= []); + } + yArray.push(id); + } + for (const yArray of pageLayout.values()) { + const currentIndex = yArray.indexOf(currentPageNumber); + if (currentIndex === -1) { + continue; + } + const numPages = yArray.length; + if (numPages === 1) { + break; + } + if (previous) { + for (let i = currentIndex - 1, ii = 0; i >= ii; i--) { + const currentId = yArray[i], + expectedId = yArray[i + 1] - 1; + if (currentId < expectedId) { + return currentPageNumber - expectedId; + } + } + } else { + for (let i = currentIndex + 1, ii = numPages; i < ii; i++) { + const currentId = yArray[i], + expectedId = yArray[i - 1] + 1; + if (currentId > expectedId) { + return expectedId - currentPageNumber; + } + } + } + if (previous) { + const firstId = yArray[0]; + if (firstId < currentPageNumber) { + return currentPageNumber - firstId + 1; + } + } else { + const lastId = yArray[numPages - 1]; + if (lastId > currentPageNumber) { + return lastId - currentPageNumber + 1; + } + } + break; + } + break; + } + case ScrollMode.HORIZONTAL: + { + break; + } + case ScrollMode.PAGE: + case ScrollMode.VERTICAL: + { + if (this._spreadMode === SpreadMode.NONE) { + break; + } + const parity = this._spreadMode - 1; + if (previous && currentPageNumber % 2 !== parity) { + break; + } else if (!previous && currentPageNumber % 2 === parity) { + break; + } + const { + views + } = this._getVisiblePages(), + expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1; + for (const { + id, + percent, + widthPercent + } of views) { + if (id !== expectedId) { + continue; + } + if (percent > 0 && widthPercent === 100) { + return 2; + } + break; + } + break; + } + } + return 1; + } + nextPage() { + const currentPageNumber = this._currentPageNumber, + pagesCount = this.pagesCount; + if (currentPageNumber >= pagesCount) { + return false; + } + const advance = this._getPageAdvance(currentPageNumber, false) || 1; + this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount); + return true; + } + previousPage() { + const currentPageNumber = this._currentPageNumber; + if (currentPageNumber <= 1) { + return false; + } + const advance = this._getPageAdvance(currentPageNumber, true) || 1; + this.currentPageNumber = Math.max(currentPageNumber - advance, 1); + return true; + } + updateScale({ + drawingDelay, + scaleFactor = null, + steps = null, + origin + }) { + if (steps === null && scaleFactor === null) { + throw new Error("Invalid updateScale options: either `steps` or `scaleFactor` must be provided."); + } + if (!this.pdfDocument) { + return; + } + let newScale = this._currentScale; + if (scaleFactor > 0 && scaleFactor !== 1) { + newScale = Math.round(newScale * scaleFactor * 100) / 100; + } else if (steps) { + const delta = steps > 0 ? DEFAULT_SCALE_DELTA : 1 / DEFAULT_SCALE_DELTA; + const round = steps > 0 ? Math.ceil : Math.floor; + steps = Math.abs(steps); + do { + newScale = round((newScale * delta).toFixed(2) * 10) / 10; + } while (--steps > 0); + } + newScale = MathClamp(newScale, MIN_SCALE, MAX_SCALE); + this.#setScale(newScale, { + noScroll: false, + drawingDelay, + origin + }); + } + increaseScale(options = {}) { + this.updateScale({ + ...options, + steps: options.steps ?? 1 + }); + } + decreaseScale(options = {}) { + this.updateScale({ + ...options, + steps: -(options.steps ?? 1) + }); + } + #updateContainerHeightCss(height = this.container.clientHeight) { + if (height !== this.#previousContainerHeight) { + this.#previousContainerHeight = height; + docStyle.setProperty("--viewer-container-height", `${height}px`); + } + } + #resizeObserverCallback(entries) { + for (const entry of entries) { + if (entry.target === this.container) { + this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize)); + this.#containerTopLeft = null; + break; + } + } + } + get containerTopLeft() { + return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft]; + } + #cleanupTimeouts() { + if (this.#scaleTimeoutId !== null) { + clearTimeout(this.#scaleTimeoutId); + this.#scaleTimeoutId = null; + } + if (this.#scrollTimeoutId !== null) { + clearTimeout(this.#scrollTimeoutId); + this.#scrollTimeoutId = null; + } + } + #cleanupSwitchAnnotationEditorMode() { + this.#switchAnnotationEditorModeAC?.abort(); + this.#switchAnnotationEditorModeAC = null; + if (this.#switchAnnotationEditorModeTimeoutId !== null) { + clearTimeout(this.#switchAnnotationEditorModeTimeoutId); + this.#switchAnnotationEditorModeTimeoutId = null; + } + } + #preloadEditingData(mode) { + switch (mode) { + case AnnotationEditorType.STAMP: + this.#mlManager?.loadModel("altText"); + break; + case AnnotationEditorType.SIGNATURE: + this.#signatureManager?.loadSignatures(); + break; + } + } + get annotationEditorMode() { + return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE; + } + set annotationEditorMode({ + mode, + editId = null, + isFromKeyboard = false, + mustEnterInEditMode = false, + editComment = false + }) { + if (!this.#annotationEditorUIManager) { + throw new Error(`The AnnotationEditor is not enabled.`); + } + if (this.#annotationEditorMode === mode) { + return; + } + if (!isValidAnnotationEditorMode(mode)) { + throw new Error(`Invalid AnnotationEditor mode: ${mode}`); + } + if (!this.pdfDocument) { + return; + } + this.#preloadEditingData(mode); + const { + eventBus, + pdfDocument + } = this; + const updater = async () => { + this.#cleanupSwitchAnnotationEditorMode(); + this.#annotationEditorMode = mode; + await this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard, mustEnterInEditMode, editComment); + if (mode !== this.#annotationEditorMode || pdfDocument !== this.pdfDocument) { + return; + } + eventBus.dispatch("annotationeditormodechanged", { + source: this, + mode + }); + }; + if (mode === AnnotationEditorType.NONE || this.#annotationEditorMode === AnnotationEditorType.NONE) { + const isEditing = mode !== AnnotationEditorType.NONE; + if (!isEditing) { + this.pdfDocument.annotationStorage.resetModifiedIds(); + } + this.cleanup(); + for (const pageView of this._pages) { + pageView.toggleEditingMode(isEditing); + } + const idsToRefresh = this.#switchToEditAnnotationMode(); + if (isEditing && idsToRefresh) { + this.#cleanupSwitchAnnotationEditorMode(); + this.#switchAnnotationEditorModeAC = new AbortController(); + const signal = AbortSignal.any([this.#eventAbortController.signal, this.#switchAnnotationEditorModeAC.signal]); + eventBus._on("pagerendered", ({ + pageNumber + }) => { + idsToRefresh.delete(pageNumber); + if (idsToRefresh.size === 0) { + this.#switchAnnotationEditorModeTimeoutId = setTimeout(updater, 0); + } + }, { + signal + }); + return; + } + } + updater(); + } + refresh(noUpdate = false, updateArgs = Object.create(null)) { + if (!this.pdfDocument) { + return; + } + for (const pageView of this._pages) { + pageView.update(updateArgs); + } + this.#cleanupTimeouts(); + if (!noUpdate) { + this.update(); + } + } +} + +;// ./web/secondary_toolbar.js + + +class SecondaryToolbar { + #opts; + constructor(options, eventBus) { + this.#opts = options; + const buttons = [{ + element: options.presentationModeButton, + eventName: "presentationmode", + close: true + }, { + element: options.printButton, + eventName: "print", + close: true + }, { + element: options.downloadButton, + eventName: "download", + close: true + }, { + element: options.viewBookmarkButton, + eventName: null, + close: true + }, { + element: options.firstPageButton, + eventName: "firstpage", + close: true + }, { + element: options.lastPageButton, + eventName: "lastpage", + close: true + }, { + element: options.pageRotateCwButton, + eventName: "rotatecw", + close: false + }, { + element: options.pageRotateCcwButton, + eventName: "rotateccw", + close: false + }, { + element: options.cursorSelectToolButton, + eventName: "switchcursortool", + eventDetails: { + tool: CursorTool.SELECT + }, + close: true + }, { + element: options.cursorHandToolButton, + eventName: "switchcursortool", + eventDetails: { + tool: CursorTool.HAND + }, + close: true + }, { + element: options.scrollPageButton, + eventName: "switchscrollmode", + eventDetails: { + mode: ScrollMode.PAGE + }, + close: true + }, { + element: options.scrollVerticalButton, + eventName: "switchscrollmode", + eventDetails: { + mode: ScrollMode.VERTICAL + }, + close: true + }, { + element: options.scrollHorizontalButton, + eventName: "switchscrollmode", + eventDetails: { + mode: ScrollMode.HORIZONTAL + }, + close: true + }, { + element: options.scrollWrappedButton, + eventName: "switchscrollmode", + eventDetails: { + mode: ScrollMode.WRAPPED + }, + close: true + }, { + element: options.spreadNoneButton, + eventName: "switchspreadmode", + eventDetails: { + mode: SpreadMode.NONE + }, + close: true + }, { + element: options.spreadOddButton, + eventName: "switchspreadmode", + eventDetails: { + mode: SpreadMode.ODD + }, + close: true + }, { + element: options.spreadEvenButton, + eventName: "switchspreadmode", + eventDetails: { + mode: SpreadMode.EVEN + }, + close: true + }, { + element: options.imageAltTextSettingsButton, + eventName: "imagealttextsettings", + close: true + }, { + element: options.documentPropertiesButton, + eventName: "documentproperties", + close: true + }]; + this.eventBus = eventBus; + this.opened = false; + this.#bindListeners(buttons); + this.reset(); + } + get isOpen() { + return this.opened; + } + setPageNumber(pageNumber) { + this.pageNumber = pageNumber; + this.#updateUIState(); + } + setPagesCount(pagesCount) { + this.pagesCount = pagesCount; + this.#updateUIState(); + } + reset() { + this.pageNumber = 0; + this.pagesCount = 0; + this.#updateUIState(); + this.eventBus.dispatch("switchcursortool", { + source: this, + reset: true + }); + this.#scrollModeChanged({ + mode: ScrollMode.VERTICAL + }); + this.#spreadModeChanged({ + mode: SpreadMode.NONE + }); + } + #updateUIState() { + const { + firstPageButton, + lastPageButton, + pageRotateCwButton, + pageRotateCcwButton + } = this.#opts; + firstPageButton.disabled = this.pageNumber <= 1; + lastPageButton.disabled = this.pageNumber >= this.pagesCount; + pageRotateCwButton.disabled = this.pagesCount === 0; + pageRotateCcwButton.disabled = this.pagesCount === 0; + } + #bindListeners(buttons) { + const { + eventBus + } = this; + const { + toggleButton + } = this.#opts; + toggleButton.addEventListener("click", this.toggle.bind(this)); + for (const { + element, + eventName, + close, + eventDetails + } of buttons) { + element.addEventListener("click", evt => { + if (eventName !== null) { + eventBus.dispatch(eventName, { + source: this, + ...eventDetails + }); + } + if (close) { + this.close(); + } + eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "buttons", + data: { + id: element.id + } + } + }); + }); + } + eventBus._on("cursortoolchanged", this.#cursorToolChanged.bind(this)); + eventBus._on("scrollmodechanged", this.#scrollModeChanged.bind(this)); + eventBus._on("spreadmodechanged", this.#spreadModeChanged.bind(this)); + } + #cursorToolChanged({ + tool, + disabled + }) { + const { + cursorSelectToolButton, + cursorHandToolButton + } = this.#opts; + toggleCheckedBtn(cursorSelectToolButton, tool === CursorTool.SELECT); + toggleCheckedBtn(cursorHandToolButton, tool === CursorTool.HAND); + cursorSelectToolButton.disabled = disabled; + cursorHandToolButton.disabled = disabled; + } + #scrollModeChanged({ + mode + }) { + const { + scrollPageButton, + scrollVerticalButton, + scrollHorizontalButton, + scrollWrappedButton, + spreadNoneButton, + spreadOddButton, + spreadEvenButton + } = this.#opts; + toggleCheckedBtn(scrollPageButton, mode === ScrollMode.PAGE); + toggleCheckedBtn(scrollVerticalButton, mode === ScrollMode.VERTICAL); + toggleCheckedBtn(scrollHorizontalButton, mode === ScrollMode.HORIZONTAL); + toggleCheckedBtn(scrollWrappedButton, mode === ScrollMode.WRAPPED); + const forceScrollModePage = this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE; + scrollPageButton.disabled = forceScrollModePage; + scrollVerticalButton.disabled = forceScrollModePage; + scrollHorizontalButton.disabled = forceScrollModePage; + scrollWrappedButton.disabled = forceScrollModePage; + const isHorizontal = mode === ScrollMode.HORIZONTAL; + spreadNoneButton.disabled = isHorizontal; + spreadOddButton.disabled = isHorizontal; + spreadEvenButton.disabled = isHorizontal; + } + #spreadModeChanged({ + mode + }) { + const { + spreadNoneButton, + spreadOddButton, + spreadEvenButton + } = this.#opts; + toggleCheckedBtn(spreadNoneButton, mode === SpreadMode.NONE); + toggleCheckedBtn(spreadOddButton, mode === SpreadMode.ODD); + toggleCheckedBtn(spreadEvenButton, mode === SpreadMode.EVEN); + } + open() { + if (this.opened) { + return; + } + this.opened = true; + const { + toggleButton, + toolbar + } = this.#opts; + toggleExpandedBtn(toggleButton, true, toolbar); + } + close() { + if (!this.opened) { + return; + } + this.opened = false; + const { + toggleButton, + toolbar + } = this.#opts; + toggleExpandedBtn(toggleButton, false, toolbar); + } + toggle() { + if (this.opened) { + this.close(); + } else { + this.open(); + } + } +} + +;// ./web/signature_manager.js + +const DEFAULT_HEIGHT_IN_PAGE = 40; +class SignatureManager { + #addButton; + #tabsToAltText = null; + #clearButton; + #clearDescription; + #currentEditor; + #description; + #dialog; + #drawCurves = null; + #drawPlaceholder; + #drawPath = null; + #drawPathString = ""; + #drawPoints = null; + #drawSVG; + #drawThickness; + #errorBar; + #errorDescription; + #errorTitle; + #extractedSignatureData = null; + #imagePath = null; + #imagePicker; + #imagePickerLink; + #imagePlaceholder; + #imageSVG; + #saveCheckbox; + #saveContainer; + #tabButtons; + #addSignatureToolbarButton; + #loadSignaturesPromise = null; + #typeInput; + #currentTab = null; + #currentTabAC = null; + #hasDescriptionChanged = false; + #eventBus; + #isStorageFull = false; + #l10n; + #overlayManager; + #editDescriptionDialog; + #signatureStorage; + #uiManager = null; + static #l10nDescription = null; + constructor({ + dialog, + panels, + typeButton, + typeInput, + drawButton, + drawPlaceholder, + drawSVG, + drawThickness, + imageButton, + imageSVG, + imagePlaceholder, + imagePicker, + imagePickerLink, + description, + clearButton, + cancelButton, + addButton, + errorCloseButton, + errorBar, + errorTitle, + errorDescription, + saveCheckbox, + saveContainer + }, editSignatureElements, addSignatureToolbarButton, overlayManager, l10n, signatureStorage, eventBus) { + this.#addButton = addButton; + this.#clearButton = clearButton; + this.#clearDescription = description.lastElementChild; + this.#description = description.firstElementChild; + this.#dialog = dialog; + this.#drawSVG = drawSVG; + this.#drawPlaceholder = drawPlaceholder; + this.#drawThickness = drawThickness; + this.#errorBar = errorBar; + this.#errorTitle = errorTitle; + this.#errorDescription = errorDescription; + this.#imageSVG = imageSVG; + this.#imagePlaceholder = imagePlaceholder; + this.#imagePicker = imagePicker; + this.#imagePickerLink = imagePickerLink; + this.#overlayManager = overlayManager; + this.#saveCheckbox = saveCheckbox; + this.#saveContainer = saveContainer; + this.#addSignatureToolbarButton = addSignatureToolbarButton; + this.#typeInput = typeInput; + this.#l10n = l10n; + this.#signatureStorage = signatureStorage; + this.#eventBus = eventBus; + this.#editDescriptionDialog = new EditDescriptionDialog(editSignatureElements, overlayManager); + SignatureManager.#l10nDescription ||= Object.freeze({ + signature: "pdfjs-editor-add-signature-description-default-when-drawing", + errorUploadTitle: "pdfjs-editor-add-signature-image-upload-error-title", + errorUploadDescription: "pdfjs-editor-add-signature-image-upload-error-description", + errorNoDataTitle: "pdfjs-editor-add-signature-image-no-data-error-title", + errorNoDataDescription: "pdfjs-editor-add-signature-image-no-data-error-description" + }); + dialog.addEventListener("close", this.#close.bind(this)); + dialog.addEventListener("contextmenu", e => { + const { + target + } = e; + if (target !== this.#typeInput && target !== this.#description) { + e.preventDefault(); + } + }); + dialog.addEventListener("drop", e => { + stopEvent(e); + }); + cancelButton.addEventListener("click", this.#cancel.bind(this)); + addButton.addEventListener("click", this.#add.bind(this)); + clearButton.addEventListener("click", () => { + this.#reportTelemetry({ + type: "signature", + action: "pdfjs.signature.clear", + data: { + type: this.#currentTab + } + }); + this.#initTab(null); + }, { + passive: true + }); + this.#description.addEventListener("input", () => { + this.#clearDescription.disabled = this.#description.value === ""; + }, { + passive: true + }); + this.#clearDescription.addEventListener("click", () => { + this.#description.value = ""; + this.#clearDescription.disabled = true; + }, { + passive: true + }); + errorCloseButton.addEventListener("click", () => { + errorBar.hidden = true; + }, { + passive: true + }); + this.#initTabButtons(typeButton, drawButton, imageButton, panels); + imagePicker.accept = SupportedImageMimeTypes.join(","); + eventBus._on("storedsignatureschanged", this.#signaturesChanged.bind(this)); + overlayManager.register(dialog); + } + #initTabButtons(typeButton, drawButton, imageButton, panels) { + const buttons = this.#tabButtons = new Map([["type", typeButton], ["draw", drawButton], ["image", imageButton]]); + const tabCallback = e => { + for (const [name, button] of buttons) { + if (button === e.target) { + button.setAttribute("aria-selected", true); + button.setAttribute("tabindex", 0); + panels.setAttribute("data-selected", name); + this.#initTab(name); + } else { + button.setAttribute("aria-selected", false); + button.setAttribute("tabindex", -1); + } + } + }; + const buttonsArray = Array.from(buttons.values()); + for (let i = 0, ii = buttonsArray.length; i < ii; i++) { + const button = buttonsArray[i]; + button.addEventListener("click", tabCallback, { + passive: true + }); + button.addEventListener("keydown", ({ + key + }) => { + if (key !== "ArrowLeft" && key !== "ArrowRight") { + return; + } + buttonsArray[i + (key === "ArrowLeft" ? -1 : 1)]?.focus(); + }, { + passive: true + }); + } + } + #resetCommon() { + this.#hasDescriptionChanged = false; + this.#description.value = ""; + if (this.#currentTab) { + this.#tabsToAltText.get(this.#currentTab).value = ""; + } + } + #resetTab(name) { + switch (name) { + case "type": + this.#typeInput.value = ""; + break; + case "draw": + this.#drawCurves = null; + this.#drawPoints = null; + this.#drawPathString = ""; + this.#drawPath?.remove(); + this.#drawPath = null; + this.#drawPlaceholder.hidden = false; + this.#drawThickness.value = 1; + break; + case "image": + this.#imagePlaceholder.hidden = false; + this.#imagePath?.remove(); + this.#imagePath = null; + break; + } + } + #initTab(name) { + if (name && this.#currentTab === name) { + return; + } + if (this.#currentTab) { + this.#tabsToAltText.get(this.#currentTab).value = this.#description.value; + } + if (name) { + this.#currentTab = name; + } + this.#errorBar.hidden = true; + const reset = !name; + if (reset) { + this.#resetCommon(); + } else { + this.#description.value = this.#tabsToAltText.get(this.#currentTab).value; + } + this.#clearDescription.disabled = this.#description.value === ""; + this.#currentTabAC?.abort(); + this.#currentTabAC = new AbortController(); + switch (this.#currentTab) { + case "type": + this.#initTypeTab(reset); + break; + case "draw": + this.#initDrawTab(reset); + break; + case "image": + this.#initImageTab(reset); + break; + } + } + #disableButtons(value) { + if (!value || !this.#isStorageFull) { + this.#saveCheckbox.disabled = !value; + } + this.#clearButton.disabled = this.#addButton.disabled = this.#description.disabled = !value; + } + #initTypeTab(reset) { + if (reset) { + this.#resetTab("type"); + } + this.#disableButtons(this.#typeInput.value); + const { + signal + } = this.#currentTabAC; + const options = { + passive: true, + signal + }; + this.#typeInput.addEventListener("input", () => { + const { + value + } = this.#typeInput; + if (!this.#hasDescriptionChanged) { + this.#tabsToAltText.get("type").default = this.#description.value = value; + this.#clearDescription.disabled = value === ""; + } + this.#disableButtons(value); + }, options); + this.#description.addEventListener("input", () => { + this.#hasDescriptionChanged = this.#typeInput.value !== this.#description.value; + }, options); + } + #initDrawTab(reset) { + if (reset) { + this.#resetTab("draw"); + } + this.#disableButtons(this.#drawPath); + const { + signal + } = this.#currentTabAC; + const options = { + signal + }; + let currentPointerId = NaN; + const drawCallback = e => { + const { + pointerId + } = e; + if (!isNaN(currentPointerId) && currentPointerId !== pointerId) { + return; + } + currentPointerId = pointerId; + e.preventDefault(); + this.#drawSVG.setPointerCapture(pointerId); + const { + width: drawWidth, + height: drawHeight + } = this.#drawSVG.getBoundingClientRect(); + let { + offsetX, + offsetY + } = e; + offsetX = Math.round(offsetX); + offsetY = Math.round(offsetY); + if (e.target === this.#drawPlaceholder) { + this.#drawPlaceholder.hidden = true; + } + if (!this.#drawCurves) { + this.#drawCurves = { + width: drawWidth, + height: drawHeight, + thickness: parseInt(this.#drawThickness.value), + curves: [] + }; + this.#disableButtons(true); + const svgFactory = new DOMSVGFactory(); + const path = this.#drawPath = svgFactory.createElement("path"); + path.setAttribute("stroke-width", this.#drawThickness.value); + this.#drawSVG.append(path); + this.#drawSVG.addEventListener("pointerdown", drawCallback, options); + this.#drawPlaceholder.removeEventListener("pointerdown", drawCallback); + if (this.#description.value === "") { + this.#l10n.get(SignatureManager.#l10nDescription.signature).then(description => { + this.#tabsToAltText.get("draw").default = description; + this.#description.value ||= description; + this.#clearDescription.disabled = this.#description.value === ""; + }); + } + } + this.#drawPoints = [offsetX, offsetY]; + this.#drawCurves.curves.push({ + points: this.#drawPoints + }); + this.#drawPathString += `M ${offsetX} ${offsetY}`; + this.#drawPath.setAttribute("d", this.#drawPathString); + const finishDrawAC = new AbortController(); + const listenerDrawOptions = { + signal: AbortSignal.any([signal, finishDrawAC.signal]) + }; + this.#drawSVG.addEventListener("contextmenu", noContextMenu, listenerDrawOptions); + this.#drawSVG.addEventListener("pointermove", evt => { + evt.preventDefault(); + let { + offsetX: x, + offsetY: y + } = evt; + x = Math.round(x); + y = Math.round(y); + const drawPoints = this.#drawPoints; + if (x < 0 || y < 0 || x > drawWidth || y > drawHeight || x === drawPoints.at(-2) && y === drawPoints.at(-1)) { + return; + } + if (drawPoints.length >= 4) { + const [x1, y1, x2, y2] = drawPoints.slice(-4); + this.#drawPathString += `C${(x1 + 5 * x2) / 6} ${(y1 + 5 * y2) / 6} ${(5 * x2 + x) / 6} ${(5 * y2 + y) / 6} ${(x2 + x) / 2} ${(y2 + y) / 2}`; + } else { + this.#drawPathString += `L${x} ${y}`; + } + drawPoints.push(x, y); + this.#drawPath.setAttribute("d", this.#drawPathString); + }, listenerDrawOptions); + this.#drawSVG.addEventListener("pointerup", evt => { + const { + pointerId: pId + } = evt; + if (!isNaN(currentPointerId) && currentPointerId !== pId) { + return; + } + currentPointerId = NaN; + evt.preventDefault(); + this.#drawSVG.releasePointerCapture(pId); + finishDrawAC.abort(); + if (this.#drawPoints.length === 2) { + this.#drawPathString += `L${this.#drawPoints[0]} ${this.#drawPoints[1]}`; + this.#drawPath.setAttribute("d", this.#drawPathString); + } + }, listenerDrawOptions); + }; + if (this.#drawCurves) { + this.#drawSVG.addEventListener("pointerdown", drawCallback, options); + } else { + this.#drawPlaceholder.addEventListener("pointerdown", drawCallback, options); + } + this.#drawThickness.addEventListener("input", () => { + const { + value: thickness + } = this.#drawThickness; + this.#drawThickness.setAttribute("data-l10n-args", JSON.stringify({ + thickness + })); + if (!this.#drawCurves) { + return; + } + this.#drawPath.setAttribute("stroke-width", thickness); + this.#drawCurves.thickness = thickness; + }, options); + } + #showError(type) { + this.#errorTitle.setAttribute("data-l10n-id", SignatureManager.#l10nDescription[`error${type}Title`]); + this.#errorDescription.setAttribute("data-l10n-id", SignatureManager.#l10nDescription[`error${type}Description`]); + this.#errorBar.hidden = false; + } + #initImageTab(reset) { + if (reset) { + this.#resetTab("image"); + } + this.#disableButtons(this.#imagePath); + const { + signal + } = this.#currentTabAC; + const options = { + signal + }; + const passiveOptions = { + passive: true, + signal + }; + this.#imagePickerLink.addEventListener("keydown", e => { + const { + key + } = e; + if (key === "Enter" || key === " ") { + stopEvent(e); + this.#imagePicker.click(); + } + }, options); + this.#imagePicker.addEventListener("click", () => { + this.#dialog.classList.toggle("waiting", true); + }, passiveOptions); + this.#imagePicker.addEventListener("change", async () => { + const file = this.#imagePicker.files?.[0]; + if (!file || !SupportedImageMimeTypes.includes(file.type)) { + this.#showError("Upload"); + this.#dialog.classList.toggle("waiting", false); + return; + } + await this.#extractSignature(file); + }, passiveOptions); + this.#imagePicker.addEventListener("cancel", () => { + this.#dialog.classList.toggle("waiting", false); + }, passiveOptions); + this.#imagePlaceholder.addEventListener("dragover", e => { + const { + dataTransfer + } = e; + for (const { + type + } of dataTransfer.items) { + if (!SupportedImageMimeTypes.includes(type)) { + continue; + } + dataTransfer.dropEffect = dataTransfer.effectAllowed === "copy" ? "copy" : "move"; + stopEvent(e); + return; + } + dataTransfer.dropEffect = "none"; + }, options); + this.#imagePlaceholder.addEventListener("drop", e => { + const { + dataTransfer: { + files + } + } = e; + if (!files?.length) { + return; + } + for (const file of files) { + if (SupportedImageMimeTypes.includes(file.type)) { + this.#extractSignature(file); + break; + } + } + stopEvent(e); + this.#dialog.classList.toggle("waiting", true); + }, options); + } + async #extractSignature(file) { + let data; + try { + data = await this.#uiManager.imageManager.getFromFile(file); + } catch (e) { + console.error("SignatureManager.#extractSignature.", e); + } + if (!data) { + this.#showError("Upload"); + this.#dialog.classList.toggle("waiting", false); + return; + } + const lineData = this.#extractedSignatureData = this.#currentEditor.getFromImage(data.bitmap); + if (!lineData) { + this.#showError("NoData"); + this.#dialog.classList.toggle("waiting", false); + return; + } + const { + outline + } = lineData; + this.#imagePlaceholder.hidden = true; + this.#disableButtons(true); + const svgFactory = new DOMSVGFactory(); + const path = this.#imagePath = svgFactory.createElement("path"); + this.#imageSVG.setAttribute("viewBox", outline.viewBox); + this.#imageSVG.setAttribute("preserveAspectRatio", "xMidYMid meet"); + this.#imageSVG.append(path); + path.setAttribute("d", outline.toSVGPath()); + this.#tabsToAltText.get("image").default = file.name; + if (this.#description.value === "") { + this.#description.value = file.name || ""; + this.#clearDescription.disabled = this.#description.value === ""; + } + this.#dialog.classList.toggle("waiting", false); + } + #getOutlineForType() { + return this.#currentEditor.getFromText(this.#typeInput.value, window.getComputedStyle(this.#typeInput)); + } + #getOutlineForDraw() { + const { + width, + height + } = this.#drawSVG.getBoundingClientRect(); + return this.#currentEditor.getDrawnSignature(this.#drawCurves, width, height); + } + #reportTelemetry(data) { + this.#eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data + } + }); + } + #addToolbarButton(signatureData, uuid, description) { + const { + curves, + areContours, + thickness, + width, + height + } = signatureData; + const maxDim = Math.max(width, height); + const outlineData = SignatureExtractor.processDrawnLines({ + lines: { + curves, + thickness, + width, + height + }, + pageWidth: maxDim, + pageHeight: maxDim, + rotation: 0, + innerMargin: 0, + mustSmooth: false, + areContours + }); + if (!outlineData) { + return; + } + const { + outline + } = outlineData; + const svgFactory = new DOMSVGFactory(); + const div = document.createElement("div"); + const button = document.createElement("button"); + button.addEventListener("click", () => { + this.#eventBus.dispatch("switchannotationeditorparams", { + source: this, + type: AnnotationEditorParamsType.CREATE, + value: { + signatureData: { + lines: { + curves, + thickness, + width, + height + }, + mustSmooth: false, + areContours, + description, + uuid, + heightInPage: DEFAULT_HEIGHT_IN_PAGE + } + } + }); + }); + div.append(button); + div.classList.add("toolbarAddSignatureButtonContainer"); + const svg = svgFactory.create(1, 1, true); + button.append(svg); + const span = document.createElement("span"); + span.ariaHidden = true; + button.append(span); + button.classList.add("toolbarAddSignatureButton"); + button.type = "button"; + span.textContent = description; + button.setAttribute("data-l10n-id", "pdfjs-editor-add-saved-signature-button"); + button.setAttribute("data-l10n-args", JSON.stringify({ + description + })); + button.tabIndex = 0; + const path = svgFactory.createElement("path"); + svg.append(path); + svg.setAttribute("viewBox", outline.viewBox); + svg.setAttribute("preserveAspectRatio", "xMidYMid meet"); + if (areContours) { + path.classList.add("contours"); + } + path.setAttribute("d", outline.toSVGPath()); + const deleteButton = document.createElement("button"); + div.append(deleteButton); + deleteButton.classList.add("toolbarButton", "deleteButton"); + deleteButton.setAttribute("data-l10n-id", "pdfjs-editor-delete-signature-button1"); + deleteButton.type = "button"; + deleteButton.tabIndex = 0; + deleteButton.addEventListener("click", async () => { + if (await this.#signatureStorage.delete(uuid)) { + div.remove(); + this.#reportTelemetry({ + type: "signature", + action: "pdfjs.signature.delete_saved", + data: { + savedCount: await this.#signatureStorage.size() + } + }); + } + }); + const deleteSpan = document.createElement("span"); + deleteButton.append(deleteSpan); + deleteSpan.setAttribute("data-l10n-id", "pdfjs-editor-delete-signature-button-label1"); + this.#addSignatureToolbarButton.before(div); + } + async #signaturesChanged() { + const parent = this.#addSignatureToolbarButton.parentElement; + while (parent.firstElementChild !== this.#addSignatureToolbarButton) { + parent.firstElementChild.remove(); + } + this.#loadSignaturesPromise = null; + await this.loadSignatures(true); + } + getSignature(params) { + return this.open(params); + } + async loadSignatures(reload = false) { + if (!this.#addSignatureToolbarButton || !reload && this.#addSignatureToolbarButton.previousElementSibling || !this.#signatureStorage) { + return; + } + if (!this.#loadSignaturesPromise) { + this.#loadSignaturesPromise = this.#signatureStorage.getAll().then(async signatures => [signatures, await Promise.all(Array.from(signatures.values(), ({ + signatureData + }) => SignatureExtractor.decompressSignature(signatureData)))]); + if (!reload) { + return; + } + } + const [signatures, signaturesData] = await this.#loadSignaturesPromise; + this.#loadSignaturesPromise = null; + let i = 0; + for (const [uuid, { + description + }] of signatures) { + const data = signaturesData[i++]; + if (!data) { + continue; + } + data.curves = data.outlines.map(points => ({ + points + })); + delete data.outlines; + this.#addToolbarButton(data, uuid, description); + } + } + async renderEditButton(editor) { + const button = document.createElement("button"); + button.classList.add("altText", "editDescription"); + button.tabIndex = 0; + if (editor.description) { + button.title = editor.description; + } + const span = document.createElement("span"); + button.append(span); + span.setAttribute("data-l10n-id", "pdfjs-editor-add-signature-edit-button-label"); + button.addEventListener("click", () => { + this.#editDescriptionDialog.open(editor); + }, { + passive: true + }); + return button; + } + async open({ + uiManager, + editor + }) { + this.#tabsToAltText ||= new Map(this.#tabButtons.keys().map(name => [name, { + value: "", + default: "" + }])); + this.#uiManager = uiManager; + this.#currentEditor = editor; + this.#uiManager.removeEditListeners(); + const isStorageFull = this.#isStorageFull = await this.#signatureStorage.isFull(); + this.#saveContainer.classList.toggle("fullStorage", isStorageFull); + this.#saveCheckbox.checked = !isStorageFull; + await this.#overlayManager.open(this.#dialog); + const tabType = this.#tabButtons.get("type"); + tabType.focus(); + tabType.click(); + } + #cancel() { + this.#finish(); + } + #finish() { + this.#overlayManager.closeIfActive(this.#dialog); + } + #close() { + if (this.#currentEditor._drawId === null) { + this.#currentEditor.remove(); + } + this.#uiManager?.addEditListeners(); + this.#currentTabAC?.abort(); + this.#currentTabAC = null; + this.#uiManager = null; + this.#currentEditor = null; + this.#resetCommon(); + for (const [name] of this.#tabButtons) { + this.#resetTab(name); + } + this.#disableButtons(false); + this.#currentTab = null; + this.#tabsToAltText = null; + } + async #add() { + let data; + const type = this.#currentTab; + switch (type) { + case "type": + data = this.#getOutlineForType(); + break; + case "draw": + data = this.#getOutlineForDraw(); + break; + case "image": + data = this.#extractedSignatureData; + break; + } + let uuid = null; + const description = this.#description.value; + if (this.#saveCheckbox.checked) { + const { + newCurves, + areContours, + thickness, + width, + height + } = data; + const signatureData = await SignatureExtractor.compressSignature({ + outlines: newCurves, + areContours, + thickness, + width, + height + }); + uuid = await this.#signatureStorage.create({ + description, + signatureData + }); + if (uuid) { + this.#addToolbarButton({ + curves: newCurves.map(points => ({ + points + })), + areContours, + thickness, + width, + height + }, uuid, description); + } else { + console.warn("SignatureManager.add: cannot save the signature."); + } + } + const altText = this.#tabsToAltText.get(type); + this.#reportTelemetry({ + type: "signature", + action: "pdfjs.signature.created", + data: { + type, + saved: !!uuid, + savedCount: await this.#signatureStorage.size(), + descriptionChanged: description !== altText.default + } + }); + this.#currentEditor.addSignature(data, DEFAULT_HEIGHT_IN_PAGE, this.#description.value, uuid); + this.#finish(); + } + destroy() { + this.#uiManager = null; + this.#finish(); + } +} +class EditDescriptionDialog { + #currentEditor; + #previousDescription; + #description; + #dialog; + #overlayManager; + #signatureSVG; + #uiManager; + constructor({ + dialog, + description, + cancelButton, + updateButton, + editSignatureView + }, overlayManager) { + const descriptionInput = this.#description = description.firstElementChild; + this.#signatureSVG = editSignatureView; + this.#dialog = dialog; + this.#overlayManager = overlayManager; + dialog.addEventListener("close", this.#close.bind(this)); + dialog.addEventListener("contextmenu", e => { + if (e.target !== this.#description) { + e.preventDefault(); + } + }); + cancelButton.addEventListener("click", this.#cancel.bind(this)); + updateButton.addEventListener("click", this.#update.bind(this)); + const clearDescription = description.lastElementChild; + clearDescription.addEventListener("click", () => { + descriptionInput.value = ""; + clearDescription.disabled = true; + updateButton.disabled = this.#previousDescription === ""; + }); + descriptionInput.addEventListener("input", () => { + const { + value + } = descriptionInput; + clearDescription.disabled = value === ""; + updateButton.disabled = value === this.#previousDescription; + editSignatureView.setAttribute("aria-label", value); + }, { + passive: true + }); + overlayManager.register(dialog); + } + async open(editor) { + this.#uiManager = editor._uiManager; + this.#currentEditor = editor; + this.#previousDescription = this.#description.value = editor.description; + this.#description.dispatchEvent(new Event("input")); + this.#uiManager.removeEditListeners(); + const { + areContours, + outline + } = editor.getSignaturePreview(); + const svgFactory = new DOMSVGFactory(); + const path = svgFactory.createElement("path"); + this.#signatureSVG.append(path); + this.#signatureSVG.setAttribute("viewBox", outline.viewBox); + path.setAttribute("d", outline.toSVGPath()); + if (areContours) { + path.classList.add("contours"); + } + await this.#overlayManager.open(this.#dialog); + } + async #update() { + this.#currentEditor._reportTelemetry({ + action: "pdfjs.signature.edit_description", + data: { + hasBeenChanged: true + } + }); + this.#currentEditor.description = this.#description.value; + this.#finish(); + } + #cancel() { + this.#currentEditor._reportTelemetry({ + action: "pdfjs.signature.edit_description", + data: { + hasBeenChanged: false + } + }); + this.#finish(); + } + #finish() { + this.#overlayManager.closeIfActive(this.#dialog); + } + #close() { + this.#uiManager?.addEditListeners(); + this.#uiManager = null; + this.#currentEditor = null; + this.#signatureSVG.firstElementChild.remove(); + } +} + +;// ./web/toolbar.js + + +class Toolbar { + #colorPicker = null; + #opts; + constructor(options, eventBus, toolbarDensity = 0) { + this.#opts = options; + this.eventBus = eventBus; + const buttons = [{ + element: options.previous, + eventName: "previouspage" + }, { + element: options.next, + eventName: "nextpage" + }, { + element: options.zoomIn, + eventName: "zoomin" + }, { + element: options.zoomOut, + eventName: "zoomout" + }, { + element: options.print, + eventName: "print" + }, { + element: options.download, + eventName: "download" + }, { + element: options.editorCommentButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorCommentButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.POPUP; + } + } + }, { + element: options.editorFreeTextButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorFreeTextButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.FREETEXT; + } + } + }, { + element: options.editorHighlightButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorHighlightButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.HIGHLIGHT; + } + } + }, { + element: options.editorInkButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorInkButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.INK; + } + } + }, { + element: options.editorStampButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorStampButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.STAMP; + } + }, + telemetry: { + type: "editing", + data: { + action: "pdfjs.image.icon_click" + } + } + }, { + element: options.editorSignatureButton, + eventName: "switchannotationeditormode", + eventDetails: { + get mode() { + const { + classList + } = options.editorSignatureButton; + return classList.contains("toggled") ? AnnotationEditorType.NONE : AnnotationEditorType.SIGNATURE; + } + } + }]; + this.#bindListeners(buttons); + this.#updateToolbarDensity({ + value: toolbarDensity + }); + this.reset(); + } + #updateToolbarDensity({ + value + }) { + let name = "normal"; + switch (value) { + case 1: + name = "compact"; + break; + case 2: + name = "touch"; + break; + } + document.documentElement.setAttribute("data-toolbar-density", name); + } + setPageNumber(pageNumber, pageLabel) { + this.pageNumber = pageNumber; + this.pageLabel = pageLabel; + this.#updateUIState(false); + } + setPagesCount(pagesCount, hasPageLabels) { + this.pagesCount = pagesCount; + this.hasPageLabels = hasPageLabels; + this.#updateUIState(true); + } + setPageScale(pageScaleValue, pageScale) { + this.pageScaleValue = (pageScaleValue || pageScale).toString(); + this.pageScale = pageScale; + this.#updateUIState(false); + } + reset() { + this.#colorPicker = null; + this.pageNumber = 0; + this.pageLabel = null; + this.hasPageLabels = false; + this.pagesCount = 0; + this.pageScaleValue = DEFAULT_SCALE_VALUE; + this.pageScale = DEFAULT_SCALE; + this.#updateUIState(true); + this.updateLoadingIndicatorState(); + this.#editorModeChanged({ + mode: AnnotationEditorType.DISABLE + }); + } + #bindListeners(buttons) { + const { + eventBus + } = this; + const { + editorHighlightColorPicker, + editorHighlightButton, + pageNumber, + scaleSelect + } = this.#opts; + const self = this; + for (const { + element, + eventName, + eventDetails, + telemetry + } of buttons) { + element.addEventListener("click", evt => { + if (eventName !== null) { + eventBus.dispatch(eventName, { + source: this, + ...eventDetails, + isFromKeyboard: evt.detail === 0 + }); + } + if (telemetry) { + eventBus.dispatch("reporttelemetry", { + source: this, + details: telemetry + }); + } + }); + } + pageNumber.addEventListener("click", function () { + this.select(); + }); + pageNumber.addEventListener("change", function () { + eventBus.dispatch("pagenumberchanged", { + source: self, + value: this.value + }); + }); + scaleSelect.addEventListener("change", function () { + if (this.value === "custom") { + return; + } + eventBus.dispatch("scalechanged", { + source: self, + value: this.value + }); + }); + scaleSelect.addEventListener("click", function ({ + target + }) { + if (this.value === self.pageScaleValue && target.tagName.toUpperCase() === "OPTION") { + this.blur(); + } + }); + scaleSelect.oncontextmenu = noContextMenu; + eventBus._on("annotationeditormodechanged", this.#editorModeChanged.bind(this)); + eventBus._on("showannotationeditorui", ({ + mode + }) => { + switch (mode) { + case AnnotationEditorType.HIGHLIGHT: + editorHighlightButton.click(); + break; + } + }); + eventBus._on("toolbardensity", this.#updateToolbarDensity.bind(this)); + if (editorHighlightColorPicker) { + eventBus._on("annotationeditoruimanager", ({ + uiManager + }) => { + const cp = this.#colorPicker = new ColorPicker({ + uiManager + }); + uiManager.setMainHighlightColorPicker(cp); + editorHighlightColorPicker.append(cp.renderMainDropdown()); + }); + eventBus._on("mainhighlightcolorpickerupdatecolor", ({ + value + }) => { + this.#colorPicker?.updateColor(value); + }); + } + } + #editorModeChanged({ + mode + }) { + const { + editorCommentButton, + editorCommentParamsToolbar, + editorFreeTextButton, + editorFreeTextParamsToolbar, + editorHighlightButton, + editorHighlightParamsToolbar, + editorInkButton, + editorInkParamsToolbar, + editorStampButton, + editorStampParamsToolbar, + editorSignatureButton, + editorSignatureParamsToolbar + } = this.#opts; + toggleExpandedBtn(editorCommentButton, mode === AnnotationEditorType.POPUP, editorCommentParamsToolbar); + toggleExpandedBtn(editorFreeTextButton, mode === AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar); + toggleExpandedBtn(editorHighlightButton, mode === AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar); + toggleExpandedBtn(editorInkButton, mode === AnnotationEditorType.INK, editorInkParamsToolbar); + toggleExpandedBtn(editorStampButton, mode === AnnotationEditorType.STAMP, editorStampParamsToolbar); + toggleExpandedBtn(editorSignatureButton, mode === AnnotationEditorType.SIGNATURE, editorSignatureParamsToolbar); + editorCommentButton.disabled = editorFreeTextButton.disabled = editorHighlightButton.disabled = editorInkButton.disabled = editorStampButton.disabled = editorSignatureButton.disabled = mode === AnnotationEditorType.DISABLE; + } + #updateUIState(resetNumPages = false) { + const { + pageNumber, + pagesCount, + pageScaleValue, + pageScale + } = this; + const opts = this.#opts; + if (resetNumPages) { + if (this.hasPageLabels) { + opts.pageNumber.type = "text"; + opts.numPages.setAttribute("data-l10n-id", "pdfjs-page-of-pages"); + } else { + opts.pageNumber.type = "number"; + opts.numPages.setAttribute("data-l10n-id", "pdfjs-of-pages"); + opts.numPages.setAttribute("data-l10n-args", JSON.stringify({ + pagesCount + })); + } + opts.pageNumber.max = pagesCount; + } + if (this.hasPageLabels) { + opts.pageNumber.value = this.pageLabel; + opts.numPages.setAttribute("data-l10n-args", JSON.stringify({ + pageNumber, + pagesCount + })); + } else { + opts.pageNumber.value = pageNumber; + } + opts.previous.disabled = pageNumber <= 1; + opts.next.disabled = pageNumber >= pagesCount; + opts.zoomOut.disabled = pageScale <= MIN_SCALE; + opts.zoomIn.disabled = pageScale >= MAX_SCALE; + let predefinedValueFound = false; + for (const option of opts.scaleSelect.options) { + if (option.value !== pageScaleValue) { + option.selected = false; + continue; + } + option.selected = true; + predefinedValueFound = true; + } + if (!predefinedValueFound) { + opts.customScaleOption.selected = true; + opts.customScaleOption.setAttribute("data-l10n-args", JSON.stringify({ + scale: Math.round(pageScale * 10000) / 100 + })); + } + } + updateLoadingIndicatorState(loading = false) { + const { + pageNumber + } = this.#opts; + pageNumber.classList.toggle("loading", loading); + } +} + +;// ./web/view_history.js +const DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20; +class ViewHistory { + constructor(fingerprint, cacheSize = DEFAULT_VIEW_HISTORY_CACHE_SIZE) { + this.fingerprint = fingerprint; + this.cacheSize = cacheSize; + this._initializedPromise = this._readFromStorage().then(databaseStr => { + const database = JSON.parse(databaseStr || "{}"); + let index = -1; + if (!Array.isArray(database.files)) { + database.files = []; + } else { + while (database.files.length >= this.cacheSize) { + database.files.shift(); + } + for (let i = 0, ii = database.files.length; i < ii; i++) { + const branch = database.files[i]; + if (branch.fingerprint === this.fingerprint) { + index = i; + break; + } + } + } + if (index === -1) { + index = database.files.push({ + fingerprint: this.fingerprint + }) - 1; + } + this.file = database.files[index]; + this.database = database; + }); + } + async _writeToStorage() { + const databaseStr = JSON.stringify(this.database); + sessionStorage.setItem("pdfjs.history", databaseStr); + } + async _readFromStorage() { + return sessionStorage.getItem("pdfjs.history"); + } + async set(name, val) { + await this._initializedPromise; + this.file[name] = val; + return this._writeToStorage(); + } + async setMultiple(properties) { + await this._initializedPromise; + for (const name in properties) { + this.file[name] = properties[name]; + } + return this._writeToStorage(); + } + async get(name, defaultValue) { + await this._initializedPromise; + const val = this.file[name]; + return val !== undefined ? val : defaultValue; + } + async getMultiple(properties) { + await this._initializedPromise; + const values = Object.create(null); + for (const name in properties) { + const val = this.file[name]; + values[name] = val !== undefined ? val : properties[name]; + } + return values; + } +} + +;// ./web/app.js + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +const FORCE_PAGES_LOADED_TIMEOUT = 10000; +const ViewOnLoad = { + UNKNOWN: -1, + PREVIOUS: 0, + INITIAL: 1 +}; +const PDFViewerApplication = { + initialBookmark: document.location.hash.substring(1), + _initializedCapability: { + ...Promise.withResolvers(), + settled: false + }, + appConfig: null, + pdfDocument: null, + pdfLoadingTask: null, + printService: null, + pdfViewer: null, + pdfThumbnailViewer: null, + pdfRenderingQueue: null, + pdfPresentationMode: null, + pdfDocumentProperties: null, + pdfLinkService: null, + pdfTextExtractor: null, + pdfHistory: null, + pdfSidebar: null, + pdfOutlineViewer: null, + pdfAttachmentViewer: null, + pdfLayerViewer: null, + pdfCursorTools: null, + pdfScriptingManager: null, + store: null, + downloadManager: null, + overlayManager: null, + preferences: new Preferences(), + toolbar: null, + secondaryToolbar: null, + eventBus: null, + l10n: null, + annotationEditorParams: null, + imageAltTextSettings: null, + isInitialViewSet: false, + isViewerEmbedded: window.parent !== window, + url: "", + baseUrl: "", + mlManager: null, + _downloadUrl: "", + _eventBusAbortController: null, + _windowAbortController: null, + _globalAbortController: new AbortController(), + documentInfo: null, + metadata: null, + _contentDispositionFilename: null, + _contentLength: null, + _saveInProgress: false, + _wheelUnusedTicks: 0, + _wheelUnusedFactor: 1, + _touchManager: null, + _touchUnusedTicks: 0, + _touchUnusedFactor: 1, + _PDFBug: null, + _hasAnnotationEditors: false, + _title: document.title, + _printAnnotationStoragePromise: null, + _isCtrlKeyDown: false, + _caretBrowsing: null, + _isScrolling: false, + editorUndoBar: null, + _printPermissionPromise: null, + async initialize(appConfig) { + this.appConfig = appConfig; + try { + await this.preferences.initializedPromise; + } catch (ex) { + console.error("initialize:", ex); + } + if (AppOptions.get("pdfBugEnabled")) { + await this._parseHashParams(); + } + let mode; + switch (AppOptions.get("viewerCssTheme")) { + case 1: + mode = "light"; + break; + case 2: + mode = "dark"; + break; + } + if (mode) { + docStyle.setProperty("color-scheme", mode); + } + if (AppOptions.get("enableAltText")) { + this.mlManager = new MLManager({ + enableGuessAltText: AppOptions.get("enableGuessAltText"), + enableAltTextModelDownload: AppOptions.get("enableAltTextModelDownload"), + altTextLearnMoreUrl: AppOptions.get("altTextLearnMoreUrl") + }); + } + this.l10n = await this.externalServices.createL10n(); + document.getElementsByTagName("html")[0].dir = this.l10n.getDirection(); + if (this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE) { + AppOptions.set("externalLinkTarget", LinkTarget.TOP); + } + await this._initializeViewerComponents(); + this.pdfTextExtractor = new PdfTextExtractor(this.externalServices); + this.bindEvents(); + this.bindWindowEvents(); + this._initializedCapability.settled = true; + this._initializedCapability.resolve(); + }, + async _parseHashParams() { + const hash = document.location.hash.substring(1); + if (!hash) { + return; + } + const { + mainContainer, + viewerContainer + } = this.appConfig, + params = parseQueryString(hash); + const loadPDFBug = async () => { + if (this._PDFBug) { + return; + } + const { + PDFBug + } = await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + AppOptions.get("debuggerSrc")); + this._PDFBug = PDFBug; + }; + if (params.get("disableworker") === "true") { + try { + GlobalWorkerOptions.workerSrc ||= AppOptions.get("workerSrc"); + await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + PDFWorker.workerSrc); + AppOptions.set("workerPort", null); + } catch (ex) { + console.error("_parseHashParams:", ex); + } + } + if (params.has("textlayer")) { + switch (params.get("textlayer")) { + case "off": + AppOptions.set("textLayerMode", TextLayerMode.DISABLE); + break; + case "visible": + case "shadow": + case "hover": + viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`); + try { + await loadPDFBug(); + this._PDFBug.loadCSS(); + } catch (ex) { + console.error("_parseHashParams:", ex); + } + break; + } + } + if (params.has("pdfbug")) { + const enabled = params.get("pdfbug").split(","); + try { + await loadPDFBug(); + this._PDFBug.init(mainContainer, enabled); + } catch (ex) { + console.error("_parseHashParams:", ex); + } + const debugOpts = { + pdfBug: true, + fontExtraProperties: true + }; + if (globalThis.StepperManager?.enabled) { + debugOpts.minDurationToUpdateCanvas = 0; + } + AppOptions.setAll(debugOpts); + } + const opts = { + disableAutoFetch: x => x === "true", + disableFontFace: x => x === "true", + disableHistory: x => x === "true", + disableRange: x => x === "true", + disableStream: x => x === "true", + verbosity: x => x | 0 + }; + for (const name in opts) { + const check = opts[name], + key = name.toLowerCase(); + if (params.has(key)) { + AppOptions.set(name, check(params.get(key))); + } + } + }, + async _initializeViewerComponents() { + const { + appConfig, + externalServices, + l10n, + mlManager + } = this; + const abortSignal = this._globalAbortController.signal; + const eventBus = new FirefoxEventBus(AppOptions.get("allowedGlobalEvents"), externalServices, AppOptions.get("isInAutomation")); + this.eventBus = AppOptions.eventBus = eventBus; + mlManager?.setEventBus(eventBus, abortSignal); + const overlayManager = this.overlayManager = new OverlayManager(); + const renderingQueue = this.pdfRenderingQueue = new PDFRenderingQueue(); + renderingQueue.onIdle = this._cleanup.bind(this); + const linkService = this.pdfLinkService = new PDFLinkService({ + eventBus, + externalLinkTarget: AppOptions.get("externalLinkTarget"), + externalLinkRel: AppOptions.get("externalLinkRel"), + ignoreDestinationZoom: AppOptions.get("ignoreDestinationZoom") + }); + const downloadManager = this.downloadManager = new DownloadManager(); + const findController = this.findController = new PDFFindController({ + linkService, + eventBus, + updateMatchesCountOnProgress: true + }); + const pdfScriptingManager = this.pdfScriptingManager = new PDFScriptingManager({ + eventBus, + externalServices, + docProperties: this._scriptingDocProperties.bind(this) + }); + const container = appConfig.mainContainer, + viewer = appConfig.viewerContainer; + const annotationEditorMode = AppOptions.get("annotationEditorMode"); + const hasForcedColors = AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches; + const pageColors = hasForcedColors ? { + background: AppOptions.get("pageColorsBackground"), + foreground: AppOptions.get("pageColorsForeground") + } : null; + let altTextManager; + if (AppOptions.get("enableUpdatedAddImage")) { + altTextManager = appConfig.newAltTextDialog ? new NewAltTextManager(appConfig.newAltTextDialog, overlayManager, eventBus) : null; + } else { + altTextManager = appConfig.altTextDialog ? new AltTextManager(appConfig.altTextDialog, container, overlayManager, eventBus) : null; + } + if (appConfig.editorUndoBar) { + this.editorUndoBar = new EditorUndoBar(appConfig.editorUndoBar, eventBus); + } + const signatureManager = AppOptions.get("enableSignatureEditor") && appConfig.addSignatureDialog ? new SignatureManager(appConfig.addSignatureDialog, appConfig.editSignatureDialog, appConfig.annotationEditorParams?.editorSignatureAddSignature || null, overlayManager, l10n, externalServices.createSignatureStorage(eventBus, abortSignal), eventBus) : null; + const ltr = appConfig.viewerContainer ? getComputedStyle(appConfig.viewerContainer).direction === "ltr" : true; + const commentManager = AppOptions.get("enableComment") && appConfig.editCommentDialog ? new CommentManager(appConfig.editCommentDialog, { + learnMoreUrl: AppOptions.get("commentLearnMoreUrl"), + sidebar: appConfig.annotationEditorParams?.editorCommentsSidebar || null, + sidebarResizer: appConfig.annotationEditorParams?.editorCommentsSidebarResizer || null, + commentsList: appConfig.annotationEditorParams?.editorCommentsSidebarList || null, + commentCount: appConfig.annotationEditorParams?.editorCommentsSidebarCount || null, + sidebarTitle: appConfig.annotationEditorParams?.editorCommentsSidebarTitle || null, + closeButton: appConfig.annotationEditorParams?.editorCommentsSidebarCloseButton || null, + commentToolbarButton: appConfig.toolbar?.editorCommentButton || null + }, eventBus, linkService, overlayManager, ltr, hasForcedColors) : null; + const enableHWA = AppOptions.get("enableHWA"), + maxCanvasPixels = AppOptions.get("maxCanvasPixels"), + maxCanvasDim = AppOptions.get("maxCanvasDim"), + capCanvasAreaFactor = AppOptions.get("capCanvasAreaFactor"); + const pdfViewer = this.pdfViewer = new PDFViewer({ + container, + viewer, + viewerAlert: appConfig.viewerAlert, + eventBus, + renderingQueue, + linkService, + downloadManager, + altTextManager, + commentManager, + signatureManager, + editorUndoBar: this.editorUndoBar, + findController, + scriptingManager: AppOptions.get("enableScripting") && pdfScriptingManager, + l10n, + textLayerMode: AppOptions.get("textLayerMode"), + annotationMode: AppOptions.get("annotationMode"), + annotationEditorMode, + annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"), + enableHighlightFloatingButton: AppOptions.get("enableHighlightFloatingButton"), + enableUpdatedAddImage: AppOptions.get("enableUpdatedAddImage"), + enableNewAltTextWhenAddingImage: AppOptions.get("enableNewAltTextWhenAddingImage"), + imageResourcesPath: AppOptions.get("imageResourcesPath"), + enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"), + maxCanvasPixels, + maxCanvasDim, + capCanvasAreaFactor, + enableDetailCanvas: AppOptions.get("enableDetailCanvas"), + enablePermissions: AppOptions.get("enablePermissions"), + enableOptimizedPartialRendering: AppOptions.get("enableOptimizedPartialRendering"), + pageColors, + mlManager, + abortSignal, + enableHWA, + supportsPinchToZoom: this.supportsPinchToZoom, + enableAutoLinking: AppOptions.get("enableAutoLinking"), + minDurationToUpdateCanvas: AppOptions.get("minDurationToUpdateCanvas") + }); + renderingQueue.setViewer(pdfViewer); + linkService.setViewer(pdfViewer); + pdfScriptingManager.setViewer(pdfViewer); + if (appConfig.sidebar?.thumbnailView) { + this.pdfThumbnailViewer = new PDFThumbnailViewer({ + container: appConfig.sidebar.thumbnailView, + eventBus, + renderingQueue, + linkService, + maxCanvasPixels, + maxCanvasDim, + pageColors, + abortSignal, + enableHWA + }); + renderingQueue.setThumbnailViewer(this.pdfThumbnailViewer); + } + if (!this.isViewerEmbedded && !AppOptions.get("disableHistory")) { + this.pdfHistory = new PDFHistory({ + linkService, + eventBus + }); + linkService.setHistory(this.pdfHistory); + } + if (!this.supportsIntegratedFind && appConfig.findBar) { + this.findBar = new PDFFindBar(appConfig.findBar, appConfig.principalContainer, eventBus); + } + if (appConfig.annotationEditorParams) { + if (annotationEditorMode !== AnnotationEditorType.DISABLE) { + const editorSignatureButton = appConfig.toolbar?.editorSignatureButton; + if (editorSignatureButton && AppOptions.get("enableSignatureEditor")) { + editorSignatureButton.parentElement.hidden = false; + } + const editorCommentButton = appConfig.toolbar?.editorCommentButton; + if (editorCommentButton && AppOptions.get("enableComment")) { + editorCommentButton.parentElement.hidden = false; + } + this.annotationEditorParams = new AnnotationEditorParams(appConfig.annotationEditorParams, eventBus); + } else { + for (const id of ["editorModeButtons", "editorModeSeparator"]) { + document.getElementById(id)?.classList.add("hidden"); + } + } + } + if (mlManager && appConfig.secondaryToolbar?.imageAltTextSettingsButton) { + this.imageAltTextSettings = new ImageAltTextSettings(appConfig.altTextSettingsDialog, overlayManager, eventBus, mlManager); + } + if (appConfig.documentProperties) { + this.pdfDocumentProperties = new PDFDocumentProperties(appConfig.documentProperties, overlayManager, eventBus, l10n, () => this._docFilename, () => this._docTitle); + } + if (appConfig.secondaryToolbar?.cursorHandToolButton) { + this.pdfCursorTools = new PDFCursorTools({ + container, + eventBus, + cursorToolOnLoad: AppOptions.get("cursorToolOnLoad") + }); + } + if (appConfig.toolbar) { + this.toolbar = new Toolbar(appConfig.toolbar, eventBus, AppOptions.get("toolbarDensity")); + } + if (appConfig.secondaryToolbar) { + if (AppOptions.get("enableAltText")) { + appConfig.secondaryToolbar.imageAltTextSettingsButton?.classList.remove("hidden"); + appConfig.secondaryToolbar.imageAltTextSettingsSeparator?.classList.remove("hidden"); + } + this.secondaryToolbar = new SecondaryToolbar(appConfig.secondaryToolbar, eventBus); + } + if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) { + this.pdfPresentationMode = new PDFPresentationMode({ + container, + pdfViewer, + eventBus + }); + } + if (appConfig.passwordOverlay) { + this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay, overlayManager, this.isViewerEmbedded); + } + if (appConfig.sidebar?.outlineView) { + this.pdfOutlineViewer = new PDFOutlineViewer({ + container: appConfig.sidebar.outlineView, + eventBus, + l10n, + linkService, + downloadManager + }); + } + if (appConfig.sidebar?.attachmentsView) { + this.pdfAttachmentViewer = new PDFAttachmentViewer({ + container: appConfig.sidebar.attachmentsView, + eventBus, + l10n, + downloadManager + }); + } + if (appConfig.sidebar?.layersView) { + this.pdfLayerViewer = new PDFLayerViewer({ + container: appConfig.sidebar.layersView, + eventBus, + l10n + }); + } + if (appConfig.sidebar) { + this.pdfSidebar = new PDFSidebar({ + elements: appConfig.sidebar, + eventBus, + l10n + }); + this.pdfSidebar.onToggled = this.forceRendering.bind(this); + this.pdfSidebar.onUpdateThumbnails = () => { + for (const pageView of pdfViewer.getCachedPageViews()) { + if (pageView.renderingState === RenderingStates.FINISHED) { + this.pdfThumbnailViewer.getThumbnail(pageView.id - 1)?.setImage(pageView); + } + } + this.pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber); + }; + } + }, + async run(config) { + await this.initialize(config); + const { + appConfig, + eventBus + } = this; + let file; + file = window.location.href; + if (!AppOptions.get("supportsDocumentFonts")) { + AppOptions.set("disableFontFace", true); + this.l10n.get("pdfjs-web-fonts-disabled").then(msg => { + console.warn(msg); + }); + } + const togglePrintingButtons = visible => { + appConfig.toolbar?.print?.classList.toggle("hidden", !visible); + appConfig.secondaryToolbar?.printButton.classList.toggle("hidden", !visible); + }; + if (!this.supportsPrinting) { + togglePrintingButtons(false); + } else { + eventBus.on("printingallowed", ({ + isAllowed + }) => togglePrintingButtons(isAllowed)); + } + if (!this.supportsFullscreen) { + appConfig.secondaryToolbar?.presentationModeButton.classList.add("hidden"); + } + if (this.supportsIntegratedFind) { + appConfig.findBar?.toggleButton?.classList.add("hidden"); + } + this.setTitleUsingUrl(file, file); + this.externalServices.initPassiveLoading(); + }, + get externalServices() { + return shadow(this, "externalServices", new ExternalServices()); + }, + get initialized() { + return this._initializedCapability.settled; + }, + get initializedPromise() { + return this._initializedCapability.promise; + }, + updateZoom(steps, scaleFactor, origin) { + if (this.pdfViewer.isInPresentationMode) { + return; + } + this.pdfViewer.updateScale({ + drawingDelay: AppOptions.get("defaultZoomDelay"), + steps, + scaleFactor, + origin + }); + }, + zoomIn() { + this.updateZoom(1); + }, + zoomOut() { + this.updateZoom(-1); + }, + zoomReset() { + if (this.pdfViewer.isInPresentationMode) { + return; + } + this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE; + }, + touchPinchCallback(origin, prevDistance, distance) { + if (this.supportsPinchToZoom) { + const newScaleFactor = this._accumulateFactor(this.pdfViewer.currentScale, distance / prevDistance, "_touchUnusedFactor"); + this.updateZoom(null, newScaleFactor, origin); + } else { + const PIXELS_PER_LINE_SCALE = 30; + const ticks = this._accumulateTicks((distance - prevDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks"); + this.updateZoom(ticks, null, origin); + } + }, + touchPinchEndCallback() { + this._touchUnusedTicks = 0; + this._touchUnusedFactor = 1; + }, + get pagesCount() { + return this.pdfDocument ? this.pdfDocument.numPages : 0; + }, + get page() { + return this.pdfViewer.currentPageNumber; + }, + set page(val) { + this.pdfViewer.currentPageNumber = val; + }, + get supportsPrinting() { + return shadow(this, "supportsPrinting", AppOptions.get("supportsPrinting") && PDFPrintServiceFactory.supportsPrinting); + }, + get supportsFullscreen() { + return shadow(this, "supportsFullscreen", document.fullscreenEnabled); + }, + get supportsPinchToZoom() { + return shadow(this, "supportsPinchToZoom", AppOptions.get("supportsPinchToZoom")); + }, + get supportsIntegratedFind() { + return shadow(this, "supportsIntegratedFind", AppOptions.get("supportsIntegratedFind")); + }, + get loadingBar() { + const barElement = document.getElementById("loadingBar"); + const bar = barElement ? new ProgressBar(barElement) : null; + return shadow(this, "loadingBar", bar); + }, + get supportsMouseWheelZoomCtrlKey() { + return shadow(this, "supportsMouseWheelZoomCtrlKey", AppOptions.get("supportsMouseWheelZoomCtrlKey")); + }, + get supportsMouseWheelZoomMetaKey() { + return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey")); + }, + get supportsCaretBrowsingMode() { + return AppOptions.get("supportsCaretBrowsingMode"); + }, + moveCaret(isUp, select) { + this._caretBrowsing ||= new CaretBrowsingMode(this._globalAbortController.signal, this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container); + this._caretBrowsing.moveCaret(isUp, select); + }, + setTitleUsingUrl(url = "", downloadUrl = null) { + this.url = url; + this.baseUrl = updateUrlHash(url, ""); + if (downloadUrl) { + this._downloadUrl = downloadUrl === url ? this.baseUrl : updateUrlHash(downloadUrl, ""); + } + if (isDataScheme(url)) { + this._hideViewBookmark(); + } else { + AppOptions.set("docBaseUrl", this.baseUrl); + } + let title = getPdfFilenameFromUrl(url, ""); + if (!title) { + try { + title = decodeURIComponent(getFilenameFromUrl(url)); + } catch {} + } + this.setTitle(title || url); + }, + setTitle(title = this._title) { + this._title = title; + if (this.isViewerEmbedded) { + return; + } + const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing; + document.title = `${editorIndicator ? "* " : ""}${title}`; + }, + get _docFilename() { + return this._contentDispositionFilename || getPdfFilenameFromUrl(this.url); + }, + get _docTitle() { + const { + documentInfo, + metadata + } = this; + const title = metadata?.get("dc:title"); + if (title) { + if (title !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(title)) { + return title; + } + } + return documentInfo.Title; + }, + _hideViewBookmark() { + const { + secondaryToolbar + } = this.appConfig; + secondaryToolbar?.viewBookmarkButton.classList.add("hidden"); + if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) { + document.getElementById("viewBookmarkSeparator")?.classList.add("hidden"); + } + }, + async close() { + this._unblockDocumentLoadEvent(); + this._hideViewBookmark(); + if (!this.pdfLoadingTask) { + return; + } + const promises = []; + promises.push(this.pdfLoadingTask.destroy()); + this.pdfLoadingTask = null; + if (this.pdfDocument) { + this.pdfDocument = null; + this.pdfThumbnailViewer?.setDocument(null); + this.pdfViewer.setDocument(null); + this.pdfLinkService.setDocument(null); + this.pdfDocumentProperties?.setDocument(null); + this.pdfTextExtractor?.setViewer(null); + } + this.pdfLinkService.externalLinkEnabled = true; + this.store = null; + this.isInitialViewSet = false; + this.url = ""; + this.baseUrl = ""; + this._downloadUrl = ""; + this.documentInfo = null; + this.metadata = null; + this._contentDispositionFilename = null; + this._contentLength = null; + this._saveInProgress = false; + this._hasAnnotationEditors = false; + promises.push(this.pdfScriptingManager.destroyPromise, this.passwordPrompt.close()); + this.setTitle(); + this.pdfSidebar?.reset(); + this.pdfOutlineViewer?.reset(); + this.pdfAttachmentViewer?.reset(); + this.pdfLayerViewer?.reset(); + this.pdfHistory?.reset(); + this.findBar?.reset(); + this.toolbar?.reset(); + this.secondaryToolbar?.reset(); + this._PDFBug?.cleanup(); + await Promise.all(promises); + }, + async open(args) { + if (this.pdfLoadingTask) { + await this.close(); + } + const workerParams = AppOptions.getAll(OptionKind.WORKER); + Object.assign(GlobalWorkerOptions, workerParams); + if (args.data && isPdfFile(args.filename)) { + this._contentDispositionFilename = args.filename; + } + const apiParams = AppOptions.getAll(OptionKind.API); + const loadingTask = getDocument({ + ...apiParams, + ...args + }); + this.pdfLoadingTask = loadingTask; + loadingTask.onPassword = (updateCallback, reason) => { + if (this.isViewerEmbedded) { + this._unblockDocumentLoadEvent(); + } + this.pdfLinkService.externalLinkEnabled = false; + this.passwordPrompt.setUpdateCallback(updateCallback, reason); + this.passwordPrompt.open(); + }; + loadingTask.onProgress = ({ + loaded, + total + }) => { + this.progress(loaded / total); + }; + return loadingTask.promise.then(pdfDocument => { + this.load(pdfDocument); + }, reason => { + if (loadingTask !== this.pdfLoadingTask) { + return undefined; + } + let key = "pdfjs-loading-error"; + if (reason instanceof InvalidPDFException) { + key = "pdfjs-invalid-file-error"; + } else if (reason instanceof ResponseException) { + key = reason.missing ? "pdfjs-missing-file-error" : "pdfjs-unexpected-response-error"; + } + return this._documentError(key, { + message: reason.message + }).then(() => { + throw reason; + }); + }); + }, + async download() { + let data; + try { + data = await (this.pdfDocument ? this.pdfDocument.getData() : this.pdfLoadingTask.getData()); + } catch {} + this.downloadManager.download(data, this._downloadUrl, this._docFilename); + }, + async save() { + if (this._saveInProgress) { + return; + } + this._saveInProgress = true; + await this.pdfScriptingManager.dispatchWillSave(); + try { + const data = await this.pdfDocument.saveDocument(); + this.downloadManager.download(data, this._downloadUrl, this._docFilename); + } catch (reason) { + console.error(`Error when saving the document:`, reason); + await this.download(); + } finally { + await this.pdfScriptingManager.dispatchDidSave(); + this._saveInProgress = false; + } + const editorStats = this.pdfDocument?.annotationStorage.editorStats; + if (editorStats) { + this.externalServices.reportTelemetry({ + type: "editing", + data: { + type: "save", + stats: editorStats + } + }); + } + }, + async downloadOrSave() { + const { + classList + } = this.appConfig.appContainer; + classList.add("wait"); + await (this.pdfDocument?.annotationStorage.size > 0 ? this.save() : this.download()); + classList.remove("wait"); + }, + async _documentError(key, moreInfo = null) { + this._unblockDocumentLoadEvent(); + const message = await this._otherError(key || "pdfjs-loading-error", moreInfo); + this.eventBus.dispatch("documenterror", { + source: this, + message, + reason: moreInfo?.message ?? null + }); + }, + async _otherError(key, moreInfo = null) { + const message = await this.l10n.get(key); + const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`]; + if (moreInfo) { + moreInfoText.push(`Message: ${moreInfo.message}`); + if (moreInfo.stack) { + moreInfoText.push(`Stack: ${moreInfo.stack}`); + } else { + if (moreInfo.filename) { + moreInfoText.push(`File: ${moreInfo.filename}`); + } + if (moreInfo.lineNumber) { + moreInfoText.push(`Line: ${moreInfo.lineNumber}`); + } + } + } + console.error(`${message}\n\n${moreInfoText.join("\n")}`); + return message; + }, + progress(level) { + const percent = Math.round(level * 100); + if (!this.loadingBar || percent <= this.loadingBar.percent) { + return; + } + this.loadingBar.percent = percent; + if (this.pdfDocument?.loadingParams.disableAutoFetch ?? AppOptions.get("disableAutoFetch")) { + this.loadingBar.setDisableAutoFetch(); + } + }, + load(pdfDocument) { + this.pdfDocument = pdfDocument; + this._printPermissionPromise = new Promise(resolve => { + this.eventBus.on("printingallowed", ({ + isAllowed + }) => { + if (!isAllowed) { + window.print = () => { + console.warn("Printing is not allowed."); + }; + } + resolve(isAllowed); + }, { + once: true + }); + }); + pdfDocument.getDownloadInfo().then(({ + length + }) => { + this._contentLength = length; + this.loadingBar?.hide(); + firstPagePromise.then(() => { + this.eventBus.dispatch("documentloaded", { + source: this + }); + }); + }); + const pageLayoutPromise = pdfDocument.getPageLayout().catch(() => {}); + const pageModePromise = pdfDocument.getPageMode().catch(() => {}); + const openActionPromise = pdfDocument.getOpenAction().catch(() => {}); + this.toolbar?.setPagesCount(pdfDocument.numPages, false); + this.secondaryToolbar?.setPagesCount(pdfDocument.numPages); + this.pdfLinkService.setDocument(pdfDocument); + this.pdfDocumentProperties?.setDocument(pdfDocument); + const pdfViewer = this.pdfViewer; + pdfViewer.setDocument(pdfDocument); + this.pdfTextExtractor.setViewer(pdfViewer); + const { + firstPagePromise, + onePageRendered, + pagesPromise + } = pdfViewer; + this.pdfThumbnailViewer?.setDocument(pdfDocument); + const storedPromise = (this.store = new ViewHistory(pdfDocument.fingerprints[0])).getMultiple({ + page: null, + zoom: DEFAULT_SCALE_VALUE, + scrollLeft: "0", + scrollTop: "0", + rotation: null, + sidebarView: SidebarView.UNKNOWN, + scrollMode: ScrollMode.UNKNOWN, + spreadMode: SpreadMode.UNKNOWN + }).catch(() => {}); + firstPagePromise.then(pdfPage => { + this.loadingBar?.setWidth(this.appConfig.viewerContainer); + this._initializeAnnotationStorageCallbacks(pdfDocument); + Promise.all([animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => { + const viewOnLoad = AppOptions.get("viewOnLoad"); + this._initializePdfHistory({ + fingerprint: pdfDocument.fingerprints[0], + viewOnLoad, + initialDest: openAction?.dest + }); + const initialBookmark = this.initialBookmark; + const zoom = AppOptions.get("defaultZoomValue"); + let hash = zoom ? `zoom=${zoom}` : null; + let rotation = null; + let sidebarView = AppOptions.get("sidebarViewOnLoad"); + let scrollMode = AppOptions.get("scrollModeOnLoad"); + let spreadMode = AppOptions.get("spreadModeOnLoad"); + if (stored?.page && viewOnLoad !== ViewOnLoad.INITIAL) { + hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`; + rotation = parseInt(stored.rotation, 10); + if (sidebarView === SidebarView.UNKNOWN) { + sidebarView = stored.sidebarView | 0; + } + if (scrollMode === ScrollMode.UNKNOWN) { + scrollMode = stored.scrollMode | 0; + } + if (spreadMode === SpreadMode.UNKNOWN) { + spreadMode = stored.spreadMode | 0; + } + } + if (pageMode && sidebarView === SidebarView.UNKNOWN) { + sidebarView = apiPageModeToSidebarView(pageMode); + } + if (pageLayout && scrollMode === ScrollMode.UNKNOWN && spreadMode === SpreadMode.UNKNOWN) { + const modes = apiPageLayoutToViewerModes(pageLayout); + spreadMode = modes.spreadMode; + } + this.setInitialView(hash, { + rotation, + sidebarView, + scrollMode, + spreadMode + }); + this.eventBus.dispatch("documentinit", { + source: this + }); + await Promise.race([pagesPromise, new Promise(resolve => { + setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); + })]); + if (!initialBookmark && !hash) { + return; + } + if (pdfViewer.hasEqualPageSizes) { + return; + } + this.initialBookmark = initialBookmark; + pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; + this.setInitialView(hash); + }).catch(() => { + this.setInitialView(); + }).then(function () { + pdfViewer.update(); + }); + }); + pagesPromise.then(() => { + this._unblockDocumentLoadEvent(); + this._initializeAutoPrint(pdfDocument, openActionPromise); + }, reason => { + this._documentError("pdfjs-loading-error", { + message: reason.message + }); + }); + onePageRendered.then(data => { + this.externalServices.reportTelemetry({ + type: "pageInfo", + timestamp: data.timestamp + }); + if (this.pdfOutlineViewer) { + pdfDocument.getOutline().then(outline => { + if (pdfDocument !== this.pdfDocument) { + return; + } + this.pdfOutlineViewer.render({ + outline, + pdfDocument + }); + }); + } + if (this.pdfAttachmentViewer) { + pdfDocument.getAttachments().then(attachments => { + if (pdfDocument !== this.pdfDocument) { + return; + } + this.pdfAttachmentViewer.render({ + attachments + }); + }); + } + if (this.pdfLayerViewer) { + pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => { + if (pdfDocument !== this.pdfDocument) { + return; + } + this.pdfLayerViewer.render({ + optionalContentConfig, + pdfDocument + }); + }); + } + }); + this._initializePageLabels(pdfDocument); + this._initializeMetadata(pdfDocument); + }, + async _scriptingDocProperties(pdfDocument) { + if (!this.documentInfo) { + await new Promise(resolve => { + this.eventBus._on("metadataloaded", resolve, { + once: true + }); + }); + if (pdfDocument !== this.pdfDocument) { + return null; + } + } + if (!this._contentLength) { + await new Promise(resolve => { + this.eventBus._on("documentloaded", resolve, { + once: true + }); + }); + if (pdfDocument !== this.pdfDocument) { + return null; + } + } + return { + ...this.documentInfo, + baseURL: this.baseUrl, + filesize: this._contentLength, + filename: this._docFilename, + metadata: this.metadata?.getRaw(), + authors: this.metadata?.get("dc:creator"), + numPages: this.pagesCount, + URL: this.url + }; + }, + async _initializeAutoPrint(pdfDocument, openActionPromise) { + const [openAction, jsActions] = await Promise.all([openActionPromise, this.pdfViewer.enableScripting ? null : pdfDocument.getJSActions()]); + if (pdfDocument !== this.pdfDocument) { + return; + } + let triggerAutoPrint = openAction?.action === "Print"; + if (jsActions) { + console.warn("Warning: JavaScript support is not enabled"); + for (const name in jsActions) { + if (triggerAutoPrint) { + break; + } + switch (name) { + case "WillClose": + case "WillSave": + case "DidSave": + case "WillPrint": + case "DidPrint": + continue; + } + triggerAutoPrint = jsActions[name].some(js => AutoPrintRegExp.test(js)); + } + } + if (triggerAutoPrint) { + this.triggerPrinting(); + } + }, + async _initializeMetadata(pdfDocument) { + const { + info, + metadata, + contentDispositionFilename, + contentLength, + hasStructTree + } = await pdfDocument.getMetadata(); + if (pdfDocument !== this.pdfDocument) { + return; + } + this.externalServices.reportTelemetry({ + type: "taggedPDF", + data: hasStructTree + }); + this.documentInfo = info; + this.metadata = metadata; + this._contentDispositionFilename ??= contentDispositionFilename; + this._contentLength ??= contentLength; + console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(metadata?.get("pdf:producer") || info.Producer || "-").trim()} / ` + `${(metadata?.get("xmp:creatortool") || info.Creator || "-").trim()}` + `] (PDF.js: ${version || "?"} [${build || "?"}])`); + const pdfTitle = this._docTitle; + if (pdfTitle) { + this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`); + } else if (this._contentDispositionFilename) { + this.setTitle(this._contentDispositionFilename); + } + if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) { + if (pdfDocument.loadingParams.enableXfa) { + console.warn("Warning: XFA Foreground documents are not supported"); + } else { + console.warn("Warning: XFA support is not enabled"); + } + } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) { + console.warn("Warning: Interactive form support is not enabled"); + } + if (info.IsSignaturesPresent) { + console.warn("Warning: Digital signatures validation is not supported"); + } + this.eventBus.dispatch("metadataloaded", { + source: this + }); + }, + async _initializePageLabels(pdfDocument) { + const labels = await pdfDocument.getPageLabels(); + if (pdfDocument !== this.pdfDocument) { + return; + } + if (!labels || AppOptions.get("disablePageLabels")) { + return; + } + const numLabels = labels.length; + let standardLabels = 0, + emptyLabels = 0; + for (let i = 0; i < numLabels; i++) { + const label = labels[i]; + if (label === (i + 1).toString()) { + standardLabels++; + } else if (label === "") { + emptyLabels++; + } else { + break; + } + } + if (standardLabels >= numLabels || emptyLabels >= numLabels) { + return; + } + const { + pdfViewer, + pdfThumbnailViewer, + toolbar + } = this; + pdfViewer.setPageLabels(labels); + pdfThumbnailViewer?.setPageLabels(labels); + toolbar?.setPagesCount(numLabels, true); + toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel); + }, + _initializePdfHistory({ + fingerprint, + viewOnLoad, + initialDest = null + }) { + if (!this.pdfHistory) { + return; + } + this.pdfHistory.initialize({ + fingerprint, + resetHistory: viewOnLoad === ViewOnLoad.INITIAL, + updateUrl: AppOptions.get("historyUpdateUrl") + }); + if (this.pdfHistory.initialBookmark) { + this.initialBookmark = this.pdfHistory.initialBookmark; + this.initialRotation = this.pdfHistory.initialRotation; + } + if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) { + this.initialBookmark = JSON.stringify(initialDest); + this.pdfHistory.push({ + explicitDest: initialDest, + pageNumber: null + }); + } + }, + _initializeAnnotationStorageCallbacks(pdfDocument) { + if (pdfDocument !== this.pdfDocument) { + return; + } + const { + annotationStorage + } = pdfDocument; + annotationStorage.onSetModified = () => { + window.addEventListener("beforeunload", beforeUnload); + }; + annotationStorage.onResetModified = () => { + window.removeEventListener("beforeunload", beforeUnload); + }; + annotationStorage.onAnnotationEditor = typeStr => { + this._hasAnnotationEditors = !!typeStr; + this.setTitle(); + }; + }, + setInitialView(storedHash, { + rotation, + sidebarView, + scrollMode, + spreadMode + } = {}) { + const setRotation = angle => { + if (isValidRotation(angle)) { + this.pdfViewer.pagesRotation = angle; + } + }; + const setViewerModes = (scroll, spread) => { + if (isValidScrollMode(scroll)) { + this.pdfViewer.scrollMode = scroll; + } + if (isValidSpreadMode(spread)) { + this.pdfViewer.spreadMode = spread; + } + }; + this.isInitialViewSet = true; + this.pdfSidebar?.setInitialView(sidebarView); + setViewerModes(scrollMode, spreadMode); + if (this.initialBookmark) { + setRotation(this.initialRotation); + delete this.initialRotation; + this.pdfLinkService.setHash(this.initialBookmark); + this.initialBookmark = null; + } else if (storedHash) { + setRotation(rotation); + this.pdfLinkService.setHash(storedHash); + } + this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel); + this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber); + if (!this.pdfViewer.currentScaleValue) { + this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE; + } + }, + _cleanup() { + if (!this.pdfDocument) { + return; + } + this.pdfViewer.cleanup(); + this.pdfThumbnailViewer?.cleanup(); + this.pdfDocument.cleanup(AppOptions.get("fontExtraProperties")); + }, + forceRendering() { + this.pdfRenderingQueue.printing = !!this.printService; + this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === SidebarView.THUMBS; + this.pdfRenderingQueue.renderHighestPriority(); + }, + beforePrint() { + this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => this.pdfDocument?.annotationStorage.print); + if (this.printService) { + return; + } + if (!this.supportsPrinting || !this.pdfViewer.printingAllowed) { + this._otherError("pdfjs-printing-not-supported"); + return; + } + if (!this.pdfViewer.pageViewsReady) { + this.l10n.get("pdfjs-printing-not-ready").then(msg => { + window.alert(msg); + }); + return; + } + this.printService = PDFPrintServiceFactory.createPrintService({ + pdfDocument: this.pdfDocument, + pagesOverview: this.pdfViewer.getPagesOverview(), + printContainer: this.appConfig.printContainer, + printResolution: AppOptions.get("printResolution"), + printAnnotationStoragePromise: this._printAnnotationStoragePromise + }); + this.forceRendering(); + this.setTitle(); + this.printService.layout(); + if (this._hasAnnotationEditors) { + this.externalServices.reportTelemetry({ + type: "editing", + data: { + type: "print", + stats: this.pdfDocument?.annotationStorage.editorStats + } + }); + } + }, + afterPrint() { + if (this._printAnnotationStoragePromise) { + this._printAnnotationStoragePromise.then(() => { + this.pdfScriptingManager.dispatchDidPrint(); + }); + this._printAnnotationStoragePromise = null; + } + if (this.printService) { + this.printService.destroy(); + this.printService = null; + this.pdfDocument?.annotationStorage.resetModified(); + } + this.forceRendering(); + this.setTitle(); + }, + rotatePages(delta) { + this.pdfViewer.pagesRotation += delta; + }, + requestPresentationMode() { + this.pdfPresentationMode?.request(); + }, + async triggerPrinting() { + if (this.supportsPrinting && (await this._printPermissionPromise)) { + window.print(); + } + }, + bindEvents() { + if (this._eventBusAbortController) { + return; + } + const ac = this._eventBusAbortController = new AbortController(); + const opts = { + signal: ac.signal + }; + const { + eventBus, + externalServices, + pdfDocumentProperties, + pdfViewer, + preferences + } = this; + eventBus._on("resize", onResize.bind(this), opts); + eventBus._on("hashchange", onHashchange.bind(this), opts); + eventBus._on("beforeprint", this.beforePrint.bind(this), opts); + eventBus._on("afterprint", this.afterPrint.bind(this), opts); + eventBus._on("pagerender", onPageRender.bind(this), opts); + eventBus._on("pagerendered", onPageRendered.bind(this), opts); + eventBus._on("updateviewarea", onUpdateViewarea.bind(this), opts); + eventBus._on("pagechanging", onPageChanging.bind(this), opts); + eventBus._on("scalechanging", onScaleChanging.bind(this), opts); + eventBus._on("rotationchanging", onRotationChanging.bind(this), opts); + eventBus._on("sidebarviewchanged", onSidebarViewChanged.bind(this), opts); + eventBus._on("pagemode", onPageMode.bind(this), opts); + eventBus._on("namedaction", onNamedAction.bind(this), opts); + eventBus._on("presentationmodechanged", evt => pdfViewer.presentationModeState = evt.state, opts); + eventBus._on("presentationmode", this.requestPresentationMode.bind(this), opts); + eventBus._on("switchannotationeditormode", evt => pdfViewer.annotationEditorMode = evt, opts); + eventBus._on("print", this.triggerPrinting.bind(this), opts); + eventBus._on("download", this.downloadOrSave.bind(this), opts); + eventBus._on("firstpage", () => this.page = 1, opts); + eventBus._on("lastpage", () => this.page = this.pagesCount, opts); + eventBus._on("nextpage", () => pdfViewer.nextPage(), opts); + eventBus._on("previouspage", () => pdfViewer.previousPage(), opts); + eventBus._on("zoomin", this.zoomIn.bind(this), opts); + eventBus._on("zoomout", this.zoomOut.bind(this), opts); + eventBus._on("zoomreset", this.zoomReset.bind(this), opts); + eventBus._on("pagenumberchanged", onPageNumberChanged.bind(this), opts); + eventBus._on("scalechanged", evt => pdfViewer.currentScaleValue = evt.value, opts); + eventBus._on("rotatecw", this.rotatePages.bind(this, 90), opts); + eventBus._on("rotateccw", this.rotatePages.bind(this, -90), opts); + eventBus._on("optionalcontentconfig", evt => pdfViewer.optionalContentConfigPromise = evt.promise, opts); + eventBus._on("switchscrollmode", evt => pdfViewer.scrollMode = evt.mode, opts); + eventBus._on("scrollmodechanged", onViewerModesChanged.bind(this, "scrollMode"), opts); + eventBus._on("switchspreadmode", evt => pdfViewer.spreadMode = evt.mode, opts); + eventBus._on("spreadmodechanged", onViewerModesChanged.bind(this, "spreadMode"), opts); + eventBus._on("imagealttextsettings", onImageAltTextSettings.bind(this), opts); + eventBus._on("documentproperties", () => pdfDocumentProperties?.open(), opts); + eventBus._on("findfromurlhash", onFindFromUrlHash.bind(this), opts); + eventBus._on("updatefindmatchescount", onUpdateFindMatchesCount.bind(this), opts); + eventBus._on("updatefindcontrolstate", onUpdateFindControlState.bind(this), opts); + eventBus._on("annotationeditorstateschanged", evt => externalServices.updateEditorStates(evt), opts); + eventBus._on("reporttelemetry", evt => externalServices.reportTelemetry(evt.details), opts); + eventBus._on("setpreference", evt => preferences.set(evt.name, evt.value), opts); + }, + bindWindowEvents() { + if (this._windowAbortController) { + return; + } + this._windowAbortController = new AbortController(); + const { + eventBus, + appConfig: { + mainContainer + }, + pdfViewer, + _windowAbortController: { + signal + } + } = this; + this._touchManager = new TouchManager({ + container: window, + isPinchingDisabled: () => pdfViewer.isInPresentationMode, + isPinchingStopped: () => this.overlayManager?.active, + onPinching: this.touchPinchCallback.bind(this), + onPinchEnd: this.touchPinchEndCallback.bind(this), + signal + }); + function addWindowResolutionChange(evt = null) { + if (evt) { + pdfViewer.refresh(); + } + const mediaQueryList = window.matchMedia(`(resolution: ${OutputScale.pixelRatio}dppx)`); + mediaQueryList.addEventListener("change", addWindowResolutionChange, { + once: true, + signal + }); + } + addWindowResolutionChange(); + window.addEventListener("wheel", onWheel.bind(this), { + passive: false, + signal + }); + window.addEventListener("click", onClick.bind(this), { + signal + }); + window.addEventListener("keydown", onKeyDown.bind(this), { + signal + }); + window.addEventListener("keyup", onKeyUp.bind(this), { + signal + }); + window.addEventListener("resize", () => eventBus.dispatch("resize", { + source: window + }), { + signal + }); + window.addEventListener("hashchange", () => { + eventBus.dispatch("hashchange", { + source: window, + hash: document.location.hash.substring(1) + }); + }, { + signal + }); + window.addEventListener("beforeprint", () => eventBus.dispatch("beforeprint", { + source: window + }), { + signal + }); + window.addEventListener("afterprint", () => eventBus.dispatch("afterprint", { + source: window + }), { + signal + }); + window.addEventListener("updatefromsandbox", evt => { + eventBus.dispatch("updatefromsandbox", { + source: window, + detail: evt.detail + }); + }, { + signal + }); + let scrollendTimeoutID, scrollAbortController; + const scrollend = () => { + clearTimeout(scrollendTimeoutID); + if (this._isScrolling) { + scrollAbortController.abort(); + scrollAbortController = null; + this._isScrolling = false; + } + }; + const scroll = () => { + if (this._isCtrlKeyDown) { + return; + } + if (!this._isScrolling) { + scrollAbortController = new AbortController(); + const abortSignal = AbortSignal.any([scrollAbortController.signal, signal]); + mainContainer.addEventListener("scrollend", scrollend, { + signal: abortSignal + }); + mainContainer.addEventListener("blur", scrollend, { + signal: abortSignal + }); + this._isScrolling = true; + } + clearTimeout(scrollendTimeoutID); + scrollendTimeoutID = setTimeout(scrollend, 100); + }; + mainContainer.addEventListener("scroll", scroll, { + passive: true, + signal + }); + }, + unbindEvents() { + this._eventBusAbortController?.abort(); + this._eventBusAbortController = null; + }, + unbindWindowEvents() { + this._windowAbortController?.abort(); + this._windowAbortController = null; + this._touchManager = null; + }, + async testingClose() { + this.unbindEvents(); + this.unbindWindowEvents(); + this._globalAbortController?.abort(); + this._globalAbortController = null; + this.findBar?.close(); + await Promise.all([this.l10n?.destroy(), this.close()]); + }, + _accumulateTicks(ticks, prop) { + if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) { + this[prop] = 0; + } + this[prop] += ticks; + const wholeTicks = Math.trunc(this[prop]); + this[prop] -= wholeTicks; + return wholeTicks; + }, + _accumulateFactor(previousScale, factor, prop) { + if (factor === 1) { + return 1; + } + if (this[prop] > 1 && factor < 1 || this[prop] < 1 && factor > 1) { + this[prop] = 1; + } + const newFactor = Math.floor(previousScale * factor * this[prop] * 100) / (100 * previousScale); + this[prop] = factor / newFactor; + return newFactor; + }, + _unblockDocumentLoadEvent() { + document.blockUnblockOnload?.(false); + this._unblockDocumentLoadEvent = () => {}; + }, + get scriptingReady() { + return this.pdfScriptingManager.ready; + } +}; +initCom(PDFViewerApplication); +function onPageRender({ + pageNumber +}) { + if (pageNumber === this.page) { + this.toolbar?.updateLoadingIndicatorState(true); + } +} +function onPageRendered({ + pageNumber, + isDetailView, + error +}) { + if (pageNumber === this.page) { + this.toolbar?.updateLoadingIndicatorState(false); + } + if (!isDetailView && this.pdfSidebar?.visibleView === SidebarView.THUMBS) { + const pageView = this.pdfViewer.getPageView(pageNumber - 1); + const thumbnailView = this.pdfThumbnailViewer?.getThumbnail(pageNumber - 1); + if (pageView) { + thumbnailView?.setImage(pageView); + } + } + if (error) { + this._otherError("pdfjs-rendering-error", error); + } +} +function onPageMode({ + mode +}) { + let view; + switch (mode) { + case "thumbs": + view = SidebarView.THUMBS; + break; + case "bookmarks": + case "outline": + view = SidebarView.OUTLINE; + break; + case "attachments": + view = SidebarView.ATTACHMENTS; + break; + case "layers": + view = SidebarView.LAYERS; + break; + case "none": + view = SidebarView.NONE; + break; + default: + console.error('Invalid "pagemode" hash parameter: ' + mode); + return; + } + this.pdfSidebar?.switchView(view, true); +} +function onNamedAction(evt) { + switch (evt.action) { + case "GoToPage": + this.appConfig.toolbar?.pageNumber.select(); + break; + case "Find": + if (!this.supportsIntegratedFind) { + this.findBar?.toggle(); + } + break; + case "Print": + this.triggerPrinting(); + break; + case "SaveAs": + this.downloadOrSave(); + break; + } +} +function onSidebarViewChanged({ + view +}) { + this.pdfRenderingQueue.isThumbnailViewEnabled = view === SidebarView.THUMBS; + if (this.isInitialViewSet) { + this.store?.set("sidebarView", view).catch(() => {}); + } +} +function onUpdateViewarea({ + location +}) { + if (this.isInitialViewSet) { + this.store?.setMultiple({ + page: location.pageNumber, + zoom: location.scale, + scrollLeft: location.left, + scrollTop: location.top, + rotation: location.rotation + }).catch(() => {}); + } + if (this.appConfig.secondaryToolbar) { + this.appConfig.secondaryToolbar.viewBookmarkButton.href = this.pdfLinkService.getAnchorUrl(location.pdfOpenParams); + } +} +function onViewerModesChanged(name, evt) { + if (this.isInitialViewSet && !this.pdfViewer.isInPresentationMode) { + this.store?.set(name, evt.mode).catch(() => {}); + } +} +function onResize() { + const { + pdfDocument, + pdfViewer, + pdfRenderingQueue + } = this; + if (pdfRenderingQueue.printing && window.matchMedia("print").matches) { + return; + } + if (!pdfDocument) { + return; + } + const currentScaleValue = pdfViewer.currentScaleValue; + if (currentScaleValue === "auto" || currentScaleValue === "page-fit" || currentScaleValue === "page-width") { + pdfViewer.currentScaleValue = currentScaleValue; + } + pdfViewer.update(); +} +function onHashchange(evt) { + const hash = evt.hash; + if (!hash) { + return; + } + if (!this.isInitialViewSet) { + this.initialBookmark = hash; + } else if (!this.pdfHistory?.popStateInProgress) { + this.pdfLinkService.setHash(hash); + } +} +function onPageNumberChanged(evt) { + const { + pdfViewer + } = this; + if (evt.value !== "") { + this.pdfLinkService.goToPage(evt.value); + } + if (evt.value !== pdfViewer.currentPageNumber.toString() && evt.value !== pdfViewer.currentPageLabel) { + this.toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel); + } +} +function onImageAltTextSettings() { + this.imageAltTextSettings?.open({ + enableGuessAltText: AppOptions.get("enableGuessAltText"), + enableNewAltTextWhenAddingImage: AppOptions.get("enableNewAltTextWhenAddingImage") + }); +} +function onFindFromUrlHash(evt) { + this.eventBus.dispatch("find", { + source: evt.source, + type: "", + query: evt.query, + caseSensitive: false, + entireWord: false, + highlightAll: true, + findPrevious: false, + matchDiacritics: true + }); +} +function onUpdateFindMatchesCount({ + matchesCount +}) { + if (this.supportsIntegratedFind) { + this.externalServices.updateFindMatchesCount(matchesCount); + } else { + this.findBar?.updateResultsCount(matchesCount); + } +} +function onUpdateFindControlState({ + state, + previous, + entireWord, + matchesCount, + rawQuery +}) { + if (this.supportsIntegratedFind) { + this.externalServices.updateFindControlState({ + result: state, + findPrevious: previous, + entireWord, + matchesCount, + rawQuery + }); + } else { + this.findBar?.updateUIState(state, previous, matchesCount); + } +} +function onScaleChanging(evt) { + this.toolbar?.setPageScale(evt.presetValue, evt.scale); + this.pdfViewer.update(); +} +function onRotationChanging(evt) { + if (this.pdfThumbnailViewer) { + this.pdfThumbnailViewer.pagesRotation = evt.pagesRotation; + } + this.forceRendering(); + this.pdfViewer.currentPageNumber = evt.pageNumber; +} +function onPageChanging({ + pageNumber, + pageLabel +}) { + this.toolbar?.setPageNumber(pageNumber, pageLabel); + this.secondaryToolbar?.setPageNumber(pageNumber); + if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) { + this.pdfThumbnailViewer?.scrollThumbnailIntoView(pageNumber); + } + const currentPage = this.pdfViewer.getPageView(pageNumber - 1); + this.toolbar?.updateLoadingIndicatorState(currentPage?.renderingState === RenderingStates.RUNNING); +} +function onWheel(evt) { + const { + pdfViewer, + supportsMouseWheelZoomCtrlKey, + supportsMouseWheelZoomMetaKey, + supportsPinchToZoom + } = this; + if (pdfViewer.isInPresentationMode) { + return; + } + const deltaMode = evt.deltaMode; + let scaleFactor = Math.exp(-evt.deltaY / 100); + const isBuiltInMac = FeatureTest.platform.isMac; + const isPinchToZoom = evt.ctrlKey && !this._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0; + const origin = [evt.clientX, evt.clientY]; + if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) { + evt.preventDefault(); + if (this._isScrolling || document.visibilityState === "hidden" || this.overlayManager.active) { + return; + } + if (isPinchToZoom && supportsPinchToZoom) { + scaleFactor = this._accumulateFactor(pdfViewer.currentScale, scaleFactor, "_wheelUnusedFactor"); + this.updateZoom(null, scaleFactor, origin); + } else { + const delta = normalizeWheelEventDirection(evt); + let ticks = 0; + if (deltaMode === WheelEvent.DOM_DELTA_LINE || deltaMode === WheelEvent.DOM_DELTA_PAGE) { + ticks = Math.abs(delta) >= 1 ? Math.sign(delta) : this._accumulateTicks(delta, "_wheelUnusedTicks"); + } else { + const PIXELS_PER_LINE_SCALE = 30; + ticks = this._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks"); + } + this.updateZoom(ticks, null, origin); + } + } +} +function closeSecondaryToolbar({ + target +}) { + if (!this.secondaryToolbar?.isOpen) { + return; + } + const { + toolbar, + secondaryToolbar + } = this.appConfig; + if (this.pdfViewer.containsElement(target) || toolbar?.container.contains(target) && !secondaryToolbar?.toolbar.contains(target) && !secondaryToolbar?.toggleButton.contains(target)) { + this.secondaryToolbar.close(); + } +} +function closeEditorUndoBar(evt) { + if (!this.editorUndoBar?.isOpen) { + return; + } + if (this.appConfig.secondaryToolbar?.toolbar.contains(evt.target)) { + this.editorUndoBar.hide(); + } +} +function onClick(evt) { + closeSecondaryToolbar.call(this, evt); + closeEditorUndoBar.call(this, evt); +} +function onKeyUp(evt) { + if (evt.key === "Control") { + this._isCtrlKeyDown = false; + } +} +function onKeyDown(evt) { + this._isCtrlKeyDown = evt.key === "Control"; + if (this.editorUndoBar?.isOpen && evt.keyCode !== 9 && evt.keyCode !== 16 && !((evt.keyCode === 13 || evt.keyCode === 32) && getActiveOrFocusedElement() === this.appConfig.editorUndoBar.undoButton)) { + this.editorUndoBar.hide(); + } + if (this.overlayManager.active) { + return; + } + const { + eventBus, + pdfViewer + } = this; + const isViewerInPresentationMode = pdfViewer.isInPresentationMode; + let handled = false, + ensureViewerFocused = false; + const cmd = (evt.ctrlKey ? 1 : 0) | (evt.altKey ? 2 : 0) | (evt.shiftKey ? 4 : 0) | (evt.metaKey ? 8 : 0); + if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) { + switch (evt.keyCode) { + case 70: + if (!this.supportsIntegratedFind && !evt.shiftKey) { + this.findBar?.open(); + handled = true; + } + break; + case 71: + if (!this.supportsIntegratedFind) { + const { + state + } = this.findController; + if (state) { + const newState = { + source: window, + type: "again", + findPrevious: cmd === 5 || cmd === 12 + }; + eventBus.dispatch("find", { + ...state, + ...newState + }); + } + handled = true; + } + break; + case 61: + case 107: + case 187: + case 171: + this.zoomIn(); + handled = true; + break; + case 173: + case 109: + case 189: + this.zoomOut(); + handled = true; + break; + case 48: + case 96: + if (!isViewerInPresentationMode) { + setTimeout(() => { + this.zoomReset(); + }); + handled = false; + } + break; + case 38: + if (isViewerInPresentationMode || this.page > 1) { + this.page = 1; + handled = true; + ensureViewerFocused = true; + } + break; + case 40: + if (isViewerInPresentationMode || this.page < this.pagesCount) { + this.page = this.pagesCount; + handled = true; + ensureViewerFocused = true; + } + break; + } + } + if (cmd === 3 || cmd === 10) { + switch (evt.keyCode) { + case 80: + this.requestPresentationMode(); + handled = true; + this.externalServices.reportTelemetry({ + type: "buttons", + data: { + id: "presentationModeKeyboard" + } + }); + break; + case 71: + if (this.appConfig.toolbar) { + this.appConfig.toolbar.pageNumber.select(); + handled = true; + } + break; + } + } + if (handled) { + if (ensureViewerFocused && !isViewerInPresentationMode) { + pdfViewer.focus(); + } + evt.preventDefault(); + return; + } + const curElement = getActiveOrFocusedElement(); + const curElementTagName = curElement?.tagName.toUpperCase(); + if (curElementTagName === "INPUT" || curElementTagName === "TEXTAREA" || curElementTagName === "SELECT" || curElementTagName === "BUTTON" && evt.keyCode === 32 || curElement?.isContentEditable) { + if (evt.keyCode !== 27) { + return; + } + } + if (cmd === 0) { + let turnPage = 0, + turnOnlyIfPageFit = false; + switch (evt.keyCode) { + case 38: + if (this.supportsCaretBrowsingMode) { + this.moveCaret(true, false); + handled = true; + break; + } + case 33: + if (pdfViewer.isVerticalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + turnPage = -1; + break; + case 8: + if (!isViewerInPresentationMode) { + turnOnlyIfPageFit = true; + } + turnPage = -1; + break; + case 37: + if (this.supportsCaretBrowsingMode) { + return; + } + if (pdfViewer.isHorizontalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + case 75: + case 80: + turnPage = -1; + break; + case 27: + if (this.secondaryToolbar?.isOpen) { + this.secondaryToolbar.close(); + handled = true; + } + if (!this.supportsIntegratedFind && this.findBar?.opened) { + this.findBar.close(); + handled = true; + } + break; + case 40: + if (this.supportsCaretBrowsingMode) { + this.moveCaret(false, false); + handled = true; + break; + } + case 34: + if (pdfViewer.isVerticalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + turnPage = 1; + break; + case 32: + if (!isViewerInPresentationMode) { + turnOnlyIfPageFit = true; + } + turnPage = 1; + break; + case 39: + if (this.supportsCaretBrowsingMode) { + return; + } + if (pdfViewer.isHorizontalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + case 74: + case 78: + turnPage = 1; + break; + case 36: + if (isViewerInPresentationMode || this.page > 1) { + this.page = 1; + handled = true; + ensureViewerFocused = true; + } + break; + case 35: + if (isViewerInPresentationMode || this.page < this.pagesCount) { + this.page = this.pagesCount; + handled = true; + ensureViewerFocused = true; + } + break; + case 83: + this.pdfCursorTools?.switchTool(CursorTool.SELECT); + break; + case 72: + this.pdfCursorTools?.switchTool(CursorTool.HAND); + break; + case 82: + this.rotatePages(90); + break; + case 115: + this.pdfSidebar?.toggle(); + break; + } + if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === "page-fit")) { + if (turnPage > 0) { + pdfViewer.nextPage(); + } else { + pdfViewer.previousPage(); + } + handled = true; + } + } + if (cmd === 4) { + switch (evt.keyCode) { + case 32: + if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== "page-fit") { + break; + } + pdfViewer.previousPage(); + handled = true; + break; + case 38: + this.moveCaret(true, true); + handled = true; + break; + case 40: + this.moveCaret(false, true); + handled = true; + break; + case 82: + this.rotatePages(-90); + break; + } + } + if (!handled && !isViewerInPresentationMode) { + if (evt.keyCode >= 33 && evt.keyCode <= 40 || evt.keyCode === 32 && curElementTagName !== "BUTTON") { + ensureViewerFocused = true; + } + } + if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) { + pdfViewer.focus(); + } + if (handled) { + evt.preventDefault(); + } +} +function beforeUnload(evt) { + evt.preventDefault(); + evt.returnValue = ""; + return false; +} + +;// ./web/viewer.js + + + + +const AppConstants = null; +window.PDFViewerApplication = PDFViewerApplication; +window.PDFViewerApplicationConstants = AppConstants; +window.PDFViewerApplicationOptions = AppOptions; +function getViewerConfiguration() { + return { + appContainer: document.body, + principalContainer: document.getElementById("mainContainer"), + mainContainer: document.getElementById("viewerContainer"), + viewerContainer: document.getElementById("viewer"), + viewerAlert: document.getElementById("viewer-alert"), + toolbar: { + container: document.getElementById("toolbarContainer"), + numPages: document.getElementById("numPages"), + pageNumber: document.getElementById("pageNumber"), + scaleSelect: document.getElementById("scaleSelect"), + customScaleOption: document.getElementById("customScaleOption"), + previous: document.getElementById("previous"), + next: document.getElementById("next"), + zoomIn: document.getElementById("zoomInButton"), + zoomOut: document.getElementById("zoomOutButton"), + print: document.getElementById("printButton"), + editorCommentButton: document.getElementById("editorCommentButton"), + editorCommentParamsToolbar: document.getElementById("editorCommentParamsToolbar"), + editorFreeTextButton: document.getElementById("editorFreeTextButton"), + editorFreeTextParamsToolbar: document.getElementById("editorFreeTextParamsToolbar"), + editorHighlightButton: document.getElementById("editorHighlightButton"), + editorHighlightParamsToolbar: document.getElementById("editorHighlightParamsToolbar"), + editorHighlightColorPicker: document.getElementById("editorHighlightColorPicker"), + editorInkButton: document.getElementById("editorInkButton"), + editorInkParamsToolbar: document.getElementById("editorInkParamsToolbar"), + editorStampButton: document.getElementById("editorStampButton"), + editorStampParamsToolbar: document.getElementById("editorStampParamsToolbar"), + editorSignatureButton: document.getElementById("editorSignatureButton"), + editorSignatureParamsToolbar: document.getElementById("editorSignatureParamsToolbar"), + download: document.getElementById("downloadButton") + }, + secondaryToolbar: { + toolbar: document.getElementById("secondaryToolbar"), + toggleButton: document.getElementById("secondaryToolbarToggleButton"), + presentationModeButton: document.getElementById("presentationMode"), + openFileButton: null, + printButton: document.getElementById("secondaryPrint"), + downloadButton: document.getElementById("secondaryDownload"), + viewBookmarkButton: document.getElementById("viewBookmark"), + firstPageButton: document.getElementById("firstPage"), + lastPageButton: document.getElementById("lastPage"), + pageRotateCwButton: document.getElementById("pageRotateCw"), + pageRotateCcwButton: document.getElementById("pageRotateCcw"), + cursorSelectToolButton: document.getElementById("cursorSelectTool"), + cursorHandToolButton: document.getElementById("cursorHandTool"), + scrollPageButton: document.getElementById("scrollPage"), + scrollVerticalButton: document.getElementById("scrollVertical"), + scrollHorizontalButton: document.getElementById("scrollHorizontal"), + scrollWrappedButton: document.getElementById("scrollWrapped"), + spreadNoneButton: document.getElementById("spreadNone"), + spreadOddButton: document.getElementById("spreadOdd"), + spreadEvenButton: document.getElementById("spreadEven"), + imageAltTextSettingsButton: document.getElementById("imageAltTextSettings"), + imageAltTextSettingsSeparator: document.getElementById("imageAltTextSettingsSeparator"), + documentPropertiesButton: document.getElementById("documentProperties") + }, + sidebar: { + outerContainer: document.getElementById("outerContainer"), + sidebarContainer: document.getElementById("sidebarContainer"), + toggleButton: document.getElementById("sidebarToggleButton"), + resizer: document.getElementById("sidebarResizer"), + thumbnailButton: document.getElementById("viewThumbnail"), + outlineButton: document.getElementById("viewOutline"), + attachmentsButton: document.getElementById("viewAttachments"), + layersButton: document.getElementById("viewLayers"), + thumbnailView: document.getElementById("thumbnailView"), + outlineView: document.getElementById("outlineView"), + attachmentsView: document.getElementById("attachmentsView"), + layersView: document.getElementById("layersView"), + currentOutlineItemButton: document.getElementById("currentOutlineItem") + }, + findBar: { + bar: document.getElementById("findbar"), + toggleButton: document.getElementById("viewFindButton"), + findField: document.getElementById("findInput"), + highlightAllCheckbox: document.getElementById("findHighlightAll"), + caseSensitiveCheckbox: document.getElementById("findMatchCase"), + matchDiacriticsCheckbox: document.getElementById("findMatchDiacritics"), + entireWordCheckbox: document.getElementById("findEntireWord"), + findMsg: document.getElementById("findMsg"), + findResultsCount: document.getElementById("findResultsCount"), + findPreviousButton: document.getElementById("findPreviousButton"), + findNextButton: document.getElementById("findNextButton") + }, + passwordOverlay: { + dialog: document.getElementById("passwordDialog"), + label: document.getElementById("passwordText"), + input: document.getElementById("password"), + submitButton: document.getElementById("passwordSubmit"), + cancelButton: document.getElementById("passwordCancel") + }, + documentProperties: { + dialog: document.getElementById("documentPropertiesDialog"), + closeButton: document.getElementById("documentPropertiesClose"), + fields: { + fileName: document.getElementById("fileNameField"), + fileSize: document.getElementById("fileSizeField"), + title: document.getElementById("titleField"), + author: document.getElementById("authorField"), + subject: document.getElementById("subjectField"), + keywords: document.getElementById("keywordsField"), + creationDate: document.getElementById("creationDateField"), + modificationDate: document.getElementById("modificationDateField"), + creator: document.getElementById("creatorField"), + producer: document.getElementById("producerField"), + version: document.getElementById("versionField"), + pageCount: document.getElementById("pageCountField"), + pageSize: document.getElementById("pageSizeField"), + linearized: document.getElementById("linearizedField") + } + }, + altTextDialog: { + dialog: document.getElementById("altTextDialog"), + optionDescription: document.getElementById("descriptionButton"), + optionDecorative: document.getElementById("decorativeButton"), + textarea: document.getElementById("descriptionTextarea"), + cancelButton: document.getElementById("altTextCancel"), + saveButton: document.getElementById("altTextSave") + }, + newAltTextDialog: { + dialog: document.getElementById("newAltTextDialog"), + title: document.getElementById("newAltTextTitle"), + descriptionContainer: document.getElementById("newAltTextDescriptionContainer"), + textarea: document.getElementById("newAltTextDescriptionTextarea"), + disclaimer: document.getElementById("newAltTextDisclaimer"), + learnMore: document.getElementById("newAltTextLearnMore"), + imagePreview: document.getElementById("newAltTextImagePreview"), + createAutomatically: document.getElementById("newAltTextCreateAutomatically"), + createAutomaticallyButton: document.getElementById("newAltTextCreateAutomaticallyButton"), + downloadModel: document.getElementById("newAltTextDownloadModel"), + downloadModelDescription: document.getElementById("newAltTextDownloadModelDescription"), + error: document.getElementById("newAltTextError"), + errorCloseButton: document.getElementById("newAltTextCloseButton"), + cancelButton: document.getElementById("newAltTextCancel"), + notNowButton: document.getElementById("newAltTextNotNow"), + saveButton: document.getElementById("newAltTextSave") + }, + altTextSettingsDialog: { + dialog: document.getElementById("altTextSettingsDialog"), + createModelButton: document.getElementById("createModelButton"), + aiModelSettings: document.getElementById("aiModelSettings"), + learnMore: document.getElementById("altTextSettingsLearnMore"), + deleteModelButton: document.getElementById("deleteModelButton"), + downloadModelButton: document.getElementById("downloadModelButton"), + showAltTextDialogButton: document.getElementById("showAltTextDialogButton"), + altTextSettingsCloseButton: document.getElementById("altTextSettingsCloseButton"), + closeButton: document.getElementById("altTextSettingsCloseButton") + }, + addSignatureDialog: { + dialog: document.getElementById("addSignatureDialog"), + panels: document.getElementById("addSignatureActionContainer"), + typeButton: document.getElementById("addSignatureTypeButton"), + typeInput: document.getElementById("addSignatureTypeInput"), + drawButton: document.getElementById("addSignatureDrawButton"), + drawSVG: document.getElementById("addSignatureDraw"), + drawPlaceholder: document.getElementById("addSignatureDrawPlaceholder"), + drawThickness: document.getElementById("addSignatureDrawThickness"), + imageButton: document.getElementById("addSignatureImageButton"), + imageSVG: document.getElementById("addSignatureImage"), + imagePlaceholder: document.getElementById("addSignatureImagePlaceholder"), + imagePicker: document.getElementById("addSignatureFilePicker"), + imagePickerLink: document.getElementById("addSignatureImageBrowse"), + description: document.getElementById("addSignatureDescription"), + clearButton: document.getElementById("clearSignatureButton"), + saveContainer: document.getElementById("addSignatureSaveContainer"), + saveCheckbox: document.getElementById("addSignatureSaveCheckbox"), + errorBar: document.getElementById("addSignatureError"), + errorTitle: document.getElementById("addSignatureErrorTitle"), + errorDescription: document.getElementById("addSignatureErrorDescription"), + errorCloseButton: document.getElementById("addSignatureErrorCloseButton"), + cancelButton: document.getElementById("addSignatureCancelButton"), + addButton: document.getElementById("addSignatureAddButton") + }, + editSignatureDialog: { + dialog: document.getElementById("editSignatureDescriptionDialog"), + description: document.getElementById("editSignatureDescription"), + editSignatureView: document.getElementById("editSignatureView"), + cancelButton: document.getElementById("editSignatureCancelButton"), + updateButton: document.getElementById("editSignatureUpdateButton") + }, + annotationEditorParams: { + editorCommentsSidebar: document.getElementById("editorCommentsSidebar"), + editorCommentsSidebarCount: document.getElementById("editorCommentsSidebarCount"), + editorCommentsSidebarTitle: document.getElementById("editorCommentsSidebarTitle"), + editorCommentsSidebarCloseButton: document.getElementById("editorCommentsSidebarCloseButton"), + editorCommentsSidebarList: document.getElementById("editorCommentsSidebarList"), + editorCommentsSidebarResizer: document.getElementById("editorCommentsSidebarResizer"), + editorFreeTextFontSize: document.getElementById("editorFreeTextFontSize"), + editorFreeTextColor: document.getElementById("editorFreeTextColor"), + editorInkColor: document.getElementById("editorInkColor"), + editorInkThickness: document.getElementById("editorInkThickness"), + editorInkOpacity: document.getElementById("editorInkOpacity"), + editorStampAddImage: document.getElementById("editorStampAddImage"), + editorSignatureAddSignature: document.getElementById("editorSignatureAddSignature"), + editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"), + editorHighlightShowAll: document.getElementById("editorHighlightShowAll") + }, + printContainer: document.getElementById("printContainer"), + editorUndoBar: { + container: document.getElementById("editorUndoBar"), + message: document.getElementById("editorUndoBarMessage"), + undoButton: document.getElementById("editorUndoBarUndoButton"), + closeButton: document.getElementById("editorUndoBarCloseButton") + }, + editCommentDialog: { + dialog: document.getElementById("commentManagerDialog"), + toolbar: document.getElementById("commentManagerToolbar"), + title: document.getElementById("commentManagerTitle"), + textInput: document.getElementById("commentManagerTextInput"), + cancelButton: document.getElementById("commentManagerCancelButton"), + saveButton: document.getElementById("commentManagerSaveButton") + } + }; +} +function webViewerLoad() { + const config = getViewerConfiguration(); + PDFViewerApplication.run(config); +} +document.blockUnblockOnload?.(true); +if (document.readyState === "interactive" || document.readyState === "complete") { + webViewerLoad(); +} else { + document.addEventListener("DOMContentLoaded", webViewerLoad, true); +} + +export { PDFViewerApplication, AppConstants as PDFViewerApplicationConstants, AppOptions as PDFViewerApplicationOptions }; diff --git a/web-vitals/base/metric.ts b/web-vitals/base/metric.ts new file mode 100644 index 0000000..2b4162e --- /dev/null +++ b/web-vitals/base/metric.ts @@ -0,0 +1,11 @@ +export abstract class BaseMetric { + value: number + entries: EntryType[] + + constructor(value: number, entries: EntryType[]) { + this.value = value + this.entries = entries + } + + abstract get attribution(): AttributionType +} diff --git a/web-vitals/base/observer.ts b/web-vitals/base/observer.ts new file mode 100644 index 0000000..aaa9596 --- /dev/null +++ b/web-vitals/base/observer.ts @@ -0,0 +1,66 @@ +import {ssrSafeDocument} from '@github-ui/ssr-utils' +import type {BaseProcessor} from './processor' +import type {BaseMetric} from './metric' + +type ObserverCallback = (metric: MetricType, opts: {url?: string}) => void + +/* + * The CLSObserver is responsible for listening to Performance events and routing them to the entryProcessor. + * It also manages resetting CLS and reporting it when navigating or hiding a page. + */ +export abstract class BaseObserver, EntryType> { + cb: ObserverCallback + entryProcessor: BaseProcessor + observer?: PerformanceObserver + url?: string + + constructor(cb: ObserverCallback) { + this.cb = cb + this.entryProcessor = this.initializeProcessor() + this.setupListeners() + } + + abstract initializeProcessor(): BaseProcessor + abstract get supported(): boolean + abstract get softNavEventToListen(): string + + setupListeners() { + if (!this.supported) return + + const onHiddenOrPageHide = (event: Event) => { + if (event.type === 'pagehide' || document.visibilityState === 'hidden') { + this.report() + } + } + + // Similar to web-vitals, we report the current CLS when hard navigating or + // when the page is hidden + ssrSafeDocument?.addEventListener('visibilitychange', onHiddenOrPageHide, true) + ssrSafeDocument?.addEventListener('pagehide', onHiddenOrPageHide, true) + + ssrSafeDocument?.addEventListener(this.softNavEventToListen, () => { + this.report() + this.reset() + }) + } + + abstract observe(initialLoad: boolean): void + + report() { + if (!this.entryProcessor.metric || this.entryProcessor.metric.value < 0) return + + this.cb(this.entryProcessor.metric, {url: this.url}) + } + + teardown() { + this.observer?.takeRecords() + this.observer?.disconnect() + } + + reset() { + this.teardown() + this.entryProcessor.teardown() + this.entryProcessor = this.initializeProcessor() + this.observe(false) + } +} diff --git a/web-vitals/base/processor.ts b/web-vitals/base/processor.ts new file mode 100644 index 0000000..7160e42 --- /dev/null +++ b/web-vitals/base/processor.ts @@ -0,0 +1,6 @@ +export abstract class BaseProcessor { + abstract processEntries(entries: EntryType[]): void + abstract get metric(): MetricType | null + + teardown() {} +} diff --git a/web-vitals/cls/layout-shift-processor.ts b/web-vitals/cls/layout-shift-processor.ts new file mode 100644 index 0000000..bd734f5 --- /dev/null +++ b/web-vitals/cls/layout-shift-processor.ts @@ -0,0 +1,65 @@ +import {BaseProcessor} from '../base/processor' +import {getSelector} from '../get-selector' +import {CLSMetric, getLargestLayoutShiftSource} from './metric' + +// From https://github.com/GoogleChrome/web-vitals/blob/1b872cf5f2159e8ace0e98d55d8eb54fb09adfbe/src/lib/LayoutShiftManager.ts#L17 +// with a few modifications to fit our needs. +export class LayoutShiftProcessor extends BaseProcessor { + sessionValue = 0 + sessionEntries: LayoutShift[] = [] + layoutShiftTargetMap: Map = new Map() + + get metric() { + // Pages without entries report CLS = 0 + if (this.sessionEntries.length === 0) { + return new CLSMetric(0, [], new Map()) + } + + return new CLSMetric(this.sessionValue, this.sessionEntries, this.layoutShiftTargetMap) + } + + processEntries(entries: LayoutShift[]) { + for (const entry of entries) { + this.processEntry(entry) + } + } + + processEntry(entry: LayoutShift) { + // Only count layout shifts without recent user input. + if (entry.hadRecentInput) return + + const firstSessionEntry = this.sessionEntries[0] + const lastSessionEntry = this.sessionEntries.at(-1) + + // If the entry occurred less than 1 second after the previous entry + // and less than 5 seconds after the first entry in the session, + // include the entry in the current session. Otherwise, start a new + // session. + if ( + this.sessionValue && + firstSessionEntry && + lastSessionEntry && + entry.startTime - lastSessionEntry.startTime < 1000 && + entry.startTime - firstSessionEntry.startTime < 5000 + ) { + this.sessionValue += entry.value + this.sessionEntries.push(entry) + } else { + this.sessionValue = entry.value + this.sessionEntries = [entry] + } + + this.setLargestShiftSource(entry) + } + + setLargestShiftSource(entry: LayoutShift) { + if (entry?.sources?.length) { + const largestSource = getLargestLayoutShiftSource(entry.sources) + const node = largestSource?.node + if (node) { + const customTarget = getSelector(node) + this.layoutShiftTargetMap.set(largestSource, customTarget) + } + } + } +} diff --git a/web-vitals/cls/metric.ts b/web-vitals/cls/metric.ts new file mode 100644 index 0000000..564e494 --- /dev/null +++ b/web-vitals/cls/metric.ts @@ -0,0 +1,40 @@ +import {BaseMetric} from '../base/metric' + +export interface CLSAttribution { + largestShiftTarget?: string +} + +const getLargestLayoutShiftEntry = (entries: LayoutShift[]) => { + return entries.reduce((a, b) => (a.value > b.value ? a : b)) +} + +export const getLargestLayoutShiftSource = (sources: LayoutShiftAttribution[]) => { + return sources.find(s => s.node?.nodeType === 1) || sources[0] +} + +/* + * The CLS metric. This class is compatible with web-vitals' CLSMetric interface that we expect to report to DataDog and Hydro. + */ +export class CLSMetric extends BaseMetric { + name = 'CLS' as const + targetMap: Map + + constructor(value: number, entries: LayoutShift[], targetMap: Map) { + super(value, entries) + this.targetMap = targetMap + } + + get attribution(): CLSAttribution { + if (!this.entries.length) return {} + + const largestEntry = getLargestLayoutShiftEntry(this.entries) + if (!largestEntry?.sources?.length) return {} + + const largestSource = getLargestLayoutShiftSource(largestEntry.sources) + if (!largestSource) return {} + + return { + largestShiftTarget: this.targetMap.get(largestSource), + } + } +} diff --git a/web-vitals/cls/observer.ts b/web-vitals/cls/observer.ts new file mode 100644 index 0000000..d2b01de --- /dev/null +++ b/web-vitals/cls/observer.ts @@ -0,0 +1,34 @@ +import {ssrSafeWindow} from '@github-ui/ssr-utils' +import type {CLSMetric} from './metric' +import {LayoutShiftProcessor} from './layout-shift-processor' +import {BaseObserver} from '../base/observer' +import {SOFT_NAV_STATE} from '@github-ui/soft-nav/states' + +const supportsCLS = ssrSafeWindow && 'LayoutShift' in ssrSafeWindow + +/* + * The CLSObserver is responsible for listening to Performance events and routing them to the entryProcessor. + * It also manages resetting CLS and reporting it when navigating or hiding a page. + */ +export class CLSObserver extends BaseObserver { + get softNavEventToListen() { + return SOFT_NAV_STATE.START + } + + initializeProcessor() { + return new LayoutShiftProcessor() + } + + override get supported(): boolean { + return !!supportsCLS + } + + observe(initialLoad = true) { + this.url = ssrSafeWindow?.location.href + this.observer = new PerformanceObserver(list => { + this.entryProcessor.processEntries(list.getEntries() as LayoutShift[]) + }) + + this.observer.observe({type: 'layout-shift', buffered: initialLoad}) + } +} diff --git a/web-vitals/dom-nodes.ts b/web-vitals/dom-nodes.ts new file mode 100644 index 0000000..a117608 --- /dev/null +++ b/web-vitals/dom-nodes.ts @@ -0,0 +1,21 @@ +import {isFeatureEnabled} from '@github-ui/feature-flags' +import {SOFT_NAV_STATE} from '@github-ui/soft-nav/states' +import {ssrSafeDocument} from '@github-ui/ssr-utils' + +let previousDomNodeCount: number = 0 + +ssrSafeDocument?.addEventListener(SOFT_NAV_STATE.START, () => { + if (!isFeatureEnabled('dom_node_counts')) return + previousDomNodeCount = countNodes() // nodes may have changes with user interactions / deferred renders +}) + +function countNodes() { + return ssrSafeDocument?.getElementsByTagName('*').length || 0 +} + +export function getDomNodes() { + return { + previous: previousDomNodeCount, + current: countNodes(), + } +} diff --git a/web-vitals/element-timing/metric.ts b/web-vitals/element-timing/metric.ts new file mode 100644 index 0000000..4292dff --- /dev/null +++ b/web-vitals/element-timing/metric.ts @@ -0,0 +1,20 @@ +import {getSelector} from '../get-selector' + +export class ElementTimingMetric { + name = 'ElementTiming' as const + value: number + identifier: string + attribution: { + target?: string + } + + declare app: string + + constructor(value: number, element: Element, identifier: string) { + this.value = value + this.identifier = identifier + this.attribution = { + target: getSelector(element), + } + } +} diff --git a/web-vitals/element-timing/observer.ts b/web-vitals/element-timing/observer.ts new file mode 100644 index 0000000..ca0263b --- /dev/null +++ b/web-vitals/element-timing/observer.ts @@ -0,0 +1,69 @@ +import {SOFT_NAV_STATE} from '@github-ui/soft-nav/states' +import {ssrSafeDocument, ssrSafeWindow} from '@github-ui/ssr-utils' +import {ElementTimingMetric} from './metric' + +const supportsElementTiming = ssrSafeWindow && 'PerformanceElementTiming' in ssrSafeWindow + +type ElementTimingTCallback = (elementTiming: ElementTimingMetric, opts: {url?: string}) => void + +interface PerformanceElementTiming extends PerformanceEntry { + renderTime: number + observer?: PerformanceObserver + element: Element + identifier: string +} +/* + * The ElementTimingObserver is responsible for listening to PerformanceElementTiming events and reporting them. + */ +export class ElementTimingObserver { + cb: ElementTimingTCallback + observer?: PerformanceObserver + url?: string + + constructor(cb: ElementTimingTCallback) { + this.cb = cb + this.setupListeners() + } + + setupListeners() { + if (!supportsElementTiming) return + + // SOFT_NAV_STATE.RENDER is dispatched when the soft navigation finished rendering. + // That means that the previous page is fully hidden so we can stop listening for its events. + ssrSafeDocument?.addEventListener(SOFT_NAV_STATE.RENDER, () => { + this.reset() + }) + } + + observe(initialLoad = true) { + if (!supportsElementTiming) return + + this.observer = new PerformanceObserver(list => { + const entries = list.getEntries() as PerformanceElementTiming[] + for (const {renderTime, element, identifier} of entries) { + this.report(new ElementTimingMetric(renderTime, element, identifier)) + } + }) + + this.observer.observe({ + type: 'element', + // buffered events are important on first page load since we may have missed + // a few until the observer was set up. + buffered: initialLoad, + }) + } + + report(metric: ElementTimingMetric) { + this.cb(metric, {url: this.url}) + } + + teardown() { + this.observer?.takeRecords() + this.observer?.disconnect() + } + + reset() { + this.teardown() + this.observe(false) + } +} diff --git a/web-vitals/get-selector.ts b/web-vitals/get-selector.ts new file mode 100644 index 0000000..2c48dea --- /dev/null +++ b/web-vitals/get-selector.ts @@ -0,0 +1,32 @@ +/* + * From https://github.com/GoogleChrome/web-vitals/blob/7b44bea0d5ba6629c5fd34c3a09cc683077871d0/src/lib/getSelector.ts + * I want to make sure we get element names the same way as web-vitals does. + */ + +const getName = (node: Node) => { + const name = node.nodeName + return node.nodeType === 1 ? name.toLowerCase() : name.toUpperCase().replace(/^#/, '') +} + +export const getSelector = (node: Node | null | undefined, maxLen?: number) => { + let sel = '' + + try { + while (node && node.nodeType !== 9) { + const el: Element = node as Element + const part = el.id + ? `#${el.id}` + : getName(el) + + (el.classList && el.classList.value && el.classList.value.trim() && el.classList.value.trim().length + ? `.${el.classList.value.trim().replace(/\s+/g, '.')}` + : '') + if (sel.length + part.length > (maxLen || 100) - 1) return sel || part + sel = sel ? `${part}>${sel}` : part + if (el.id) break + node = el.parentNode + } + } catch { + // Do nothing... + } + return sel +} diff --git a/web-vitals/hpc-events.ts b/web-vitals/hpc-events.ts new file mode 100644 index 0000000..a67473a --- /dev/null +++ b/web-vitals/hpc-events.ts @@ -0,0 +1,84 @@ +import type {SoftNavMechanism} from '@github-ui/soft-nav/events' +import {getSelector} from './get-selector' + +export interface HPCEventTarget extends EventTarget { + addEventListener( + type: 'hpc:timing', + listener: (event: HPCTimingEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + addEventListener( + type: 'hpc:dom-insertion', + listener: (event: HPCDomInsertionEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + addEventListener(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void + + removeEventListener( + type: 'hpc:timing', + listener: (event: HPCTimingEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + removeEventListener( + type: 'hpc:dom-insertion', + listener: (event: HPCDomInsertionEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + removeEventListener(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void +} + +export class HPCTimingEvent extends Event { + name = 'HPC' as const + value: number + attribution: { + element?: string + } + + soft: boolean + ssr: boolean + lazy: boolean + alternate: boolean + mechanism: SoftNavMechanism | 'hard' + found: boolean + gqlFetched: boolean + jsFetched: boolean + app: string + + constructor( + soft: boolean, + ssr: boolean, + lazy: boolean, + alternate: boolean, + mechanism: SoftNavMechanism | 'hard', + found: boolean, + gqlFetched: boolean, + jsFetched: boolean, + app: string, + start: number, + element: Element | null, + ) { + super('hpc:timing') + this.soft = soft + this.ssr = ssr + this.lazy = lazy + this.alternate = alternate + this.mechanism = mechanism + this.found = found + this.gqlFetched = gqlFetched + this.jsFetched = jsFetched + this.app = app + + this.value = performance.now() - start + this.attribution = { + element: getSelector(element), + } + } +} + +export class HPCDomInsertionEvent extends Event { + element: Element | null + constructor(element: Element | null) { + super('hpc:dom-insertion') + this.element = element + } +} diff --git a/web-vitals/hpc-events1.ts b/web-vitals/hpc-events1.ts new file mode 100644 index 0000000..a67473a --- /dev/null +++ b/web-vitals/hpc-events1.ts @@ -0,0 +1,84 @@ +import type {SoftNavMechanism} from '@github-ui/soft-nav/events' +import {getSelector} from './get-selector' + +export interface HPCEventTarget extends EventTarget { + addEventListener( + type: 'hpc:timing', + listener: (event: HPCTimingEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + addEventListener( + type: 'hpc:dom-insertion', + listener: (event: HPCDomInsertionEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + addEventListener(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void + + removeEventListener( + type: 'hpc:timing', + listener: (event: HPCTimingEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + removeEventListener( + type: 'hpc:dom-insertion', + listener: (event: HPCDomInsertionEvent) => void, + options?: boolean | AddEventListenerOptions, + ): void + removeEventListener(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void +} + +export class HPCTimingEvent extends Event { + name = 'HPC' as const + value: number + attribution: { + element?: string + } + + soft: boolean + ssr: boolean + lazy: boolean + alternate: boolean + mechanism: SoftNavMechanism | 'hard' + found: boolean + gqlFetched: boolean + jsFetched: boolean + app: string + + constructor( + soft: boolean, + ssr: boolean, + lazy: boolean, + alternate: boolean, + mechanism: SoftNavMechanism | 'hard', + found: boolean, + gqlFetched: boolean, + jsFetched: boolean, + app: string, + start: number, + element: Element | null, + ) { + super('hpc:timing') + this.soft = soft + this.ssr = ssr + this.lazy = lazy + this.alternate = alternate + this.mechanism = mechanism + this.found = found + this.gqlFetched = gqlFetched + this.jsFetched = jsFetched + this.app = app + + this.value = performance.now() - start + this.attribution = { + element: getSelector(element), + } + } +} + +export class HPCDomInsertionEvent extends Event { + element: Element | null + constructor(element: Element | null) { + super('hpc:dom-insertion') + this.element = element + } +} diff --git a/web-vitals/hpc.ts b/web-vitals/hpc.ts new file mode 100644 index 0000000..4af0361 --- /dev/null +++ b/web-vitals/hpc.ts @@ -0,0 +1,293 @@ +import {wasServerRendered} from '@github-ui/ssr-utils' +import {onLCP} from 'web-vitals/attribution' +import {hasFetchedGQL, hasFetchedJS, isReactAlternate, isReactLazyPayload} from './web-vitals' +import type {SoftNavMechanism} from '@github-ui/soft-nav/events' +import {HPCDomInsertionEvent, HPCTimingEvent, type HPCEventTarget} from './hpc-events' +import {hasSoftNavFailure} from '@github-ui/soft-nav/utils' +import {SOFT_NAV_STATE} from '@github-ui/soft-nav/states' +import {getCurrentReactAppName} from '@github-ui/stats-metadata' + +const INSERTION_TIMEOUT = 10000 +const ELEMENTS_TO_IGNORE = ['meta', 'script', 'link'] + +function getAppName() { + return getCurrentReactAppName() || 'rails' +} + +function isVisible(element: HTMLElement) { + // Safari doesn't support `checkVisibility` yet. + if (typeof element.checkVisibility === 'function') return element.checkVisibility() + + return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight) +} + +type CallbackFunction = (metric: HPCTimingEvent) => void + +interface HPCObserverAttributes { + soft: boolean + mechanism: SoftNavMechanism | 'hard' + latestHPCElement: Element | null + callback: CallbackFunction +} + +export class HPCObserver { + abortController = new AbortController() + tabHidden = false + insertionFound = false + hpcElement: Element | null = null + + soft: boolean + mechanism: SoftNavMechanism | 'hard' + latestHPCElement: Element | null + hpcStart: DOMHighResTimeStamp + hpcTarget: HPCEventTarget = new EventTarget() as HPCEventTarget + animationFrame?: number + dataHPCanimationFrame?: number + emulatedHPCTimer?: ReturnType + listenerOpts: AddEventListenerOptions + hpcDOMInsertionObserver: MutationObserver | null = null + callback: CallbackFunction + + constructor({soft, mechanism, latestHPCElement, callback}: HPCObserverAttributes) { + this.soft = soft + this.mechanism = mechanism + + if (hasSoftNavFailure()) { + this.mechanism = 'turbo.error' + } + + this.latestHPCElement = latestHPCElement + this.hpcStart = soft ? performance.now() : 0 + this.listenerOpts = {capture: true, passive: true, once: true, signal: this.abortController.signal} + this.callback = callback + } + + connect() { + if (!this.soft) { + // In a hard-load, if the script is evaluated after the `data-hpc` element is rendered, + // we default the HPC value to LCP. + const hpcElement = document.querySelector('[data-hpc]') + if (hpcElement) { + this.hpcElement = hpcElement + this.setLCPasHPC(this.soft, true, this.callback) + return + } + + // if the element is not in the page yet, listen for mutations. + setTimeout(() => { + // if no mutations happen after INSERTION_TIMEOUT, default to LCP again + if (!this.insertionFound) this.setLCPasHPC(this.soft, false, this.callback) + }, INSERTION_TIMEOUT) + } + + this.#setupListeners() + this.hpcDOMInsertionObserver = this.#buildMutationObserver() + this.hpcDOMInsertionObserver.observe(document, {childList: true, subtree: true}) + } + + disconnect() { + this.#cleanupListeners() + this.hpcDOMInsertionObserver?.disconnect() + } + + // Observer to listen to ALL mutations to the DOM. We need to check all added nodes + // for the `data-hpc` attribue. If none are found, we keep listening until all mutations are done. + #buildMutationObserver() { + return new MutationObserver(mutations => { + let hasDataHPC = false + let visibleElement = false + let hpcElement: Element | null = null + let insertionElement: Element | null = null + + const validMutations = mutations.filter( + mutation => mutation.type === 'childList' && mutation.addedNodes.length > 0, + ) + + // if the mutation didn't add any nodes, we don't track its HPC + if (validMutations.length === 0) return + + const addedNodes = validMutations + .flatMap(mutation => Array.from(mutation.addedNodes)) + .filter(node => node instanceof Element && !ELEMENTS_TO_IGNORE.includes(node.tagName.toLowerCase())) + + if (addedNodes.length === 0) return + + for (const node of addedNodes) { + const el = node as Element + hpcElement = el.hasAttribute('data-hpc') ? el : el.querySelector('[data-hpc]') + if (hpcElement) { + this.hpcElement = hpcElement + if (this.animationFrame) cancelAnimationFrame(this.animationFrame) + hasDataHPC = true + break + } + } + + if (hasDataHPC && hpcElement) { + this.#reportHPC(hpcElement) + return + } + + for (const node of addedNodes) { + const el = node as HTMLElement + // we only care about visible elements + if (isVisible(el)) { + insertionElement = el + if (this.animationFrame) cancelAnimationFrame(this.animationFrame) + visibleElement = true + break + } + } + + if (visibleElement) { + const insertionEvent = new HPCDomInsertionEvent(insertionElement) + this.animationFrame = requestAnimationFrame(() => { + this.hpcTarget.dispatchEvent(insertionEvent) + }) + } + }) + } + + #reportHPC(element: Element) { + window.performance.measure('HPC', 'navigationStart') + // data-hpc found, we can stop listening to mutations. + this.hpcDOMInsertionObserver?.disconnect() + // only cancel the animation frame if the controller aborts. + const timingEvent = new HPCTimingEvent( + this.soft, + wasServerRendered(), + isReactLazyPayload(), + isReactAlternate(), + this.mechanism, + true, + hasFetchedGQL(), + hasFetchedJS(), + getAppName(), + this.hpcStart, + element, + ) + + this.dataHPCanimationFrame = requestAnimationFrame(() => { + this.hpcTarget.dispatchEvent(timingEvent) + }) + } + + #cleanupListeners() { + document.removeEventListener('touchstart', this.stop, this.listenerOpts) + document.removeEventListener('mousedown', this.stop, this.listenerOpts) + document.removeEventListener('keydown', this.stop, this.listenerOpts) + document.removeEventListener('pointerdown', this.stop, this.listenerOpts) + document.removeEventListener('visibilitychange', this.onVisibilityChange) + document.removeEventListener(SOFT_NAV_STATE.RENDER, this.onSoftNavRender) + + this.hpcTarget.removeEventListener('hpc:dom-insertion', this.onDOMInsertion) + this.hpcTarget.removeEventListener('hpc:timing', this.onHPCTiming) + + this.abortController.signal.removeEventListener('abort', this.onAbort) + } + + #setupListeners() { + // Stop listening for HPC events if the user has interacted, as interactions + // can cause DOM mutations, which we want to avoid capturing for HPC. + // eslint-disable-next-line github/require-passive-events + document.addEventListener('touchstart', this.stop, this.listenerOpts) + document.addEventListener('mousedown', this.stop, this.listenerOpts) + document.addEventListener('keydown', this.stop, this.listenerOpts) + document.addEventListener('pointerdown', this.stop, this.listenerOpts) + + // Process HPC events + this.hpcTarget.addEventListener('hpc:dom-insertion', this.onDOMInsertion, { + signal: this.abortController.signal, + }) + this.hpcTarget.addEventListener('hpc:timing', this.onHPCTiming, {signal: this.abortController.signal}) + document.addEventListener(SOFT_NAV_STATE.RENDER, this.onSoftNavRender) + + // If the user changes tab, we don't want to send the recorded metrics since it may send garbage data. + document.addEventListener('visibilitychange', this.onVisibilityChange, { + signal: this.abortController.signal, + }) + + // If the stop event is triggered, we want to stop listening to DOM mutations. + this.abortController.signal.addEventListener('abort', this.onAbort) + } + + stop = () => { + this.abortController.abort() + } + + onDOMInsertion = (e: HPCDomInsertionEvent) => { + this.insertionFound = true + clearTimeout(this.emulatedHPCTimer) + // Whenever we see a DOM insertion, we keep track of when it happened. + const event = new HPCTimingEvent( + this.soft, + wasServerRendered(), + isReactLazyPayload(), + isReactAlternate(), + this.mechanism, + false, + hasFetchedGQL(), + hasFetchedJS(), + getAppName(), + this.hpcStart, + e.element, + ) + + // If no mutations happen after the timeout, we assume that the DOM is fully loaded, so we send the + // last seen mutation values. + this.emulatedHPCTimer = setTimeout(() => this.hpcTarget.dispatchEvent(event), INSERTION_TIMEOUT) + } + + onHPCTiming = (e: HPCTimingEvent) => { + if (!this.tabHidden && e.value < 60_000) this.callback(e) + + this.abortController.abort() + } + + onVisibilityChange = () => { + this.tabHidden = true + this.abortController.abort() + } + + onSoftNavRender = () => { + const currentHPCElement = document.querySelector('[data-hpc]') + this.hpcElement = currentHPCElement + + // In case the soft navigation doesn't change the root data-hpc element, the MutationObserver + // won't catch it, so we use the soft navigation timing as HPC. + if (!currentHPCElement || currentHPCElement !== this.latestHPCElement) return + + this.#reportHPC(currentHPCElement) + } + + onAbort = () => { + if (this.dataHPCanimationFrame) cancelAnimationFrame(this.dataHPCanimationFrame) + if (this.animationFrame) cancelAnimationFrame(this.animationFrame) + clearTimeout(this.emulatedHPCTimer) + this.disconnect() + } + + setLCPasHPC(soft: boolean, found: boolean, cb: CallbackFunction) { + const mechanism = this.mechanism === 'turbo.error' ? this.mechanism : 'hard' + + onLCP(({value, attribution}) => { + window.performance.measure('HPC', {start: 'navigationStart', end: value}) + cb({ + name: 'HPC', + value, + soft, + found, + gqlFetched: hasFetchedGQL(), + jsFetched: hasFetchedJS(), + ssr: wasServerRendered(), + lazy: isReactLazyPayload(), + alternate: isReactAlternate(), + mechanism, + app: getAppName(), + attribution: { + element: attribution?.target, + }, + } as HPCTimingEvent) + }) + } +} diff --git a/web-vitals/hydro-stats.ts b/web-vitals/hydro-stats.ts new file mode 100644 index 0000000..cf9b429 --- /dev/null +++ b/web-vitals/hydro-stats.ts @@ -0,0 +1,198 @@ +import {sendEvent, stringifyObjectValues} from '@github-ui/hydro-analytics' +import {getEnabledFeatures, isFeatureEnabled} from '@github-ui/feature-flags' +import {loaded} from '@github-ui/document-ready' +import type {WebVitalMetric, MetricOrHPC} from './web-vitals' +import type {HPCTimingEvent} from './hpc-events' +import {getCPUBucket} from '@github-ui/cpu-bucket' +import type {INPAttribution} from './inp/metric' + +interface WebVitalInformation { + name: string + value: number + element?: string + events?: string + interactionType?: string + eventType?: string + inputDelay?: number + processingDuration?: number + presentationDelay?: number +} + +interface HPCInformation extends WebVitalInformation { + mechanism: HPCTimingEvent['mechanism'] + soft: boolean +} + +interface HydroStat { + react?: boolean + reactApp?: string | null + reactPartials?: string[] + featureFlags?: string[] + ssr?: boolean + hpc?: HPCInformation + ttfb?: WebVitalInformation + fcp?: WebVitalInformation + lcp?: WebVitalInformation + fid?: WebVitalInformation + inp?: WebVitalInformation + cls?: WebVitalInformation + elementtiming?: WebVitalInformation + longTasks?: PerformanceEntryList + longAnimationFrames?: PerformanceEntryList + controller?: string + action?: string + routePattern?: string + cpu?: string + domNodes?: number + previousDomNodes?: number +} + +let queued: HydroStat | undefined + +/** + * Batched report of vital to hydro + */ +export function sendToHydro({ + metric, + ssr, + domNodes, + previousDomNodes, + longTasks, + longAnimationFrames, +}: { + metric?: MetricOrHPC + ssr: boolean + domNodes?: number + previousDomNodes?: number + longTasks?: PerformanceEntryList + longAnimationFrames?: PerformanceEntryList +}) { + let hydroStat: HydroStat | undefined + if (isFeatureEnabled('report_hydro_web_vitals')) return + + if (!hydroStat) { + const reactApp = document.querySelector('react-app') + hydroStat = queueStat() + hydroStat.react = !!reactApp + hydroStat.reactApp = reactApp?.getAttribute('app-name') + // Convert to Set and back to Array to remove duplicates. + hydroStat.reactPartials = [ + ...new Set( + Array.from(document.querySelectorAll('react-partial')).map( + partial => partial.getAttribute('partial-name') || '', + ), + ), + ] + hydroStat.featureFlags = getFeatureFlags() + hydroStat.ssr = ssr + hydroStat.controller = document.querySelector('meta[name="route-controller"]')?.content + hydroStat.action = document.querySelector('meta[name="route-action"]')?.content + hydroStat.routePattern = document.querySelector('meta[name="route-pattern"]')?.content + hydroStat.cpu = getCPUBucket() + + if (domNodes) hydroStat.domNodes = domNodes + if (previousDomNodes) hydroStat.previousDomNodes = previousDomNodes + } + + if (metric) { + return sendWebVital(hydroStat, metric) + } + + hydroStat.longTasks = longTasks + hydroStat.longAnimationFrames = longAnimationFrames +} + +interface ReactApp extends Element { + enabledFeatures: string[] +} + +function getFeatureFlags() { + const globalFlags = getEnabledFeatures() + const reactAppFlags = document.querySelector('react-app')?.enabledFeatures || [] + // need to many to check for speculation_rules otherwise it will get minified away + const speculationRulesFlag = isFeatureEnabled('speculation_rules') ? ['speculation_rules'] : [] + + return Array.from(new Set([...globalFlags, ...reactAppFlags, ...speculationRulesFlag])) +} + +function sendWebVital(hydroStat: HydroStat, metric: MetricOrHPC) { + if (metric.value < 60_000) { + if (metric.name === 'HPC') { + hydroStat[metric.name.toLocaleLowerCase() as Lowercase] = buildHPCInformation(metric) + } else { + hydroStat[metric.name.toLocaleLowerCase() as Lowercase] = buildWebVitalInformation(metric) + } + } +} + +function buildHPCInformation(metric: HPCTimingEvent): HPCInformation { + return { + name: metric.name, + value: metric.value, + element: metric.attribution?.element, + soft: !!metric.soft, + mechanism: metric.mechanism, + } +} + +function buildWebVitalInformation(metric: WebVitalMetric): WebVitalInformation { + const vitalInformation: WebVitalInformation = { + name: metric.name, + value: metric.value, + } + + switch (metric.name) { + case 'LCP': + case 'ElementTiming': + vitalInformation.element = metric.attribution?.target + break + case 'INP': + vitalInformation.element = metric.attribution?.interactionTarget + // Only include custom fields if they exist (from our custom INPMetric class) + if (metric.attribution && 'interactionType' in metric.attribution) { + const customAttribution = metric.attribution as INPAttribution + vitalInformation.interactionType = customAttribution.interactionType + vitalInformation.eventType = customAttribution.eventType + vitalInformation.inputDelay = customAttribution.inputDelay + vitalInformation.processingDuration = customAttribution.processingDuration + vitalInformation.presentationDelay = customAttribution.presentationDelay + } + if (metric.entries?.length) vitalInformation.events = metric.entries.map(entry => entry.name).join(',') + break + case 'CLS': + vitalInformation.element = metric.attribution?.largestShiftTarget + break + } + + return vitalInformation +} + +/** + * Create a new stat object and schedule it to be sent to hydro + */ +function queueStat(): HydroStat { + if (!queued) { + queued = {} + scheduleSend() + } + return queued +} + +/** + * Schedule a send to hydro + */ +async function scheduleSend() { + await loaded + // eslint-disable-next-line compat/compat + window.requestIdleCallback(send) +} + +/** + * Send the queued event to hydro + */ +function send() { + if (!queued) return + + sendEvent('web-vital', stringifyObjectValues(queued)) + queued = undefined +} diff --git a/web-vitals/hydro-stats1.ts b/web-vitals/hydro-stats1.ts new file mode 100644 index 0000000..cf9b429 --- /dev/null +++ b/web-vitals/hydro-stats1.ts @@ -0,0 +1,198 @@ +import {sendEvent, stringifyObjectValues} from '@github-ui/hydro-analytics' +import {getEnabledFeatures, isFeatureEnabled} from '@github-ui/feature-flags' +import {loaded} from '@github-ui/document-ready' +import type {WebVitalMetric, MetricOrHPC} from './web-vitals' +import type {HPCTimingEvent} from './hpc-events' +import {getCPUBucket} from '@github-ui/cpu-bucket' +import type {INPAttribution} from './inp/metric' + +interface WebVitalInformation { + name: string + value: number + element?: string + events?: string + interactionType?: string + eventType?: string + inputDelay?: number + processingDuration?: number + presentationDelay?: number +} + +interface HPCInformation extends WebVitalInformation { + mechanism: HPCTimingEvent['mechanism'] + soft: boolean +} + +interface HydroStat { + react?: boolean + reactApp?: string | null + reactPartials?: string[] + featureFlags?: string[] + ssr?: boolean + hpc?: HPCInformation + ttfb?: WebVitalInformation + fcp?: WebVitalInformation + lcp?: WebVitalInformation + fid?: WebVitalInformation + inp?: WebVitalInformation + cls?: WebVitalInformation + elementtiming?: WebVitalInformation + longTasks?: PerformanceEntryList + longAnimationFrames?: PerformanceEntryList + controller?: string + action?: string + routePattern?: string + cpu?: string + domNodes?: number + previousDomNodes?: number +} + +let queued: HydroStat | undefined + +/** + * Batched report of vital to hydro + */ +export function sendToHydro({ + metric, + ssr, + domNodes, + previousDomNodes, + longTasks, + longAnimationFrames, +}: { + metric?: MetricOrHPC + ssr: boolean + domNodes?: number + previousDomNodes?: number + longTasks?: PerformanceEntryList + longAnimationFrames?: PerformanceEntryList +}) { + let hydroStat: HydroStat | undefined + if (isFeatureEnabled('report_hydro_web_vitals')) return + + if (!hydroStat) { + const reactApp = document.querySelector('react-app') + hydroStat = queueStat() + hydroStat.react = !!reactApp + hydroStat.reactApp = reactApp?.getAttribute('app-name') + // Convert to Set and back to Array to remove duplicates. + hydroStat.reactPartials = [ + ...new Set( + Array.from(document.querySelectorAll('react-partial')).map( + partial => partial.getAttribute('partial-name') || '', + ), + ), + ] + hydroStat.featureFlags = getFeatureFlags() + hydroStat.ssr = ssr + hydroStat.controller = document.querySelector('meta[name="route-controller"]')?.content + hydroStat.action = document.querySelector('meta[name="route-action"]')?.content + hydroStat.routePattern = document.querySelector('meta[name="route-pattern"]')?.content + hydroStat.cpu = getCPUBucket() + + if (domNodes) hydroStat.domNodes = domNodes + if (previousDomNodes) hydroStat.previousDomNodes = previousDomNodes + } + + if (metric) { + return sendWebVital(hydroStat, metric) + } + + hydroStat.longTasks = longTasks + hydroStat.longAnimationFrames = longAnimationFrames +} + +interface ReactApp extends Element { + enabledFeatures: string[] +} + +function getFeatureFlags() { + const globalFlags = getEnabledFeatures() + const reactAppFlags = document.querySelector('react-app')?.enabledFeatures || [] + // need to many to check for speculation_rules otherwise it will get minified away + const speculationRulesFlag = isFeatureEnabled('speculation_rules') ? ['speculation_rules'] : [] + + return Array.from(new Set([...globalFlags, ...reactAppFlags, ...speculationRulesFlag])) +} + +function sendWebVital(hydroStat: HydroStat, metric: MetricOrHPC) { + if (metric.value < 60_000) { + if (metric.name === 'HPC') { + hydroStat[metric.name.toLocaleLowerCase() as Lowercase] = buildHPCInformation(metric) + } else { + hydroStat[metric.name.toLocaleLowerCase() as Lowercase] = buildWebVitalInformation(metric) + } + } +} + +function buildHPCInformation(metric: HPCTimingEvent): HPCInformation { + return { + name: metric.name, + value: metric.value, + element: metric.attribution?.element, + soft: !!metric.soft, + mechanism: metric.mechanism, + } +} + +function buildWebVitalInformation(metric: WebVitalMetric): WebVitalInformation { + const vitalInformation: WebVitalInformation = { + name: metric.name, + value: metric.value, + } + + switch (metric.name) { + case 'LCP': + case 'ElementTiming': + vitalInformation.element = metric.attribution?.target + break + case 'INP': + vitalInformation.element = metric.attribution?.interactionTarget + // Only include custom fields if they exist (from our custom INPMetric class) + if (metric.attribution && 'interactionType' in metric.attribution) { + const customAttribution = metric.attribution as INPAttribution + vitalInformation.interactionType = customAttribution.interactionType + vitalInformation.eventType = customAttribution.eventType + vitalInformation.inputDelay = customAttribution.inputDelay + vitalInformation.processingDuration = customAttribution.processingDuration + vitalInformation.presentationDelay = customAttribution.presentationDelay + } + if (metric.entries?.length) vitalInformation.events = metric.entries.map(entry => entry.name).join(',') + break + case 'CLS': + vitalInformation.element = metric.attribution?.largestShiftTarget + break + } + + return vitalInformation +} + +/** + * Create a new stat object and schedule it to be sent to hydro + */ +function queueStat(): HydroStat { + if (!queued) { + queued = {} + scheduleSend() + } + return queued +} + +/** + * Schedule a send to hydro + */ +async function scheduleSend() { + await loaded + // eslint-disable-next-line compat/compat + window.requestIdleCallback(send) +} + +/** + * Send the queued event to hydro + */ +function send() { + if (!queued) return + + sendEvent('web-vital', stringifyObjectValues(queued)) + queued = undefined +} diff --git a/web-vitals/inp/interaction-count.ts b/web-vitals/inp/interaction-count.ts new file mode 100644 index 0000000..f3b4117 --- /dev/null +++ b/web-vitals/inp/interaction-count.ts @@ -0,0 +1,63 @@ +// Based on https://github.com/GoogleChrome/web-vitals/blob/7b44bea0d5ba6629c5fd34c3a09cc683077871d0/src/lib/polyfills/interactionCountPolyfill.ts +declare global { + interface Performance { + interactionCount: number + } +} + +/* + * The InteractionCountObserver tracks the number of interactions that have occurred on the page. This + * is used to estimate INP's p98 value. + */ +export class InteractionCountObserver { + interactionCountEstimate = 0 + minKnownInteractionId = Infinity + maxKnownInteractionId = 0 + observer?: PerformanceObserver + + get interactionCount() { + return this.observer ? this.interactionCountEstimate : performance.interactionCount || 0 + } + + teardown() { + if (this.observer) { + // take the records so a new observer will start empty + this.observer.takeRecords() + this.observer.disconnect() + this.observer = undefined + } + } + + // from https://github.com/GoogleChrome/web-vitals/blob/7b44bea0d5ba6629c5fd34c3a09cc683077871d0/src/lib/polyfills/interactionCountPolyfill.ts#L29-L40 + updateEstimate = (entries: PerformanceEventTiming[]) => { + for (const e of entries) { + if (e.interactionId) { + this.minKnownInteractionId = Math.min(this.minKnownInteractionId, e.interactionId) + this.maxKnownInteractionId = Math.max(this.maxKnownInteractionId, e.interactionId) + + this.interactionCountEstimate = this.maxKnownInteractionId + ? (this.maxKnownInteractionId - this.minKnownInteractionId) / 7 + 1 + : 0 + } + } + } + + observe() { + if ('interactionCount' in performance || this.observer) return + + this.observer = new PerformanceObserver(async list => { + // Delay by a microtask to workaround a bug in Safari where the + // callback is invoked immediately, rather than in a separate task. + // See: https://github.com/GoogleChrome/web-vitals/issues/277 + await Promise.resolve() + + this.updateEstimate(list.getEntries() as PerformanceEventTiming[]) + }) + + this.observer.observe({ + type: 'event', + buffered: true, + durationThreshold: 0, + }) + } +} diff --git a/web-vitals/inp/interaction-list.ts b/web-vitals/inp/interaction-list.ts new file mode 100644 index 0000000..f8e8086 --- /dev/null +++ b/web-vitals/inp/interaction-list.ts @@ -0,0 +1,77 @@ +export interface Interaction { + id: string + latency: number + entries: PerformanceEventTiming[] +} + +/* + * The InteractionList is a list of interactions that are sorted by latency DESCENDING. + * The list has a maximum size and will remove the shortest interaction if the list is full. + */ +export class InteractionList { + interactions: Interaction[] = [] + interactionsMap: Map = new Map() + maxSize: number + + constructor(size: number) { + this.maxSize = size + } + + get shortestInteraction() { + return this.interactions[this.interactions.length - 1] + } + + get(id: string) { + return this.interactionsMap.get(id) + } + + update(interaction: Interaction, entry: PerformanceEventTiming) { + const newLatency = Math.max(interaction.latency, entry.duration) + interaction.entries.push(entry) + + if (newLatency !== interaction.latency) { + interaction.latency = Math.max(interaction.latency, entry.duration) + // the new value may change sorting order so we need to sort the list + this.sort() + } + } + + add(interaction: Interaction) { + const shortestInteraction = this.shortestInteraction + + // Only add interaction if list is not full or if the interaction is longer than the shortest one + if ( + this.interactions.length <= this.maxSize || + !shortestInteraction || + interaction.latency > shortestInteraction.latency + ) { + this.interactionsMap.set(interaction.id, interaction) + this.interactions.push(interaction) + this.sort() + + // Remove the shortest interaction if list reached the limit + if (this.interactions.length > this.maxSize) { + this.interactions.pop() + } + } + } + + sort() { + this.interactions.sort((a, b) => b.latency - a.latency) + } + + findEntry(entry: PerformanceEventTiming) { + return this.interactions.some((interaction: Interaction) => { + return interaction.entries.some(prevEntry => { + return entry.duration === prevEntry.duration && entry.startTime === prevEntry.startTime + }) + }) + } + + // from https://github.com/GoogleChrome/web-vitals/blob/7b44bea0d5ba6629c5fd34c3a09cc683077871d0/src/onINP.ts#L112-L123 + estimateP98(numOfPageInteractions: number) { + const candidateInteractionIndex = Math.min(this.interactions.length - 1, Math.floor(numOfPageInteractions / 50)) + + return this.interactions[candidateInteractionIndex] + } +} diff --git a/web-vitals/inp/interaction-processor.ts b/web-vitals/inp/interaction-processor.ts new file mode 100644 index 0000000..9112dd0 --- /dev/null +++ b/web-vitals/inp/interaction-processor.ts @@ -0,0 +1,124 @@ +import {BaseProcessor} from '../base/processor' +import {InteractionCountObserver} from './interaction-count' +import {InteractionList, type Interaction} from './interaction-list' +import {INPMetric} from './metric' + +export interface CallbackRegistration { + event: Event + cb: CallbackFn +} +export type CallbackFn = (data: Interaction) => void + +const MAX_INTERACTION_ENTRIES = 10 + +// Event to PerformanceEventTiming type mapping +const EVENT_TO_PERF_MAP: Record = { + // Mouse events → Pointer events + mousedown: 'pointerdown', + mouseup: 'pointerup', + mousemove: 'pointermove', + mouseenter: 'pointerenter', + mouseleave: 'pointerleave', + mouseover: 'pointerover', + mouseout: 'pointerout', + // Touch events → Pointer events + touchstart: 'pointerdown', + touchend: 'pointerup', + touchmove: 'pointermove', + touchcancel: 'pointercancel', +} + +function normalizeEventType(eventType: string): string { + return EVENT_TO_PERF_MAP[eventType] ?? eventType +} + +function eventMatches(entry: PerformanceEventTiming, event: Event) { + // performance entries don't have a reference to the original event, + // so we match them based on their type and target. Since the target + // may not be present in the entry anymore, we match timestamps to within 1ms + const normalizedEventType = normalizeEventType(event.type) + return ( + (entry.name === normalizedEventType || entry.name === event.type) && + (entry.target === event.target || Math.abs(entry.startTime - event.timeStamp) < 1) + ) +} +/* + * The InteractionProcessor is responsible for processing PerformanceEventTiming entries and keeping track of the current INP. + */ +export class InteractionProcessor extends BaseProcessor { + interactions: InteractionList = new InteractionList(MAX_INTERACTION_ENTRIES) + interactionCountObserver: InteractionCountObserver + registeredCallbacks: Set = new Set() + + constructor() { + super() + this.interactionCountObserver = new InteractionCountObserver() + this.interactionCountObserver.observe() + } + + get metric() { + const interaction = this.interactions.estimateP98(this.interactionCountObserver.interactionCount) + + // Pages without interactions report INP = 0 + if (!interaction) { + return null + } + + return new INPMetric(interaction.latency, interaction.entries) + } + + override teardown() { + this.registeredCallbacks.clear() + this.interactionCountObserver.teardown() + } + + processEntries(entries: PerformanceEventTiming[]) { + const callbackMap = new Map() + + for (const entry of entries) { + // This is a `event` type entry + if (entry.interactionId) { + for (const callback of this.registeredCallbacks) { + if (eventMatches(entry, callback.event)) { + callbackMap.set(String(entry.interactionId), callback.cb) + // avoid checking this callback again since we already found a match + this.registeredCallbacks.delete(callback) + } + } + + this.processEntry(entry) + continue + } + + // see https://github.com/GoogleChrome/web-vitals/blob/7b44bea0d5ba6629c5fd34c3a09cc683077871d0/src/onINP.ts#L169-L189 + if (entry.entryType === 'first-input') { + if (!this.interactions.findEntry(entry)) { + this.processEntry(entry) + } + } + } + + for (const [interactionId, fn] of callbackMap) { + const interaction = this.interactions.get(interactionId) + if (interaction) fn(interaction) + } + } + + processEntry(entry: PerformanceEventTiming) { + const existingInteraction = this.interactions.get(String(entry.interactionId)) + + // multiple events may be fired for the same interaction, so we'll only keep + // the longest duration. + if (existingInteraction) { + return this.interactions.update(existingInteraction, entry) + } + + const interaction: Interaction = { + id: String(entry.interactionId), + latency: entry.duration, + entries: [entry], + } + + this.interactions.add(interaction) + } +} diff --git a/web-vitals/inp/metric.ts b/web-vitals/inp/metric.ts new file mode 100644 index 0000000..e387c2c --- /dev/null +++ b/web-vitals/inp/metric.ts @@ -0,0 +1,187 @@ +import {BaseMetric} from '../base/metric' +import {getSelector} from '../get-selector' + +export type InteractionType = 'text_input' | 'action_click' | 'disclosure' | 'selection' | 'submit' | 'unknown' + +export interface INPAttribution { + interactionTarget?: string + interactionType?: InteractionType + eventType?: string + // Phase timing fields + inputDelay?: number + processingDuration?: number + presentationDelay?: number +} + +const INPUT_EVENTS = new Set(['input', 'keydown', 'keyup', 'keypress']) +const POINTER_EVENTS = new Set(['click', 'pointerdown', 'pointerup', 'mousedown', 'mouseup']) + +interface EntryFlags { + isDisclosure: boolean + isSubmitButton: boolean + isTextInput: boolean + isSelection: boolean + isPointerEventEventType: boolean + isInputEventType: boolean +} + +// WeakMap to store precomputed flags per entry +const entryFlagsMap = new WeakMap() + +function isPointerEvent(eventType: string) { + return POINTER_EVENTS.has(eventType) +} + +/** + * Check if element is a selection element using native DOM checks for performance. + * Avoids CSS selector matching. + */ +function isSelectionElement(el: Element): boolean { + if (el.tagName === 'SELECT') return true + const role = el.getAttribute('role') + return role === 'listbox' || role === 'combobox' +} + +/** + * Lazily compute and cache DOM-derived flags for an entry. + * Ensures each DOM traversal happens only once per entry. + * Performance optimizations: + * - Uses native closest() for DOM traversal for better performance + * - Lazy computation of isSelection only when needed + * - Native DOM property checks for better performance + */ +function getEntryFlags(entry: PerformanceEventTiming, target: Element | null): EntryFlags { + const cached = entryFlagsMap.get(entry) + if (cached) return cached + + const isPointerEventEventType = isPointerEvent(entry.name) + const isInputEventType = INPUT_EVENTS.has(entry.name) + + // Early return for unknown events on non-select, non-input, non-pointer + // Only compute isSelection if needed (after checking event type) + if (!isPointerEventEventType && !isInputEventType) { + // Lazy computation: only check selection elements when we might need it + const isSelection = !!(target && isSelectionElement(target)) + if (!isSelection) { + const flags: EntryFlags = { + isDisclosure: false, + isSubmitButton: false, + isTextInput: false, + isSelection: false, + isPointerEventEventType, + isInputEventType, + } + entryFlagsMap.set(entry, flags) + return flags + } + } + + let disclosure = false + let submitButton = false + let textInput = false + // Compute isSelection only when needed (for pointer/input events or when early return didn't happen) + let isSelection = false + + if (target) { + // Check if target is a selection element (only when we need it) + isSelection = isSelectionElement(target) + + // Disclosure and submit detection + if (isPointerEventEventType) { + // Use native closest() for disclosure and submit detection + // This is more efficient than manual traversal as it's implemented in browser native code + const match = target.closest('details, [aria-expanded], button[type="submit"], input[type="submit"]') + + if (match) { + // Precedence: disclosure takes priority over submit + if (match.tagName === 'DETAILS' || match.hasAttribute('aria-expanded')) { + disclosure = true + } else if ( + (match.tagName === 'BUTTON' && (match as HTMLButtonElement).type === 'submit') || + (match.tagName === 'INPUT' && (match as HTMLInputElement).type === 'submit') + ) { + submitButton = true + } + } + } + + // Only compute textInput if event is input type + // Use direct property checks instead of complex :not() selectors for performance + if (isInputEventType) { + if (target.tagName === 'TEXTAREA') { + textInput = true + } else if (target.tagName === 'INPUT') { + const inputType = (target as HTMLInputElement).type + // Input elements are text inputs unless they're button or submit types + textInput = inputType !== 'button' && inputType !== 'submit' + } else if (target instanceof HTMLElement && target.isContentEditable) { + textInput = true + } + } + } + + const flags: EntryFlags = { + isDisclosure: disclosure, + isSubmitButton: submitButton, + isTextInput: textInput, + isSelection, + isPointerEventEventType, + isInputEventType, + } + + entryFlagsMap.set(entry, flags) + return flags +} + +/** + * Determine interaction type using precomputed flags. + */ +function detectInteractionType(entry: PerformanceEventTiming, target: Element | null): InteractionType { + const eventType = entry.name + const {isDisclosure, isSubmitButton, isTextInput, isSelection, isPointerEventEventType} = getEntryFlags(entry, target) + + // Precedence rules + if (isDisclosure) return 'disclosure' + if (isSubmitButton) return 'submit' + if (eventType === 'submit') return 'submit' + if (isTextInput) return 'text_input' + if (isSelection) return 'selection' + if (isPointerEventEventType) return 'action_click' + + return 'unknown' +} + +/* + * The INP metric. Compatible with web-vitals' INPMetric interface + * and suitable for reporting to DataDog and Hydro. + */ +export class INPMetric extends BaseMetric { + name = 'INP' as const + + get attribution(): INPAttribution { + let entry: PerformanceEventTiming | undefined + + // Select the longest interaction (INP definition) + for (const e of this.entries) { + if (!entry || e.duration > entry.duration) { + entry = e + } + } + + const target = (entry?.target as Element | null) ?? null + + // Compute phase durations from the PerformanceEventTiming entry + const inputDelay = entry ? entry.processingStart - entry.startTime : undefined + const processingDuration = entry ? entry.processingEnd - entry.processingStart : undefined + const presentationDelay = entry ? entry.duration - (entry.processingEnd - entry.startTime) : undefined + + return { + interactionTarget: entry && target ? getSelector(target) : '', + interactionType: entry ? detectInteractionType(entry, target) : undefined, + eventType: entry?.name, + inputDelay, + processingDuration, + presentationDelay, + } + } +} diff --git a/web-vitals/inp/observer.ts b/web-vitals/inp/observer.ts new file mode 100644 index 0000000..49ebf4e --- /dev/null +++ b/web-vitals/inp/observer.ts @@ -0,0 +1,80 @@ +import {ssrSafeDocument, ssrSafeWindow} from '@github-ui/ssr-utils' +import type {INPMetric} from './metric' +import {InteractionProcessor, type CallbackRegistration} from './interaction-processor' +import {BaseObserver} from '../base/observer' +import {SOFT_NAV_STATE} from '@github-ui/soft-nav/states' +import {whenIdleOrHidden} from '../utils/when-idle-or-hidden' + +const supportsINP = + // eslint-disable-next-line compat/compat + ssrSafeWindow && 'PerformanceEventTiming' in ssrSafeWindow && 'interactionId' in PerformanceEventTiming.prototype + +/* + * The INPObserver is responsible for listening to Performance events and routing them to the InteractionProcessor. + * It also manages resetting INP and reporting it when navigating or hiding a page. + */ +export class INPObserver extends BaseObserver { + get softNavEventToListen() { + return SOFT_NAV_STATE.START + } + + initializeProcessor() { + return new InteractionProcessor() + } + + override get supported(): boolean { + return !!supportsINP + } + + observe(initialLoad = true) { + if (!supportsINP) return + + this.url = ssrSafeWindow?.location.href + this.observer = new PerformanceObserver(list => { + whenIdleOrHidden(() => { + this.entryProcessor.processEntries(list.getEntries() as PerformanceEventTiming[]) + }) + }) + + if (initialLoad) { + return this.observeEvents(initialLoad) + } + + // SOFT_NAV_STATE.RENDER is dispatched when the soft navigation finished rendering. + // That means that the previous page is fully hidden so we can start listening for new events. + ssrSafeDocument?.addEventListener(SOFT_NAV_STATE.RENDER, () => { + this.observeEvents(initialLoad) + }) + } + + observeEvents(initialLoad: boolean) { + if (!this.observer) return + + this.observer.observe({type: 'first-input', buffered: initialLoad}) + this.observer.observe({ + type: 'event', + durationThreshold: 40, + // buffered events are important on first page load since we may have missed + // a few until the observer was set up. + buffered: initialLoad, + }) + } + + registerCallback(callback: CallbackRegistration) { + this.interactionProcessor.registeredCallbacks.add(callback) + } + + override report() { + const entries = this.observer?.takeRecords() + + if (entries && entries.length) { + this.entryProcessor.processEntries(entries as PerformanceEventTiming[]) + } + + super.report() + } + + get interactionProcessor(): InteractionProcessor { + return this.entryProcessor as InteractionProcessor + } +} diff --git a/web-vitals/long-animation-frames.ts b/web-vitals/long-animation-frames.ts new file mode 100644 index 0000000..1d5febf --- /dev/null +++ b/web-vitals/long-animation-frames.ts @@ -0,0 +1,28 @@ +import {sendStats} from '@github-ui/stats' +import {sendToHydro} from './hydro-stats' +import {wasServerRendered} from '@github-ui/ssr-utils' + +export const observeLongAnimationFrames = () => { + if ( + typeof PerformanceObserver !== 'undefined' && + (PerformanceObserver.supportedEntryTypes || []).includes('long-animation-frame') + ) { + const observer = new PerformanceObserver(function (list) { + const longAnimationFrameEntries = list.getEntries() + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const longAnimationFrames = longAnimationFrameEntries.map(({name, duration, blockingDuration}: any) => ({ + name, + duration, + blockingDuration, + url: window.location.href, + })) + + if (longAnimationFrames.length > 0) { + sendToHydro({longAnimationFrames: longAnimationFrameEntries, ssr: wasServerRendered()}) + } + + sendStats({longAnimationFrames}) + }) + observer.observe({type: 'long-animation-frame', buffered: true}) + } +} diff --git a/web-vitals/utils/when-idle-or-hidden.ts b/web-vitals/utils/when-idle-or-hidden.ts new file mode 100644 index 0000000..d799173 --- /dev/null +++ b/web-vitals/utils/when-idle-or-hidden.ts @@ -0,0 +1,24 @@ +// from https://github.com/GoogleChrome/web-vitals/blob/255855743e6c7a28a81a568ae229bd454559701d/src/lib/whenIdleOrHidden.ts#L23 + +export const whenIdleOrHidden = (cb: () => void) => { + // If the document is hidden, run the callback immediately, otherwise + // race an idle callback with the next `visibilitychange` event. + if (document.visibilityState === 'hidden') return cb() + + // run callback only once + let called = false + + const callback = () => { + if (called) return + called = true + cb() + } + + addEventListener('visibilitychange', callback, {once: true, capture: true}) + // eslint-disable-next-line compat/compat + requestIdleCallback(() => { + callback() + // cleanup listener + removeEventListener('visibilitychange', callback, {capture: true}) + }) +} diff --git a/web-vitals/web-vitals.ts b/web-vitals/web-vitals.ts new file mode 100644 index 0000000..e126901 --- /dev/null +++ b/web-vitals/web-vitals.ts @@ -0,0 +1,69 @@ +import type { + CLSMetricWithAttribution, + FCPMetricWithAttribution, + INPMetricWithAttribution, + LCPMetricWithAttribution, + TTFBMetricWithAttribution, +} from 'web-vitals/attribution' +import type {HPCTimingEvent} from './hpc-events' +import type {INPMetric} from './inp/metric' +import type {ElementTimingMetric} from './element-timing/metric' +import type {CLSMetric} from './cls/metric' +import type {INPObserver} from './inp/observer' +import {isFeatureEnabled} from '@github-ui/feature-flags' + +// eslint-disable-next-line no-barrel-files/no-barrel-files +export {initMemorySampling} from './memory-sampling' + +export type WebVitalMetric = + | CLSMetricWithAttribution + | FCPMetricWithAttribution + | INPMetricWithAttribution + | LCPMetricWithAttribution + | TTFBMetricWithAttribution + | INPMetric + | CLSMetric + | ElementTimingMetric + +export type SoftWebVitalMetric = + | CLSMetricWithAttribution + | FCPMetricWithAttribution + | INPMetricWithAttribution + | LCPMetricWithAttribution + | TTFBMetricWithAttribution + +export type MetricOrHPC = WebVitalMetric | HPCTimingEvent + +export function isReactLazyPayload() { + return Boolean(document.querySelector('react-app[data-lazy="true"]')) +} + +export function isReactAlternate() { + return Boolean(document.querySelector('react-app[data-alternate="true"]')) +} + +export function isHeaderRedesign() { + return Boolean(document.querySelector('header.AppHeader')) +} + +export function hasFetchedGQL(): boolean { + return performance.getEntriesByType('resource').some(e => e.initiatorType === 'fetch' && e.name.includes('_graphql?')) +} + +export function hasFetchedJS(): boolean { + return performance.getEntriesByType('resource').some(e => e.initiatorType === 'script') +} + +let inpObserver: INPObserver | null = null + +export function getGlobalINPObserver(): INPObserver | null { + return inpObserver +} + +export function setGlobalINPObserver(observer: INPObserver) { + inpObserver = observer +} + +export function isSpeculationRulesEnabled(): boolean { + return isFeatureEnabled('speculation_rules') +} From 7690819329b69e23c8151f8df9255d287631ee36 Mon Sep 17 00:00:00 2001 From: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> Date: Mon, 9 Feb 2026 02:12:11 -0700 Subject: [PATCH 4/4] Add files via upload Signed-off-by: Ahfu C Kit III <196157628+ahfuckit@users.noreply.github.com> --- 42653471084.devtools | 1797 ++ 6488-de87864e6818.js | 3 + 66721-c03c0d8e4fbe.js | 22 + 913-ca2305638c53.js | 64 + AgentsIcon.tsx | 39 + AnalyticsProvider.tsx | 10 + AuthorSettingsContext.tsx | 34 + AuthorTooltip.tsx | 20 + Blankslate-f5a9755a.css | 2 + CommitAttribution.tsx | 196 + CommitAuthorStack.tsx | 47 + Document.rtf | 6 + Document.txt | 25643 +++++++++++++++++ OrgLink.tsx | 28 + Overlay-43cda449.css | 2 + aclient-env.ts | 80 + agentutils.ts | 12 + alive.ts | 236 + analytics-overrides.ts | 40 + apiinsights | 91 + app-uuid.ts | 38 + arianotify-polyfill.js | 196 + blob-anchor.ts | 271 + bootstrap | 30 + bootstrap.js | 30 + bsindex.js | 66 + catalystbind.js | 101 + catalystcore.js | 76 + catalystfindtarget.js | 41 + catalystlazy-define.js | 91 + catalystregister.js | 25 + catalysttarget.js | 35 + check-allindex.js | 101 + checkboxcheckallindex.js | 101 + chunk-EPOLDU6W.mjs | 10994 +++++++ client-env.ts | 80 + client-id.js | 50 + client-version.ts | 9 + clipboard-copy-element-define.js | 13 + clipboard-copy-element.js | 85 + clipboarditem.js | 44 + comboboxindex.js | 185 + connect-alive-subscription.ts | 66 + console-debug.ts | 32 + copyelementclipboard.js | 39 + custom-formatter.mjs | 261 + detailsdialogelementindex.js | 248 + document-ready.ts | 32 + drag-drop-addon-installer.js | 81 + drag-drop-addon-installer.txt | 356 + element-checkvisibility.js | 40 + emit-to-codemirror.ts | 14 + environment-fb75ae3199db.js | 2 + environment.ts | 22 + error-serialization.ts | 30 + error.mjs | 317 + failbot-error.ts | 23 + failbot.ts | 342 + feature-flags.ts | 42 + fetch-headers.ts | 28 + fetch-nonce.ts | 40 + fetch-overrides.ts | 34 + fetch-patch.ts | 45 + get javascript chunk filename.devtools | 320 + github-7b2c79a47cf5.css | 4 + githubworker.txt | 45 + grip-length-bubble.mjs | 55 + grip.mjs | 385 + hasOwnProperty shorthand.devtools | 1 + index.js | 38 + insert-before-patch.ts | 18 + invoker.js | 429 + is-react-in-stack-trace.ts | 9 + lit-html.js | 58 + navigator-clipboard.js | 27 + notifications-global-d4747c5b0c07.js | 2 + popover-fn.js | 673 + primer-dc3bfaf4b78e.css | 4 + primer-react.4e7455f297b9951a53ae.module.css | 3 + promise-withResolvers.js | 23 + q.zip | Bin 0 -> 920133 bytes recent-request-ids.ts | 39 + reftest.xhtml | 17 + registry.ts | 20 + remove-child-patch.ts | 18 + requestidlecallback.js | 41 + runtime-environment.ts | 19 + safe-storage.ts | 157 + session-storage.ts | 3 + ssr-globals.ts | 61 + ssr.ts | 27 + stack-trace-parser.esm.js | 136 + stats.ts | 144 + 93 files changed, 45904 insertions(+) create mode 100644 42653471084.devtools create mode 100644 6488-de87864e6818.js create mode 100644 66721-c03c0d8e4fbe.js create mode 100644 913-ca2305638c53.js create mode 100644 AgentsIcon.tsx create mode 100644 AnalyticsProvider.tsx create mode 100644 AuthorSettingsContext.tsx create mode 100644 AuthorTooltip.tsx create mode 100644 Blankslate-f5a9755a.css create mode 100644 CommitAttribution.tsx create mode 100644 CommitAuthorStack.tsx create mode 100644 Document.rtf create mode 100644 Document.txt create mode 100644 OrgLink.tsx create mode 100644 Overlay-43cda449.css create mode 100644 aclient-env.ts create mode 100644 agentutils.ts create mode 100644 alive.ts create mode 100644 analytics-overrides.ts create mode 100644 apiinsights create mode 100644 app-uuid.ts create mode 100644 arianotify-polyfill.js create mode 100644 blob-anchor.ts create mode 100644 bootstrap create mode 100644 bootstrap.js create mode 100644 bsindex.js create mode 100644 catalystbind.js create mode 100644 catalystcore.js create mode 100644 catalystfindtarget.js create mode 100644 catalystlazy-define.js create mode 100644 catalystregister.js create mode 100644 catalysttarget.js create mode 100644 check-allindex.js create mode 100644 checkboxcheckallindex.js create mode 100644 chunk-EPOLDU6W.mjs create mode 100644 client-env.ts create mode 100644 client-id.js create mode 100644 client-version.ts create mode 100644 clipboard-copy-element-define.js create mode 100644 clipboard-copy-element.js create mode 100644 clipboarditem.js create mode 100644 comboboxindex.js create mode 100644 connect-alive-subscription.ts create mode 100644 console-debug.ts create mode 100644 copyelementclipboard.js create mode 100644 custom-formatter.mjs create mode 100644 detailsdialogelementindex.js create mode 100644 document-ready.ts create mode 100644 drag-drop-addon-installer.js create mode 100644 drag-drop-addon-installer.txt create mode 100644 element-checkvisibility.js create mode 100644 emit-to-codemirror.ts create mode 100644 environment-fb75ae3199db.js create mode 100644 environment.ts create mode 100644 error-serialization.ts create mode 100644 error.mjs create mode 100644 failbot-error.ts create mode 100644 failbot.ts create mode 100644 feature-flags.ts create mode 100644 fetch-headers.ts create mode 100644 fetch-nonce.ts create mode 100644 fetch-overrides.ts create mode 100644 fetch-patch.ts create mode 100644 get javascript chunk filename.devtools create mode 100644 github-7b2c79a47cf5.css create mode 100644 githubworker.txt create mode 100644 grip-length-bubble.mjs create mode 100644 grip.mjs create mode 100644 hasOwnProperty shorthand.devtools create mode 100644 index.js create mode 100644 insert-before-patch.ts create mode 100644 invoker.js create mode 100644 is-react-in-stack-trace.ts create mode 100644 lit-html.js create mode 100644 navigator-clipboard.js create mode 100644 notifications-global-d4747c5b0c07.js create mode 100644 popover-fn.js create mode 100644 primer-dc3bfaf4b78e.css create mode 100644 primer-react.4e7455f297b9951a53ae.module.css create mode 100644 promise-withResolvers.js create mode 100644 q.zip create mode 100644 recent-request-ids.ts create mode 100644 reftest.xhtml create mode 100644 registry.ts create mode 100644 remove-child-patch.ts create mode 100644 requestidlecallback.js create mode 100644 runtime-environment.ts create mode 100644 safe-storage.ts create mode 100644 session-storage.ts create mode 100644 ssr-globals.ts create mode 100644 ssr.ts create mode 100644 stack-trace-parser.esm.js create mode 100644 stats.ts diff --git a/42653471084.devtools b/42653471084.devtools new file mode 100644 index 0000000..d724311 --- /dev/null +++ b/42653471084.devtools @@ -0,0 +1,1797 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fixing issue #2543 · microsoft/ApplicationInsights-JS@eb09574 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + +
      + Skip to content + + + + + + + + + + + +
      +
      + + + + + + + + + + + + + + + +
      + +
      + + + + + + + + +
      + + + + + + + + + +
      + + + + + + + + + + + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + +
      + + +
      +
      +
      + + + +
      +
      +
      +
      + + +
      + +
      + +
      + + +
      + +
      + +
      +
      +

      + + Fixing issue #2543 + + #39 + +

      +
      + +
      + + + + +
      + +
      +
      +
      + + + +
      +
      +
      +

      + Fixing issue #2543 +

      +

      + +
      + +
      + + + Fixing issue #2543 #39 + +

      + +
      +
      + +
      +
      + +
      + +
      + + + +
      +
      + +
      +
      +
      + + +
      +
      +
      + + + + + +
      +
      + + + + +
      +
      +
      + +
      + +
      + +
      +
      +
      +
      + +
      +

      The logs for this run have expired and are no longer available.

      +
      +
      + +
      + +
      +
      + + + +
      +
      +
      +
      + + +
      + + +
      + +
      + + + +
      + + +
      +
      + +
      + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + + + diff --git a/6488-de87864e6818.js b/6488-de87864e6818.js new file mode 100644 index 0000000..63eb410 --- /dev/null +++ b/6488-de87864e6818.js @@ -0,0 +1,3 @@ +"use strict";(globalThis.webpackChunk_github_ui_github_ui=globalThis.webpackChunk_github_ui_github_ui||[]).push([[6488],{24212:(e,t,o)=>{o.d(t,{q:()=>r});var n="";function r(e){return e.split(` +`).reduce(function(e,t){var o,r,d,p=function(e){var t=i.exec(e);if(!t)return null;var o=t[2]&&0===t[2].indexOf("native"),r=t[2]&&0===t[2].indexOf("eval"),l=a.exec(t[2]);return r&&null!=l&&(t[2]=l[1],t[3]=l[2],t[4]=l[3]),{file:o?null:t[2],methodName:t[1]||n,arguments:o?[t[2]]:[],lineNumber:t[3]?+t[3]:null,column:t[4]?+t[4]:null}}(t)||((o=l.exec(t))?{file:o[2],methodName:o[1]||n,arguments:[],lineNumber:+o[3],column:o[4]?+o[4]:null}:null)||function(e){var t=c.exec(e);if(!t)return null;var o=t[3]&&t[3].indexOf(" > eval")>-1,r=s.exec(t[3]);return o&&null!=r&&(t[3]=r[1],t[4]=r[2],t[5]=null),{file:t[3],methodName:t[1]||n,arguments:t[2]?t[2].split(","):[],lineNumber:t[4]?+t[4]:null,column:t[5]?+t[5]:null}}(t)||((r=u.exec(t))?{file:r[2],methodName:r[1]||n,arguments:[],lineNumber:+r[3],column:r[4]?+r[4]:null}:null)||((d=m.exec(t))?{file:d[3],methodName:d[1]||n,arguments:[],lineNumber:+d[4],column:d[5]?+d[5]:null}:null);return p&&e.push(p),e},[])}var i=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|rsc||\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,a=/\((\S*)(?::(\d+))(?::(\d+))\)/,l=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|rsc|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,c=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|rsc|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,s=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,m=/^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i,u=/^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i},77065:(e,t,o)=>{o.d(t,{Bb:()=>V,TT:()=>q});var n={};o.r(n),o.d(n,{ClipboardItem:()=>clipboarditem_ClipboardItem,apply:()=>p,isPolyfilled:()=>d,isSupported:()=>u});var r={};o.r(r),o.d(r,{apply:()=>v,checkVisibility:()=>h,isPolyfilled:()=>f,isSupported:()=>b});var i={};o.r(i),o.d(i,{apply:()=>k,clipboardRead:()=>y,clipboardWrite:()=>g,isPolyfilled:()=>E,isSupported:()=>w});var a={};o.r(a),o.d(a,{apply:()=>S,isPolyfilled:()=>I,isSupported:()=>C,withResolvers:()=>T});var l={};o.r(l),o.d(l,{apply:()=>O,cancelIdleCallback:()=>A,isPolyfilled:()=>j,isSupported:()=>x,requestIdleCallback:()=>P});var c={};o.r(c),o.d(c,{apply:()=>L,isPolyfilled:()=>R,isSupported:()=>N});let s=new WeakMap,m=new WeakMap;let clipboarditem_ClipboardItem=class clipboarditem_ClipboardItem{constructor(e,t={}){if(0===Object.keys(e).length)throw TypeError("Empty dictionary argument");s.set(this,e),m.set(this,t.presentationStyle||"unspecified")}get presentationStyle(){return m.get(this)||"unspecified"}get types(){return Object.freeze(Object.keys(s.get(this)||{}))}async getType(e){let t=s.get(this);if(t&&e in t){let o=await t[e];return"string"==typeof o?new Blob([o],{type:e}):o}throw new DOMException("Failed to execute 'getType' on 'ClipboardItem': The type was not found","NotFoundError")}};function u(){try{return new globalThis.ClipboardItem({"text/plain":Promise.resolve("")}),!0}catch{return!1}}function d(){return globalThis.ClipboardItem===clipboarditem_ClipboardItem}function p(){u()||(globalThis.ClipboardItem=clipboarditem_ClipboardItem)}function h({checkOpacity:e=!1,checkVisibilityCSS:t=!1}={}){if(!this.isConnected)return!1;let o=getComputedStyle(this);if("contents"===o.getPropertyValue("display")||t&&"visible"!==o.getPropertyValue("visibility"))return!1;let n=this;for(;n;){let t=n===this?o:getComputedStyle(n);if("none"===t.getPropertyValue("display")||e&&"0"===t.getPropertyValue("opacity")||n!==this&&"hidden"===t.getPropertyValue("content-visibility"))return!1;n=!n.parentElement&&n.getRootNode()instanceof ShadowRoot?n.getRootNode().host:n.parentElement}return!0}function b(){return"checkVisibility"in Element.prototype&&"function"==typeof Element.prototype.checkVisibility}function f(){return Element.prototype.checkVisibility===h}function v(){b()||(Element.prototype.checkVisibility=h)}async function g(e){if(0===e.length)return;let t=e[0],o=await t.getType(t.types.includes("text/plain")?"text/plain":t.types[0]);return navigator.clipboard.writeText("string"==typeof o?o:await o.text())}async function y(){return[new ClipboardItem({"text/plain":navigator.clipboard.readText()})]}function w(){return"clipboard"in navigator&&"function"==typeof navigator.clipboard.read&&"function"==typeof navigator.clipboard.write}function E(){return"clipboard"in navigator&&(navigator.clipboard.write===g||navigator.clipboard.read===y)}function k(){"clipboard"in navigator&&!w()&&(navigator.clipboard.write=g,navigator.clipboard.read=y)}function T(){let e={};return e.promise=new Promise((t,o)=>{e.resolve=t,e.reject=o}),e}function C(){return"withResolvers"in Promise&&"function"==typeof Promise.withResolvers}function I(){return"withResolvers"in Promise&&Promise.withResolvers===T}function S(){C()||Object.assign(Promise,{withResolvers:T})}function P(e,t={}){let o=Date.now(),n=t.timeout||0,r=Object.defineProperty({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-o))},"didTimeout",{get:()=>Date.now()-o>n});return window.setTimeout(()=>{e(r)})}function A(e){clearTimeout(e)}function x(){return"function"==typeof globalThis.requestIdleCallback}function j(){return globalThis.requestIdleCallback===P&&globalThis.cancelIdleCallback===A}function O(){x()||(globalThis.requestIdleCallback=P,globalThis.cancelIdleCallback=A)}var M=o(913);function N(){return"undefined"!=typeof HTMLButtonElement&&"command"in HTMLButtonElement.prototype&&"source"in((globalThis.CommandEvent||{}).prototype||{})}function R(){return!/native code/i.test((globalThis.CommandEvent||{}).toString())}function L(){var e,t;let o,n;function r(e,t,o=!0){Object.defineProperty(e,t,{...Object.getOwnPropertyDescriptor(e,t),enumerable:o})}function i(e){return e&&"function"==typeof e.getRootNode?e.getRootNode():e&&e.parentNode?i(e.parentNode):e}document.addEventListener("invoke",e=>{"invoke"==e.type&&e.isTrusted&&(e.stopImmediatePropagation(),e.preventDefault())},!0),document.addEventListener("command",e=>{"command"==e.type&&e.isTrusted&&(e.stopImmediatePropagation(),e.preventDefault())},!0);let a=globalThis.ShadowRoot||function(){},l=new WeakMap,c=new WeakMap;let CommandEvent=class CommandEvent extends Event{constructor(e,t={}){super(e,t);const{source:o,command:n}=t;if(null!=o&&!(o instanceof Element))throw TypeError("source must be an element");l.set(this,o||null),c.set(this,void 0!==n?String(n):"")}get[Symbol.toStringTag](){return"CommandEvent"}get source(){if(!l.has(this))throw TypeError("illegal invocation");let e=l.get(this);if(!(e instanceof Element))return null;let t=i(e);return t!==i(this.target||document)?t.host:e}get command(){if(!c.has(this))throw TypeError("illegal invocation");return c.get(this)}get action(){throw Error("CommandEvent#action was renamed to CommandEvent#command")}get invoker(){throw Error("CommandEvent#invoker was renamed to CommandEvent#source")}};r(CommandEvent.prototype,"source"),r(CommandEvent.prototype,"command");let InvokeEvent=class InvokeEvent extends Event{constructor(){throw Error("InvokeEvent has been deprecated, it has been renamed to `CommandEvent`")}};let s=new WeakMap,m=new WeakMap;function u(e){for(let t of e)t.oncommand=Function("event",t.getAttribute("oncommand"))}Object.defineProperties(HTMLElement.prototype,{oncommand:{enumerable:!0,configurable:!0,get(){return d.takeRecords(),m.get(this)||null},set(e){let t=m.get(this)||null;t&&this.removeEventListener("command",t),m.set(this,"object"==typeof e||"function"==typeof e?e:null),"function"==typeof e&&this.addEventListener("command",e)}}});let d=new MutationObserver(e=>{for(let t of e){let{target:e}=t;"childList"===t.type?u(e.querySelectorAll("[oncommand]")):u([e])}});function p(e){if(e.defaultPrevented||"click"!==e.type)return;let t=e.target.closest("button[invoketarget], button[invokeaction], input[invoketarget], input[invokeaction]");if(t&&(console.warn("Elements with `invoketarget` or `invokeaction` are deprecated and should be renamed to use `commandfor` and `command` respectively"),t.matches("input")))throw Error("Input elements no longer support `commandfor`");let o=e.target.closest("button[commandfor], button[command]");if(!o)return;if(this.form&&"button"!==this.getAttribute("type"))throw e.preventDefault(),Error("Element with `commandFor` is a form participant. It should explicitly set `type=button` in order for `commandFor` to work. In order for it to act as a Submit button, it must not have command or commandfor attributes");if(o.hasAttribute("command")!==o.hasAttribute("commandfor")){let e=o.hasAttribute("command")?"command":"commandfor",t=o.hasAttribute("command")?"commandfor":"command";throw Error(`Element with ${e} attribute must also have a ${t} attribute to function.`)}if("show-popover"!==o.command&&"hide-popover"!==o.command&&"toggle-popover"!==o.command&&"show-modal"!==o.command&&"close"!==o.command&&!o.command.startsWith("--"))return void console.warn(`"${o.command}" is not a valid command value. Custom commands must begin with --`);let n=o.commandForElement;if(!n)return;let r=new CommandEvent("command",{command:o.command,source:o,cancelable:!0});if(n.dispatchEvent(r),r.defaultPrevented)return;let i=r.command.toLowerCase();if(n.popover){let e=!n.matches(":popover-open");e&&("toggle-popover"===i||"show-popover"===i)?n.showPopover({source:o}):e||"hide-popover"!==i||n.hidePopover()}else if("dialog"===n.localName){let e=!n.hasAttribute("open");e&&"show-modal"===i?n.showModal():e||"close"!==i||n.close()}}function h(e){e.addEventListener("click",p,!0)}d.observe(document,{subtree:!0,childList:!0,attributeFilter:["oncommand"]}),u(document.querySelectorAll("[oncommand]")),Object.defineProperties((globalThis.HTMLButtonElement||function(){}).prototype,{commandForElement:{enumerable:!0,configurable:!0,set(e){if(this.hasAttribute("invokeaction"))throw TypeError("Element has deprecated `invokeaction` attribute, replace with `command`");if(this.hasAttribute("invoketarget"))throw TypeError("Element has deprecated `invoketarget` attribute, replace with `commandfor`");if(null===e)this.removeAttribute("commandfor"),s.delete(this);else if(e instanceof Element){this.setAttribute("commandfor","");let t=i(e);i(this)===t||t===this.ownerDocument?s.set(this,e):s.delete(this)}else throw TypeError("commandForElement must be an element or null")},get(){if("button"!==this.localName)return null;if(this.hasAttribute("invokeaction")||this.hasAttribute("invoketarget"))return console.warn("Element has deprecated `invoketarget` or `invokeaction` attribute, use `commandfor` and `command` instead"),null;if(this.disabled)return null;if(this.form&&"button"!==this.getAttribute("type"))return console.warn("Element with `commandFor` is a form participant. It should explicitly set `type=button` in order for `commandFor` to work"),null;let e=s.get(this);if(e)if(e.isConnected)return e;else return s.delete(this),null;let t=i(this),o=this.getAttribute("commandfor");return(t instanceof Document||t instanceof a)&&o&&t.getElementById(o)||null}},command:{enumerable:!0,configurable:!0,get(){let e=this.getAttribute("command")||"";if(e.startsWith("--"))return e;let t=e.toLowerCase();switch(t){case"show-modal":case"close":case"toggle-popover":case"hide-popover":case"show-popover":return t}return""},set(e){this.setAttribute("command",e)}},invokeAction:{enumerable:!1,configurable:!0,get(){throw Error("invokeAction is deprecated. It has been renamed to command")},set(e){throw Error("invokeAction is deprecated. It has been renamed to command")}},invokeTargetElement:{enumerable:!1,configurable:!0,get(){throw Error("invokeTargetElement is deprecated. It has been renamed to command")},set(e){throw Error("invokeTargetElement is deprecated. It has been renamed to command")}}}),e=globalThis.HTMLElement||function(){},t=e=>{h(e),d.observe(e,{attributeFilter:["oncommand"]}),u(e.querySelectorAll("[oncommand]"))},o=e.prototype.attachShadow,e.prototype.attachShadow=function(e){let n=o.call(this,e);return t(n),n},n=e.prototype.attachInternals,e.prototype.attachInternals=function(){let e=n.call(this);return e.shadowRoot&&t(e.shadowRoot),e},h(document),Object.defineProperty(window,"CommandEvent",{value:CommandEvent,configurable:!0,writable:!0}),Object.defineProperty(window,"InvokeEvent",{value:InvokeEvent,configurable:!0,writable:!0})}let F=!1;try{F=!1===document.body.matches(":modal")}catch{F=!1}let D="object"==typeof globalThis&&"fromEntries"in Object&&"flatMap"in Array.prototype&&"trimEnd"in String.prototype&&"allSettled"in Promise&&"matchAll"in String.prototype&&"replaceAll"in String.prototype&&"any"in Promise&&"at"in String.prototype&&"at"in Array.prototype&&"hasOwn"in Object&&"abort"in AbortSignal&&"timeout"in AbortSignal&&"function"==typeof queueMicrotask&&"function"==typeof HTMLDialogElement&&F&&"function"==typeof AggregateError&&"function"==typeof BroadcastChannel&&"randomUUID"in crypto&&"replaceChildren"in Element.prototype&&"requestSubmit"in HTMLFormElement.prototype&&!0,_={clipboardItem:n,elementCheckVisibility:r,navigatorClipboard:i,requestIdleCallback:l,withResolvers:a,popover:M,commandAndCommandFor:c};function q(){return D&&Object.values(_).every(e=>e.isSupported())}function V(){for(let e of Object.values(_))e.isSupported()||e.apply()}}}]); +//# sourceMappingURL=6488-cf47b8fa3801.js.map \ No newline at end of file diff --git a/66721-c03c0d8e4fbe.js b/66721-c03c0d8e4fbe.js new file mode 100644 index 0000000..3fc06b7 --- /dev/null +++ b/66721-c03c0d8e4fbe.js @@ -0,0 +1,22 @@ +(globalThis.webpackChunk_github_ui_github_ui=globalThis.webpackChunk_github_ui_github_ui||[]).push([[66721],{5497:(e,t,n)=>{"use strict";function r(e,t){var n,r,i,l=(void 0===t?{}:t).viewportMarginBottom,a=void 0===l?100:l,o=null,s=!1;function u(t){if(n!==t.clientX||r!==t.clientY){var l=e.style.height;i&&i!==l&&(s=!0,e.style.maxHeight="",e.removeEventListener("mousemove",u)),i=l}n=t.clientX,r=t.clientY}var c=e.ownerDocument,d=c.documentElement;function h(){if(!s&&e.value!==o&&(!(e.offsetWidth<=0)||!(e.offsetHeight<=0))){var t=function(){for(var t=0,n=e;n!==c.body&&null!==n;)t+=n.offsetTop||0,n=n.offsetParent;var r=t-c.defaultView.pageYOffset,i=d.clientHeight-(r+e.offsetHeight);return{top:r,bottom:i}}(),n=t.top,r=t.bottom;if(!(n<0)&&!(r<0)){var l=getComputedStyle(e),u=Math.ceil(parseFloat(l.borderTopWidth)),h=Math.ceil(parseFloat(l.borderBottomWidth)),f="border-box"===l.boxSizing,p=parseFloat(l.height)+r;e.style.maxHeight=p-(rr})},8507:(e,t,n)=>{let r=n(15659);e.exports=function(e){let t=function(e){let t=function(){let e={},t=Object.keys(r);for(let n=t.length,r=0;r{let r=n(15659),i=n(8507),l={};Object.keys(r).forEach(e=>{l[e]={},Object.defineProperty(l[e],"channels",{value:r[e].channels}),Object.defineProperty(l[e],"labels",{value:r[e].labels});let t=i(e);Object.keys(t).forEach(n=>{let r,i,a=t[n];l[e][n]=(r=function(...e){let t=e[0];if(null==t)return t;t.length>1&&(e=t);let n=a(e);if("object"==typeof n)for(let e=n.length,t=0;t1&&(e=t),a(e))},"conversion"in a&&(i.conversion=a.conversion),i)})}),e.exports=l},15659:(e,t,n)=>{let r=n(51031),i={};for(let e of Object.keys(r))i[r[e]]=e;let l={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(let t of(e.exports=l,Object.keys(l))){if(!("channels"in l[t]))throw Error("missing channels property: "+t);if(!("labels"in l[t]))throw Error("missing channel labels property: "+t);if(l[t].labels.length!==l[t].channels)throw Error("channel and label counts mismatch: "+t);let{channels:e,labels:n}=l[t];delete l[t].channels,delete l[t].labels,Object.defineProperty(l[t],"channels",{value:e}),Object.defineProperty(l[t],"labels",{value:n})}l.rgb.hsl=function(e){let t,n=e[0]/255,r=e[1]/255,i=e[2]/255,l=Math.min(n,r,i),a=Math.max(n,r,i),o=a-l;a===l?t=0:n===a?t=(r-i)/o:r===a?t=2+(i-n)/o:i===a&&(t=4+(n-r)/o),(t=Math.min(60*t,360))<0&&(t+=360);let s=(l+a)/2;return[t,100*(a===l?0:s<=.5?o/(a+l):o/(2-a-l)),100*s]},l.rgb.hsv=function(e){let t,n,r,i,l,a=e[0]/255,o=e[1]/255,s=e[2]/255,u=Math.max(a,o,s),c=u-Math.min(a,o,s),d=function(e){return(u-e)/6/c+.5};return 0===c?(i=0,l=0):(l=c/u,t=d(a),n=d(o),r=d(s),a===u?i=r-n:o===u?i=1/3+t-r:s===u&&(i=2/3+n-t),i<0?i+=1:i>1&&(i-=1)),[360*i,100*l,100*u]},l.rgb.hwb=function(e){let t=e[0],n=e[1],r=e[2];return[l.rgb.hsl(e)[0],1/255*Math.min(t,Math.min(n,r))*100,100*(r=1-1/255*Math.max(t,Math.max(n,r)))]},l.rgb.cmyk=function(e){let t=e[0]/255,n=e[1]/255,r=e[2]/255,i=Math.min(1-t,1-n,1-r);return[100*((1-t-i)/(1-i)||0),100*((1-n-i)/(1-i)||0),100*((1-r-i)/(1-i)||0),100*i]},l.rgb.keyword=function(e){let t,n=i[e];if(n)return n;let l=1/0;for(let n of Object.keys(r)){let i=r[n],a=(e[0]-i[0])**2+(e[1]-i[1])**2+(e[2]-i[2])**2;a.04045?((t+.055)/1.055)**2.4:t/12.92)+.3576*(n=n>.04045?((n+.055)/1.055)**2.4:n/12.92)+.1805*(r=r>.04045?((r+.055)/1.055)**2.4:r/12.92)),100*(.2126*t+.7152*n+.0722*r),100*(.0193*t+.1192*n+.9505*r)]},l.rgb.lab=function(e){let t=l.rgb.xyz(e),n=t[0],r=t[1],i=t[2];return n/=95.047,r/=100,i/=108.883,[116*(r=r>.008856?r**(1/3):7.787*r+16/116)-16,500*((n=n>.008856?n**(1/3):7.787*n+16/116)-r),200*(r-(i=i>.008856?i**(1/3):7.787*i+16/116))]},l.hsl.rgb=function(e){let t,n,r,i=e[0]/360,l=e[1]/100,a=e[2]/100;if(0===l)return[r=255*a,r,r];t=a<.5?a*(1+l):a+l-a*l;let o=2*a-t,s=[0,0,0];for(let e=0;e<3;e++)(n=i+-(1/3*(e-1)))<0&&n++,n>1&&n--,r=6*n<1?o+(t-o)*6*n:2*n<1?t:3*n<2?o+(t-o)*(2/3-n)*6:o,s[e]=255*r;return s},l.hsl.hsv=function(e){let t=e[0],n=e[1]/100,r=e[2]/100,i=n,l=Math.max(r,.01);r*=2,n*=r<=1?r:2-r,i*=l<=1?l:2-l;let a=(r+n)/2;return[t,100*(0===r?2*i/(l+i):2*n/(r+n)),100*a]},l.hsv.rgb=function(e){let t=e[0]/60,n=e[1]/100,r=e[2]/100,i=Math.floor(t)%6,l=t-Math.floor(t),a=255*r*(1-n),o=255*r*(1-n*l),s=255*r*(1-n*(1-l));switch(r*=255,i){case 0:return[r,s,a];case 1:return[o,r,a];case 2:return[a,r,s];case 3:return[a,o,r];case 4:return[s,a,r];case 5:return[r,a,o]}},l.hsv.hsl=function(e){let t,n,r=e[0],i=e[1]/100,l=e[2]/100,a=Math.max(l,.01);n=(2-i)*l;let o=(2-i)*a;return[r,100*(t=(t=i*a/(o<=1?o:2-o))||0),100*(n/=2)]},l.hwb.rgb=function(e){let t,n,r,i,l=e[0]/360,a=e[1]/100,o=e[2]/100,s=a+o;s>1&&(a/=s,o/=s);let u=Math.floor(6*l),c=1-o;t=6*l-u,(1&u)!=0&&(t=1-t);let d=a+t*(c-a);switch(u){default:case 6:case 0:n=c,r=d,i=a;break;case 1:n=d,r=c,i=a;break;case 2:n=a,r=c,i=d;break;case 3:n=a,r=d,i=c;break;case 4:n=d,r=a,i=c;break;case 5:n=c,r=a,i=d}return[255*n,255*r,255*i]},l.cmyk.rgb=function(e){let t=e[0]/100,n=e[1]/100,r=e[2]/100,i=e[3]/100;return[255*(1-Math.min(1,t*(1-i)+i)),255*(1-Math.min(1,n*(1-i)+i)),255*(1-Math.min(1,r*(1-i)+i))]},l.xyz.rgb=function(e){let t,n,r,i=e[0]/100,l=e[1]/100,a=e[2]/100;return t=(t=3.2406*i+-1.5372*l+-.4986*a)>.0031308?1.055*t**(1/2.4)-.055:12.92*t,n=(n=-.9689*i+1.8758*l+.0415*a)>.0031308?1.055*n**(1/2.4)-.055:12.92*n,r=(r=.0557*i+-.204*l+1.057*a)>.0031308?1.055*r**(1/2.4)-.055:12.92*r,[255*(t=Math.min(Math.max(0,t),1)),255*(n=Math.min(Math.max(0,n),1)),255*(r=Math.min(Math.max(0,r),1))]},l.xyz.lab=function(e){let t=e[0],n=e[1],r=e[2];return t/=95.047,n/=100,r/=108.883,[116*(n=n>.008856?n**(1/3):7.787*n+16/116)-16,500*((t=t>.008856?t**(1/3):7.787*t+16/116)-n),200*(n-(r=r>.008856?r**(1/3):7.787*r+16/116))]},l.lab.xyz=function(e){let t,n,r,i=e[0],l=e[1],a=e[2];t=l/500+(n=(i+16)/116),r=n-a/200;let o=n**3,s=t**3,u=r**3;return n=(o>.008856?o:(n-16/116)/7.787)*100,[t=(s>.008856?s:(t-16/116)/7.787)*95.047,n,r=(u>.008856?u:(r-16/116)/7.787)*108.883]},l.lab.lch=function(e){let t,n=e[0],r=e[1],i=e[2];return(t=360*Math.atan2(i,r)/2/Math.PI)<0&&(t+=360),[n,Math.sqrt(r*r+i*i),t]},l.lch.lab=function(e){let t=e[0],n=e[1],r=e[2]/360*2*Math.PI;return[t,n*Math.cos(r),n*Math.sin(r)]},l.rgb.ansi16=function(e,t=null){let[n,r,i]=e,a=null===t?l.rgb.hsv(e)[2]:t;if(0===(a=Math.round(a/50)))return 30;let o=30+(Math.round(i/255)<<2|Math.round(r/255)<<1|Math.round(n/255));return 2===a&&(o+=60),o},l.hsv.ansi16=function(e){return l.rgb.ansi16(l.hsv.rgb(e),e[2])},l.rgb.ansi256=function(e){let t=e[0],n=e[1],r=e[2];return t===n&&n===r?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(n/255*5)+Math.round(r/255*5)},l.ansi16.rgb=function(e){let t=e%10;if(0===t||7===t)return e>50&&(t+=3.5),[t=t/10.5*255,t,t];let n=(~~(e>50)+1)*.5;return[(1&t)*n*255,(t>>1&1)*n*255,(t>>2&1)*n*255]},l.ansi256.rgb=function(e){let t;if(e>=232){let t=(e-232)*10+8;return[t,t,t]}return[Math.floor((e-=16)/36)/5*255,Math.floor((t=e%36)/6)/5*255,t%6/5*255]},l.rgb.hex=function(e){let t=(((255&Math.round(e[0]))<<16)+((255&Math.round(e[1]))<<8)+(255&Math.round(e[2]))).toString(16).toUpperCase();return"000000".substring(t.length)+t},l.hex.rgb=function(e){let t=e.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!t)return[0,0,0];let n=t[0];3===t[0].length&&(n=n.split("").map(e=>e+e).join(""));let r=parseInt(n,16);return[r>>16&255,r>>8&255,255&r]},l.rgb.hcg=function(e){let t,n=e[0]/255,r=e[1]/255,i=e[2]/255,l=Math.max(Math.max(n,r),i),a=Math.min(Math.min(n,r),i),o=l-a;return t=o<1?a/(1-o):0,[360*((o<=0?0:l===n?(r-i)/o%6:l===r?2+(i-n)/o:4+(n-r)/o)/6%1),100*o,100*t]},l.hsl.hcg=function(e){let t=e[1]/100,n=e[2]/100,r=n<.5?2*t*n:2*t*(1-n),i=0;return r<1&&(i=(n-.5*r)/(1-r)),[e[0],100*r,100*i]},l.hsv.hcg=function(e){let t=e[1]/100,n=e[2]/100,r=t*n,i=0;return r<1&&(i=(n-r)/(1-r)),[e[0],100*r,100*i]},l.hcg.rgb=function(e){let t=e[0]/360,n=e[1]/100,r=e[2]/100;if(0===n)return[255*r,255*r,255*r];let i=[0,0,0],l=t%1*6,a=l%1,o=1-a,s=0;switch(Math.floor(l)){case 0:i[0]=1,i[1]=a,i[2]=0;break;case 1:i[0]=o,i[1]=1,i[2]=0;break;case 2:i[0]=0,i[1]=1,i[2]=a;break;case 3:i[0]=0,i[1]=o,i[2]=1;break;case 4:i[0]=a,i[1]=0,i[2]=1;break;default:i[0]=1,i[1]=0,i[2]=o}return s=(1-n)*r,[(n*i[0]+s)*255,(n*i[1]+s)*255,(n*i[2]+s)*255]},l.hcg.hsv=function(e){let t=e[1]/100,n=t+e[2]/100*(1-t),r=0;return n>0&&(r=t/n),[e[0],100*r,100*n]},l.hcg.hsl=function(e){let t=e[1]/100,n=e[2]/100*(1-t)+.5*t,r=0;return n>0&&n<.5?r=t/(2*n):n>=.5&&n<1&&(r=t/(2*(1-n))),[e[0],100*r,100*n]},l.hcg.hwb=function(e){let t=e[1]/100,n=t+e[2]/100*(1-t);return[e[0],(n-t)*100,(1-n)*100]},l.hwb.hcg=function(e){let t=e[1]/100,n=1-e[2]/100,r=n-t,i=0;return r<1&&(i=(n-r)/(1-r)),[e[0],100*r,100*i]},l.apple.rgb=function(e){return[e[0]/65535*255,e[1]/65535*255,e[2]/65535*255]},l.rgb.apple=function(e){return[e[0]/255*65535,e[1]/255*65535,e[2]/255*65535]},l.gray.rgb=function(e){return[e[0]/100*255,e[0]/100*255,e[0]/100*255]},l.gray.hsl=function(e){return[0,0,e[0]]},l.gray.hsv=l.gray.hsl,l.gray.hwb=function(e){return[0,100,e[0]]},l.gray.cmyk=function(e){return[0,0,0,e[0]]},l.gray.lab=function(e){return[e[0],0,0]},l.gray.hex=function(e){let t=255&Math.round(e[0]/100*255),n=((t<<16)+(t<<8)+t).toString(16).toUpperCase();return"000000".substring(n.length)+n},l.rgb.gray=function(e){return[(e[0]+e[1]+e[2])/3/255*100]}},15955:(e,t,n)=>{"use strict";function r(e){let t=!1,n=null;function r(e,t,n,i=!1){t instanceof HTMLInputElement&&(t.indeterminate=i,t.checked!==n&&(t.checked=n,setTimeout(()=>{let n=new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{relatedTarget:e}});t.dispatchEvent(n)})))}function i(i){let l=i.target;l instanceof Element&&(l.hasAttribute("data-check-all")?function(t){if(t instanceof CustomEvent&&t.detail){let{relatedTarget:e}=t.detail;if(e&&e.hasAttribute("data-check-all-item"))return}let i=t.target;if(i instanceof HTMLInputElement){for(let t of(n=null,e.querySelectorAll("[data-check-all-item]")))r(i,t,i.checked);i.indeterminate=!1,a()}}(i):l.hasAttribute("data-check-all-item")&&function(i){if(i instanceof CustomEvent&&i.detail){let{relatedTarget:e}=i.detail;if(e&&(e.hasAttribute("data-check-all")||e.hasAttribute("data-check-all-item")))return}let l=i.target;if(!(l instanceof HTMLInputElement))return;let o=Array.from(e.querySelectorAll("[data-check-all-item]"));if(t&&n){let[e,t]=[o.indexOf(n),o.indexOf(l)].sort();for(let n of o.slice(e,+t+1||9e9))r(l,n,l.checked)}t=!1,n=l;let s=e.querySelector("[data-check-all]");if(s){let e=o.length,t=o.filter(e=>e instanceof HTMLInputElement&&e.checked).length;r(l,s,t===e,e>t&&t>0)}a()}(i))}function l(e){e.target instanceof Element&&(e.target instanceof HTMLLabelElement&&e.target.control||e.target).hasAttribute("data-check-all-item")&&(t=e.shiftKey)}function a(){let t=e.querySelector("[data-check-all-count]");t&&(t.textContent=e.querySelectorAll("[data-check-all-item]:checked").length.toString())}return e.addEventListener("mousedown",l),e.addEventListener("change",i),{unsubscribe:()=>{e.removeEventListener("mousedown",l),e.removeEventListener("change",i)}}}n.d(t,{A:()=>r})},16213:(e,t,n)=>{"use strict";n.d(t,{_:()=>i});var r=n(53482);function i(e,t){(0,r._)(e,t),t.add(e)}},18679:(e,t,n)=>{"use strict";n.d(t,{s:()=>AnalyticsClient});let r=["utm_source","utm_medium","utm_campaign","utm_term","utm_content","scid"];var i=n(36301);let AnalyticsClient=class AnalyticsClient{constructor(e){this.options=e}get collectorUrl(){return this.options.collectorUrl}get clientId(){return this.options.clientId?this.options.clientId:(0,i.y)()}createEvent(e){return{page:location.href,title:document.title,context:{...this.options.baseContext,...function(){let e={};try{for(let[t,n]of new URLSearchParams(window.location.search)){let i=t.toLowerCase();r.includes(i)&&(e[i]=n)}return e}catch(e){return{}}}(),...e}}}sendPageView(e){let t=this.createEvent(e);this.send({page_views:[t]})}sendEvent(e,t){let n={...this.createEvent(t),type:e};this.send({events:[n]})}send({page_views:e,events:t}){let n=JSON.stringify({client_id:this.clientId,page_views:e,events:t,request_context:{referrer:function(){let e;try{e=window.top.document.referrer}catch(t){if(window.parent)try{e=window.parent.document.referrer}catch(e){}}return""===e&&(e=document.referrer),e}(),user_agent:navigator.userAgent,screen_resolution:function(){try{return`${screen.width}x${screen.height}`}catch(e){return"unknown"}}(),browser_resolution:function(){let e=0,t=0;try{return"number"==typeof window.innerWidth?(t=window.innerWidth,e=window.innerHeight):null!=document.documentElement&&null!=document.documentElement.clientWidth?(t=document.documentElement.clientWidth,e=document.documentElement.clientHeight):null!=document.body&&null!=document.body.clientWidth&&(t=document.body.clientWidth,e=document.body.clientHeight),`${t}x${e}`}catch(e){return"unknown"}}(),browser_languages:navigator.languages?navigator.languages.join(","):navigator.language||"",pixel_ratio:window.devicePixelRatio,timestamp:Date.now(),tz_seconds:-60*new Date().getTimezoneOffset()}});try{if(navigator.sendBeacon)return void navigator.sendBeacon(this.collectorUrl,n)}catch{}fetch(this.collectorUrl,{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json"},body:n,keepalive:!1})}}},31143:(e,t,n)=>{"use strict";n.d(t,{qy:()=>x,XX:()=>v,_3:()=>L});let r=new Map;function i(e){if(r.has(e))return r.get(e);let t=e.length,n=0,i=0,l=0,a=[];for(let r=0;rn&&(a.push(Object.freeze({type:"string",start:n,end:i,value:e.slice(n,i)})),n=i),a.push(Object.freeze({type:"part",start:i,end:r+2,value:e.slice(n+2,r).trim()})),r+=1,n=r+1)}return n"string"==typeof e?e:e.value).join("");this.element.setAttributeNS(this.attr.namespaceURI,this.attr.name,e)}}};let o=new WeakMap;let NodeTemplatePart=class NodeTemplatePart{constructor(e,t){this.expression=t,o.set(this,[e]),e.textContent=""}get value(){return o.get(this).map(e=>e.textContent).join("")}set value(e){this.replace(e)}get previousSibling(){return o.get(this)[0].previousSibling}get nextSibling(){return o.get(this)[o.get(this).length-1].nextSibling}replace(...e){let t=e.map(e=>"string"==typeof e?new Text(e):e);for(let e of(t.length||t.push(new Text("")),o.get(this)[0].before(...t),o.get(this)))e.remove();o.set(this,t)}};function s(e){return{processCallback(t,n,r){var i;if("object"==typeof r&&r){for(let t of n)if(t.expression in r){let n=null!=(i=r[t.expression])?i:"";e(t,n)}}}}}function u(e,t){e.value=String(t)}function c(e,t){return"boolean"==typeof t&&e instanceof AttributeTemplatePart&&"boolean"==typeof e.element[e.attributeName]&&(e.booleanValue=t,!0)}let d=s(u);s((e,t)=>{c(e,t)||u(e,t)});let h=new WeakMap,f=new WeakMap;let TemplateInstance=class TemplateInstance extends DocumentFragment{constructor(e,t,n=d){var r,l;super(),Object.getPrototypeOf(this)!==TemplateInstance.prototype&&Object.setPrototypeOf(this,TemplateInstance.prototype),this.appendChild(e.content.cloneNode(!0)),f.set(this,Array.from(function*(e){let t,n=e.ownerDocument.createTreeWalker(e,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null,!1);for(;t=n.nextNode();)if(t instanceof Element&&t.hasAttributes())for(let e=0;ee+t+(n{let n=e(...t);return b.add(n),n}}let T=new WeakMap;let EventHandler=class EventHandler{constructor(e,t){this.element=e,this.type=t,this.element.addEventListener(this.type,this),T.get(this.element).set(this.type,this)}set(e){"function"==typeof e?this.handleEvent=e.bind(this.element):"object"==typeof e&&"function"==typeof e.handleEvent?this.handleEvent=e.handleEvent.bind(e):(this.element.removeEventListener(this.type,this),T.get(this.element).delete(this.type))}static for(e){T.has(e.element)||T.set(e.element,new Map);let t=e.attributeName.slice(2),n=T.get(e.element);return n.has(t)?n.get(t):new EventHandler(e.element,t)}};function w(e,t){b.has(t)&&(t(e),1)||c(e,t)||e instanceof AttributeTemplatePart&&e.attributeName.startsWith("on")&&(EventHandler.for(e).set(t),e.element.removeAttributeNS(e.attributeNamespace,e.attributeName),1)||t instanceof TemplateResult&&e instanceof NodeTemplatePart&&(t.renderInto(e),1)||t instanceof DocumentFragment&&e instanceof NodeTemplatePart&&(t.childNodes.length&&e.replace(...t.childNodes),1)||function(e,t){if(!("object"==typeof t&&Symbol.iterator in t))return!1;if(!(e instanceof NodeTemplatePart))return e.value=Array.from(t).join(" "),!0;{let n=[];for(let e of t)if(e instanceof TemplateResult){let t=document.createDocumentFragment();e.renderInto(t),n.push(...t.childNodes)}else e instanceof DocumentFragment?n.push(...e.childNodes):n.push(String(e));return n.length&&e.replace(...n),!0}}(e,t)||u(e,t)}let E=s(w);function x(e,...t){return new TemplateResult(e,t,E)}let k=new WeakMap;y((...e)=>t=>{k.has(t)||k.set(t,{i:e.length});let n=k.get(t);for(let r=0;r{rt=>{var n,r;if(!(t instanceof NodeTemplatePart))return;let i=document.createElement("template");i.innerHTML=null!=(r=null==(n=TemplateResult.cspTrustedTypesPolicy)?void 0:n.createHTML(e))?r:e;let l=document.importNode(i.content,!0);t.replace(...l.childNodes)})},44358:(e,t,n)=>{"use strict";function r(e,t){var n,r,i;let l=e.value.slice(0,null!=(n=e.selectionStart)?n:void 0),a=e.value.slice(null!=(r=e.selectionEnd)?r:void 0),o=!0;e.contentEditable="true";try{o=document.execCommand("insertText",!1,t)}catch(e){o=!1}if(e.contentEditable="false",o&&!e.value.slice(0,null!=(i=e.selectionStart)?i:void 0).endsWith(t)&&(o=!1),!o){try{document.execCommand("ms-beginUndoUnit")}catch(e){}e.value=l+t+a;try{document.execCommand("ms-endUndoUnit")}catch(e){}e.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!0}))}}n.d(t,{B1:()=>I});let i=new WeakMap;function l(e){let{currentTarget:t}=e,n="KeyV"===e.code&&(e.ctrlKey||e.metaKey)&&e.shiftKey;(n||n&&e.altKey)&&i.set(t,!0)}function a(e){let{currentTarget:t}=e;i.delete(t)}function o(e){var t;return null!=(t=i.get(e))&&t}function s(e){e.addEventListener("paste",u)}function u(e){var t;let n,i=e.clipboardData,{currentTarget:l}=e;if(o(l)||!i||!i.types.includes("text/html"))return;let a=e.currentTarget;if(!(a instanceof HTMLTextAreaElement)||0!==(n=(t=a).selectionStart||0)&&"@"===t.value.substring(n-1,n))return;let s=i.getData("text/plain"),u=i.getData("text/html"),d=u.replace(/\u00A0/g," ").replace(/\uC2A0/g," ");if(!u||!(s=s.trim()))return;let h=new DOMParser().parseFromString(d,"text/html"),f=function(e,t){let n=t.firstChild(),r=e,i=0,l=0;for(;n&&l<1e4;){var a;l++;let e=c(n)?(n.textContent||"").replace(/[\t\n\r ]+/g," "):(null==n?void 0:n.wholeText)||"";if(!(a=e)||(null==a?void 0:a.trim().length)===0){n=t.nextNode();continue}if(!c(n)){i+=e.replace(/[\t\n\r ]+/g," ").trimStart().length,n=t.nextNode();continue}let o=r.indexOf(e,i);if(o>=0){let t=function(e,t){var n,r,i;let l=e.href||"";return function(e){var t;return(null==(t=e.textContent)?void 0:t.slice(0,1))==="@"&&"user"===e.getAttribute("data-hovercard-type")}(e)||function(e){var t;return(null==(t=e.textContent)?void 0:t.slice(0,1))==="@"&&"team"===e.getAttribute("data-hovercard-type")}(e)?t:(n=e).className.indexOf("commit-link")>=0||n.getAttribute("data-hovercard-type")&&"user"!==n.getAttribute("data-hovercard-type")||(r=l,i=t,r="/"===r.slice(-1)?r.slice(0,-1):r,i="/"===i.slice(-1)?i.slice(0,-1):i,r.toLowerCase()===i.toLowerCase())?l:`[${t}](${l})`}(n,e);r=r.slice(0,o)+t+r.slice(o+e.length),i=o+t.length}n=t.nextNode()}return 1e4===l?e:r}(s,h.createTreeWalker(h.body,NodeFilter.SHOW_ALL,e=>e.parentNode&&c(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT));f!==s&&(e.stopPropagation(),e.preventDefault(),r(a,f))}function c(e){var t;return(null==(t=e.tagName)?void 0:t.toLowerCase())==="a"&&e.hasAttribute("href")}function d(e){e.addEventListener("dragover",f),e.addEventListener("drop",h),e.addEventListener("paste",p)}function h(e){let t=e.dataTransfer;if(!t||Array.from(t.types).indexOf("Files")>=0||!g(t))return;let n=v(t);if(!n.some(y))return;e.stopPropagation(),e.preventDefault();let i=e.currentTarget;i instanceof HTMLTextAreaElement&&r(i,n.map(m).join(""))}function f(e){let t=e.dataTransfer;t&&(t.dropEffect="link")}function p(e){let{currentTarget:t}=e;if(o(t))return;let n=e.clipboardData;if(!n||!g(n))return;let i=v(n);if(!i.some(y))return;e.stopPropagation(),e.preventDefault();let l=e.currentTarget;l instanceof HTMLTextAreaElement&&r(l,i.map(m).join(""))}function m(e){return y(e)?` +![](${e}) +`:e}function g(e){return Array.from(e.types).indexOf("text/uri-list")>=0}function v(e){return(e.getData("text/uri-list")||"").split(`\r +`)}let b=/\.(gif|png|jpe?g)$/i;function y(e){return b.test(e)}let T=new WeakMap;function w(e,t){var n;T.set(e,(null==(n=null==t?void 0:t.defaultPlainTextPaste)?void 0:n.urlLinks)===!0),e.addEventListener("paste",E)}function E(e){var t,n,i,l;let a,{currentTarget:s}=e,u=null!=(t=T.get(s))&&t,c=o(s);if(!u&&c||u&&!c)return;let d=e.clipboardData;if(!d||!Array.from(d.types).includes("text/plain"))return;let h=e.currentTarget;if(!(h instanceof HTMLTextAreaElement))return;let f=d.getData("text/plain");if(!f||!x(f)||(a=(n=h).selectionStart||0)>1&&"]("===n.value.substring(a-2,a))return;let p=h.value.substring(h.selectionStart,h.selectionEnd);!p.length||x(p.trim())||(e.stopPropagation(),e.preventDefault(),r(h,(i=p,l=f.trim(),`[${i}](${l})`)))}function x(e){try{let t=new URL(e);return k(t.href).trim()===k(e).trim()}catch(e){return!1}}function k(e){return e.endsWith("/")?e.slice(0,e.length-1):e}function L(e){e.addEventListener("dragover",M),e.addEventListener("drop",S),e.addEventListener("paste",C)}function S(e){let t=e.dataTransfer;if(!t||Array.from(t.types).indexOf("Files")>=0)return;let n=O(t);if(!n)return;e.stopPropagation(),e.preventDefault();let i=e.currentTarget;i instanceof HTMLTextAreaElement&&r(i,n)}function M(e){let t=e.dataTransfer;t&&(t.dropEffect="copy")}function C(e){let{currentTarget:t}=e;if(o(t)||!e.clipboardData)return;let n=O(e.clipboardData);if(!n)return;e.stopPropagation(),e.preventDefault();let i=e.currentTarget;i instanceof HTMLTextAreaElement&&r(i,n)}function A(e){return(e.textContent||"").trim().replace(/\|/g,"\\|").replace(/\n/g," ")||"\xa0"}function O(e){if(-1===Array.from(e.types).indexOf("text/html"))return;let t=e.getData("text/html");if(!/");if(!n||!r)return;let i=t.substring(r+8),l=new DOMParser().parseFromString(t,"text/html").querySelector("table");if(!(l=!l||l.closest("[data-paste-markdown-skip]")?null:l))return;let a=function(e){let t=Array.from(e.querySelectorAll("tr")),n=t.shift();if(!n)return"";let r=Array.from(n.querySelectorAll("td, th")).map(A),i=r.map(()=>"--"),l=`${r.join(" | ")} +${i.join(" | ")} +`,a=t.map(e=>Array.from(e.querySelectorAll("td")).map(A).join(" | ")).join(` +`);return` +${l}${a} + +`}(l);if(a)return[n,a,i].join("").replace(//,"")}function P(e){e.addEventListener("paste",H)}function H(e){let{currentTarget:t}=e;if(o(t))return;let n=e.clipboardData;if(!n||!(Array.from(n.types).indexOf("text/x-gfm")>=0))return;let i=e.currentTarget;if(!(i instanceof HTMLTextAreaElement))return;let l=n.getData("text/x-gfm");l&&(e.stopPropagation(),e.preventDefault(),r(i,l))}function I(e,t){for(let n of(e.addEventListener("keydown",l),[L,d,w,P,s]))n(e,t);return e.addEventListener("paste",a),{unsubscribe:()=>{e.removeEventListener("keydown",l),e.removeEventListener("paste",a),e.removeEventListener("dragover",M),e.removeEventListener("drop",S),e.removeEventListener("paste",C),e.removeEventListener("paste",u),e.removeEventListener("dragover",f),e.removeEventListener("drop",h),e.removeEventListener("paste",p),e.removeEventListener("paste",E),e.removeEventListener("paste",H)}}}},50515:(e,t,n)=>{"use strict";n.d(t,{JC:()=>b,KK:()=>SequenceTracker,Vy:()=>a,ai:()=>v,rd:()=>c});let Leaf=class Leaf{constructor(e){this.children=[],this.parent=e}delete(e){let t=this.children.indexOf(e);return -1!==t&&(this.children=this.children.slice(0,t).concat(this.children.slice(t+1)),0===this.children.length&&this.parent.delete(this),!0)}add(e){return this.children.push(e),this}};let RadixTrie=class RadixTrie{constructor(e){this.parent=null,this.children={},this.parent=e||null}get(e){return this.children[e]}insert(e){let t=this;for(let n=0;n","\xbf":"?"},i={"`":"~",1:"!",2:"@",3:"#",4:"$",5:"%",6:"^",7:"&",8:"*",9:"(",0:")","-":"_","=":"+","[":"{","]":"}","\\":"|",";":":","'":'"',",":"<",".":">","/":"?",q:"Q",w:"W",e:"E",r:"R",t:"T",y:"Y",u:"U",i:"I",o:"O",p:"P",a:"A",s:"S",d:"D",f:"F",g:"G",h:"H",j:"J",k:"K",l:"L",z:"Z",x:"X",c:"C",v:"V",b:"B",n:"N",m:"M"},l={" ":"Space","+":"Plus"};function a(e,t=navigator.platform){var n,s,c;let{ctrlKey:d,altKey:h,metaKey:f,shiftKey:p,key:m}=e,g=[];for(let[e,t]of[d,h,f,p].entries())t&&g.push(o[e]);if(!o.includes(m)){let e=g.includes("Alt")&&u.test(t)&&null!=(n=r[m])?n:m,a=g.includes("Shift")&&u.test(t)&&null!=(s=i[e])?s:e,o=null!=(c=l[a])?c:a;g.push(o)}return g.join("+")}let o=["Control","Alt","Meta","Shift"];function s(e,t){let n,r,i;{var l,a,o,s=(l=e,a=t,r="undefined"==typeof window?void 0:window,i=u.test(null!=(o=null!=a?a:null==r?void 0:r.navigator.platform)?o:"")?"Meta":"Control",n=l.replace("Mod",i));let c=s.split("+").pop(),d=[];for(let e of["Control","Alt","Meta","Shift"])s.includes(e)&&d.push(e);return c&&d.push(c),d.join("+")}}let u=/Mac|iPod|iPhone|iPad/i;let SequenceTracker=class SequenceTracker{constructor({onReset:e}={}){this._path=[],this.timer=null,this.onReset=e}get path(){return this._path}get sequence(){return this._path.join(" ")}registerKeypress(e){this._path=[...this._path,a(e)],this.startTimer()}reset(){var e;this.killTimer(),this._path=[],null==(e=this.onReset)||e.call(this)}killTimer(){null!=this.timer&&window.clearTimeout(this.timer),this.timer=null}startTimer(){this.killTimer(),this.timer=window.setTimeout(()=>this.reset(),SequenceTracker.CHORD_TIMEOUT)}};function c(e){return e.split(" ").map(e=>s(e)).join(" ")}function d(e){if(!(e instanceof HTMLElement))return!1;let t=e.nodeName.toLowerCase(),n=(e.getAttribute("type")||"").toLowerCase();return"select"===t||"textarea"===t||"input"===t&&"submit"!==n&&"reset"!==n&&"checkbox"!==n&&"radio"!==n&&"file"!==n||e.isContentEditable}SequenceTracker.CHORD_TIMEOUT=1500;let h=new RadixTrie,f=new WeakMap,p=h,m=new SequenceTracker({onReset(){p=h}});function g(e){if(e.defaultPrevented||!(e.target instanceof Node))return;if(d(e.target)){let t=e.target;if(!t.id||!t.ownerDocument.querySelector(`[data-hotkey-scope="${t.id}"]`))return}let t=p.get(a(e));if(!t)return void m.reset();if(m.registerKeypress(e),p=t,t instanceof Leaf){let r,i=e.target,l=!1,a=d(i);for(let e=t.children.length-1;e>=0;e-=1){let n=(r=t.children[e]).getAttribute("data-hotkey-scope");if(!a&&!n||a&&i.id===n){l=!0;break}}if(r&&l){var n;let t;n=r,t=new CustomEvent("hotkey-fire",{cancelable:!0,detail:{path:m.path}}),n.dispatchEvent(t)&&(d(n)?n.focus():n.click()),e.preventDefault()}m.reset()}}function v(e,t){0===Object.keys(h.children).length&&document.addEventListener("keydown",g);let n=(function(e){let t=[],n=[""],r=!1;for(let i=0;ie.map(e=>s(e)).filter(e=>""!==e)).filter(e=>e.length>0)})(t||e.getAttribute("data-hotkey")||"").map(t=>h.insert(t).add(e));f.set(e,n)}function b(e){let t=f.get(e);if(t&&t.length)for(let n of t)n&&n.delete(e);0===Object.keys(h.children).length&&document.removeEventListener("keydown",g)}},51031:e=>{"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},55150:(e,t,n)=>{"use strict";n.d(t,{Bu:()=>u,YV:()=>o,o:()=>s});let r=null;function i(e){return e instanceof HTMLSelectElement||(a(e)?e.checked!==e.defaultChecked:e.value!==e.defaultValue)}function l(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement}function a(e){return e instanceof HTMLInputElement&&/checkbox|radio/.test(e.type)}function o(e,t){var n,a,o,s,u,c;let d,h=null!=(n=null==t?void 0:t.scope)?n:document,f=null!=(a=null==t?void 0:t.selector)?a:".js-session-resumable",p=null!=(o=null==t?void 0:t.fields)?o:h.querySelectorAll(f),m=null!=(s=null==t?void 0:t.keyPrefix)?s:"session-resume:",g=null!=(u=null==t?void 0:t.storageFilter)?u:i;try{d=null!=(c=null==t?void 0:t.storage)?c:sessionStorage}catch(e){return}let v=`${m}${e}`,b=[];for(let e of p)l(e)&&b.push(e);let y=b.filter(e=>!!e.id&&g(e)&&e.form!==r).map(e=>e instanceof HTMLSelectElement?[e.id,Array.from(e.selectedOptions).map(e=>e.value)]:[e.id,e.value]);if(y.length)try{let e=d.getItem(v);if(null!==e){let t=JSON.parse(e).filter(function(e){return!y.some(t=>t[0]===e[0])});y=y.concat(t)}d.setItem(v,JSON.stringify(y))}catch(e){}}function s(e,t){var n,r;let i,o,s=null!=(n=null==t?void 0:t.keyPrefix)?n:"session-resume:";try{i=null!=(r=null==t?void 0:t.storage)?r:sessionStorage}catch(e){return}let u=`${s}${e}`;try{o=i.getItem(u)}catch(e){}if(!o)return;let c=[],d=[];for(let[e,t]of JSON.parse(o)){let n=new CustomEvent("session:resume",{bubbles:!0,cancelable:!0,detail:{targetId:e,targetValue:t}});if(document.dispatchEvent(n)){let n=document.getElementById(e);if(l(n))if(n instanceof HTMLSelectElement){for(let e of n.options)e.selected=t.includes(e.value);c.push(n)}else a(n)?(n.checked=!n.defaultChecked,c.push(n)):n.value===n.defaultValue&&(n.value=t,c.push(n));else d.push([e,t])}}if(0===d.length)try{i.removeItem(u)}catch(e){}else i.setItem(u,JSON.stringify(d));setTimeout(function(){for(let e of c)e.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!0}))},0)}function u(e){r=e.target,setTimeout(function(){e.defaultPrevented&&(r=null)},0)}},57226:(e,t,n)=>{"use strict";n.d(t,{Ck:()=>C,fK:()=>L,zB:()=>x});let r=()=>{let e=performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart{if("loading"===document.readyState)return"loading";{let t=r();if(t){if(e{let t=e.nodeName;return 1===e.nodeType?t.toLowerCase():t.toUpperCase().replace(/^#/,"")},a=new WeakMap;function o(e,t){return a.get(e)||a.set(e,new t),a.get(e)}let s=-1,u=e=>{addEventListener("pageshow",t=>{t.persisted&&(s=t.timeStamp,e(t))},!0)},c=(e,t,n,r)=>{let i,l;return a=>{let o;t.value>=0&&(a||r)&&((l=t.value-(i??0))||void 0===i)&&(i=t.value,t.delta=l,o=t.value,t.rating=o>n[1]?"poor":o>n[0]?"needs-improvement":"good",e(t))}},d=e=>{requestAnimationFrame(()=>requestAnimationFrame(()=>e()))},h=()=>{let e=r();return e?.activationStart??0},f=(e,t=-1)=>{let n=r(),i="navigate";return s>=0?i="back-forward-cache":n&&(document.prerendering||h()>0?i="prerender":document.wasDiscarded?i="restore":n.type&&(i=n.type.replace(/_/g,"-"))),{name:e,value:t,rating:"good",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(0x82f79cd8fff*Math.random())+1e12}`,navigationType:i}},p=(e,t,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(e)){let r=new PerformanceObserver(e=>{Promise.resolve().then(()=>{t(e.getEntries())})});return r.observe({type:e,buffered:!0,...n}),r}}catch{}},m=e=>{let t=!1;return()=>{t||(e(),t=!0)}},g=-1,v=new Set,b=()=>"hidden"!==document.visibilityState||document.prerendering?1/0:0,y=e=>{if("hidden"===document.visibilityState){if("visibilitychange"===e.type)for(let e of v)e();isFinite(g)||(g="visibilitychange"===e.type?e.timeStamp:0,removeEventListener("prerenderingchange",y,!0))}},T=()=>{if(g<0){let e=h();g=(document.prerendering?void 0:globalThis.performance.getEntriesByType("visibility-state").filter(t=>"hidden"===t.name&&t.startTime>e)[0]?.startTime)??b(),addEventListener("visibilitychange",y,!0),addEventListener("prerenderingchange",y,!0),u(()=>{setTimeout(()=>{g=b()})})}return{get firstHiddenTime(){return g},onHidden(e){v.add(e)}}},w=e=>{document.prerendering?addEventListener("prerenderingchange",()=>e(),!0):e()},E=[1800,3e3],x=(e,t={})=>{((e,t={})=>{w(()=>{let n=T(),r,i=f("FCP"),l=p("paint",e=>{for(let t of e)"first-contentful-paint"===t.name&&(l.disconnect(),t.startTime{r=c(e,i=f("FCP"),E,t.reportAllChanges),d(()=>{i.value=performance.now()-n.timeStamp,r(!0)})}))})})(t=>{e((e=>{let t={timeToFirstByte:0,firstByteToFCP:e.value,loadState:i(s)};if(e.entries.length){let n=r(),l=e.entries.at(-1);if(n){let r=n.activationStart||0,a=Math.max(0,n.responseStart-r);t={timeToFirstByte:a,firstByteToFCP:e.value-a,loadState:i(e.entries[0].startTime),navigationEntry:n,fcpEntry:l}}}return Object.assign(e,{attribution:t})})(t))},t)};let N=class N{m;u(e){this.m?.(e)}};let k=[2500,4e3],L=(e,t={})=>{let n=o(t=Object.assign({},t),N),i=new WeakMap;n.m=e=>{let n=e.element;if(n){let r=t.generateTarget?.(n)??(e=>{let t="";try{for(;9!==e?.nodeType;){let n=e,r=n.id?"#"+n.id:[l(n),...Array.from(n.classList).sort()].join(".");if(t.length+r.length>99)return t||r;if(t=t?r+">"+t:r,n.id)break;e=n.parentNode}}catch{}return t})(n);i.set(e,r)}},((e,t={})=>{w(()=>{let n=T(),r,i=f("LCP"),l=o(t,N),a=e=>{for(let a of(t.reportAllChanges||(e=e.slice(-1)),e))l.u(a),a.startTime{a(s.takeRecords()),s.disconnect(),r(!0)}),l=e=>{var t;let r;e.isTrusted&&(t=n,r=globalThis.requestIdleCallback||setTimeout,"hidden"===document.visibilityState?t():(addEventListener("visibilitychange",t=m(t),{once:!0,capture:!0}),r(()=>{t(),removeEventListener("visibilitychange",t,{capture:!0})})),removeEventListener(e.type,l,{capture:!0}))};for(let e of["keydown","click","visibilitychange"])addEventListener(e,l,{capture:!0});u(n=>{r=c(e,i=f("LCP"),k,t.reportAllChanges),d(()=>{i.value=performance.now()-n.timeStamp,r(!0)})})}})})(t=>{e((e=>{let t={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadDuration:0,elementRenderDelay:e.value};if(e.entries.length){let n=r();if(n){let r=n.activationStart||0,l=e.entries.at(-1),a=l.url&&performance.getEntriesByType("resource").filter(e=>e.name===l.url)[0],o=Math.max(0,n.responseStart-r),s=Math.max(o,a?(a.requestStart||a.startTime)-r:0),u=Math.min(e.value,Math.max(s,a?a.responseEnd-r:0));t={target:i.get(l),timeToFirstByte:o,resourceLoadDelay:s-o,resourceLoadDuration:u-s,elementRenderDelay:e.value-u,navigationEntry:n,lcpEntry:l},l.url&&(t.url=l.url),a&&(t.lcpResourceEntry=a)}}return Object.assign(e,{attribution:t})})(t))},t)},S=[800,1800],M=e=>{document.prerendering?w(()=>M(e)):"complete"!==document.readyState?addEventListener("load",()=>M(e),!0):setTimeout(e)},C=(e,t={})=>{((e,t={})=>{let n=f("TTFB"),i=c(e,n,S,t.reportAllChanges);M(()=>{let l=r();l&&(n.value=Math.max(l.responseStart-h(),0),n.entries=[l],i(!0),u(()=>{(i=c(e,n=f("TTFB",0),S,t.reportAllChanges))(!0)}))})})(t=>{e((e=>{let t={waitingDuration:0,cacheDuration:0,dnsDuration:0,connectionDuration:0,requestDuration:0};if(e.entries.length){let n=e.entries[0],r=n.activationStart||0,i=Math.max((n.workerStart||n.fetchStart)-r,0),l=Math.max(n.domainLookupStart-r,0),a=Math.max(n.connectStart-r,0),o=Math.max(n.connectEnd-r,0);t={waitingDuration:i,cacheDuration:l-i,dnsDuration:a-l,connectionDuration:o-a,requestDuration:e.value-o,navigationEntry:n}}return Object.assign(e,{attribution:t})})(t))},t)}},66661:(e,t,n)=>{"use strict";function r(e){let t=e.parentNode;if(null===t||!(t instanceof HTMLElement))throw Error();let n=0;t instanceof HTMLOListElement&&1!==t.start&&(n=t.start-1);let r=t.children;for(let t=0;tQuote,g:()=>MarkdownQuote});let i=0;function l(e){return e.replace(/&/g,"&").replace(/'/g,"'").replace(/"/g,""").replace(//g,">")}let a={INPUT:e=>e instanceof HTMLInputElement&&e.checked?"[x] ":"[ ] ",CODE(e){let t=e.textContent||"";return e.parentNode&&"PRE"===e.parentNode.nodeName?(e.textContent=`\`\`\` +${t.replace(/\n+$/,"")} +\`\`\` + +`,e):t.indexOf("`")>=0?`\`\` ${t} \`\``:`\`${t}\``},P(e){let t=document.createElement("p");return t.textContent=(e.textContent||"").replace(/<(\/?)(pre|strong|weak|em)>/g,"\\<$1$2\\>"),t},STRONG:e=>`**${e.textContent||""}**`,EM:e=>`_${e.textContent||""}_`,DEL:e=>`~${e.textContent||""}~`,BLOCKQUOTE(e){let t=(e.textContent||"").trim().replace(/^/gm,"> "),n=document.createElement("pre");return n.textContent=`${t} + +`,n},A(e){let t=e.textContent||"",n=e.getAttribute("href");return/^https?:/.test(t)&&t===n?t:n?`[${t}](${n})`:t},IMG(e){let t=e.getAttribute("alt")||"",n=e.getAttribute("src");if(!n)throw Error();let r=e.hasAttribute("width")?` width="${l(e.getAttribute("width")||"")}"`:"",i=e.hasAttribute("height")?` height="${l(e.getAttribute("height")||"")}"`:"";return r||i?`${l(t)}`:`![${t}](${n})`},LI(e){let t,n,l=e.parentNode;if(!l)throw Error();let a="";if(t=e.childNodes[0],n=e.childNodes[1],!t||!(e.childNodes.length<3)||"OL"!==t.nodeName&&"UL"!==t.nodeName||n&&(n.nodeType!==Node.TEXT_NODE||(n.textContent||"").trim()))if("OL"===l.nodeName)if(i>0&&!l.previousSibling){let t=r(e)+i+1;a=`${t}\\. `}else a=`${r(e)+1}. `;else a="* ";let o=a.replace(/\S/g," "),s=(e.textContent||"").trim().replace(/^/gm,o),u=document.createElement("pre");return u.textContent=s.replace(o,a),u},OL(e){let t=document.createElement("li");return t.appendChild(document.createElement("br")),e.append(t),e},H1(e){let t=parseInt(e.nodeName.slice(1));return e.prepend(`${Array(t+1).join("#")} `),e},UL:e=>e};a.UL=a.OL;for(let e=2;e<=6;++e)a[`H${e}`]=a.H1;let Quote=class Quote{constructor(){this.selection=window.getSelection(),this.processSelectionText=e=>e}closest(e){let t=this.range.startContainer,n=t instanceof Element?t:t.parentElement;return n?n.closest(e):null}get active(){var e;return((null==(e=this.selection)?void 0:e.rangeCount)||0)>0}get range(){var e;return(null==(e=this.selection)?void 0:e.rangeCount)?this.selection.getRangeAt(0):new Range}set range(e){var t,n;null==(t=this.selection)||t.removeAllRanges(),null==(n=this.selection)||n.addRange(e)}set processSelectionTextFn(e){this.processSelectionText=e}get selectionText(){var e;return this.processSelectionText((null==(e=this.selection)?void 0:e.toString().trim())||"")}get quotedText(){return`> ${this.selectionText.replace(/\n/g,` +> `)} + +`}select(e){this.selection&&(this.selection.removeAllRanges(),this.selection.selectAllChildren(e))}insert(e){e.value?e.value=`${e.value} + +${this.quotedText}`:e.value=this.quotedText,e.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1})),e.focus(),e.selectionStart=e.value.length,e.scrollTop=e.scrollHeight}};let MarkdownQuote=class MarkdownQuote extends Quote{constructor(e="",t){super(),this.scopeSelector=e,this.callback=t}get selectionText(){var e,t;if(!this.selection)return"";let n=function(e,t){let n=e.startContainer;if(!n||!n.parentNode||!(n.parentNode instanceof HTMLElement))throw Error("the range must start within an HTMLElement");let l=n.parentNode,a=e.cloneContents();if(t){let e=a.querySelector(t);e&&(a=document.createDocumentFragment()).appendChild(e)}i=0;let o=l.closest("li");if(l.closest("pre")){let e=document.createElement("pre");e.appendChild(a),(a=document.createDocumentFragment()).appendChild(e)}else if(o&&o.parentNode&&("OL"===o.parentNode.nodeName&&(i=r(o)),!a.querySelector("li"))){let e=document.createElement("li");if(!o.parentNode)throw Error();let t=document.createElement(o.parentNode.nodeName);e.appendChild(a),t.appendChild(e),(a=document.createDocumentFragment()).appendChild(t)}return a}(this.range,null!=(e=this.scopeSelector)?e:"");null==(t=this.callback)||t.call(this,n);let l=document.createNodeIterator(n,NodeFilter.SHOW_ELEMENT,{acceptNode:e=>e.nodeName in a&&!function(e){if(e instanceof HTMLAnchorElement&&1===e.childNodes.length){let t=e.childNodes[0];if(t instanceof HTMLImageElement)return t.src===e.href}return!1}(e)&&("IMG"===e.nodeName||null!=e.firstChild||"INPUT"===e.nodeName&&e instanceof HTMLInputElement&&"checkbox"===e.type)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}),o=[],s=l.nextNode();for(;s;)s instanceof HTMLElement&&o.push(s),s=l.nextNode();for(let e of(o.reverse(),o))e.replaceWith(a[e.nodeName](e));let u=document.body;if(!u)return"";let c=document.createElement("div");c.appendChild(n),c.style.cssText="position:absolute;left:-9999px;",u.appendChild(c);let d="";try{let e=document.createRange();e.selectNodeContents(c),this.selection.removeAllRanges(),this.selection.addRange(e),d=this.selection.toString(),this.selection.removeAllRanges(),e.detach()}finally{u.removeChild(c)}return this.processSelectionText(d.trim())}}},70837:(e,t,n)=>{"use strict";function r(e="ha"){let t,n={};for(let r of Array.from(document.head.querySelectorAll(`meta[name^="${e}-"]`))){let{name:i,content:l}=r,a=i.replace(`${e}-`,"").replace(/-/g,"_");"url"===a?t=l:n[a]=l}if(!t)throw Error(`AnalyticsClient ${e}-url meta tag not found`);return{collectorUrl:t,...Object.keys(n).length>0?{baseContext:n}:{}}}n.d(t,{O:()=>r})},77783:(e,t,n)=>{"use strict";let r;function i(e){return new Promise((t,n)=>{e.oncomplete=e.onsuccess=()=>t(e.result),e.onabort=e.onerror=()=>n(e.error)})}function l(e,t){let n;return(r,l)=>(()=>{if(n)return n;let r=indexedDB.open(e);return r.onupgradeneeded=()=>r.result.createObjectStore(t),(n=i(r)).then(e=>{e.onclose=()=>n=void 0},()=>{}),n})().then(e=>l(e.transaction(t,r).objectStore(t)))}function a(){return r||(r=l("keyval-store","keyval")),r}function o(e,t=a()){return t("readonly",t=>i(t.get(e)))}function s(e,t,n=a()){return n("readwrite",n=>(n.put(t,e),i(n.transaction)))}function u(e,t=a()){return t("readwrite",t=>(t.delete(e),i(t.transaction)))}function c(e=a()){return e("readwrite",e=>(e.clear(),i(e.transaction)))}function d(e=a()){return e("readonly",t=>{if(t.getAll&&t.getAllKeys)return Promise.all([i(t.getAllKeys()),i(t.getAll())]).then(([e,t])=>e.map((e,n)=>[e,t[n]]));let n=[];return e("readonly",e=>{var t;return(t=e=>n.push([e.key,e.value]),e.openCursor().onsuccess=function(){this.result&&(t(this.result),this.result.continue())},i(e.transaction)).then(()=>n)})})}n.d(t,{IU:()=>c,Jt:()=>o,hZ:()=>s,jO:()=>d,y$:()=>l,yH:()=>u})},78134:(e,t,n)=>{"use strict";n.d(t,{i4:()=>TemplateInstance,xr:()=>d});let r=new Map;function i(e){if(r.has(e))return r.get(e);let t=e.length,n=0,i=0,l=0,a=[];for(let r=0;rn&&(a.push(Object.freeze({type:"string",start:n,end:i,value:e.slice(n,i)})),n=i),a.push(Object.freeze({type:"part",start:i,end:r+2,value:e.slice(n+2,r).trim()})),r+=1,n=r+1)}return n"string"==typeof e?e:e.value).join("");this.element.setAttributeNS(this.attr.namespaceURI,this.attr.name,e)}}};let o=new WeakMap;let NodeTemplatePart=class NodeTemplatePart{constructor(e,t){this.expression=t,o.set(this,[e]),e.textContent=""}get value(){return o.get(this).map(e=>e.textContent).join("")}set value(e){this.replace(e)}get previousSibling(){return o.get(this)[0].previousSibling}get nextSibling(){return o.get(this)[o.get(this).length-1].nextSibling}replace(...e){var t,n;let r=e.map(e=>"string"==typeof e?new Text(e):e);r.length||r.push(new Text(""));let i=o.get(this)[0];for(let e of r)null==(t=i.parentNode)||t.insertBefore(e,i);for(let e of o.get(this))null==(n=e.parentNode)||n.removeChild(e);o.set(this,r)}};let InnerTemplatePart=class InnerTemplatePart extends NodeTemplatePart{constructor(e){var t;super(e,null!=(t=e.getAttribute("expression"))?t:""),this.template=e}get directive(){var e;return null!=(e=this.template.getAttribute("directive"))?e:""}};function s(e){return{processCallback(t,n,r){var i;if("object"==typeof r&&r){for(let t of n)if(t.expression in r){let n=null!=(i=r[t.expression])?i:"";e(t,n,r)}}}}}function u(e,t){e.value=t instanceof Node?t:String(t)}let c=s(u),d=s((e,t)=>{"boolean"==typeof t&&e instanceof AttributeTemplatePart&&"boolean"==typeof e.element[e.attributeName]&&(e.booleanValue=t,1)||u(e,t)}),h=new WeakMap,f=new WeakMap;let TemplateInstance=class TemplateInstance extends(globalThis.DocumentFragment||EventTarget){constructor(e,t,n=c){var r,l;super(),Object.getPrototypeOf(this)!==TemplateInstance.prototype&&Object.setPrototypeOf(this,TemplateInstance.prototype),this.appendChild(e.content.cloneNode(!0)),f.set(this,Array.from(function* e(t){let n,r=t.ownerDocument.createTreeWalker(t,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null);for(;n=r.nextNode();)if(n instanceof HTMLTemplateElement)if(n.hasAttribute("directive"))yield new InnerTemplatePart(n);else for(let t of e(n.content))yield t;else if(n instanceof Element&&n.hasAttributes())for(let e=0;e{"use strict";function r(e,t,n){if(!t.has(e))throw TypeError("attempted to get private field on non-instance");return n}n.d(t,{_:()=>r})},95493:(e,t,n)=>{"use strict";function r(e,t){return i(function(e){if(e.activeElement!==e.body)return e.activeElement;var t=e.querySelectorAll(":hover"),n=t.length;if(n)return t[n-1]}(e),t)}function i(e,t){var n=e;if(!n)return Promise.resolve(t());var r=n.ownerDocument.documentElement,i=function(e){for(var t=[];e;){var n=e.getBoundingClientRect(),r=n.top,i=n.left;t.push({element:e,top:r,left:i}),e=e.parentElement}return t}(n);return Promise.resolve(t()).then(function(e){var t=function(e){for(var t=0;tr,_H:()=>i})},95754:(e,t,n)=>{"use strict";n.d(t,{A:()=>l});let r=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","borderStyle","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing","tabSize","MozTabSize"],i="undefined"!=typeof window&&null!=window.mozInnerScreenX;function l(e,t,n){let l=n&&n.debug||!1;if(l){let e=document.querySelector("#input-textarea-caret-position-mirror-div");e&&e.parentNode.removeChild(e)}let a=document.createElement("div");a.id="input-textarea-caret-position-mirror-div",document.body.appendChild(a);let o=a.style,s=window.getComputedStyle?window.getComputedStyle(e):e.currentStyle,u="INPUT"===e.nodeName;for(let t of(o.whiteSpace="pre-wrap",u||(o.wordWrap="break-word"),o.position="absolute",l||(o.visibility="hidden"),r))if(u&&"lineHeight"===t)if("border-box"===s.boxSizing){let e=parseInt(s.height),t=parseInt(s.paddingTop)+parseInt(s.paddingBottom)+parseInt(s.borderTopWidth)+parseInt(s.borderBottomWidth),n=t+parseInt(s.lineHeight);e>n?o.lineHeight=`${e-t}px`:e===n?o.lineHeight=s.lineHeight:o.lineHeight=0}else o.lineHeight=s.height;else if(u||"width"!==t||"border-box"!==s.boxSizing)o[t]=s[t];else{let n=parseFloat(s.borderLeftWidth)+parseFloat(s.borderRightWidth),r=i?parseFloat(s[t])-n:e.clientWidth+n;o[t]=`${r}px`}i?e.scrollHeight>parseInt(s.height)&&(o.overflowY="scroll"):o.overflow="hidden",a.textContent=e.value.substring(0,t),u&&(a.textContent=a.textContent.replace(/\s/g,"\xa0"));let c=document.createElement("span");c.textContent=e.value.substring(t)||".",a.appendChild(c);let d={top:c.offsetTop+parseInt(s.borderTopWidth),left:c.offsetLeft+parseInt(s.borderLeftWidth),height:parseInt(s.lineHeight)};return l?c.style.backgroundColor="#aaa":document.body.removeChild(a),d}}}]); +//# sourceMappingURL=66721-cd654e33abbf.js.map \ No newline at end of file diff --git a/913-ca2305638c53.js b/913-ca2305638c53.js new file mode 100644 index 0000000..9fa5838 --- /dev/null +++ b/913-ca2305638c53.js @@ -0,0 +1,64 @@ +"use strict";(globalThis.webpackChunk_github_ui_github_ui=globalThis.webpackChunk_github_ui_github_ui||[]).push([[913],{913:(e,t,o)=>{o.r(t),o.d(t,{apply:()=>N,injectStyles:()=>C,isPolyfilled:()=>D,isSupported:()=>H});var n=class extends Event{oldState;newState;constructor(e,{oldState:t="",newState:o="",...n}={}){super(e,n),this.oldState=String(t||""),this.newState=String(o||"")}},r=new WeakMap;function i(e,t,o){r.set(e,setTimeout(()=>{r.has(e)&&e.dispatchEvent(new n("toggle",{cancelable:!1,oldState:t,newState:o}))},0))}var l=globalThis.ShadowRoot||function(){},a=globalThis.HTMLDialogElement||function(){},p=new WeakMap,u=new WeakMap,s=new WeakMap;function c(e){return s.get(e)||"hidden"}var f=new WeakMap;function d(e,t){return!("auto"!==e.popover&&"manual"!==e.popover||!e.isConnected||t&&"showing"!==c(e)||!t&&"hidden"!==c(e)||e instanceof a&&e.hasAttribute("open"))&&document.fullscreenElement!==e}function h(e){return e?Array.from(u.get(e.ownerDocument)||[]).indexOf(e)+1:0}function g(e){let t=u.get(e);for(let e of t||[])if(e.isConnected)return e;else t.delete(e);return null}function m(e){return"function"==typeof e.getRootNode?e.getRootNode():e.parentNode?m(e.parentNode):e}function v(e){for(;e;){if(e instanceof HTMLElement&&"auto"===e.popover&&"showing"===s.get(e))return e;if((e=e instanceof Element&&e.assignedSlot||e.parentElement||m(e))instanceof l&&(e=e.host),e instanceof Document)return}}var w=new WeakMap;function b(e){if(!d(e,!1))return;let t=e.ownerDocument;if(!e.dispatchEvent(new n("beforetoggle",{cancelable:!0,oldState:"closed",newState:"open"}))||!d(e,!1))return;let o=!1;if("auto"===e.popover){let o=e.getAttribute("popover");if(T(function(e){let t=new Map,o=0;for(let n of u.get(e.ownerDocument)||[])t.set(n,o),o+=1;t.set(e,o),o+=1;let n=null;return!function(e){let o=v(e);if(null===o)return;let r=t.get(o);(null===n||t.get(n)h(o)?t:o);if(i&&"pointerdown"===e.type)S.set(r,i);else if("pointerup"===e.type){let e=S.get(r)===i;S.delete(r),e&&T(i||r,!1,!0)}}var L=new WeakMap;function A(e,t=!1){if(!e)return;L.has(e)||L.set(e,e.getAttribute("aria-expanded"));let o=e.popoverTargetElement;if(o instanceof HTMLElement&&"auto"===o.popover)e.setAttribute("aria-expanded",String(t));else{let t=L.get(e);t?e.setAttribute("aria-expanded",t):e.removeAttribute("aria-expanded")}}var k=globalThis.ShadowRoot||function(){};function H(){return"undefined"!=typeof HTMLElement&&"object"==typeof HTMLElement.prototype&&"popover"in HTMLElement.prototype}function D(){return!!(document.body?.showPopover&&!/native code/i.test(document.body.showPopover.toString()))}function x(e,t,o){let n=e[t];Object.defineProperty(e,t,{value(e){return n.call(this,o(e))}})}var P=/(^|[^\\]):popover-open\b/g,R=null;function C(e){let t,o=(t="function"==typeof globalThis.CSSLayerBlockRule,` +${t?"@layer popover-polyfill {":""} + :where([popover]) { + position: fixed; + z-index: 2147483647; + inset: 0; + padding: 0.25em; + width: fit-content; + height: fit-content; + border-width: initial; + border-color: initial; + border-image: initial; + border-style: solid; + background-color: canvas; + color: canvastext; + overflow: auto; + margin: auto; + } + + :where([popover]:not(.\\:popover-open)) { + display: none; + } + + :where(dialog[popover].\\:popover-open) { + display: block; + } + + :where(dialog[popover][open]) { + display: revert; + } + + :where([anchor].\\:popover-open) { + inset: auto; + } + + :where([anchor]:popover-open) { + inset: auto; + } + + @supports not (background-color: canvas) { + :where([popover]) { + background-color: white; + color: black; + } + } + + @supports (width: -moz-fit-content) { + :where([popover]) { + width: -moz-fit-content; + height: -moz-fit-content; + } + } + + @supports not (inset: 0) { + :where([popover]) { + top: 0; + left: 0; + right: 0; + bottom: 0; + } + } +${t?"}":""} +`);if(null===R)try{(R=new CSSStyleSheet).replaceSync(o)}catch{R=!1}if(!1===R){let t=document.createElement("style");t.textContent=o,e instanceof Document?e.head.prepend(t):e.prepend(t)}else e.adoptedStyleSheets=[R,...e.adoptedStyleSheets]}function N(){var e;if("undefined"==typeof window)return;function t(e){return e?.includes(":popover-open")&&(e=e.replace(P,"$1.\\:popover-open")),e}window.ToggleEvent=window.ToggleEvent||n,x(Document.prototype,"querySelector",t),x(Document.prototype,"querySelectorAll",t),x(Element.prototype,"querySelector",t),x(Element.prototype,"querySelectorAll",t),x(Element.prototype,"matches",t),x(Element.prototype,"closest",t),x(DocumentFragment.prototype,"querySelectorAll",t),Object.defineProperties(HTMLElement.prototype,{popover:{enumerable:!0,configurable:!0,get(){if(!this.hasAttribute("popover"))return null;let e=(this.getAttribute("popover")||"").toLowerCase();return""===e||"auto"==e?"auto":"manual"},set(e){null===e?this.removeAttribute("popover"):this.setAttribute("popover",e)}},showPopover:{enumerable:!0,configurable:!0,value(){b(this)}},hidePopover:{enumerable:!0,configurable:!0,value(){y(this,!0,!0)}},togglePopover:{enumerable:!0,configurable:!0,value(e){"showing"===s.get(this)&&void 0===e||!1===e?y(this,!0,!0):(void 0===e||!0===e)&&b(this)}}});let o=Element.prototype.attachShadow;o&&Object.defineProperties(Element.prototype,{attachShadow:{enumerable:!0,configurable:!0,writable:!0,value(e){let t=o.call(this,e);return C(t),t}}});let r=HTMLElement.prototype.attachInternals;r&&Object.defineProperties(HTMLElement.prototype,{attachInternals:{enumerable:!0,configurable:!0,writable:!0,value(){let e=r.call(this);return e.shadowRoot&&C(e.shadowRoot),e}}});let i=new WeakMap;function l(e){Object.defineProperties(e.prototype,{popoverTargetElement:{enumerable:!0,configurable:!0,set(e){if(null===e)this.removeAttribute("popovertarget"),i.delete(this);else if(e instanceof Element)this.setAttribute("popovertarget",""),i.set(this,e);else throw TypeError("popoverTargetElement must be an element or null")},get(){if("button"!==this.localName&&"input"!==this.localName||"input"===this.localName&&"reset"!==this.type&&"image"!==this.type&&"button"!==this.type||this.disabled||this.form&&"submit"===this.type)return null;let e=i.get(this);if(e&&e.isConnected)return e;if(e&&!e.isConnected)return i.delete(this),null;let t=m(this),o=this.getAttribute("popovertarget");return(t instanceof Document||t instanceof k)&&o&&t.getElementById(o)||null}},popoverTargetAction:{enumerable:!0,configurable:!0,get(){let e=(this.getAttribute("popovertargetaction")||"").toLowerCase();return"show"===e||"hide"===e?e:"toggle"},set(e){this.setAttribute("popovertargetaction",e)}}})}l(HTMLButtonElement),l(HTMLInputElement);(e=document).addEventListener("click",e=>{let t=e.composedPath(),o=t[0];if(!(o instanceof Element)||o?.shadowRoot)return;let n=m(o);if(!(n instanceof k||n instanceof Document))return;let r=t.find(e=>e.matches?.("[popovertargetaction],[popovertarget]"));if(r){!function(e){let t=e.popoverTargetElement;if(!(t instanceof HTMLElement))return;let o=c(t);"show"===e.popoverTargetAction&&"showing"===o||("hide"!==e.popoverTargetAction||"hidden"!==o)&&("showing"===o?y(t,!0,!0):d(t,!1)&&(f.set(t,e),b(t)))}(r),e.preventDefault();return}}),e.addEventListener("keydown",e=>{let t=e.key,o=e.target;!e.defaultPrevented&&o&&("Escape"===t||"Esc"===t)&&T(o.ownerDocument,!0,!0)}),e.addEventListener("pointerdown",M),e.addEventListener("pointerup",M),C(document)}}}]); +//# sourceMappingURL=913-6ad5fae424fd.js.map \ No newline at end of file diff --git a/AgentsIcon.tsx b/AgentsIcon.tsx new file mode 100644 index 0000000..df74548 --- /dev/null +++ b/AgentsIcon.tsx @@ -0,0 +1,39 @@ +import type {Icon} from '@primer/octicons-react' + +export const AgentsIcon16: Icon = props => { + return ( + + ) +} + +export const AgentsIcon32: Icon = props => { + return ( + + ) +} diff --git a/AnalyticsProvider.tsx b/AnalyticsProvider.tsx new file mode 100644 index 0000000..0e357ef --- /dev/null +++ b/AnalyticsProvider.tsx @@ -0,0 +1,10 @@ +import {useMemo} from 'react' +import type {PropsWithChildren} from 'react' +import {AnalyticsContext, type AnalyticsProviderProps} from './context' + +export function AnalyticsProvider({children, appName, category, metadata}: PropsWithChildren) { + const value = useMemo(() => ({appName, category, metadata}), [appName, category, metadata]) + return {children} +} + +try{ AnalyticsProvider.displayName ||= 'AnalyticsProvider' } catch {} \ No newline at end of file diff --git a/AuthorSettingsContext.tsx b/AuthorSettingsContext.tsx new file mode 100644 index 0000000..48ed6f5 --- /dev/null +++ b/AuthorSettingsContext.tsx @@ -0,0 +1,34 @@ +import {merge} from '@primer/styled-react' +import type React from 'react' +import {createContext, use} from 'react' + +export type AuthorSettings = { + fontWeight: 'normal' | 'semibold' | 'bold' + fontColor: 'fg.default' | 'fg.muted' + includeTooltip: boolean + avatarSize: 16 | 20 | undefined +} + +const defaultSettings: AuthorSettings = { + fontWeight: 'bold' as const, + fontColor: 'fg.default' as const, + includeTooltip: false, + avatarSize: undefined, // defaults to primer component default +} + +const AuthorSettingsContext = createContext(defaultSettings) + +export function AuthorSettingsProvider({ + authorSettings, + children, +}: React.PropsWithChildren<{authorSettings: Partial | undefined}>) { + const authorSettingsOrDefault = merge(defaultSettings, authorSettings ?? {}) + return {children} +} + +export function useAuthorSettings() { + return use(AuthorSettingsContext) || defaultSettings +} + +try{ AuthorSettingsContext.displayName ||= 'AuthorSettingsContext' } catch {} +try{ AuthorSettingsProvider.displayName ||= 'AuthorSettingsProvider' } catch {} \ No newline at end of file diff --git a/AuthorTooltip.tsx b/AuthorTooltip.tsx new file mode 100644 index 0000000..87781b7 --- /dev/null +++ b/AuthorTooltip.tsx @@ -0,0 +1,20 @@ +import {Tooltip} from '@primer/react/next' +import type {PropsWithChildren} from 'react' +import type {Author} from '../commit-attribution-types' + +type AuthorTooltipProps = { + author: Author + renderTooltip?: boolean +} + +export function AuthorTooltip({renderTooltip, author, children}: PropsWithChildren) { + if (renderTooltip === false) return <>{children} + + return ( + + {children} + + ) +} + +try{ AuthorTooltip.displayName ||= 'AuthorTooltip' } catch {} \ No newline at end of file diff --git a/Blankslate-f5a9755a.css b/Blankslate-f5a9755a.css new file mode 100644 index 0000000..986c128 --- /dev/null +++ b/Blankslate-f5a9755a.css @@ -0,0 +1,2 @@ +@layer primer-react { .prc-Blankslate-Container-Vr9Ce{container:blankslate/inline-size}.prc-Blankslate-Blankslate-Eihy3{display:grid;justify-items:center;padding:var(--blankslate-padding)}.prc-Blankslate-Blankslate-Eihy3:where([data-border]){border:var(--borderWidth-thin,.0625rem) solid var(--borderColor-default,var(--color-border-default));border-radius:var(--borderRadius-medium,.375rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-narrow]){margin:0 auto;max-width:485px}.prc-Blankslate-Blankslate-Eihy3:where([data-size=medium]){--blankslate-heading-text:var(--text-title-shorthand-medium,600 1.25rem/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-heading-margin-block:0 var(--base-size-4,0.25rem);--blankslate-description-text:var(--text-body-shorthand-large,400 1rem/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-padding:var(--base-size-32,2rem);--blankslate-action-margin-block-end:var(--base-size-16,1rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-size=medium][data-spacious]){--blankslate-padding:var(--base-size-80,5rem) var(--base-size-40,2.5rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-size=small]){--blankslate-heading-text:var(--text-title-shorthand-small,600 1rem/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-heading-margin-block:0 var(--base-size-4,0.25rem);--blankslate-description-text:var(--text-body-shorthand-medium,400 0.875rem/1.42857 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-padding:var(--base-size-32,2rem) var(--base-size-20,1.25rem);--blankslate-action-margin-block-end:var(--base-size-12,0.75rem);--blankslate-visual-size:var(--base-size-24,1.5rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-size=small][data-spacious]){--blankslate-padding:var(--base-size-44,2.75rem) var(--base-size-28,1.75rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-size=large]){--blankslate-heading-text:var(--text-title-shorthand-large,600 2rem/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-heading-margin-block:var(--base-size-8,0.5rem) var(--base-size-4,0.25rem);--blankslate-description-text:var(--text-body-shorthand-large,400 1rem/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-description-margin-block:0 var(--base-size-8,0.5rem);--blankslate-padding:var(--base-size-32,2rem);--blankslate-action-margin-block-end:var(--base-size-16,1rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-size=large][data-spacious]){--blankslate-padding:var(--base-size-80,5rem) var(--base-size-40,2.5rem)}.prc-Blankslate-Description-nqiRV,.prc-Blankslate-Heading-tVZsq{margin:0;text-align:center}.prc-Blankslate-Heading-tVZsq{font:var(--blankslate-heading-text);margin-block:var(--blankslate-heading-margin-block)}.prc-Blankslate-Description-nqiRV{font:var(--blankslate-description-text);margin-block:var(--blankslate-description-margin-block)}.prc-Blankslate-Description-nqiRV,.prc-Blankslate-Visual-10aPl{color:var(--fgColor-muted,var(--color-fg-muted))}.prc-Blankslate-Visual-10aPl{display:inline-flex;margin-block-end:var(--base-size-8,.5rem);max-width:var(--blankslate-visual-size)}.prc-Blankslate-Visual-10aPl svg{width:100%}.prc-Blankslate-Action-RsgHG{font:var(--blankslate-description-text);margin-block-start:var(--base-size-16,1rem)}.prc-Blankslate-Action-RsgHG:where(:last-of-type){margin-block-end:var(--blankslate-action-margin-block-end)}@container blankslate (max-width: 34rem){.prc-Blankslate-Blankslate-Eihy3{--blankslate-padding:var(--base-size-20,1.25rem)}.prc-Blankslate-Blankslate-Eihy3:where([data-spacious=true]){--blankslate-padding:var(--base-size-44,2.75rem) var(--base-size-28,1.75rem)}.prc-Blankslate-Blankslate-Eihy3{--blankslate-heading-text:var(--text-title-shorthand-small,600 1rem/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji");--blankslate-description-text:var(--text-body-shorthand-medium,400 0.875rem/1.42857 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji")}.prc-Blankslate-Visual-10aPl{color:var(--fgColor-muted,var(--color-fg-muted));margin-bottom:var(--base-size-8,.5rem);max-width:var(--base-size-24,1.5rem)}.prc-Blankslate-Action-RsgHG{margin-top:var(--base-size-8,.5rem)}.prc-Blankslate-Action-RsgHG:first-of-type{margin-top:var(--base-size-16,1rem)}.prc-Blankslate-Action-RsgHG:last-of-type{margin-bottom:calc(var(--base-size-8,.5rem)/2)}} +/*# sourceMappingURL=Blankslate-f5a9755a.css.map */ } \ No newline at end of file diff --git a/CommitAttribution.tsx b/CommitAttribution.tsx new file mode 100644 index 0000000..c3080ad --- /dev/null +++ b/CommitAttribution.tsx @@ -0,0 +1,196 @@ +import {Fragment, type PropsWithChildren} from 'react' + +import type {Author} from './commit-attribution-types' +import {AuthorsDialog} from './components/AuthorsDialog' +import {CommitAuthorStack} from './components/CommitAuthorStack' +import {AuthorLink} from './components/AuthorLink' +import {OrgLink} from './components/OrgLink' +import type {RepositoryNWO} from '@github-ui/current-repository' +import {AuthorAvatar} from './components/AuthorAvatar' +import {AuthorSettingsProvider, type AuthorSettings} from './contexts/AuthorSettingsContext' + +import {RepoPushIcon} from '@primer/octicons-react' +import styles from './CommitAttribution.module.css' +import {clsx} from 'clsx' + +export interface CommitAttributionProps { + authors: Author[] + committer?: Author + committerAttribution?: boolean + onBehalfOf?: Author + includeVerbs: boolean + repo: RepositoryNWO + authorSettings?: Partial + textVariant?: 'default' | 'muted' +} + +function SingleAuthor({author, repo}: {author: Author; repo: RepositoryNWO}) { + return +} + +function AuthorByline({ + author, + committer, + committerAttribution, + onBehalfOf, + repo, +}: { + author: Author + committer?: Author + committerAttribution?: boolean + onBehalfOf?: Author + repo: RepositoryNWO +}) { + const authors = [author] + if (committer && committerAttribution) { + authors.push(committer) + } + + return ( + <> + + + + ) +} + +function TwoAuthors({authors, onBehalfOf, repo}: {authors: Author[]; onBehalfOf?: Author; repo: RepositoryNWO}) { + return ( + <> + + {authors.map((author, index) => ( + // eslint-disable-next-line @eslint-react/no-array-index-key + + + {index !== authors.length - 1 && and} + + ))} + + ) +} + +function MultipleAuthors({authors, onBehalfOf, repo}: {authors: Author[]; onBehalfOf?: Author; repo: RepositoryNWO}) { + return ( + <> + + + + ) +} + +export function CommitAttribution({ + authors, + committer, + committerAttribution, + onBehalfOf, + repo, + children, + includeVerbs = true, + authorSettings, + textVariant = 'default', +}: PropsWithChildren) { + const singleAuthor = authors.length === 1 && !committerAttribution && !onBehalfOf + const authorAndCommitter = authors.length === 1 && (committerAttribution || onBehalfOf) + const inlineAuthorNames = authors.length === 2 && !committerAttribution + const multipleAuthors = !singleAuthor && !authorAndCommitter && !inlineAuthorNames + const firstAuthor = authors[0] + const verbClass = includeVerbs ? 'pl-1' : '' + + return ( +
      + + {singleAuthor && firstAuthor && } + {authorAndCommitter && firstAuthor && ( + + )} + {inlineAuthorNames && } + {multipleAuthors && } + + + + {onBehalfOf && ( + <> + on behalf of + + + )} + + {children} + +
      + ) +} + +function AuthoredOrCommitted({ + committer, + committerAttribution, + includeVerbs, + repo, + verbClass, +}: { + committer: Author | undefined + committerAttribution: boolean + includeVerbs: boolean + repo: RepositoryNWO + verbClass: string +}) { + if (committer && committer.isGitHub) { + return {includeVerbs && 'authored'} + } else if (!committerAttribution) { + return {includeVerbs && 'committed'} + } else { + return ( + <> + {includeVerbs ? 'authored and' : 'and'} + + {includeVerbs && 'committed'} + + ) + } +} + +export interface PushAttributionProps { + pusher?: Author + repo: RepositoryNWO + textVariant?: 'default' | 'muted' +} + +export function PushAttribution({ + pusher, + repo, + children, + textVariant = 'default', +}: PropsWithChildren) { + if (!pusher) return null + + return ( +
      + + + + + pushed + {children} +
      + ) +} + +try{ SingleAuthor.displayName ||= 'SingleAuthor' } catch {} +try{ AuthorByline.displayName ||= 'AuthorByline' } catch {} +try{ TwoAuthors.displayName ||= 'TwoAuthors' } catch {} +try{ MultipleAuthors.displayName ||= 'MultipleAuthors' } catch {} +try{ CommitAttribution.displayName ||= 'CommitAttribution' } catch {} +try{ AuthoredOrCommitted.displayName ||= 'AuthoredOrCommitted' } catch {} +try{ PushAttribution.displayName ||= 'PushAttribution' } catch {} \ No newline at end of file diff --git a/CommitAuthorStack.tsx b/CommitAuthorStack.tsx new file mode 100644 index 0000000..c6dc25f --- /dev/null +++ b/CommitAuthorStack.tsx @@ -0,0 +1,47 @@ +import {AvatarStack} from '@primer/react' +import {GitHubAvatar} from '@github-ui/github-avatar' +import {userHovercardPath, orgHovercardPath} from '@github-ui/paths' +import type {Author} from '../commit-attribution-types' +import {isBotOrApp} from '../utils' +import {useAuthorSettings} from '../contexts/AuthorSettingsContext' + +type CommitAuthorStackProps = { + authors: Author[] + onBehalfOf?: Author +} + +const maxAvatarCount = 5 + +export function CommitAuthorStack({authors, onBehalfOf}: CommitAuthorStackProps) { + const authorSettings = useAuthorSettings() + + return ( + + {authors.slice(0, maxAvatarCount).map((author, index) => ( + + ))} + {onBehalfOf && ( + + )} + + ) +} + +try{ CommitAuthorStack.displayName ||= 'CommitAuthorStack' } catch {} \ No newline at end of file diff --git a/Document.rtf b/Document.rtf new file mode 100644 index 0000000..6412f83 --- /dev/null +++ b/Document.rtf @@ -0,0 +1,6 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang4105{\fonttbl{\f0\fnil\fcharset0 Calibri;}{\f1\fnil\fcharset1 Cambria Math;}{\f2\fnil Calibri;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Riched20 10.0.26100}{\*\mmathPr\mmathFont1\mwrapIndent1440 }\viewkind4\uc1 +\pard\sa200\sl276\slmult1\f0\fs22\lang9 https://wpewebkit.org/wpt-status/<"line1"> <"line2"><html prefix="og: {{\field{\*\fldinst{HYPERLINK https://ogp.me/ns# }}{\fldrslt{https://ogp.me/ns#\ul0\cf0}}}}\f0\fs22 " lang="en"> <"line3"> <"line4"> <head> <"line5"> <"line6"> <meta charset="utf-8"> <"line7"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <"line8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <"line9"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <"line10"> <meta name="author" content=""> <"line11"> <"line12"> <title>WPE Specification Supporttitle> <"line13"> <link rel="canonical" href="https://wpewebkit.org/wpt-status/"> <"line14"> <link rel="alternate" type="application/rss+xml" title="WPE WebKit Blog" href="https://wpewebkit.org/blog.xml"> <"line15"> <link rel="alternate" type="application/rss+xml" title="WPE WebKit Posts" href="https://wpewebkit.org/feed.xml"> <"line16"> <link rel="alternate" type="application/rss+xml" title="WPE WebKit Security Advisories" href="https://wpewebkit.org/security.xml"> <"line17"> <meta property="og:url" content="https://wpewebkit.org/wpt-status/"> <"line18"> <meta property="og:title" content="WPE Specification Support"> <"line19"> <meta property="og:image" content="https://wpewebkit.org/assets/twitter_Profile_WhiteBg_400px.png"> <"line20"> <meta property="og:image:secure_url" content="https://wpewebkit.org/assets/twitter_Profile_WhiteBg_400px.png"> <"line21"> <meta property="og:image:alt" content="WPE logo"> <"line22"> <meta property="og:image:type" content="image/png"> <"line23"> <meta property="og:image:width" content="400"> <"line24"> <meta property="og:image:height" content="400"> <"line25"> <meta property="og:type" content="article"> <"line26"> <meta property="article:published_time" content="2025-12-19T15:45:15.557Z"> <"line27"> <meta property="article:tag" content="devs"> <"line28"> <meta name="twitter:card" content="summary"> <"line29"> <meta name="twitter:site" content="@WPEWebKit"> <"line30"> <"line31"> <"line32"> <link rel="stylesheet" href="/css/v2.css"> <"line33"> <"line34"> <"line35"> <link rel="stylesheet" href="/vendor/font-awesome/css/font-awesome.min.css"> <"line36"> <link rel="stylesheet" href="/css/fonts.css"> <"line37"> <"line38"> <"line39"> <link rel="stylesheet" href="/css/prism.css"> <"line40"> <"line41"> <"line42"> <link rel="stylesheet" href="/css/stylish-portfolio.css"> <"line43"> <script type="text/javascript"> <"line44"> window.addEventListener('load',function() \{document.querySelector('nav.global>div>.burger').addEventListener('click',menutog)\}); <"line45"> function menutog(e) \{ <"line46"> document.querySelector('nav.global>div>ul').classList.toggle('off'); <"line47"> e.preventDefault(); <"line48"> \} <"line49"> script> <"line50"> <"line51"> <script type="text/javascript"> <"line52"> var _paq = window._paq = window._paq || []; <"line53"> /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ <"line54"> _paq.push(['trackPageView']); <"line55"> _paq.push(['enableLinkTracking']); <"line56"> (function() \{ <"line57"> var u="//stats.igalia.com/"; <"line58"> _paq.push(['setTrackerUrl', u+'matomo.php']); <"line59"> _paq.push(['setSiteId', '6']); <"line60"> var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; <"line61"> g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); <"line62"> \})(); <"line63"> script> <"line64"> <"line65">head> <"line66"> <"line67"> <"line68"> <body id="page-top" class="subpage"> <"line69"> <"line70"> <nav class="global"> <"line71">\tab <div> <"line72">\tab <a class="igalia logo home" href="/"><img src="/assets/img/logo-blue.svg" alt="WPE">a> <"line73">\tab <ul class="wpt-status off"><li> <"line74">\tab <a class="nav-link" href="/">Homea> <"line75">\tab li><li> <"line76">\tab <a class="nav-link" href="/about/">Learn && Discovera> <"line77">\tab li><li> <"line78">\tab <a class="nav-link" href="/blog/">Bloga> <"line79">\tab li><li> <"line80">\tab <a class="nav-link" href="/developers/">Developersa> <"line81">\tab li><li> <"line82">\tab <a class="btn cta" href="/about/get-wpe.html">Get WPEa> <"line83">\tab li>ul> <"line84">\tab <a href="#" class="burger">Menua> <"line85">\tab div> <"line86">nav> <"line87"> <"line88"> <"line89"> <main> <"line90"> <"line91"><style> <"line92">body \{ <"line93"> font-family: sans-serif; <"line94">\} <"line95"> <"line96">h1 \{ <"line97"> margin-block-end: 0; <"line98">\} <"line99"> <"line100">#stickyheader \{ <"line101"> position: sticky; <"line102"> top: 4.5em; <"line103"> display: flex; <"line104"> flex-wrap: nowrap; <"line105"> justify-content: space-between; <"line106"> align-items: baseline; <"line107"> gap: 0 2em; <"line108"> padding-block: 1em; <"line109"> z-index: 1; <"line110"> background: #FFF; <"line111"> white-space: nowrap; <"line112"> overflow: hidden; <"line113"> text-overflow: ellipsis; <"line114">\} <"line115"> <"line116">#stickyheader>label \{ <"line117"> line-height: 1.6; <"line118">\} <"line119"> <"line120">#stickyheader+p \{ <"line121"> margin-block-start: 0em; <"line122">\} <"line123"> <"line124">#version-select \{ <"line125"> margin-inline: 0.67em 0; <"line126">\} <"line127"> <"line128">#results-table \{ <"line129"> border-collapse: collapse; <"line130"> width: 100%; <"line131"> margin-block: 1.25em 1em; <"line132"> table-layout: fixed; <"line133">\} <"line134"> <"line135">#results-table :is(th, td) \{ <"line136"> border: 1px solid #ccc; <"line137"> padding-inline: 0.5em; <"line138"> padding-block: 0.5em 0.4em; <"line139"> text-align: left; <"line140">\} <"line141"> <"line142">#results-table thead th \{ <"line143"> background-color: #f4f4f4; <"line144"> background-repeat: no-repeat; <"line145"> background-position: 0 0, 100% 100%; <"line146"> background-size: 100% 1px; <"line147"> background-image: linear-gradient(90deg, #0003, #0003), linear-gradient(90deg, #0005, #0005); <"line148">\} <"line149"> <"line150">#results-table thead \{ <"line151"> position: sticky; <"line152"> top: 7.5em; <"line153"> z-index: 1; <"line154">\} <"line155"> <"line156">#results-table tbody a[href] \{ <"line157"> text-decoration-color: color-mix(in hsl, currentColor 60%, transparent); <"line158"> text-underline-offset: 0.15em; <"line159">\} <"line160"> <"line161">#results-table tbody td.barred \{ <"line162"> background-image: linear-gradient(90deg, hsl(calc(var(--dataHue) * 1.2) 70% 90%) 0, hsl(calc(var(--dataHue) * 1.2) 70% 70%) 100%); <"line163"> background-size: var(--dataPct) 100%; <"line164"> background-repeat: no-repeat; <"line165"> text-shadow: <"line166"> 0 0 0.25em hsl(0, 0%, 93.7%), <"line167"> 0 0 0.25em hsl(0, 0%, 93.7%), <"line168"> 0 0 0.25em hsl(0, 0%, 93.7%), <"line169"> 0 0 0.25em hsl(0, 0%, 93.7%), <"line170"> 0 0 0.25em hsl(0, 0%, 93.7%), <"line171"> 0 0 0.15em hsl(0, 0%, 93.7%), <"line172"> 0 0 0.15em hsl(0, 0%, 93.7%), <"line173"> 0 0 0.15em hsl(0, 0%, 93.7%), <"line174"> 0 0 0.15em hsl(0, 0%, 93.7%), <"line175"> 0 0 0.15em hsl(0, 0%, 93.7%); <"line176">\} <"line177"> <"line178">#results-table tbody td small \{ <"line179"> margin-inline: 0.33ch 0; <"line180">\} <"line181"> <"line182">#results-table tbody td \{ <"line183"> word-break: break-word; <"line184">\} <"line185"> <"line186">#support-combo-filter \{ <"line187"> display: grid; <"line188"> grid-template-columns: 1fr 1fr; <"line189"> gap: 0.5em 1em; <"line190"> background: inherit; <"line191">\} <"line192"> <"line193">#support-combo-filter legend \{ <"line194"> grid-column: span 2; <"line195">\} <"line196"> <"line197">details \{ <"line198"> padding-block-end: 1px; <"line199">\} <"line200"> <"line201">fieldset.smaller \{ <"line202"> font-size: 0.85em; <"line203"> padding: 0.5em 1em; <"line204"> margin: 0.5em 0; <"line205"> border: 1px solid #ccc; <"line206">\} <"line207"> <"line208">fieldset.smaller label \{ <"line209"> margin: 0.2em 0; <"line210"> display: block; <"line211">\} <"line212"> <"line213">.help-text \{ <"line214"> font-size: 0.8em; <"line215"> color: #666; <"line216"> margin-left: 1.5em; <"line217"> margin-top: 0.2em; <"line218">\} <"line219"> <"line220"> <"line221">#controls \{ <"line222"> display: flex; <"line223"> align-items: center; <"line224"> gap: 0.5rem; <"line225"> flex-wrap: nowrap; <"line226"> flex-shrink: 0; <"line227">\} <"line228"> <"line229">.source-tab \{ <"line230"> display: inline-flex; <"line231"> border: 1px solid #ccc; <"line232"> border-radius: 6px; <"line233"> overflow: hidden; <"line234"> box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); <"line235">\} <"line236"> <"line237">.toggle-btn \{ <"line238"> appearance: none; <"line239"> border: none; <"line240"> background: #f5f5f5; <"line241"> padding: 0.25em 0.6em; <"line242"> font-size: 0.9em; <"line243"> cursor: pointer; <"line244"> color: #333; <"line245"> transition: background 0.2s, color 0.2s; <"line246">\} <"line247"> <"line248">.toggle-btn:hover \{ <"line249"> background: #eaeaea; <"line250">\} <"line251"> <"line252">.toggle-btn.active \{ <"line253"> background: #0066cc; <"line254"> color: white; <"line255">\} <"line256"> <"line257">#controls label, <"line258">#controls span \{ <"line259"> white-space: nowrap; <"line260">\} <"line261"> <"line262">[id="info-run"] \{ <"line263"> flex: 0 1 auto; <"line264"> min-width: 0; <"line265"> font-family: monospace; <"line266"> background-color: #f5f5f5; <"line267"> color: #333; <"line268"> padding: 0.3em 0.6em; <"line269"> border: 1px solid #ccc; <"line270"> border-radius: 4px; <"line271"> display: inline-block; <"line272"> white-space: nowrap; <"line273"> font-size: 0.9em; <"line274"> overflow: hidden; <"line275"> text-overflow: ellipsis; <"line276"> text-align: right; <"line277">\} <"line278"> <"line279">.tight-label \{ <"line280"> margin-right: -0.5em; /* pulls WPE closer to the select */ <"line281">\} <"line282"> <"line283">.filter-input-notfound \{ <"line284"> background-color: #62293c; <"line285"> color: white; <"line286">\} <"line287"> <"line288">style> <"line289"> <"line290"><div id="header"> <"line291"> <h1>WPE Web Support Statush1> <"line292"> <p>Change the result source, the WPE version or advanced options. The view will update live and provide a stable, sharable URL.p> <"line293">div> <"line294"> <"line295"><div id="stickyheader"> <"line296"> <div id="controls"> <"line297"> <span title="Result source">&&#x1F4CA;span> <"line298"> <label>Source <"line299"> <select id="viewType" aria-controls="results-table"> <"line300"> <option selected data-view="BCD">BCDoption> <"line301"> <option data-view="WPT">WPToption> <"line302"> select> <"line303"> label> <"line304">&&nbsp; <"line305"> <label for="version-select"> <"line306"> <span class="tight-label">&&#x2699;Versionspan> <"line307"> <select id="version-select">select> <"line308"> label> <"line309"> div> <"line310"> <"line311"> <div id="info-run"> <"line312"> Results from <"line313"> <strong><a id="meta-run-link" href="" target="_blank">a>strong> <"line314"> (Date: <strong><span id="meta-run-date">span>strong>) <"line315"> div> <"line316"> <"line317">div> <"line318"> <"line319"><details id="advanced-options"> <"line320"><summary>Advanced optionssummary> <"line321"><div id="support-combo-filter"> <"line322"> <label class="wpt-advanced-option"> <"line323"> <input type="checkbox" id="show-unknown">Show not yet named or linked <"line324"> <div class="help-text">Include results for WPT dirs we haven't yet linked to their specification.div> <"line325"> label> <"line326"> <label class="wpt-advanced-option"> <"line327"> <input type="checkbox" id="show-wpt-details">Show WPT directories and test counts <"line328"> <div class="help-text">Show columns with WPT dirs info along with test and subtest counts.div> <"line329"> label> <"line330"> <label class="wpt-advanced-option"> <"line331"> <input type="checkbox" id="show-interoperable">Include specs with low support but high interoperability <"line332"> <div class="help-text">Include results with \f1\u8805?\f0 70% pass rate in at least two major Web engines, even if WPE scores &&lt;30%div> <"line333"> label> <"line334"> <label class="bcd-advanced-option"> <"line335"> <input type="checkbox" id="show-bcd-supported-in">Show supported-in column <"line336"> <div class="help-text">Show column with info about where a feature is supported.div> <"line337"> label> <"line338"> <label class="bcd-advanced-option">&&nbsp;&&nbsp;&&nbsp;&&nbsp;&&nbsp;Show features supported in <"line339"> <select id="bcd-support-selector" title="Show features supported in"> <"line340"> <option value="Any" selected>Anyoption> <"line341"> <option value="ServiceWorker">ServiceWorkeroption> <"line342"> <option value="SharedWorker">SharedWorkeroption> <"line343"> <option value="Window">Windowoption> <"line344"> <option value="Worker">Workeroption> <"line345"> <option value="WebAssembly">WebAssemblyoption> <"line346"> select> <"line347"> <div class="help-text">Filter the features shown by where those are supported.div> <"line348"> label> <"line349">div> <"line350">details> <"line351"> <"line352"><details id="explanation-text" open> <"line353"> <summary>Explanationsummary> <"line354"> <"line355"><section id="wpt-explanation-panel"> <"line356"><p> <"line357">This data is automatically obtained by running <a href="https://web-platform-tests.org" target="_blank">Web Platform Tests (WPT)a> with WPE. <"line358"> It shows all Web specifications supported or partially supported by WPE <"line359"> <i>(\f1\u8805?\f0 30% WPT pass rate)i>. <"line360">p> <"line361"><p> <"line362">The numbers given below are necessarily a crude measure of support: it's <"line363"> possible to have what looks like a poor score while supporting the main <"line364"> body of a specification and missing a number of tiny edge cases, for <"line365"> example. That said, in general, a specification with a score above 70% <"line366"> can be considered supported; any score between 30% and 70% can be <"line367"> considered partially supported; and any score below 30% indicates <"line368"> limited or almost no support. <"line369">p> <"line370"><p> <"line371">If a score drop over time is observed, then the most likely cause is either <"line372"> flaky tests that fail intermittently, or the addition of new tests in WPT, <"line373"> often reflecting new specification features, rather than a removal of <"line374"> capabilities from WPE WebKit. <"line375">p> <"line376"><p> <"line377">For an alternative view that includes a more detailed list of supported <"line378"> Web APIs, JavaScript features and CSS properties, check the <a href="#" id="bcd-view-link">BCD test resultsa>. <"line379">p> <"line380">Notes: <"line381"><ul> <"line382"><li>These results were obtained using a WPE build with experimental features enabled. <"line383"> Because feature availability can vary by build configuration, certain features shown here may not be present in other WPE builds.li> <"line384"><li>Detailed results of the automated WPT tests for WPE are available at <"line385"> <a id="wpt-link" href="https://wpt.fyi/results/?product=wpewebkit" target="_blank">wpt.fyia>li> <"line386"><li>JavaScript specifications are barely covered here. <"line387"> To explore those, see the results for <i>JavaScriptCorei> at <"line388"> <a href="https://test262.fyi/#|jsc" target="_blank">test262.fyia>li> <"line389">ul> <"line390">section> <"line391"> <"line392"><section id="bcd-explanation-panel" hidden> <"line393"><p> <"line394">This data is automatically obtained by running <a href="https://mdn-bcd-collector.gooborg.com/" target="_blank">mdn-bcd-collectora> tests with WPE. <"line395">It presents Browser Compatibility Data (BCD) for different WPE versions, covering Web technologies, such as Web APIs, JavaScript features, CSS properties and more. <"line396">p> <"line397"><p> <"line398">The list below shows features available in the selected WPE version. It indicates only the presence of each feature, not the level of support. For an alternative view that includes specifications and support scores, refer to <a href="#" id="wpt-view-link">the WPT test resultsa>. <"line399">p> <"line400">Notes: <"line401"><ul> <"line402"><li>These results were obtained using a WPE build with experimental features enabled. <"line403"> Because feature availability can vary by build configuration, certain features shown here may not be present in other WPE builds.li> <"line404">ul> <"line405">section> <"line406"> <"line407">details> <"line408"> <"line409"><table id="results-table" aria-describedby="info-run"> <"line410"> <thead>thead> <"line411"> <tbody>tbody> <"line412">table> <"line413"> <"line414"><script> <"line415">// The json data on wpewebkit.org/wptreport-distilled-data is automatically updated <"line416">// by a cronjob on the server running wptreport-distiller <"line417">// IMPORTANT: WPTReportDistilledBaseURL should be either empty '' or end in slash '/' <"line418">const WPTReportDistilledBaseURL = '{{\field{\*\fldinst{HYPERLINK https://wpewebkit.org/wptreport-distilled-data/ }}{\fldrslt{https://wpewebkit.org/wptreport-distilled-data/\ul0\cf0}}}}\f0\fs22 ' <"line419">const versionsFile = 'versions_available.json' <"line420">const viewType = document.getElementById('viewType'); <"line421">const versionSelect = document.getElementById('version-select'); <"line422">const detailsWPTCheckbox = document.getElementById('show-wpt-details'); <"line423">const unknownCheckbox = document.getElementById('show-unknown'); <"line424">const BCDSupportSelector = document.getElementById('bcd-support-selector'); <"line425">const showBCDSupportColumn = document.getElementById('show-bcd-supported-in'); <"line426">const interoperableCheckbox = document.getElementById('show-interoperable'); <"line427">const tableHead = document.querySelector('#results-table thead'); <"line428">const tableBody = document.querySelector('#results-table tbody'); <"line429">const metaRunDate = document.getElementById('meta-run-date'); <"line430">const metaRunLink = document.getElementById('meta-run-link'); <"line431">const detailsExplanation = document.getElementById("explanation-text"); <"line432">const detailsAdvancedOptions = document.getElementById("advanced-options"); <"line433">const explanationsPanelWPT = document.getElementById('wpt-explanation-panel'); <"line434">const explanationsPanelBCD = document.getElementById('bcd-explanation-panel'); <"line435">const jsonCache = Object.create(null); <"line436">let tableSourceResults; <"line437">let paramsURL; <"line438">let tableSearch; <"line439">let tableCounter; <"line440">let tableRows; <"line441"> <"line442">function clearTable() \{ <"line443"> tableSearch = null; <"line444"> tableCounter = null; <"line445"> tableRows = null; <"line446"> tableHead.innerHTML = ''; <"line447"> tableBody.innerHTML = ''; <"line448">\} <"line449"> <"line450">function refreshURLWithParams(queryStringName, queryStringValue, queryStringDefault) \{ <"line451"> if (queryStringValue === queryStringDefault) <"line452"> paramsURL.delete(queryStringName); <"line453"> else <"line454"> paramsURL.set(queryStringName, queryStringValue); <"line455"> // Update URL without reloading <"line456"> const queryStringFull = paramsURL.toString(); <"line457"> if (queryStringFull) <"line458"> history.pushState(null, '', `$\{window.location.pathname\}?$\{queryStringFull\}`); <"line459"> else <"line460"> history.pushState(null, '', `$\{window.location.pathname\}`); <"line461">\} <"line462"> <"line463">unknownCheckbox.addEventListener('change', (e) => \{ <"line464"> clearTable(); <"line465"> renderTableWPT(); <"line466"> refreshURLWithParams('wu', unknownCheckbox.checked? 1 : 0, 0); <"line467">\}); <"line468">detailsWPTCheckbox.addEventListener('change', (e) => \{ <"line469"> clearTable(); <"line470"> renderTableWPT(); <"line471"> refreshURLWithParams('wd', detailsWPTCheckbox.checked? 1 : 0, 0); <"line472">\}); <"line473">interoperableCheckbox.addEventListener('change', (e) => \{ <"line474"> clearTable(); <"line475"> renderTableWPT(); <"line476"> refreshURLWithParams('wi', interoperableCheckbox.checked? 1 : 0, 0); <"line477">\}); <"line478">BCDSupportSelector.addEventListener('change', (e) => \{ <"line479"> clearTable(); <"line480"> renderTableBCD(); <"line481"> refreshURLWithParams('bs', BCDSupportSelector.value); <"line482">\}); <"line483">showBCDSupportColumn.addEventListener('change', (e) => \{ <"line484"> clearTable(); <"line485"> renderTableBCD(); <"line486"> refreshURLWithParams('bc', showBCDSupportColumn.checked? 1 : 0, 0); <"line487">\}); <"line488">versionSelect.addEventListener('change', (e) => \{ <"line489"> clearTable(); <"line490"> loadData(); <"line491"> refreshURLWithParams('ver', versionSelect.value); <"line492">\}); <"line493"> <"line494">document.getElementById('bcd-view-link').addEventListener('click', function(event) \{ <"line495"> event.preventDefault(); <"line496"> document.querySelector('option[data-view="BCD"]').selected = true; <"line497"> viewType.dispatchEvent(new Event('change')); <"line498">\}); <"line499"> <"line500">document.getElementById('wpt-view-link').addEventListener('click', function(event) \{ <"line501"> event.preventDefault(); <"line502"> document.querySelector('option[data-view="WPT"]').selected = true; <"line503"> viewType.dispatchEvent(new Event('change')); <"line504">\}); <"line505"> <"line506"> <"line507">function getViewName() \{ <"line508"> return viewType[viewType.selectedIndex].dataset.view <"line509">\} <"line510"> <"line511">function updateView() \{ <"line512"> tableSourceResults = getViewName() <"line513"> clearTable(); <"line514"> updateTableSourceResultsView(); <"line515"> refreshURLWithParams('src', tableSourceResults); <"line516">\} <"line517"> <"line518">viewType.onchange = updateView <"line519"> <"line520">detailsExplanation.addEventListener('toggle', () => \{ <"line521"> refreshURLWithParams('de', detailsExplanation.open? 1 : 0, 1); <"line522">\}); <"line523">detailsAdvancedOptions.addEventListener('toggle', () => \{ <"line524"> refreshURLWithParams('da', detailsAdvancedOptions.open? 1 : 0, 0); <"line525">\}); <"line526"> <"line527">// update things also when the back button is pressed <"line528">window.addEventListener('popstate', () => \{ loadAndRenderView(false); \}); <"line529"> <"line530"> <"line531">function toggleExplanationSection() \{ <"line532"> explanationsPanelWPT.hidden = (tableSourceResults !== 'WPT'); <"line533"> explanationsPanelBCD.hidden = (tableSourceResults !== 'BCD'); <"line534">\} <"line535"> <"line536"> <"line537">function updateAdvancedOptions() \{ <"line538"> if (tableSourceResults === "WPT") \{ <"line539"> document.querySelectorAll('.wpt-advanced-option').forEach(el => el.style.removeProperty("display")); <"line540"> document.querySelectorAll('.bcd-advanced-option').forEach(el => el.style.display = 'none'); <"line541"> \} else \{ <"line542"> document.querySelectorAll('.bcd-advanced-option').forEach(el => el.style.removeProperty("display")); <"line543"> document.querySelectorAll('.wpt-advanced-option').forEach(el => el.style.display = 'none') <"line544"> \} <"line545">\} <"line546"> <"line547">function maybeUpdateCheckboxDefValue(checkBoxObject, queryStringName) \{ <"line548"> const valueFromQS = paramsURL.get(queryStringName); <"line549"> checkBoxObject.checked = valueFromQS === '1'; <"line550"> <"line551">\} <"line552"> <"line553">function maybeUpdateSelectDefValue(selectObject, queryStringName) \{ <"line554"> const valueFromQS = paramsURL.get(queryStringName); <"line555"> if (valueFromQS) \{ <"line556"> const optionExists = Array.from(selectObject.options).some(opt => opt.value === valueFromQS); <"line557"> if (optionExists) <"line558"> selectObject.value = valueFromQS; <"line559"> \} else \{ <"line560"> // if no value passed, default to select the first option <"line561"> selectObject.selectedIndex = 0; <"line562"> \} <"line563">\} <"line564"> <"line565">function maybeUpdateDetailsOpenValue(detailsObject, queryStringName, defValue) \{ <"line566"> const valueFromQS = paramsURL.get(queryStringName); <"line567"> detailsObject.open = valueFromQS? valueFromQS === '1' : defValue; <"line568">\} <"line569"> <"line570"> <"line571">function updateOptionsDefaultValues() \{ <"line572"> maybeUpdateCheckboxDefValue(unknownCheckbox, 'wu'); <"line573"> maybeUpdateCheckboxDefValue(detailsWPTCheckbox, 'wd'); <"line574"> maybeUpdateCheckboxDefValue(interoperableCheckbox, 'wi'); <"line575"> maybeUpdateCheckboxDefValue(showBCDSupportColumn, 'bc'); <"line576"> maybeUpdateSelectDefValue(BCDSupportSelector, 'bs'); <"line577"> maybeUpdateDetailsOpenValue(detailsExplanation, 'de', true); <"line578"> maybeUpdateDetailsOpenValue(detailsAdvancedOptions, 'da', false); <"line579"> tableSourceResults = paramsURL.get('src') === 'BCD' ? 'BCD' : 'WPT'; // default view <"line580"> document.querySelector(`option[data-view="$\{tableSourceResults\}"]`).selected = true; <"line581">\} <"line582"> <"line583"> <"line584">// Preloading all the jsons makes the UI much faster when changing views and needs <5MB of RAM <"line585">async function lazyPreloadAllJsons() \{ <"line586"> const shouldAvoidPreload = (navigator.connection &&&& (navigator.connection.saveData || ['slow-2g', '2g', '3g'].includes(navigator.connection.effectiveType))); <"line587"> if (shouldAvoidPreload) <"line588"> return; <"line589"> // preload them in per-version-sets instead all at the same time to minimize network load <"line590"> for (const v of versionsAvailable.versions) \{ <"line591"> const fileList = [v.bcd_results, v.wpt_interoperability, v.wpt_results, v.wpt_specs]; <"line592"> const uniqueJsonURLs = [...new Set(fileList.filter(Boolean).map(filename => WPTReportDistilledBaseURL + filename))]; <"line593"> await jsonFetchCache(uniqueJsonURLs); <"line594"> \} <"line595">\} <"line596"> <"line597">async function loadAndRenderView(firstLoad) \{ <"line598"> clearTable(); <"line599"> paramsURL = new URLSearchParams(window.location.search); <"line600"> updateOptionsDefaultValues(); <"line601"> if (firstLoad) <"line602"> await loadVersionsAvailable(); <"line603"> maybeUpdateSelectDefValue(versionSelect, 'ver'); <"line604"> await updateTableSourceResultsView(); <"line605"> if (firstLoad) \{ <"line606"> if ('requestIdleCallback' in window) \{ <"line607"> requestIdleCallback(() => lazyPreloadAllJsons()); <"line608"> \} else \{ <"line609"> if (document.readyState === 'complete') <"line610"> lazyPreloadAllJsons(); <"line611"> else <"line612"> window.addEventListener('load', () => lazyPreloadAllJsons()); <"line613"> \} <"line614"> \} <"line615">\} <"line616"> <"line617"> <"line618">async function updateTableSourceResultsView() \{ <"line619"> toggleExplanationSection(); <"line620"> updateAdvancedOptions(); <"line621"> return await loadData(); <"line622">\} <"line623"> <"line624">let versionsAvailable = null; <"line625">let specsData = null; <"line626">let resultsData = null; <"line627">let productVersionQueryString = null; <"line628"> <"line629">async function loadVersionsAvailable() \{ <"line630"> [versionsAvailable] = await jsonFetchCache([WPTReportDistilledBaseURL + versionsFile]) <"line631"> const defVersion = versionSelect.value || versionsAvailable.metadata.default_version; <"line632"> versionSelect.innerHTML = ""; <"line633"> if (versionsAvailable &&&& versionsAvailable.versions) \{ <"line634"> versionsAvailable.versions.forEach(v => \{ <"line635"> const option = document.createElement('option'); <"line636"> option.value = v.version; <"line637"> option.textContent = v.version; <"line638"> versionSelect.appendChild(option); <"line639"> \}); <"line640"> const existsVersion = Array.from(versionSelect.options).some(opt => opt.value === defVersion); <"line641"> if (existsVersion) <"line642"> versionSelect.value = defVersion; <"line643"> \} else \{ <"line644"> const option = document.createElement('option'); <"line645"> option.disabled = true; <"line646"> option.textContent = "Error loading versions"; <"line647"> versionSelect.appendChild(option); <"line648"> \} <"line649">\} <"line650"> <"line651">async function loadData() \{ <"line652"> if (!versionsAvailable) <"line653"> return; <"line654"> if (tableSourceResults === "WPT") <"line655"> return await loadWPTData(); <"line656"> return await loadBCDData(); <"line657">\} <"line658"> <"line659"> <"line660">function updateRunInfo(resultsData, version) \{ <"line661"> let browserVersion; <"line662"> browserVersion = version === "nightly" ? (resultsData.metadata.browser_version || version) : (resultsData.metadata.browser_version?.split('.').slice(0, 2).join('.') || version); <"line663"> if (tableSourceResults === "WPT") \{ <"line664"> // We can't pass the version for the nightlies until {{\field{\*\fldinst{HYPERLINK https://github.com/web-platform-tests/wpt.fyi/pull/4398 }}{\fldrslt{https://github.com/web-platform-tests/wpt.fyi/pull/4398\ul0\cf0}}}}\f0\fs22 gets fixed <"line665"> // But it should work fine anyway because is not expected to find more than one nightly/experimental run per WPT commit <"line666"> productVersionQueryString = version === "nightly" ? `sha=$\{resultsData.metadata.wpt_version\}&&label=experimental&&product=wpewebkit` : `sha=$\{resultsData.metadata.wpt_version\}&&label=stable&&product=wpewebkit-$\{resultsData.metadata.browser_version\}`; <"line667"> document.getElementById('wpt-link').href = `https://wpt.fyi/results/?$\{productVersionQueryString\}`; <"line668"> // short to 7 chars because its the same short-sha length used on wpt.fyi <"line669"> const wptShaShort = resultsData.metadata.wpt_version.slice(0, 7) || '\f2\emdash '; <"line670"> metaRunLink.textContent = `test run using WPT $\{wptShaShort\} and WPE $\{browserVersion\}`; <"line671"> metaRunLink.href = `https://wpt.fyi/results/?$\{productVersionQueryString\}`; <"line672"> \} else \{ <"line673"> metaRunLink.textContent = `test run using BCD v$\{resultsData.metadata.mdn_bcd_collector_version\} and WPE $\{browserVersion\}`; <"line674"> metaRunLink.href = `https://mdn-bcd-collector.gooborg.com/changelog`; <"line675"> \} <"line676"> metaRunDate.textContent = new Date(resultsData.metadata.testrun_timestamp_end * 1000).toISOString().slice(0, 10) || '\emdash '; <"line677">\} <"line678"> <"line679"> <"line680">async function jsonFetchCache(urls) \{ <"line681"> const results = await Promise.all(urls.map(async (url) =\f0\lang1033 >\f2 \{ <"line682"> const cached = jsonCache[url]; <"line683"> if (cached) <"line684"> return cached; <"line685"> const fetchPromise = fetch(url) <"line686"> .then(res =\f0\lang1033 >\f2 \{ <"line687"> if (!res.ok) <"line688"> throw new Error(`Failed to fetch $\{url\}: $\{res.status\}`); <"line689"> return res.json(); <"line690"> \}) <"line691"> .catch(err =\f0\lang1033 >\f2 \{ <"line692"> delete jsonCache[url]; // allow retry <"line693"> throw err; <"line694"> \}); <"line695"> jsonCache[url] = fetchPromise; <"line696"> const data = await fetchPromise; <"line697"> jsonCache[url] = data; <"line698"> return data; <"line699"> \})); <"line700"> return results; <"line701">\} <"line702"> <"line703"> <"line704">async function loadBCDData() \{ <"line705"> const version = versionSelect.value; <"line706"> const selected = versionsAvailable.versions.find(v =\f0\lang1033 >\f2 v.version === version); <"line707"> const currentResultsUrl = WPTReportDistilledBaseURL + selected.bcd_results; <"line708"> [resultsData] = await jsonFetchCache([currentResultsUrl]); <"line709"> updateRunInfo(resultsData, version); <"line710"> renderTableBCD(); <"line711">\} <"line712"> <"line713">async function loadWPTData() \{ <"line714"> const version = versionSelect.value; <"line715"> const selected = versionsAvailable.versions.find(v =\f0\lang1033 >\f2 v.version === version); <"line716"> const currentSpecUrl = WPTReportDistilledBaseURL + selected.wpt_specs; <"line717"> const currentResultsUrl = WPTReportDistilledBaseURL + selected.wpt_results; <"line718"> const currentResultsEnginesUrl = WPTReportDistilledBaseURL + selected.wpt_interoperability; <"line719"> [specsData, resultsData, resultsEnginesData] = await jsonFetchCache([currentSpecUrl, currentResultsUrl, currentResultsEnginesUrl]) <"line720"> updateRunInfo(resultsData, version); <"line721"> renderTableWPT(); <"line722">\} <"line723"> <"line724"> <"line725">function calculatePercentage(pass, total) \{ <"line726"> return total \f0\lang1033 >\f2 0 ? Math.round(1000 * pass / total) / 10 : 0; <"line727">\} <"line728"> <"line729">function getSubtestsMaintests(testStr) \{ <"line730"> const [subtestsStr, maintestsStr] = testStr.split(':'); <"line731"> const [subtestPass, subtestTotal] = subtestsStr.split('/'); <"line732"> const [maintestsPass, maintestsTotal] = maintestsStr.split('/'); <"line733"> return [ <"line734"> parseInt(subtestPass, 10), <"line735"> parseInt(subtestTotal, 10), <"line736"> parseFloat(maintestsPass), <"line737"> parseInt(maintestsTotal, 10) <"line738"> ]; <"line739">\} <"line740"> <"line741"> <"line742">function runSearchFilter() \{ <"line743"> if (!tableSearch) <"line744"> return; <"line745"> const inputFilter = tableSearch.value.trim(); <"line746"> if (!inputFilter) \{ <"line747"> for (const row of tableRows) \{ <"line748"> const firstCell = row.cells[0]; <"line749"> if (!firstCell) <"line750"> continue; <"line751"> firstCell.querySelectorAll('mark').forEach(m =\f0\lang1033 >\f2 <"line752"> m.replaceWith(document.createTextNode(m.textContent)) <"line753"> ); <"line754"> row.hidden = false; <"line755"> \} <"line756"> tableSearch.classList.remove('filter-input-notfound'); <"line757"> tableCounter.textContent = ` ($\{tableRows.length\})`; <"line758"> return; <"line759"> \} <"line760"> // sort by substring length, so with "he" and "hello" in "hello word" it matches "hello". <"line761"> const filterWords = [...new Set(inputFilter.toLowerCase().split(/\\s+/).filter(Boolean))].sort((a, b) =\f0\lang1033 >\f2 b.length - a.length); <"line762"> const regexPattern = filterWords.map(w =\f0\lang1033 >\f2 w.replace(/[.*+?^$\{\}()|[\\]\\\\]/g, '{{\field{\*\fldinst{HYPERLINK "\\\\\\\\$&&')).join('|"}}{\fldrslt{\\\\$&&')).join('|\ul0\cf0}}}}\f2\fs22 '); <"line763"> const regex = new RegExp(regexPattern, 'gi'); <"line764"> let visibleRows = 0; <"line765"> for (const row of tableRows) \{ <"line766"> const firstCell = row.cells[0]; <"line767"> if (!firstCell) <"line768"> continue; <"line769"> const originalText = firstCell.textContent; <"line770"> const originalTextLower = originalText.toLowerCase(); <"line771"> const allFilterWordsMatch = filterWords.every(w =\f0\lang1033 >\f2 originalTextLower.includes(w)); <"line772"> if (!allFilterWordsMatch) \{ <"line773"> row.hidden = true; <"line774"> continue; <"line775"> \} <"line776"> visibleRows++; <"line777"> row.hidden = false; <"line778"> const targetElement = firstCell.querySelector('a') || firstCell; <"line779"> targetElement.innerHTML = originalText.replace(regex, '\f0\lang1033 <\f2 mark\f0\lang1033 >\f2 $&&\f0\lang1033 <\f2 /mark\f0\lang1033 >\f2 '); <"line780"> \} <"line781"> tableSearch.classList.toggle("filter-input-notfound", !visibleRows); <"line782"> tableCounter.textContent = ` ($\{visibleRows\})`; <"line783">\} <"line784"> <"line785"> <"line786">function createThWithSearch(thText) \{ <"line787"> const th = document.createElement("th"); <"line788"> const thWrapper = document.createElement("div"); <"line789"> thWrapper.style.display = "flex"; <"line790"> thWrapper.style.justifyContent = "space-between"; <"line791"> thWrapper.style.alignItems = "center"; <"line792"> thWrapper.style.width = "100%"; <"line793"> <"line794"> const labelWrapper = document.createElement("span"); <"line795"> const label = document.createElement("span"); <"line796"> label.id = "th-search-text-content"; <"line797"> label.textContent = thText; <"line798"> tableCounter = document.createElement("span"); <"line799"> tableCounter.id = "th-search-counter"; <"line800"> tableCounter.textContent = '(0)'; <"line801"> labelWrapper.appendChild(label); <"line802"> labelWrapper.appendChild(tableCounter); <"line803"> <"line804"> tableSearch = document.createElement("input"); <"line805"> tableSearch.type = "text"; <"line806"> tableSearch.id = "tableSearch"; <"line807"> tableSearch.placeholder = "Filter..."; <"line808"> tableSearch.style.maxWidth = "15ch"; <"line809"> <"line810"> let searchTimeout; <"line811"> tableSearch.addEventListener("input", function () \{ <"line812"> clearTimeout(searchTimeout); <"line813"> searchTimeout = setTimeout(runSearchFilter, 250); <"line814"> \}); <"line815"> <"line816"> thWrapper.appendChild(labelWrapper); <"line817"> thWrapper.appendChild(tableSearch); <"line818"> th.appendChild(thWrapper); <"line819"> return th; <"line820">\} <"line821"> <"line822"> <"line823">function renderTableBCD() \{ <"line824"> let total_specs = 0; <"line825"> const headRow = document.createElement('tr'); <"line826"> const thSearch = createThWithSearch('Features'); <"line827"> headRow.appendChild(thSearch); <"line828"> const showSupportColumn = showBCDSupportColumn.checked; <"line829"> if (showSupportColumn) \{ <"line830"> const thSupport = document.createElement('th'); <"line831"> thSupport.textContent = 'Supported in'; <"line832"> headRow.appendChild(thSupport); <"line833"> \} <"line834"> tableHead.appendChild(headRow); <"line835"> <"line836"> const selectorValue = BCDSupportSelector.value; <"line837"> const isAnySelector = selectorValue === "Any"; <"line838"> <"line839"> // Process test results <"line840"> for (const testName in resultsData.results) \{ <"line841"> const \{ link: linkUrl, pass: passList = [] \} = resultsData.results[testName]; <"line842"> if (isAnySelector || passList.includes(selectorValue)) \{ <"line843"> const row = document.createElement('tr'); <"line844"> const tdSpec = document.createElement('td'); <"line845"> if (linkUrl) \{ <"line846"> const a = document.createElement('a'); <"line847"> a.href = linkUrl; <"line848"> a.target = '_blank'; <"line849"> a.textContent = testName; <"line850"> tdSpec.appendChild(a); <"line851"> \} else \{ <"line852"> tdSpec.textContent = testName; <"line853"> \} <"line854"> row.appendChild(tdSpec); <"line855"> if (showSupportColumn) \{ <"line856"> const tdSupport = document.createElement('td'); <"line857"> tdSupport.textContent = passList.sort().join(', '); <"line858"> row.appendChild(tdSupport); <"line859"> \} <"line860"> <"line861"> tableBody.appendChild(row); <"line862"> total_specs++; <"line863"> \} <"line864"> \} <"line865"> document.getElementById('th-search-text-content').textContent = 'Features'; <"line866"> tableCounter.textContent = ` ($\{total_specs\})`; <"line867"> tableRows = document.querySelectorAll("#results-table tbody tr"); <"line868">\} // end renderTableBCD() <"line869"> <"line870"> <"line871">function renderTableWPT() \{ <"line872"> const showDetailsWPT = detailsWPTCheckbox.checked; <"line873"> const showUnknown = unknownCheckbox.checked; <"line874"> const showInteroperable = interoperableCheckbox.checked; <"line875"> let total_specs = 0; <"line876"> <"line877"> const headers = []; <"line878"> const headRow = document.createElement('tr'); <"line879"> const thSearch = createThWithSearch('Specifications'); <"line880"> headRow.appendChild(thSearch); <"line881"> headers.push('Passrate% (subtests)'); <"line882"> if (showDetailsWPT) \{ <"line883"> headers.push('Subtest counts'); <"line884"> headers.push('WPT Directory'); <"line885"> \} <"line886"> headers.forEach(h =\f0\lang1033 >\f2 \{ <"line887"> const th = document.createElement('th'); <"line888"> th.textContent = h; <"line889"> headRow.appendChild(th); <"line890"> \}); <"line891"> tableHead.appendChild(headRow); <"line892"> <"line893"> // start for-loop drawing the rows <"line894"> for (const [dir, value] of Object.entries(resultsData.results)) \{ <"line895"> <"line896"> const [subTestsPass, subTestsTotal, mainTestsPass, mainTestsTotal] = getSubtestsMaintests(value); <"line897"> let percent = calculatePercentage(subTestsPass, subTestsTotal); <"line898"> let spec = specsData.specs.find(s =\f0\lang1033 >\f2 s.dirw === dir); <"line899"> let specText = spec ? spec.text : undefined; <"line900"> let specLink = spec ? spec.link : undefined; <"line901"> <"line902"> if (!showUnknown &&&& !specText) <"line903"> continue; <"line904"> <"line905"> // calculate interoperable specs and skip non-interoperable unless the selected browser supports them <"line906"> let engines; <"line907"> let enginePassrateList; <"line908"> <"line909"> engines = resultsEnginesData.results_engines || \{\}; <"line910"> enginePassrateList = Object.entries(engines).map(([engine, engineResults]) =\f0\lang1033 >\f2 \{ <"line911"> const str = engineResults[dir]; <"line912"> if (!str) return null; <"line913"> const [engineSubTestsPass, engineSubTestsTotal, engineMainTestsPass, engineMainTestsTotal] = getSubtestsMaintests(str); <"line914"> const rate = calculatePercentage(engineSubTestsPass, engineSubTestsTotal); <"line915"> // console.log(`ENGINE: $\{engine\}, DIR: $\{dir\}, STRING: $\{str\}, RATE: $\{rate\}`); <"line916"> return \{ <"line917"> engine, <"line918"> rate <"line919"> \}; <"line920"> \}).filter(r =\f0\lang1033 >\f2 r !== null); <"line921"> <"line922"> // for clarity only render specs supported or interoperable <"line923"> const numberSupportedEngines = enginePassrateList.filter(r =\f0\lang1033 >\f2 r.rate \f0\lang1033 >\f2 = 70).length; <"line924"> if (enginePassrateList.length === 3) \{ <"line925"> if (numberSupportedEngines \f0\lang1033 <\f2 2) \{ <"line926"> // non-interoperable: render only if browser supports it <"line927"> if (percent \f0\lang1033 <\f2 30) \{ <"line928"> // console.log(`SKIP non-interoperable: $\{specText\}`); <"line929"> continue; <"line930"> \} <"line931"> \} else \{ <"line932"> // interoperable: render if browser supports it, or if showInteroperable button checked <"line933"> if (percent \f0\lang1033 <\f2 30 &&&& !showInteroperable) \{ <"line934"> // console.log(`SKIP interoperable: $\{specText\}`); <"line935"> continue; <"line936"> \} <"line937"> \} <"line938"> \} else if (enginePassrateList.length === 0) \{ <"line939"> console.log(`WARNING: We have no data of web-engines pass-rate for spec $\{dir\}. Likely new spec. Ignoring it`) <"line940"> continue; <"line941"> \} else \{ <"line942"> console.error(`ERROR: Number of engines is not 3 but $\{enginePassrateList.length\} for spec $\{dir\}!!!`); <"line943"> throw new Error("Number of Web engines is not 3!!!"); <"line944"> \} <"line945"> <"line946"> const row = document.createElement('tr'); <"line947"> const tdSpec = document.createElement('td'); <"line948"> if (specText) \{ <"line949"> const a = document.createElement('a'); <"line950"> a.href = specLink; <"line951"> a.target = '_blank'; <"line952"> a.textContent = specText; <"line953"> tdSpec.appendChild(a); <"line954"> \} else \{ <"line955"> tdSpec.textContent = dir; <"line956"> \} <"line957"> row.appendChild(tdSpec); <"line958"> const tdRate = document.createElement('td'); <"line959"> tdRate.textContent = new Intl.NumberFormat(navigator.language).format(percent) + '%' <"line960"> if (!showDetailsWPT) \{ <"line961"> let smallnote = document.createElement('small'); <"line962"> smallnote.textContent = ` (of $\{new Intl.NumberFormat(navigator.language).format(subTestsTotal)\})`; <"line963"> tdRate.appendChild(smallnote); <"line964"> \} <"line965"> tdRate.classList.add('barred'); <"line966"> tdRate.style.setProperty('--dataPct', percent + '%'); <"line967"> tdRate.style.setProperty('--dataHue', percent + 'deg'); <"line968"> row.appendChild(tdRate); <"line969"> <"line970"> if (showDetailsWPT) \{ <"line971"> const tdInfo = document.createElement('td'); <"line972"> tdInfo.textContent = `$\{subTestsPass\}/$\{subTestsTotal\} pass ($\{mainTestsTotal\} tests)`; <"line973"> row.appendChild(tdInfo); <"line974"> const tdDir = document.createElement('td'); <"line975"> let testLink = document.createElement('a'); <"line976"> testLink.href = `https://wpt.fyi/results/$\{dir\}?$\{productVersionQueryString\}`; <"line977"> testLink.target = '_blank'; <"line978"> testLink.textContent = dir; <"line979"> tdDir.appendChild(testLink); <"line980"> row.appendChild(tdDir); <"line981"> \} <"line982"> <"line983"> tableBody.appendChild(row); <"line984"> total_specs += 1; <"line985"> \} // end for-loop drawing the rows <"line986"> <"line987"> tableHead.querySelectorAll('th')[1].textContent = showDetailsWPT? 'Passrate%' : 'Passrate% (subtests)'; <"line988"> document.getElementById('th-search-text-content').textContent = 'Specifications'; <"line989"> tableCounter.textContent = ` ($\{total_specs\})`; <"line990"> tableRows = document.querySelectorAll("#results-table tbody tr"); <"line991">\} // end renderTable() <"line992"> <"line993">loadAndRenderView(true); <"line994">\f0\lang1033 <\f2 /script\f0\lang1033 >\f2 <"line995"> <"line996"> \f0\lang1033 <\f2 div class="survey"\f0\lang1033 >\f2 <"line997"> \f0\lang1033 <\f2 p\f0\lang1033 >\f2 <"line998"> If you\rquote re using WPE WebKit, or are considering doing so, \f0\lang1033 <\f2 strong\f0\lang1033 >\f2 \f0\lang1033 <\f2 a href="https://docs.google.com/forms/d/e/1FAIpQLSchPgMGzuVc9ry5bdxF2uFnW2q3FcrSSqxJdOM4Fd2BD4s7dg/viewform?usp=pp_url&&amp;entry.1179679285=WPEWebKit.org+website"\f0\lang1033 >\f2 please take our brief user survey\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 \f0\lang1033 <\f2 /strong\f0\lang1033 >\f2 . Your input will help us make WPE WebKit better for you! <"line999"> \f0\lang1033 <\f2 /p\f0\lang1033 >\f2 <"line1000"> \f0\lang1033 <\f2 /div\f0\lang1033 >\f2 <"line1001"> \f0\lang1033 <\f2 style\f0\lang1033 >\f2 <"line1002"> .survey \{ <"line1003"> position: relative; <"line1004"> padding-block: 2em 3em; <"line1005"> margin-block: 3em 0; <"line1006"> --bgrad: linear-gradient(180deg,#00C6 0.25em,#00B4 20%,40%,#00B2); <"line1007"> background: var(--bgrad); <"line1008"> border-image: var(--bgrad) 1; <"line1009"> border-image-outset: 0 50vmax; <"line1010"> border-image-width: 0 50vmax; <"line1011"> font-size: 1.25em; <"line1012"> \} <"line1013"> .survey::before \{ <"line1014"> content: url(/assets/img/survey.svg); <"line1015"> position: absolute; <"line1016"> top: -1.5em; <"line1017"> left: 0; <"line1018"> right: 0; <"line1019"> margin-inline: auto; <"line1020"> height: 3em; <"line1021"> width: auto; <"line1022"> aspect-ratio: 1/1; <"line1023"> filter: drop-shadow(0.25em 0.33em 0.33em #0006); <"line1024"> \} <"line1025"> .survey p \{ <"line1026"> padding-inline: 1em; <"line1027"> \} <"line1028"> \f0\lang1033 <\f2 /style\f0\lang1033 >\f2 <"line1029"> <"line1030"> \f0\lang1033 <\f2 /main\f0\lang1033 >\f2 <"line1031"> <"line1032"> \f0\lang1033 <\f2 dialog id="splash"\f0\lang1033 >\f2 <"line1033">\f0\lang1033 <\f2 p\f0\lang1033 >\f2 If you\rquote re using WPE WebKit, or are considering doing so, \f0\lang1033 <\f2 strong\f0\lang1033 >\f2 please take our brief user survey!\f0\lang1033 <\f2 /strong\f0\lang1033 >\f2 Your input will help us make WPE WebKit better for you.\f0\lang1033 <\f2 /p\f0\lang1033 >\f2 <"line1034">\f0\lang1033 <\f2 div\f0\lang1033 >\f2 <"line1035">\f0\lang1033 <\f2 button is="dis-misser" id="dismiss-Y"\f0\lang1033 >\f2 Yes\f0\lang1033 <\f2 /button\f0\lang1033 >\f2 <"line1036">\f0\lang1033 <\f2 button is="dis-misser" id="dismiss-L"\f0\lang1033 >\f2 Ask again later\f0\lang1033 <\f2 /button\f0\lang1033 >\f2 <"line1037">\f0\lang1033 <\f2 button is="dis-misser" id="dismiss-N"\f0\lang1033 >\f2 No\f0\lang1033 <\f2 /button\f0\lang1033 >\f2 <"line1038">\f0\lang1033 <\f2 /div\f0\lang1033 >\f2 <"line1039">\f0\lang1033 <\f2 /dialog\f0\lang1033 >\f2 <"line1040">\f0\lang1033 <\f2 style\f0\lang1033 >\f2 <"line1041">#splash \{max-width: 50%; border-radius: 1em; padding-inline: 2em; outline: 50vmax solid #141316D0; background: #EEE;\} <"line1042">#splash p \{font-size: 1.25em; color: inherit;\} <"line1043">#splash img \{max-width: 60vw; max-height: 50vh; aspect-ratio: 1.88/1;\} <"line1044">@media (max-width: 600px) \{ <"line1045">\tab #splash img \{object-fit: contain; object-position: 100% 100%;\} <"line1046">\} <"line1047">#splash div \{margin-block: 1em 1.5em; text-align: center; display: flex; gap: 1em; justify-content: center;\} <"line1048">#splash button \{font-size: 1.33em; border-radius: 1em; padding-inline: 0.75em; padding-block: 0.2em; border: 0; background: #888; color: #EEE; cursor: pointer;\} <"line1049">#splash button:focus \{outline: 0.25em solid black;\} <"line1050">#splash button#dismiss-Y \{background: hsl(205deg 84.8% 50%);\} <"line1051">#splash button#dismiss-L \{background: hsl(102.5deg 15.2% 50%);\} <"line1052">#splash button#dismiss-N \{background: hsl(0deg 84.8% 50%);\} <"line1053">\f0\lang1033 <\f2 /style\f0\lang1033 >\f2 <"line1054">\f0\lang1033 <\f2 footer class="global"\f0\lang1033 >\f2 <"line1055">\tab \f0\lang1033 <\f2 b\f0\lang1033 >\f2 \f0\lang1033 <\f2 /b\f0\lang1033 >\f2 <"line1056">\tab \f0\lang1033 <\f2 div\f0\lang1033 >\f2 <"line1057">\tab \f0\lang1033 <\f2 a href="/" class="igalia logo home"\f0\lang1033 >\f2 \f0\lang1033 <\f2 img src="/assets/img/logo-white.svg" alt="WPE"\f0\lang1033 >\f2 \f0\lang1033 <\f2 /a\f0\lang1033 >\f2 <"line1058">\tab \f0\lang1033 <\f2 ul\f0\lang1033 >\f2 <"line1059">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 Connect on \f0\lang1033 <\f2 a rel="me" href="https://floss.social/@WPEWebKit"\f0\lang1033 >\f2 Mastodon\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 , \f0\lang1033 <\f2 a href="https://bsky.app/profile/wpewebkit.org"\f0\lang1033 >\f2 Bluesky\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 \f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1060">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 mailing list: \f0\lang1033 <\f2 a href="https://lists.webkit.org/mailman3/lists/webkit-wpe.lists.webkit.org/"\f0\lang1033 >\f2 webkit-wpe\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 \f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1061">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 OFTC: \f0\lang1033 <\f2 a href="https://webchat.oftc.net/?channels=wpe"\f0\lang1033 >\f2 #wpe\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 \f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1062">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 Matrix: \f0\lang1033 <\f2 a href="https://matrix.to/#/#wpe:matrix.org"\f0\lang1033 >\f2 #wpe:matrix.org\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 \f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1063">\tab \f0\lang1033 <\f2 /ul\f0\lang1033 >\f2 <"line1064">\tab \f0\lang1033 <\f2 ul\f0\lang1033 >\f2 <"line1065">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 Copyright &&copy; 2018-2025 The WPE WebKit Team.\f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1066">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 Hosting kindly provided by \f0\lang1033 <\f2 a href="https://www.igalia.com"\f0\lang1033 >\f2 Igalia\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 .\f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1067">\tab \f0\lang1033 <\f2 li\f0\lang1033 >\f2 \f0\lang1033 <\f2 a href="/sitemap/"\f0\lang1033 >\f2 Site map\f0\lang1033 <\f2 /a\f0\lang1033 >\f2 .\f0\lang1033 <\f2 /li\f0\lang1033 >\f2 <"line1068">\tab \f0\lang1033 <\f2 /ul\f0\lang1033 >\f2 <"line1069">\tab \f0\lang1033 <\f2 /div\f0\lang1033 >\f2 <"line1070">\f0\lang1033 <\f2 /footer\f0\lang1033 >\f2 <"line1071">\f0\lang1033 <\f2 script\f0\lang1033 >\f2 <"line1072">let storedInfo = \{\}; <"line1073">const flagName = 'survey-splash'; <"line1074"> <"line1075">function startup(flagName) \{ <"line1076">\tab if (!flagName) \{ <"line1077">\tab console.error('Missing flagName'); <"line1078">\tab return; <"line1079">\tab\} <"line1080">\tab if (storageAvailable("localStorage")) \{ <"line1081">\tab let currentTime = Date.now(); <"line1082">\tab let timeOut = 1; <"line1083">\tab timeOut *= 86400 * 1000; <"line1084">\tab let localStore = localStorage.getItem(flagName); <"line1085">\tab if (!localStore) \{ <"line1086">\tab storedInfo = \{ <"line1087">\tab 'status': null, <"line1088">\tab 'datetime': currentTime, <"line1089">\tab 'pageloads' : 0 <"line1090">\tab\} <"line1091">\tab\} else \{ <"line1092">\tab storedInfo = JSON.parse(localStore); <"line1093">\tab\} <"line1094">\tab storedInfo.pageloads++; <"line1095">\tab localStorage.setItem(flagName, JSON.stringify(storedInfo)); <"line1096"> <"line1097">\tab if (storedInfo.pageloads \f0\lang1033 <\f2 11) return; <"line1098">\tab if (storedInfo.status == "Y" || storedInfo.status == "N") return; <"line1099">\tab if (storedInfo.status &&&& currentTime - storedInfo.datetime \f0\lang1033 <\f2 timeOut) return; <"line1100"> <"line1101">\tab splash.showModal(); <"line1102">\tab storedInfo.datetime = currentTime; <"line1103">\tab\} <"line1104">\} <"line1105"> <"line1106">function storageAvailable(type) \{ <"line1107">\tab // {{\field{\*\fldinst{HYPERLINK https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API }}{\fldrslt{https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API\ul0\cf0}}}}\f2\fs22 <"line1108"> let storage; <"line1109"> try \{ <"line1110"> storage = window[type]; <"line1111"> const x = "__storage_test__"; <"line1112"> storage.setItem(x, x); <"line1113"> storage.removeItem(x); <"line1114"> return true; <"line1115"> \} catch (e) \{ <"line1116"> return ( <"line1117"> e instanceof DOMException &&&& <"line1118"> // everything except Firefox <"line1119"> (e.code === 22 || <"line1120"> // Firefox <"line1121"> e.code === 1014 || <"line1122"> // test name field too, because code might not be present <"line1123"> // everything except Firefox <"line1124"> e.name === "QuotaExceededError" || <"line1125"> // Firefox <"line1126"> e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&&& <"line1127"> // acknowledge QuotaExceededError only if there's something already stored <"line1128"> storage &&&& <"line1129"> storage.length !== 0 <"line1130"> ); <"line1131"> \} <"line1132">\} <"line1133"> <"line1134">function surveyRedirect() \{ <"line1135">\tab let surveyURL = "{{\field{\*\fldinst{HYPERLINK https://docs.google.com/forms/d/e/1FAIpQLSchPgMGzuVc9ry5bdxF2uFnW2q3FcrSSqxJdOM4Fd2BD4s7dg/viewform?usp=pp_url&&entry.1179679285=WPEWebKit.org+website }}{\fldrslt{https://docs.google.com/forms/d/e/1FAIpQLSchPgMGzuVc9ry5bdxF2uFnW2q3FcrSSqxJdOM4Fd2BD4s7dg/viewform?usp=pp_url&&entry.1179679285=WPEWebKit.org+website\ul0\cf0}}}}\f2\fs22 "; <"line1136">\tab if (surveyURL) window.location = surveyURL; <"line1137">\} <"line1138"> <"line1139">document.querySelectorAll('button[is="dis-misser"]').forEach(el =\f0\lang1033 >\f2 \{ <"line1140">\tab el.addEventListener("click", () =\f0\lang1033 >\f2 \{ <"line1141">\tab splash.close(); <"line1142">\tab storedInfo.status = el.getAttribute('id').replace('dismiss-',''); <"line1143">\tab console.log(storedInfo); <"line1144">\tab localStorage.setItem(flagName, JSON.stringify(storedInfo)); <"line1145">\tab if (storedInfo.status == "Y") surveyRedirect(); <"line1146">\tab\}); <"line1147">\}); <"line1148"> <"line1149">window.onload = startup(flagName); <"line1150">\f0\lang1033 <\f2 /script\f0\lang1033 >\f2 <"line1151"> <"line1152"> <"line1153"> \f0\lang1033 <\f2 /body\f0\lang1033 >\f2 <"line1154">\f0\lang1033 <\f2 /html\f0\lang1033 >\f2 <"line1155">\f0\lang9\par +} + \ No newline at end of file diff --git a/Document.txt b/Document.txt new file mode 100644 index 0000000..b8a52ad --- /dev/null +++ b/Document.txt @@ -0,0 +1,25643 @@ +https://pr-preview.s3.amazonaws.com/w3c/performance-timeline/204/925ae5e...e1b67dc.html#dom-performanceobserver-takerecords + + + + + + + + + + + +Performance Timeline + + + + + + + + + + + + + +
      +

      + +

      +

      +Performance +Timeline +Level +2 + +

      +

      + +W3C +Editor's +Draft + + +

      +
      + +More +details +about +this +document + +
      +
      +This +version: +
      + +https://w3c.github.io/performance-timeline/ + +
      +
      +Latest +published +version: +
      + +https://www.w3.org/TR/performance-timeline/ + +
      +
      +Latest +editor's +draft: +
      + +https://w3c.github.io/performance-timeline/ + +
      +
      +History: +
      + +https://www.w3.org/standards/history/performance-timeline +
      + +Commit +history + +
      +
      +Test +suite: +
      + +https://github.com/web-platform-tests/wpt/tree/master/performance-timeline + +
      +
      +Editor: +
      + +Nicolás +Peña +Moreno + +( + +Google + +) +
      +
      +Former +editors: +
      + +Ilya +Grigorik + +( + +Google + +) +
      + +( + +Microsoft +Corp. + +) +(Until +November +2014) +
      + +Zhiheng +Wang + +( + +Google + +) +(Until +July +2013) +
      +
      +Feedback: +
      + +GitHub +w3c/performance-timeline + +( + +pull +requests +, + +new +issue +, + +open +issues + +) +
      +
      +
      + +
      +
      +
      +

      +Abstract +

      +

      +This +specification +extends +the +High +Resolution +Time +specification +[ + + +HR-TIME-3 + + +] +by +providing +methods +to +store +and +retrieve +high +resolution +performance +metric +data. +

      +
      +
      +

      +Status +of +This +Document +

      +
      + +This +is +a +preview + +

      +Do +not +attempt +to +implement +this +version +of +the +specification. +Do +not +reference +this +version +as +authoritative +in +any +way. +Instead, +see + +https://w3c.github.io/performance-timeline/ + +for +the +Editor's +draft. +

      +
      +

      + +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +index + +at +https://www.w3.org/TR/. + +

      +

      +This + +Performance +Timeline +Level +2 + +specification + +replaces +the +first +version +of +[ + + +PERFORMANCE-TIMELINE + + +] +and +includes: +

      + +

      +This +document +was +published +by +the + +Web +Performance +Working +Group + +as +an +Editor's +Draft. +

      +Publication +as +an +Editor's +Draft +does +not +imply +endorsement +by + +W3C + +and +its +Members. +

      +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

      +This +document +was +produced +by +a +group +operating +under +the + + +W3C + +Patent +Policy +. + +W3C + +maintains +a + +public +list +of +any +patent +disclosures + +made +in +connection +with +the +deliverables +of +the +group; +that +page +also +includes +instructions +for +disclosing +a +patent. +An +individual +who +has +actual +knowledge +of +a +patent +which +the +individual +believes +contains + +Essential +Claim(s) + +must +disclose +the +information +in +accordance +with + +section +6 +of +the + +W3C + +Patent +Policy +. +

      +This +document +is +governed +by +the + +2 +November +2021 + +W3C + +Process +Document +. +

      + +
      +
      +

      + +1. + +Introduction +

      + + +
      +

      + +This +section +is +non-normative. + +

      +

      +Accurately +measuring +performance +characteristics +of +web +applications +is +an +important +aspect +of +making +web +applications +faster. +This +specification +defines +the +necessary + +Performance +Timeline + +primitives +that +enable +web +developers +to +access, +instrument, +and +retrieve +various +performance +metrics +from +the +full +lifecycle +of +a +web +application. +

      +

      +[ + + +NAVIGATION-TIMING-2 + + +], +[ + + +RESOURCE-TIMING-2 + + +], +and +[ + + +USER-TIMING-2 + + +] +are +examples +of +specifications +that +define +timing +information +related +to +the +navigation +of +the +document, +resources +on +the +page, +and +developer +scripts, +respectively. +Together +these +and +other +performance +interfaces +define +performance +metrics +that +describe +the + +Performance +Timeline + +of +a +web +application. +For +example, +the +following +script +shows +how +a +developer +can +access +the + +Performance +Timeline + +to +obtain +performance +metrics +related +to +the +navigation +of +the +document, +resources +on +the +page, +and +developer +scripts: +

      +
      +
      <!doctype html>
      +<html>
      +<head></head>
      +<body onload="init()">
      +  <img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
      +  <script>
      +    function init() {
      +      // see [[USER-TIMING-2]]
      +      performance.mark("startWork");
      +      doWork(); // Some developer code
      +      performance.mark("endWork");
      +      measurePerf();
      +    }
      +    function measurePerf() {
      +      performance
      +        .getEntries()
      +        .map(entry => JSON.stringify(entry, null, 2))
      +        .forEach(json => console.log(json));
      +    }
      +  </script>
      +  </body>
      +
      +</
      +
      +html
      +
      +>
      +
      +
      +
      +
      +

      +Alternatively, +the +developer +can +observe +the + +Performance +Timeline + +and +be +notified +of +new +performance +metrics +and, +optionally, +previously +buffered +performance +metrics +of +specified +type, +via +the + + +PerformanceObserver + + +interface. +

      +

      +The + + +PerformanceObserver + + +interface +was +added +in +Performance +Timeline +Level +2 + +and +is +designed +to +address +limitations +of +the +buffer-based +approach +shown +in +the +first +example. +By +using +the +PerformanceObserver +interface, +the +application +can: +

      +
        +
      • +Avoid +polling +the +timeline +to +detect +new +metrics +
      • +
      • +Eliminate +costly +deduplication +logic +to +identify +new +metrics +
      • +
      • +Eliminate +race +conditions +with +other +consumers +that +may +want +to +manipulate +the +buffer +
      • +
      +

      +The +developer +is +encouraged +to +use + + +PerformanceObserver + + +where +possible. +Further, +new +performance +API's +and +metrics +may +only +be +available +through +the + + +PerformanceObserver + + +interface. +The +observer +works +by +specifying +a +callback +in +the +constructor +and +specifying +the +performance +entries +it's +interested +in +via +the + + +observe() + + +method. +The +user +agent +chooses +when +to +execute +the +callback, +which +receives +performance +entries +that +have +been +queued. +

      +

      +There +are +special +considerations +regarding +initial +page +load +when +using +the + + +PerformanceObserver + + +interface: +a +registration +must +be +active +to +receive +events +but +the +registration +script +may +not +be +available +or +may +not +be +desired +in +the +critical +path. +To +address +this, +user +agents +buffer +some +number +of +events +while +the +page +is +being +constructed, +and +these +buffered +events +can +be +accessed +via +the + + +buffered + + +flag +when +registering +the +observer. +When +this +flag +is +set, +the +user +agent +retrieves +and +dispatches +events +that +it +has +buffered, +for +the +specified +entry +type, +and +delivers +them +in +the +first +callback +after +the + + +observe() + + +call +occurs. +

      +
      +
      + +Note + +
      +

      +The +number +of +buffered +events +is +determined +by +the +specification +that +defines +the +metric +and +buffering +is +intended +to +used +for +first-N +events +only; +buffering +is +not +unbounded +or +continuous. +

      +
      +
      <!doctype html>
      +<html>
      +<head></head>
      +<body>
      +<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
      +<script>
      +// Know when the entry types we would like to use are not supported.
      +function detectSupport(entryTypes) {
      +  for (const entryType of entryTypes) {
      +    if (!PerformanceObserver.supportedEntryTypes.includes(entryType)) {
      +      // Indicate to client-side analytics that |entryType| is not supported.
      +    }
      +  }
      +}
      +detectSupport(["resource", "mark", "measure"]);
      +const userTimingObserver = new PerformanceObserver(list => {
      +  list
      +    .getEntries()
      +    // Get the values we are interested in
      +    .map(({ name, entryType, startTime, duration }) => {
      +      const obj = {
      +        "Duration": duration,
      +        "Entry Type": entryType,
      +        "Name": name,
      +        "Start Time": startTime,
      +      };
      +      return JSON.stringify(obj, null, 2);
      +    })
      +    // Display them to the console.
      +    .forEach(console.log);
      +  // Disconnect after processing the events.
      +  userTimingObserver.disconnect();
      +});
      +// Subscribe to new events for User-Timing.
      +userTimingObserver.observe({entryTypes: ["mark", "measure"]});
      +const resourceObserver = new PerformanceObserver(list => {
      +  list
      +    .getEntries()
      +    // Get the values we are interested in
      +    .map(({ name, startTime, fetchStart, responseStart, responseEnd }) => {
      +      const obj = {
      +        "Name": name,
      +        "Start Time": startTime,
      +        "Fetch Start": fetchStart,
      +        "Response Start": responseStart,
      +        "Response End": responseEnd,
      +      };
      +      return JSON.stringify(obj, null, 2);
      +    })
      +    // Display them to the console.
      +    .forEach(console.log);
      +  // Disconnect after processing the events.
      +  resourceObserver.disconnect();
      +});
      +// Retrieve buffered events and subscribe to newer events for Resource Timing.
      +resourceObserver.observe({type: "resource", buffered: true});
      +</script>
      +</body>
      +
      +</
      +
      +html
      +
      +>
      +
      +
      +
      +
      +
      +
      +
      +

      + +2. + +Conformance +

      + + +
      +

      +As +well +as +sections +marked +as +non-normative, +all +authoring +guidelines, +diagrams, +examples, +and +notes +in +this +specification +are +non-normative. +Everything +else +in +this +specification +is +normative. +

      +The +key +words + +MUST +, + +MUST +NOT +, +and + +SHOULD + +in +this +document +are +to +be +interpreted +as +described +in + +BCP +14 + +[ + + +RFC2119 + + +] +[ + + +RFC8174 + + +] +when, +and +only +when, +they +appear +in +all +capitals, +as +shown +here. +

      +

      +Conformance +requirements +phrased +as +algorithms +or +specific +steps +may +be +implemented +in +any +manner, +so +long +as +the +end +result +is +equivalent. +(In +particular, +the +algorithms +defined +in +this +specification +are +intended +to +be +easy +to +follow, +and +not +intended +to +be +performant). +

      +
      +
      +
      +

      + +3. + + +Performance +Timeline + +

      + + +
      +

      +Each + +global +object + +has: +

      +
        +
      • +a + +performance +observer +task +queued +flag + +
      • +
      • +a + +list +of + +registered +performance +observer + +objects + +that +is +initially +empty +
      • +
      • +a + +performance +entry +buffer +map + + +map +, + +keyed + +on +a + +DOMString +, +representing +the +entry +type +to +which +the +buffer +belongs. +The + +map + +'s + +value + +is +the +following +tuple: +
          +
        • +A + +performance +entry +buffer + +to +store + + +PerformanceEntry + + +objects, +that +is +initially +empty. +
        • +
        • +An +integer + +maxBufferSize +, +initialized +to +the + +registry + +value +for +this +entry +type. +
        • +
        • +A + +boolean + + +availableFromTimeline +, +initialized +to +the + +registry + +value +for +this +entry +type. +
        • +
        • +An +integer + +dropped +entries +count + +that +is +initially +0. +
        • +
        +
      • +
      +

      +In +order +to +get +the + +relevant +performance +entry +tuple +, +given + +entryType + +and + +globalObject + +as +input, +run +the +following +steps: +

      +
        +
      1. +Let + +map + +be +the + +performance +entry +buffer +map + +associated +with + +globalObject +. +
      2. +
      3. +Return +the +result +of + +getting +the +value +of +an +entry + +from + +map +, +given + +entryType + +as +the + +key +. +
      4. +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +Chrome + +6+ +
      +Chrome +Android + +? +
      +Edge + +12+ +
      +Edge +Mobile + +? +
      +Firefox + +7+ +
      +Firefox +Android + +? +
      +Opera + +? +
      +Opera +Android + +? +
      +Safari + +8+ +
      +Safari +iOS + +9+ +
      +Samsung +Internet + +? +
      +WebView +Android + +37+ +
      + + +
      +
      +

      + +3.1 + +Extensions +to +the + + +Performance + + +interface +

      + + +
      +

      +This +extends +the + + +Performance + + +interface +from +[ + + +HR-TIME-3 + + +] +and +hosts +performance +related +attributes +and +methods +used +to +retrieve +the +performance +metric +data +from +the + +Performance +Timeline +. +

      +
      WebIDLpartial interface Performance {
      +  PerformanceEntryList getEntries ();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +typedef
      +
      +
      +sequence
      +
      +<
      +
      +
      +PerformanceEntry
      +
      +
      +>
      +
      +
      +
      +PerformanceEntryList
      +
      +
      +;
      +
      +
      +
      +

      +The + + +PerformanceEntryList + + +represents +a +sequence +of + + +PerformanceEntry + +, +providing +developers +with +all +the +convenience +methods +found +on +JavaScript +arrays. +

      + +
      +
      +

      + +3.1.1 + + + +getEntries() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by +the + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +and + +type + +set +to + +null +. +

      +
      + +
      +
      +

      + +3.1.2 + + + +getEntriesByType() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +set +to + +null +, +and + +type + +set +to +the +method's +input + +type + +parameter. +

      +
      + +
      +
      +

      + +3.1.3 + + + +getEntriesByName() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +set +to +the +method +input + +name + +parameter, +and + +type + +set +to + +null + +if +optional + +entryType + +is +omitted, +or +set +to +the +method's +input + +type + +parameter +otherwise. +

      +
      +
      + + +
      +
      +

      + +4. + +The + + +PerformanceEntry + + +interface +

      + + +
      +

      +The + + +PerformanceEntry + + +interface +hosts +the +performance +data +of +various +metrics. +

      +
      WebIDL[Exposed=(Window,Worker)]
      +interface PerformanceEntry {
      +  readonly    attribute DOMString           name;
      +  readonly    attribute DOMString           entryType;
      +  readonly    attribute DOMHighResTimeStamp startTime;
      +  readonly    attribute DOMHighResTimeStamp duration;
      +  [Default] object toJSON();
      +};
      +
      +
      +
      +
      +
      + + +name + + +
      +
      +This +attribute + +MUST + +return +an +identifier +for +this + + +PerformanceEntry + + +object. +This +identifier +does +not +have +to +be +unique. +
      +
      + + +entryType + + +
      +
      +This +attribute + +MUST + +return +the +type +of +the +interface +represented +by +this + + +PerformanceEntry + + +object. +
      +
      + +Note + +
      +

      +All + +entryType + +values +are +defined +in +the +relevant + +registry +. +Examples +include: + +"mark" + +and + +"measure" + +[ + + +USER-TIMING-2 + + +], + +"navigation" + +[ + + +NAVIGATION-TIMING-2 + + +], + +"resource" + +[ + + +RESOURCE-TIMING-2 + + +], +and + +"longtask" +. +

      +
      +
      + + +startTime + + +
      +
      +This +attribute + +MUST + +return +the +time +value +of +the +first +recorded +timestamp +of +this +performance +metric. +If +the +startTime +concept +doesn't +apply, +a +performance +metric +may +choose +to +return +a + +startTime + +of + +0 +. +
      +
      + + +duration + + +
      +
      +This +attribute + +MUST + +return +the +time +value +of +the +duration +of +the +entire +event +being +recorded +by +this + + +PerformanceEntry + +. +Typically, +this +would +be +the +time +difference +between +the +last +recorded +timestamp +and +the +first +recorded +timestamp +of +this + + +PerformanceEntry + +. +If +the +duration +concept +doesn't +apply, +a +performance +metric +may +choose +to +return +a + +duration + +of + +0 +. +
      +
      +

      +When + + +toJSON + + +is +called, +run +[ + + +WebIDL + + +]'s + +default +toJSON +steps +. +

      +
      + +
      +
      +

      + +5. + +The + + +PerformanceObserver + + +interface +

      + + +
      +

      +The + + +PerformanceObserver + + +interface +can +be +used +to +observe +the + +Performance +Timeline + +to +be +notified +of +new +performance +metrics +as +they +are +recorded, +and +optionally +buffered +performance +metrics. +

      +

      +Each + + +PerformanceObserver + + +has +these +associated +concepts: +

      +
        +
      • +A + + +PerformanceObserverCallback + + + +observer +callback + +set +on +creation. +
      • +
      • +A + + +PerformanceEntryList + + +object +called +the + +observer +buffer + +that +is +initially +empty. +
      • +
      • +A + +DOMString + + +observer +type + +which +is +initially + +"undefined" +. +
      • +
      • +A +boolean + +requires +dropped +entries + +which +is +initially +set +to +false. +
      • +
      +

      +The + +PerformanceObserver(callback) + +constructor +must +create +a +new + + +PerformanceObserver + + +object +with +its + +observer +callback + +set +to + +callback + +and +then +return +it. +

      +

      +A + +registered +performance +observer + +is +a + +struct + +consisting +of +an + +observer + +member +(a + + +PerformanceObserver + + +object) +and +an + +options +list + +member +(a +list +of + + +PerformanceObserverInit + + +dictionaries). +

      +
      WebIDLcallback PerformanceObserverCallback = undefined (PerformanceObserverEntryList entries,
      +                                             PerformanceObserver observer,
      +                                             optional PerformanceObserverCallbackOptions options = {});
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserver {
      +  constructor(PerformanceObserverCallback callback);
      +  undefined observe (optional PerformanceObserverInit options = {});
      +  undefined disconnect ();
      +  PerformanceEntryList takeRecords();
      +  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
      +};
      +
      +
      +
      +
      +
      + +Note + +
      +

      +To +keep +the +performance +overhead +to +minimum +the +application +ought +to +only +subscribe +to +event +types +that +it +is +interested +in, +and +disconnect +the +observer +once +it +no +longer +needs +to +observe +the +performance +data. +Filtering +by +name +is +not +supported, +as +it +would +implicitly +require +a +subscription +for +all +event +types +— +this +is +possible, +but +discouraged, +as +it +will +generate +a +significant +volume +of +events. +

      +
      +
      +

      + +5.1 + + + +PerformanceObserverCallbackOptions + + +dictionary +

      + + +
      +> +
      WebIDLdictionary PerformanceObserverCallbackOptions {
      +  unsigned long long droppedEntriesCount;
      +};
      +
      +
      +
      +
      +
      + + +droppedEntriesCount + + +
      +
      +An +integer +representing +the +dropped +entries +count +for +the +entry +types +that +the +observer +is +observing +when +the + + +PerformanceObserver + + +'s + +requires +dropped +entries + +is +set. +
      +
      +
      + +
      +
      +

      + +5.2 + + + +observe() + + +method +

      + + +
      +

      +The + + +observe() + + +method +instructs +the +user +agent +to +register +the +observer +and +must +run +these +steps: +

      +
        +
      1. +Let + +relevantGlobal + +be + +this + +'s + +relevant +global +object +. +
      2. +
      3. +If + +options + +'s + + +entryTypes + + +and + + +type + + +members +are +both +omitted, +then + +throw + +a +" + + +TypeError + + +". +
      4. +
      5. +If + +options + +'s + + +entryTypes + + +is +present +and +any +other +member +is +also +present, +then + +throw + +a +" + + +TypeError + + +". +
      6. +
      7. +Update +or +check + +this + +'s + +observer +type + +by +running +these +steps: +
          +
        1. +If + +this + +'s + +observer +type + +is + +"undefined" +: +
            +
          1. +If + +options + +'s + + +entryTypes + + +member +is +present, +then +set + +this + +'s + +observer +type + +to + +"multiple" +. +
          2. +
          3. +If + +options + +'s + + +type + + +member +is +present, +then +set + +this + +'s + +observer +type + +to + +"single" +. +
          4. +
          +
        2. +
        3. +If + +this + +'s + +observer +type + +is + +"single" + +and + +options + +'s + + +entryTypes + + +member +is +present, +then + +throw + +an +" + + +InvalidModificationError + + +". +
        4. +
        5. +If + +this + +'s + +observer +type + +is + +"multiple" + +and + +options + +'s + + +type + + +member +is +present, +then + +throw + +an +" + + +InvalidModificationError + + +". +
        6. +
        +
      8. +
      9. +Set + +this + +'s + +requires +dropped +entries + +to +true. +
      10. +
      11. +If + +this + +'s + +observer +type + +is + +"multiple" +, +run +the +following +steps: +
          +
        1. +Let + +entry +types + +be + +options + +'s + + +entryTypes + + +sequence. +
        2. +
        3. +Remove +all +types +from + +entry +types + +that +are +not +contained +in + +relevantGlobal + +'s + +frozen +array +of +supported +entry +types +. +The +user +agent + +SHOULD + +notify +developers +if + +entry +types + +is +modified. +For +example, +a +console +warning +listing +removed +types +might +be +appropriate. +
        4. +
        5. +If +the +resulting + +entry +types + +sequence +is +an +empty +sequence, +abort +these +steps. +The +user +agent + +SHOULD + +notify +developers +when +the +steps +are +aborted +to +notify +that +registration +has +been +aborted. +For +example, +a +console +warning +might +be +appropriate. +
        6. +
        7. +If +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal + +contains +a + +registered +performance +observer + +whose + +observer + +is + +this +, +replace +its + +options +list + +with +a +list +containing + +options + +as +its +only +item. +
        8. +
        9. +Otherwise, +create +and +append +a + +registered +performance +observer + +object +to +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal +, +with + +observer + +set +to + +this + +and + +options +list + +set +to +a +list +containing + +options + +as +its +only +item. +
        10. +
        +
      12. +
      13. +Otherwise, +run +the +following +steps: +
          +
        1. +Assert +that + +this + +'s + +observer +type + +is + +"single" +. +
        2. +
        3. +If + +options + +'s + + +type + + +is +not +contained +in +the + +relevantGlobal + +'s + +frozen +array +of +supported +entry +types +, +abort +these +steps. +The +user +agent + +SHOULD + +notify +developers +when +this +happens, +for +instance +via +a +console +warning. +
        4. +
        5. +If +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal + +contains +a + +registered +performance +observer + + +obs + +whose + +observer + +is + +this +: +
            +
          1. +If + +obs + +'s + +options +list + +contains +a + + +PerformanceObserverInit + + +item + +currentOptions + +whose + + +type + + +is +equal +to + +options + +'s + + +type + +, +replace + +currentOptions + +with + +options + +in + +obs + +'s + +options +list +. +
          2. +
          3. +Otherwise, +append + +options + +to + +obs + +'s + +options +list +. +
          4. +
          +
        6. +
        7. +Otherwise, +create +and +append +a + +registered +performance +observer + +object +to +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal +, +with + +observer + +set +to +the + +this + +and + +options +list + +set +to +a +list +containing + +options + +as +its +only +item. +
        8. +
        9. +If + +options + +'s + + +buffered + + +flag +is +set: +
            +
          1. +Let + +tuple + +be +the + +relevant +performance +entry +tuple + +of + +options + +'s + + +type + + +and + +relevantGlobal +. +
          2. +
          3. +

            +For +each + +entry + +in + +tuple + +'s + +performance +entry +buffer +: +

            +
              +
            1. +If + +should +add +entry + +with + +entry + +and + +options + +as +parameters +returns +true, + +append + + +entry + +to +the + +observer +buffer +. +
            2. +
            +
          4. +
          5. + +Queue +the +PerformanceObserver +task + +with + +relevantGlobal + +as +input. +
          6. +
          +
        10. +
        +
      14. +
      +
      +
      + +Note + +
      +

      +A + + +PerformanceObserver + + +object +needs +to +always +call + + +observe() + + +with + +options + +'s + + +entryTypes + + +set +OR +always +call + + +observe() + + +with + +options + +'s + + +type + + +set. +If +one + + +PerformanceObserver + + +calls + + +observe() + + +with + + +entryTypes + + +and +also +calls +observe +with + + +type + +, +then +an +exception +is +thrown. +This +is +meant +to +avoid +confusion +with +how +calls +would +stack. +When +using + + +entryTypes + +, +no +other +parameters +in + + +PerformanceObserverInit + + +can +be +used. +In +addition, +multiple + + +observe() + + +calls +will +override +for +backwards +compatibility +and +because +a +single +call +should +suffice +in +this +case. +On +the +other +hand, +when +using + + +type + +, +calls +will +stack +because +a +single +call +can +only +specify +one +type. +Calling + + +observe() + + +with +a +repeated + + +type + + +will +also +override. +

      +
      +
      +

      + +5.2.1 + + + +PerformanceObserverInit + + +dictionary +

      + + +
      +
      WebIDLdictionary PerformanceObserverInit {
      +  sequence<DOMString> entryTypes;
      +  DOMString type;
      +  boolean buffered;
      +};
      +
      +
      +
      +
      +
      + + +entryTypes + + +
      +
      +A +list +of +entry +types +to +be +observed. +If +present, +the +list + +MUST +NOT + +be +empty +and +all +other +members + +MUST +NOT + +be +present. +Types +not +recognized +by +the +user +agent + +MUST + +be +ignored. +
      +
      +
      +
      + + +type + + +
      +
      +A +single +entry +type +to +be +observed. +A +type +that +is +not +recognized +by +the +user +agent + +MUST + +be +ignored. +Other +members +may +be +present. +
      +
      +
      +
      + + +buffered + + +
      +
      +A +flag +to +indicate +whether +buffered +entries +should +be +queued +into +observer's +buffer. +
      +
      +
      + +
      +
      +

      + +5.2.2 + + + +PerformanceObserverEntryList + + +interface +

      + + +
      +
      WebIDL[Exposed=(Window,Worker)]
      +interface PerformanceObserverEntryList {
      +  PerformanceEntryList getEntries();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +
      +
      +
      +

      +Each + + +PerformanceObserverEntryList + + +object +has +an +associated + +entry +list +, +which +consists +of +a + + +PerformanceEntryList + + +and +is +initialized +upon +construction. +

      + +
      +
      +
      + +5.2.2.1 + + + +getEntries() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +and + +type + +set +to + +null +. +

      +
      + +
      +
      +
      + +5.2.2.2 + + + +getEntriesByType() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +set +to + +null +, +and + +type + +set +to +the +method's +input + +type + +parameter. +

      +
      + +
      +
      +
      + +5.2.2.3 + + + +getEntriesByName() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +set +to +the +method +input + +name + +parameter, +and + +type + +set +to + +null + +if +optional + +entryType + +is +omitted, +or +set +to +the +method's +input + +type + +parameter +otherwise. +

      +
      +
      +
      + +
      +
      +

      + +5.3 + + + +takeRecords() + + +method +

      + + +
      +

      +The + + +takeRecords() + + +method +must +return +a +copy +of + +this + +'s + +observer +buffer +, +and +also +empty + +this + +'s + +observer +buffer +. +

      +
      + +
      +
      +

      + +5.4 + + + +disconnect() + + +method +

      + + +
      +

      +The + + +disconnect() + + +method +must +do +the +following: +

      +
        +
      1. +Remove + +this + +from +the + +list +of +registered +performance +observer +objects + +of + +relevant +global +object +. +
      2. +
      3. +Empty + +this + +'s + +observer +buffer +. +
      4. +
      5. +Empty + +this + +'s + +options +list +. +
      6. +
      +
      + +
      +
      +

      + +5.5 + + + +supportedEntryTypes + + +attribute +

      + + +
      +

      +Each + +global +object + +has +an +associated + +frozen +array +of +supported +entry +types +, +which +is +initialized +to +the + +FrozenArray + + +created + +from +the +sequence +of +strings +among +the + +registry + +that +are +supported +for +the +global +object, +in +alphabetical +order. +

      +

      +When + + +supportedEntryTypes + + +'s +attribute +getter +is +called, +run +the +following +steps: +

      +
        +
      1. +Let + +globalObject + +be +the + +environment +settings +object's +global +object +. +
      2. +
      3. +Return + +globalObject + +'s + +frozen +array +of +supported +entry +types +. +
      4. +
      +
      +
      + +Note + +
      +

      +This +attribute +allows +web +developers +to +easily +know +which +entry +types +are +supported +by +the +user +agent. +

      +
      +
      +
      +
      +

      + +6. + +Processing +

      + + +
      +
      +
      +

      + +6.1 + +Queue +a + +PerformanceEntry + +

      + + +
      +

      +To + +queue +a +PerformanceEntry + +( + +newEntry + +), +run +these +steps: +

      +
        +
      1. +Let + +interested +observers + +be +an +initially +empty +set +of + + +PerformanceObserver + + +objects. +
      2. +
      3. +Let + +entryType + +be + +newEntry + +’s + + +entryType + + +value. +
      4. +
      5. +Let + +relevantGlobal + +be + +newEntry + +'s + +relevant +global +object +. +
      6. +
      7. +For +each + +registered +performance +observer + + +regObs + +in + +relevantGlobal + +'s + +list +of +registered +performance +observer +objects +: +
          +
        1. +

          +If + +regObs + +'s + +options +list + +contains +a + + +PerformanceObserverInit + + + +options + +whose + + +entryTypes + + +member +includes + +entryType + +or +whose + + +type + + +member +equals +to + +entryType +: +

          +
            +
          1. +If + +should +add +entry + +with + +newEntry + +and + +options + +returns +true, +append + +regObs + +'s + +observer + +to + +interested +observers +. +
          2. +
          +
        2. +
        +
      8. +
      9. +For +each + +observer + +in + +interested +observers +: +
          +
        1. +Append + +newEntry + +to + +observer + +'s + +observer +buffer +. +
        2. +
        +
      10. +
      11. +Let + +tuple + +be +the + +relevant +performance +entry +tuple + +of + +entryType + +and + +relevantGlobal +. +
      12. +
      13. +Let + +isBufferFull + +be +the +return +value +of +the + +determine +if +a +performance +entry +buffer +is +full + +algorithm +with + +tuple + +as +input. +
      14. +
      15. +Let + +shouldAdd + +be +the +result +of + +should +add +entry + +with + +newEntry + +as +input. +
      16. +
      17. +If + +isBufferFull + +is +false +and + +shouldAdd + +is +true, + +append + + +newEntry + +to + +tuple + +'s + +performance +entry +buffer +. +
      18. +
      19. + +Queue +the +PerformanceObserver +task + +with + +relevantGlobal + +as +input. +
      20. +
      +
      +
      +
      +

      + +6.2 + +Queue +the +PerformanceObserver +task +

      + + +
      +

      +When +asked +to + +queue +the +PerformanceObserver +task +, +given + +relevantGlobal + +as +input, +run +the +following +steps: +

      +
        +
      1. +If + +relevantGlobal + +'s + +performance +observer +task +queued +flag + +is +set, +terminate +these +steps. +
      2. +
      3. +Set + +relevantGlobal + +'s + +performance +observer +task +queued +flag +. +
      4. +
      5. + +Queue +a +task + +that +consists +of +running +the +following +substeps. +The + +task +source + +for +the +queued +task +is +the + +performance +timeline +task +source +. +
          +
        1. +Unset + +performance +observer +task +queued +flag + +of + +relevantGlobal +. +
        2. +
        3. +Let + +notifyList + +be +a +copy +of + +relevantGlobal + +'s + +list +of +registered +performance +observer +objects +. +
        4. +
        5. +For +each + +registered +performance +observer + +object + +registeredObserver + +in + +notifyList +, +run +these +steps: +
            +
          1. +Let + +po + +be + +registeredObserver + +'s + +observer +. +
          2. +
          3. +Let + +entries + +be +a +copy +of + +po + +’s + +observer +buffer +. +
          4. +
          5. +If + +entries + +is +empty, +return. +
          6. +
          7. +Empty + +po + +’s + +observer +buffer +. +
          8. +
          9. +Let + +observerEntryList + +be +a +new + + +PerformanceObserverEntryList + +, +with +its + +entry +list + +set +to + +entries +. +
          10. +
          11. +Let + +droppedEntriesCount + +be +null. +
          12. +
          13. +If + +po + +'s + +requires +dropped +entries + +is +set, +perform +the +following +steps: +
              +
            1. +Set + +droppedEntriesCount + +to +0. +
            2. +
            3. +For +each + + +PerformanceObserverInit + + + +item + +in + +registeredObserver + +'s + +options +list +: +
                +
              1. +For +each + +DOMString + + +entryType + +that +appears +either +as + +item + +'s + + +type + + +or +in + +item + +'s + + +entryTypes + +: +
                  +
                1. +Let + +map + +be + +relevantGlobal + +'s + +performance +entry +buffer +map +. +
                2. +
                3. +Let + +tuple + +be +the +result +of + +getting +the +value +of +entry + +on + +map + +given + +entryType + +as + +key +. +
                4. +
                5. +Increase + +droppedEntriesCount + +by + +tuple + +'s + +dropped +entries +count +. +
                6. +
                +
              2. +
              +
            4. +
            5. +Set + +po + +'s + +requires +dropped +entries + +to +false. +
            6. +
            +
          14. +
          15. +Let + +callbackOptions + +be +a + + +PerformanceObserverCallbackOptions + + +with +its + + +droppedEntriesCount + + +set +to + +droppedEntriesCount + +if + +droppedEntriesCount + +is +not +null, +otherwise +unset. +
          16. +
          17. +Call + +po + +’s + +observer +callback + +with + +observerEntryList + +as +the +first +argument, +with + +po + +as +the +second +argument +and +as + +callback +this +value +, +and +with + +callbackOptions + +as +the +third +argument. +If +this + +throws + +an +exception, + +report +the +exception +. +
          18. +
          +
        6. +
        +
      6. +
      +

      +The + +performance +timeline + + +task +queue + +is +a +low +priority +queue +that, +if +possible, +should +be +processed +by +the +user +agent +during +idle +periods +to +minimize +impact +of +performance +monitoring +code. +

      +
      +
      +
      +

      + +6.3 + +Filter +buffer +map +by +name +and +type +

      + + +
      +

      +When +asked +to +run +the + +filter +buffer +map +by +name +and +type + +algorithm +with +optional + +name + +and + +type +, +run +the +following +steps: +

      +
        +
      1. +Let + +result + +be +an +initially +empty + +list +. +
      2. +
      3. +Let + +map + +be +the + +performance +entry +buffer +map + +associated +with +the + +relevant +global +object + +of + +this +. +
      4. +
      5. +Let + +tuple +list + +be +an +empty + +list +. +
      6. +
      7. +If + +type + +is +not +null, +append +the +result +of + +getting +the +value +of +entry + +on + +map + +given + +type + +as + +key + +to + +tuple +list +. +Otherwise, +assign +the +result +of + +get +the +values + +on + +map + +to + +tuple +list +. +
      8. +
      9. +For +each + +tuple + +in + +tuple +list +, +run +the +following +steps: +
          +
        1. +Let + +buffer + +be + +tuple + +'s + +performance +entry +buffer +. +
        2. +
        3. +If + +tuple + +'s + +availableFromTimeline + +is +false, +continue +to +the +next + +tuple +. +
        4. +
        5. +Let + +entries + +be +the +result +of +running + +filter +buffer +by +name +and +type + +with + +buffer +, + +name + +and + +type + +as +inputs. +
        6. +
        7. +For +each + +entry + +in + +entries +, + +append + + +entry + +to + +result +. +
        8. +
        +
      10. +
      11. +Sort + +results + +'s +entries +in +chronological +order +with +respect +to + + +startTime + + +
      12. +
      13. +Return + +result +. +
      14. +
      +
      +
      +
      +

      + +6.4 + +Filter +buffer +by +name +and +type +

      + + +
      +

      +When +asked +to +run +the + +filter +buffer +by +name +and +type + +algorithm, +with + +buffer +, + +name +, +and + +type + +as +inputs, +run +the +following +steps: +

      +
        +
      1. +Let + +result + +be +an +initially +empty + +list +. +
      2. +
      3. +For +each + + +PerformanceEntry + + + +entry + +in + +buffer +, +run +the +following +steps: +
          +
        1. +If + +type + +is +not +null +and +if + +type + +is +not + +identical +to + + +entry + +'s + +entryType + +attribute, +continue +to +next + +entry +. +
        2. +
        3. +If + +name + +is +not +null +and +if + +name + +is +not + +identical +to + + +entry + +'s + +name + +attribute, +continue +to +next + +entry +. +
        4. +
        5. + +append + + +entry + +to + +result +. +
        6. +
        +
      4. +
      5. +Sort + +results + +'s +entries +in +chronological +order +with +respect +to + + +startTime + + +
      6. +
      7. +Return + +result +. +
      8. +
      +
      +
      +
      +

      + +6.5 + +Determine +if +a +performance +entry +buffer +is +full +

      + + +
      +

      +To + +determine +if +a +performance +entry +buffer +is +full +, +with + +tuple + +as +input, +run +the +following +steps: +

      +
        +
      1. +Let + +num +current +entries + +be +the +size +of + +tuple + +'s + +performance +entry +buffer +. +
      2. +
      3. +If + +num +current +entries + +is +less +than + +tuples + +'s + +maxBufferSize +, +return +false. +
      4. +
      5. +Increase + +tuple + +'s + +dropped +entries +count + +by +1. +
      6. +
      7. +Return +true. +
      8. +
      +
      +
      +
      +
      +

      + +7. + +Privacy +Considerations +

      + + +
      +

      +This +specification +extends +the + + +Performance + + +interface +defined +by +[ + + +HR-TIME-3 + + +] +and +provides +methods +to +queue +and +retrieve +entries +from +the + +performance +timeline +. +Please +refer +to +[ + + +HR-TIME-3 + + +] +for +privacy +considerations +of +exposing +high-resoluting +timing +information. +Each +new +specification +introducing +new +performance +entries +should +have +its +own +privacy +considerations +as +well. +

      +
      +
      +
      +

      + +8. + +Security +Considerations +

      + + +
      +

      +This +specification +extends +the + + +Performance + + +interface +defined +by +[ + + +HR-TIME-3 + + +] +and +provides +methods +to +queue +and +retrieve +entries +from +the + +performance +timeline +. +Please +refer +to +[ + + +HR-TIME-3 + + +] +for +security +considerations +of +exposing +high-resoluting +timing +information. +Each +new +specification +introducing +new +performance +entries +should +have +its +own +security +considerations +as +well. +

      +
      +
      +
      +

      + +9. + +Dependencies +

      + + +
      +

      +The +[ + + +INFRA + + +] +specification +defines +the +following: + + +key + +, + + +getting +the +value +of +an +entry + +. +

      +
      +

      A. IDL Index

      WebIDLpartial interface Performance {
      +  PerformanceEntryList getEntries ();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +typedef sequence<PerformanceEntry> PerformanceEntryList;
      +[Exposed=(Window,Worker)]
      +interface PerformanceEntry {
      +  readonly    attribute DOMString           name;
      +  readonly    attribute DOMString           entryType;
      +  readonly    attribute DOMHighResTimeStamp startTime;
      +  readonly    attribute DOMHighResTimeStamp duration;
      +  [Default] object toJSON();
      +};
      +callback PerformanceObserverCallback = undefined (PerformanceObserverEntryList entries,
      +                                             PerformanceObserver observer,
      +                                             optional PerformanceObserverCallbackOptions options = {});
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserver {
      +  constructor(PerformanceObserverCallback callback);
      +  undefined observe (optional PerformanceObserverInit options = {});
      +  undefined disconnect ();
      +  PerformanceEntryList takeRecords();
      +  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
      +};
      +dictionary PerformanceObserverCallbackOptions {
      +  unsigned long long droppedEntriesCount;
      +};
      +dictionary PerformanceObserverInit {
      +  sequence<DOMString> entryTypes;
      +  DOMString type;
      +  boolean buffered;
      +};
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserverEntryList {
      +  PerformanceEntryList getEntries();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +
      +
      +
      +
      +
      +
      +

      + +B. + +Acknowledgments +

      + + +
      +

      +Thanks +to +Arvind +Jain, +Boris +Zbarsky, +Jatinder +Mann, +Nat +Duca, +Philippe +Le +Hegaret, +Ryosuke +Niwa, +Shubhie +Panicker, +Todd +Reifsteck, +Yoav +Weiss, +and +Zhiheng +Wang, +for +their +contributions +to +this +work. +

      +
      +
      +
      +

      + +C. + +References +

      + + +
      +
      +
      +

      + +C.1 + +Normative +references +

      + + +
      +
      +
      +[HR-TIME-3] +
      + + +High +Resolution +Time + +. +Yoav +Weiss. +W3C. +20 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/hr-time-3/ + +
      +[HTML] +
      + + +HTML +Standard + +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. +URL: + +https://html.spec.whatwg.org/multipage/ + +
      +[INFRA] +
      + + +Infra +Standard + +. +Anne +van +Kesteren; +Domenic +Denicola. +WHATWG. +Living +Standard. +URL: + +https://infra.spec.whatwg.org/ + +
      +[RFC2119] +
      + + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://www.rfc-editor.org/rfc/rfc2119 + +
      +[RFC8174] +
      + + +Ambiguity +of +Uppercase +vs +Lowercase +in +RFC +2119 +Key +Words + +. +B. +Leiba. +IETF. +May +2017. +Best +Current +Practice. +URL: + +https://www.rfc-editor.org/rfc/rfc8174 + +
      +[WebIDL] +
      + + +Web +IDL +Standard + +. +Edgar +Chen; +Timothy +Gu. +WHATWG. +Living +Standard. +URL: + +https://webidl.spec.whatwg.org/ + +
      +
      +
      +
      +

      + +C.2 + +Informative +references +

      + + +
      +
      +
      +[NAVIGATION-TIMING-2] +
      + + +Navigation +Timing +Level +2 + +. +Yoav +Weiss; +Noam +Rosenthal. +W3C. +7 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/navigation-timing-2/ + +
      +[PERFORMANCE-TIMELINE] +
      + + +Performance +Timeline + +. +Nicolas +Pena +Moreno. +W3C. +2 +December +2021. +W3C +Candidate +Recommendation. +URL: + +https://www.w3.org/TR/performance-timeline/ + +
      +[RESOURCE-TIMING-2] +
      + + +Resource +Timing +Level +2 + +. +Yoav +Weiss; +Noam +Rosenthal. +W3C. +29 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/resource-timing-2/ + +
      +[USER-TIMING-2] +
      + + +User +Timing +Level +2 + +. +Ilya +Grigorik. +W3C. +26 +February +2019. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/user-timing-2/ + +
      +[WORKERS] +
      + + +Web +Workers + +. +Ian +Hickson. +W3C. +28 +January +2021. +W3C +Working +Group +Note. +URL: + +https://www.w3.org/TR/workers/ + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Performance Timeline + + + + + + + + + + + + + +
      +

      + +

      +

      +Performance +Timeline +Level +2 + +

      +

      + +W3C +Editor's +Draft + + +

      +
      + +More +details +about +this +document + +
      +
      +This +version: +
      + +https://w3c.github.io/performance-timeline/ + +
      +
      +Latest +published +version: +
      + +https://www.w3.org/TR/performance-timeline/ + +
      +
      +Latest +editor's +draft: +
      + +https://w3c.github.io/performance-timeline/ + +
      +
      +History: +
      + +https://www.w3.org/standards/history/performance-timeline +
      + +Commit +history + +
      +
      +Test +suite: +
      + +https://github.com/web-platform-tests/wpt/tree/master/performance-timeline + +
      +
      +Editor: +
      + +Nicolás +Peña +Moreno + +( + +Google + +) +
      +
      +Former +editors: +
      + +Ilya +Grigorik + +( + +Google + +) +
      + +( + +Microsoft +Corp. + +) +(Until +November +2014) +
      + +Zhiheng +Wang + +( + +Google + +) +(Until +July +2013) +
      +
      +Feedback: +
      + +GitHub +w3c/performance-timeline + +( + +pull +requests +, + +new +issue +, + +open +issues + +) +
      +
      +
      + +
      +
      +
      +

      +Abstract +

      +

      +This +specification +extends +the +High +Resolution +Time +specification +[ + + +HR-TIME-3 + + +] +by +providing +methods +to +store +and +retrieve +high +resolution +performance +metric +data. +

      +
      +
      +

      +Status +of +This +Document +

      +
      + +This +is +a +preview + +

      +Do +not +attempt +to +implement +this +version +of +the +specification. +Do +not +reference +this +version +as +authoritative +in +any +way. +Instead, +see + +https://w3c.github.io/performance-timeline/ + +for +the +Editor's +draft. +

      +
      +

      + +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +index + +at +https://www.w3.org/TR/. + +

      +

      +This + +Performance +Timeline +Level +2 + +specification + +replaces +the +first +version +of +[ + + +PERFORMANCE-TIMELINE + + +] +and +includes: +

      + +

      +This +document +was +published +by +the + +Web +Performance +Working +Group + +as +an +Editor's +Draft. +

      +Publication +as +an +Editor's +Draft +does +not +imply +endorsement +by + +W3C + +and +its +Members. +

      +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

      +This +document +was +produced +by +a +group +operating +under +the + + +W3C + +Patent +Policy +. + +W3C + +maintains +a + +public +list +of +any +patent +disclosures + +made +in +connection +with +the +deliverables +of +the +group; +that +page +also +includes +instructions +for +disclosing +a +patent. +An +individual +who +has +actual +knowledge +of +a +patent +which +the +individual +believes +contains + +Essential +Claim(s) + +must +disclose +the +information +in +accordance +with + +section +6 +of +the + +W3C + +Patent +Policy +. +

      +This +document +is +governed +by +the + +2 +November +2021 + +W3C + +Process +Document +. +

      + +
      +
      +

      + +1. + +Introduction +

      + + +
      +

      + +This +section +is +non-normative. + +

      +

      +Accurately +measuring +performance +characteristics +of +web +applications +is +an +important +aspect +of +making +web +applications +faster. +This +specification +defines +the +necessary + +Performance +Timeline + +primitives +that +enable +web +developers +to +access, +instrument, +and +retrieve +various +performance +metrics +from +the +full +lifecycle +of +a +web +application. +

      +

      +[ + + +NAVIGATION-TIMING-2 + + +], +[ + + +RESOURCE-TIMING-2 + + +], +and +[ + + +USER-TIMING-2 + + +] +are +examples +of +specifications +that +define +timing +information +related +to +the +navigation +of +the +document, +resources +on +the +page, +and +developer +scripts, +respectively. +Together +these +and +other +performance +interfaces +define +performance +metrics +that +describe +the + +Performance +Timeline + +of +a +web +application. +For +example, +the +following +script +shows +how +a +developer +can +access +the + +Performance +Timeline + +to +obtain +performance +metrics +related +to +the +navigation +of +the +document, +resources +on +the +page, +and +developer +scripts: +

      +
      +
      <!doctype html>
      +<html>
      +<head></head>
      +<body onload="init()">
      +  <img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
      +  <script>
      +    function init() {
      +      // see [[USER-TIMING-2]]
      +      performance.mark("startWork");
      +      doWork(); // Some developer code
      +      performance.mark("endWork");
      +      measurePerf();
      +    }
      +    function measurePerf() {
      +      performance
      +        .getEntries()
      +        .map(entry => JSON.stringify(entry, null, 2))
      +        .forEach(json => console.log(json));
      +    }
      +  </script>
      +  </body>
      +
      +</
      +
      +html
      +
      +>
      +
      +
      +
      +
      +

      +Alternatively, +the +developer +can +observe +the + +Performance +Timeline + +and +be +notified +of +new +performance +metrics +and, +optionally, +previously +buffered +performance +metrics +of +specified +type, +via +the + + +PerformanceObserver + + +interface. +

      +

      +The + + +PerformanceObserver + + +interface +was +added +in +Performance +Timeline +Level +2 + +and +is +designed +to +address +limitations +of +the +buffer-based +approach +shown +in +the +first +example. +By +using +the +PerformanceObserver +interface, +the +application +can: +

      +
        +
      • +Avoid +polling +the +timeline +to +detect +new +metrics +
      • +
      • +Eliminate +costly +deduplication +logic +to +identify +new +metrics +
      • +
      • +Eliminate +race +conditions +with +other +consumers +that +may +want +to +manipulate +the +buffer +
      • +
      +

      +The +developer +is +encouraged +to +use + + +PerformanceObserver + + +where +possible. +Further, +new +performance +API's +and +metrics +may +only +be +available +through +the + + +PerformanceObserver + + +interface. +The +observer +works +by +specifying +a +callback +in +the +constructor +and +specifying +the +performance +entries +it's +interested +in +via +the + + +observe() + + +method. +The +user +agent +chooses +when +to +execute +the +callback, +which +receives +performance +entries +that +have +been +queued. +

      +

      +There +are +special +considerations +regarding +initial +page +load +when +using +the + + +PerformanceObserver + + +interface: +a +registration +must +be +active +to +receive +events +but +the +registration +script +may +not +be +available +or +may +not +be +desired +in +the +critical +path. +To +address +this, +user +agents +buffer +some +number +of +events +while +the +page +is +being +constructed, +and +these +buffered +events +can +be +accessed +via +the + + +buffered + + +flag +when +registering +the +observer. +When +this +flag +is +set, +the +user +agent +retrieves +and +dispatches +events +that +it +has +buffered, +for +the +specified +entry +type, +and +delivers +them +in +the +first +callback +after +the + + +observe() + + +call +occurs. +

      +
      +
      + +Note + +
      +

      +The +number +of +buffered +events +is +determined +by +the +specification +that +defines +the +metric +and +buffering +is +intended +to +used +for +first-N +events +only; +buffering +is +not +unbounded +or +continuous. +

      +
      +
      <!doctype html>
      +<html>
      +<head></head>
      +<body>
      +<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
      +<script>
      +// Know when the entry types we would like to use are not supported.
      +function detectSupport(entryTypes) {
      +  for (const entryType of entryTypes) {
      +    if (!PerformanceObserver.supportedEntryTypes.includes(entryType)) {
      +      // Indicate to client-side analytics that |entryType| is not supported.
      +    }
      +  }
      +}
      +detectSupport(["resource", "mark", "measure"]);
      +const userTimingObserver = new PerformanceObserver(list => {
      +  list
      +    .getEntries()
      +    // Get the values we are interested in
      +    .map(({ name, entryType, startTime, duration }) => {
      +      const obj = {
      +        "Duration": duration,
      +        "Entry Type": entryType,
      +        "Name": name,
      +        "Start Time": startTime,
      +      };
      +      return JSON.stringify(obj, null, 2);
      +    })
      +    // Display them to the console.
      +    .forEach(console.log);
      +  // Disconnect after processing the events.
      +  userTimingObserver.disconnect();
      +});
      +// Subscribe to new events for User-Timing.
      +userTimingObserver.observe({entryTypes: ["mark", "measure"]});
      +const resourceObserver = new PerformanceObserver(list => {
      +  list
      +    .getEntries()
      +    // Get the values we are interested in
      +    .map(({ name, startTime, fetchStart, responseStart, responseEnd }) => {
      +      const obj = {
      +        "Name": name,
      +        "Start Time": startTime,
      +        "Fetch Start": fetchStart,
      +        "Response Start": responseStart,
      +        "Response End": responseEnd,
      +      };
      +      return JSON.stringify(obj, null, 2);
      +    })
      +    // Display them to the console.
      +    .forEach(console.log);
      +  // Disconnect after processing the events.
      +  resourceObserver.disconnect();
      +});
      +// Retrieve buffered events and subscribe to newer events for Resource Timing.
      +resourceObserver.observe({type: "resource", buffered: true});
      +</script>
      +</body>
      +
      +</
      +
      +html
      +
      +>
      +
      +
      +
      +
      +
      +
      +
      +

      + +2. + +Conformance +

      + + +
      +

      +As +well +as +sections +marked +as +non-normative, +all +authoring +guidelines, +diagrams, +examples, +and +notes +in +this +specification +are +non-normative. +Everything +else +in +this +specification +is +normative. +

      +The +key +words + +MUST +, + +MUST +NOT +, +and + +SHOULD + +in +this +document +are +to +be +interpreted +as +described +in + +BCP +14 + +[ + + +RFC2119 + + +] +[ + + +RFC8174 + + +] +when, +and +only +when, +they +appear +in +all +capitals, +as +shown +here. +

      +

      +Conformance +requirements +phrased +as +algorithms +or +specific +steps +may +be +implemented +in +any +manner, +so +long +as +the +end +result +is +equivalent. +(In +particular, +the +algorithms +defined +in +this +specification +are +intended +to +be +easy +to +follow, +and +not +intended +to +be +performant). +

      +
      +
      +
      +

      + +3. + + +Performance +Timeline + +

      + + +
      +

      +Each + +global +object + +has: +

      +
        +
      • +a + +performance +observer +task +queued +flag + +
      • +
      • +a + +list +of + +registered +performance +observer + +objects + +that +is +initially +empty +
      • +
      • +a + +performance +entry +buffer +map + + +map +, + +keyed + +on +a + +DOMString +, +representing +the +entry +type +to +which +the +buffer +belongs. +The + +map + +'s + +value + +is +the +following +tuple: +
          +
        • +A + +performance +entry +buffer + +to +store + + +PerformanceEntry + + +objects, +that +is +initially +empty. +
        • +
        • +An +integer + +maxBufferSize +, +initialized +to +the + +registry + +value +for +this +entry +type. +
        • +
        • +A + +boolean + + +availableFromTimeline +, +initialized +to +the + +registry + +value +for +this +entry +type. +
        • +
        • +An +integer + +dropped +entries +count + +that +is +initially +0. +
        • +
        +
      • +
      +

      +In +order +to +get +the + +relevant +performance +entry +tuple +, +given + +entryType + +and + +globalObject + +as +input, +run +the +following +steps: +

      +
        +
      1. +Let + +map + +be +the + +performance +entry +buffer +map + +associated +with + +globalObject +. +
      2. +
      3. +Return +the +result +of + +getting +the +value +of +an +entry + +from + +map +, +given + +entryType + +as +the + +key +. +
      4. +
      + +
      +
      +

      + +3.1 + +Extensions +to +the + + +Performance + + +interface +

      + + +
      +

      +This +extends +the + + +Performance + + +interface +from +[ + + +HR-TIME-3 + + +] +and +hosts +performance +related +attributes +and +methods +used +to +retrieve +the +performance +metric +data +from +the + +Performance +Timeline +. +

      +
      WebIDLpartial interface Performance {
      +  PerformanceEntryList getEntries ();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +typedef
      +
      +
      +sequence
      +
      +<
      +
      +
      +PerformanceEntry
      +
      +
      +>
      +
      +
      +
      +PerformanceEntryList
      +
      +
      +;
      +
      +
      +
      +

      +The + + +PerformanceEntryList + + +represents +a +sequence +of + + +PerformanceEntry + +, +providing +developers +with +all +the +convenience +methods +found +on +JavaScript +arrays. +

      + +
      +
      +

      + +3.1.1 + + + +getEntries() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by +the + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +and + +type + +set +to + +null +. +

      +
      + +
      +
      +

      + +3.1.2 + + + +getEntriesByType() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +set +to + +null +, +and + +type + +set +to +the +method's +input + +type + +parameter. +

      +
      + +
      +
      +

      + +3.1.3 + + + +getEntriesByName() + + +method +

      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +map +by +name +and +type + +algorithm +with + +name + +set +to +the +method +input + +name + +parameter, +and + +type + +set +to + +null + +if +optional + +entryType + +is +omitted, +or +set +to +the +method's +input + +type + +parameter +otherwise. +

      +
      +
      +
      + +
      +
      +

      + +4. + +The + + +PerformanceEntry + + +interface +

      + + +
      +

      +The + + +PerformanceEntry + + +interface +hosts +the +performance +data +of +various +metrics. +

      +
      WebIDL[Exposed=(Window,Worker)]
      +interface PerformanceEntry {
      +  readonly    attribute DOMString           name;
      +  readonly    attribute DOMString           entryType;
      +  readonly    attribute DOMHighResTimeStamp startTime;
      +  readonly    attribute DOMHighResTimeStamp duration;
      +  [Default] object toJSON();
      +};
      +
      +
      +
      +
      +
      + + +name + + +
      +
      +This +attribute + +MUST + +return +an +identifier +for +this + + +PerformanceEntry + + +object. +This +identifier +does +not +have +to +be +unique. +
      +
      + + +entryType + + +
      +
      +This +attribute + +MUST + +return +the +type +of +the +interface +represented +by +this + + +PerformanceEntry + + +object. +
      +
      + +Note + +
      +

      +All + +entryType + +values +are +defined +in +the +relevant + +registry +. +Examples +include: + +"mark" + +and + +"measure" + +[ + + +USER-TIMING-2 + + +], + +"navigation" + +[ + + +NAVIGATION-TIMING-2 + + +], + +"resource" + +[ + + +RESOURCE-TIMING-2 + + +], +and + +"longtask" +. +

      +
      +
      + + +startTime + + +
      +
      +This +attribute + +MUST + +return +the +time +value +of +the +first +recorded +timestamp +of +this +performance +metric. +If +the +startTime +concept +doesn't +apply, +a +performance +metric +may +choose +to +return +a + +startTime + +of + +0 +. +
      +
      + + +duration + + +
      +
      +This +attribute + +MUST + +return +the +time +value +of +the +duration +of +the +entire +event +being +recorded +by +this + + +PerformanceEntry + +. +Typically, +this +would +be +the +time +difference +between +the +last +recorded +timestamp +and +the +first +recorded +timestamp +of +this + + +PerformanceEntry + +. +If +the +duration +concept +doesn't +apply, +a +performance +metric +may +choose +to +return +a + +duration + +of + +0 +. +
      +
      +

      +When + + +toJSON + + +is +called, +run +[ + + +WebIDL + + +]'s + +default +toJSON +steps +. +

      +
      + +
      +
      +

      + +5. + +The + + +PerformanceObserver + + +interface +

      + + +
      +

      +The + + +PerformanceObserver + + +interface +can +be +used +to +observe +the + +Performance +Timeline + +to +be +notified +of +new +performance +metrics +as +they +are +recorded, +and +optionally +buffered +performance +metrics. +

      +

      +Each + + +PerformanceObserver + + +has +these +associated +concepts: +

      +
        +
      • +A + + +PerformanceObserverCallback + + + +observer +callback + +set +on +creation. +
      • +
      • +A + + +PerformanceEntryList + + +object +called +the + +observer +buffer + +that +is +initially +empty. +
      • +
      • +A + +DOMString + + +observer +type + +which +is +initially + +"undefined" +. +
      • +
      • +A +boolean + +requires +dropped +entries + +which +is +initially +set +to +false. +
      • +
      +

      +The + +PerformanceObserver(callback) + +constructor +must +create +a +new + + +PerformanceObserver + + +object +with +its + +observer +callback + +set +to + +callback + +and +then +return +it. +

      +

      +A + +registered +performance +observer + +is +a + +struct + +consisting +of +an + +observer + +member +(a + + +PerformanceObserver + + +object) +and +an + +options +list + +member +(a +list +of + + +PerformanceObserverInit + + +dictionaries). +

      +
      WebIDLcallback PerformanceObserverCallback = undefined (PerformanceObserverEntryList entries,
      +                                             PerformanceObserver observer,
      +                                             optional PerformanceObserverCallbackOptions options = {});
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserver {
      +  constructor(PerformanceObserverCallback callback);
      +  undefined observe (optional PerformanceObserverInit options = {});
      +  undefined disconnect ();
      +  PerformanceEntryList takeRecords();
      +  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
      +};
      +
      +
      +
      +
      +
      + +Note + +
      +

      +To +keep +the +performance +overhead +to +minimum +the +application +ought +to +only +subscribe +to +event +types +that +it +is +interested +in, +and +disconnect +the +observer +once +it +no +longer +needs +to +observe +the +performance +data. +Filtering +by +name +is +not +supported, +as +it +would +implicitly +require +a +subscription +for +all +event +types +— +this +is +possible, +but +discouraged, +as +it +will +generate +a +significant +volume +of +events. +

      +
      +
      +

      + +5.1 + + + +PerformanceObserverCallbackOptions + + +dictionary +

      + + +
      +> +
      WebIDLdictionary PerformanceObserverCallbackOptions {
      +  unsigned long long droppedEntriesCount;
      +};
      +
      +
      +
      +
      +
      + + +droppedEntriesCount + + +
      +
      +An +integer +representing +the +dropped +entries +count +for +the +entry +types +that +the +observer +is +observing +when +the + + +PerformanceObserver + + +'s + +requires +dropped +entries + +is +set. +
      +
      +
      + +
      +
      +

      + +5.2 + + + +observe() + + +method +

      + + +
      +

      +The + + +observe() + + +method +instructs +the +user +agent +to +register +the +observer +and +must +run +these +steps: +

      +
        +
      1. +Let + +relevantGlobal + +be + +this + +'s + +relevant +global +object +. +
      2. +
      3. +If + +options + +'s + + +entryTypes + + +and + + +type + + +members +are +both +omitted, +then + +throw + +a +" + + +TypeError + + +". +
      4. +
      5. +If + +options + +'s + + +entryTypes + + +is +present +and +any +other +member +is +also +present, +then + +throw + +a +" + + +TypeError + + +". +
      6. +
      7. +Update +or +check + +this + +'s + +observer +type + +by +running +these +steps: +
          +
        1. +If + +this + +'s + +observer +type + +is + +"undefined" +: +
            +
          1. +If + +options + +'s + + +entryTypes + + +member +is +present, +then +set + +this + +'s + +observer +type + +to + +"multiple" +. +
          2. +
          3. +If + +options + +'s + + +type + + +member +is +present, +then +set + +this + +'s + +observer +type + +to + +"single" +. +
          4. +
          +
        2. +
        3. +If + +this + +'s + +observer +type + +is + +"single" + +and + +options + +'s + + +entryTypes + + +member +is +present, +then + +throw + +an +" + + +InvalidModificationError + + +". +
        4. +
        5. +If + +this + +'s + +observer +type + +is + +"multiple" + +and + +options + +'s + + +type + + +member +is +present, +then + +throw + +an +" + + +InvalidModificationError + + +". +
        6. +
        +
      8. +
      9. +Set + +this + +'s + +requires +dropped +entries + +to +true. +
      10. +
      11. +If + +this + +'s + +observer +type + +is + +"multiple" +, +run +the +following +steps: +
          +
        1. +Let + +entry +types + +be + +options + +'s + + +entryTypes + + +sequence. +
        2. +
        3. +Remove +all +types +from + +entry +types + +that +are +not +contained +in + +relevantGlobal + +'s + +frozen +array +of +supported +entry +types +. +The +user +agent + +SHOULD + +notify +developers +if + +entry +types + +is +modified. +For +example, +a +console +warning +listing +removed +types +might +be +appropriate. +
        4. +
        5. +If +the +resulting + +entry +types + +sequence +is +an +empty +sequence, +abort +these +steps. +The +user +agent + +SHOULD + +notify +developers +when +the +steps +are +aborted +to +notify +that +registration +has +been +aborted. +For +example, +a +console +warning +might +be +appropriate. +
        6. +
        7. +If +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal + +contains +a + +registered +performance +observer + +whose + +observer + +is + +this +, +replace +its + +options +list + +with +a +list +containing + +options + +as +its +only +item. +
        8. +
        9. +Otherwise, +create +and +append +a + +registered +performance +observer + +object +to +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal +, +with + +observer + +set +to + +this + +and + +options +list + +set +to +a +list +containing + +options + +as +its +only +item. +
        10. +
        +
      12. +
      13. +Otherwise, +run +the +following +steps: +
          +
        1. +Assert +that + +this + +'s + +observer +type + +is + +"single" +. +
        2. +
        3. +If + +options + +'s + + +type + + +is +not +contained +in +the + +relevantGlobal + +'s + +frozen +array +of +supported +entry +types +, +abort +these +steps. +The +user +agent + +SHOULD + +notify +developers +when +this +happens, +for +instance +via +a +console +warning. +
        4. +
        5. +If +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal + +contains +a + +registered +performance +observer + + +obs + +whose + +observer + +is + +this +: +
            +
          1. +If + +obs + +'s + +options +list + +contains +a + + +PerformanceObserverInit + + +item + +currentOptions + +whose + + +type + + +is +equal +to + +options + +'s + + +type + +, +replace + +currentOptions + +with + +options + +in + +obs + +'s + +options +list +. +
          2. +
          3. +Otherwise, +append + +options + +to + +obs + +'s + +options +list +. +
          4. +
          +
        6. +
        7. +Otherwise, +create +and +append +a + +registered +performance +observer + +object +to +the + +list +of +registered +performance +observer +objects + +of + +relevantGlobal +, +with + +observer + +set +to +the + +this + +and + +options +list + +set +to +a +list +containing + +options + +as +its +only +item. +
        8. +
        9. +If + +options + +'s + + +buffered + + +flag +is +set: +
            +
          1. +Let + +tuple + +be +the + +relevant +performance +entry +tuple + +of + +options + +'s + + +type + + +and + +relevantGlobal +. +
          2. +
          3. +

            +For +each + +entry + +in + +tuple + +'s + +performance +entry +buffer +: +

            +
              +
            1. +If + +should +add +entry + +with + +entry + +and + +options + +as +parameters +returns +true, + +append + + +entry + +to +the + +observer +buffer +. +
            2. +
            +
          4. +
          5. + +Queue +the +PerformanceObserver +task + +with + +relevantGlobal + +as +input. +
          6. +
          +
        10. +
        +
      14. +
      +
      +
      + +Note + +
      +

      +A + + +PerformanceObserver + + +object +needs +to +always +call + + +observe() + + +with + +options + +'s + + +entryTypes + + +set +OR +always +call + + +observe() + + +with + +options + +'s + + +type + + +set. +If +one + + +PerformanceObserver + + +calls + + +observe() + + +with + + +entryTypes + + +and +also +calls +observe +with + + +type + +, +then +an +exception +is +thrown. +This +is +meant +to +avoid +confusion +with +how +calls +would +stack. +When +using + + +entryTypes + +, +no +other +parameters +in + + +PerformanceObserverInit + + +can +be +used. +In +addition, +multiple + + +observe() + + +calls +will +override +for +backwards +compatibility +and +because +a +single +call +should +suffice +in +this +case. +On +the +other +hand, +when +using + + +type + +, +calls +will +stack +because +a +single +call +can +only +specify +one +type. +Calling + + +observe() + + +with +a +repeated + + +type + + +will +also +override. +

      +
      +
      +

      + +5.2.1 + + + +PerformanceObserverInit + + +dictionary +

      + + +
      +
      WebIDLdictionary PerformanceObserverInit {
      +  sequence<DOMString> entryTypes;
      +  DOMString type;
      +  boolean buffered;
      +};
      +
      +
      +
      +
      +
      + + +entryTypes + + +
      +
      +A +list +of +entry +types +to +be +observed. +If +present, +the +list + +MUST +NOT + +be +empty +and +all +other +members + +MUST +NOT + +be +present. +Types +not +recognized +by +the +user +agent + +MUST + +be +ignored. +
      +
      +
      +
      + + +type + + +
      +
      +A +single +entry +type +to +be +observed. +A +type +that +is +not +recognized +by +the +user +agent + +MUST + +be +ignored. +Other +members +may +be +present. +
      +
      +
      +
      + + +buffered + + +
      +
      +A +flag +to +indicate +whether +buffered +entries +should +be +queued +into +observer's +buffer. +
      +
      +
      + +
      +
      +

      + +5.2.2 + + + +PerformanceObserverEntryList + + +interface +

      + + +
      +
      WebIDL[Exposed=(Window,Worker)]
      +interface PerformanceObserverEntryList {
      +  PerformanceEntryList getEntries();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +
      +
      +
      +

      +Each + + +PerformanceObserverEntryList + + +object +has +an +associated + +entry +list +, +which +consists +of +a + + +PerformanceEntryList + + +and +is +initialized +upon +construction. +

      + +
      +
      +
      + +5.2.2.1 + + + +getEntries() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +and + +type + +set +to + +null +. +

      +
      + +
      +
      +
      + +5.2.2.2 + + + +getEntriesByType() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +set +to + +null +, +and + +type + +set +to +the +method's +input + +type + +parameter. +

      +
      + +
      +
      +
      + +5.2.2.3 + + + +getEntriesByName() + + +method +
      + + +
      +

      +Returns +a + + +PerformanceEntryList + + +object +returned +by + +filter +buffer +by +name +and +type + +algorithm +with + +this + +'s + +entry +list +, + +name + +set +to +the +method +input + +name + +parameter, +and + +type + +set +to + +null + +if +optional + +entryType + +is +omitted, +or +set +to +the +method's +input + +type + +parameter +otherwise. +

      +
      +
      +
      + +
      +
      +

      + +5.3 + + + +takeRecords() + + +method +

      + + +
      +

      +The + + +takeRecords() + + +method +must +return +a +copy +of + +this + +'s + +observer +buffer +, +and +also +empty + +this + +'s + +observer +buffer +. +

      +
      + +
      +
      +

      + +5.4 + + + +disconnect() + + +method +

      + + +
      +

      +The + + +disconnect() + + +method +must +do +the +following: +

      +
        +
      1. +Remove + +this + +from +the + +list +of +registered +performance +observer +objects + +of + +relevant +global +object +. +
      2. +
      3. +Empty + +this + +'s + +observer +buffer +. +
      4. +
      5. +Empty + +this + +'s + +options +list +. +
      6. +
      +
      + +
      +
      +

      + +5.5 + + + +supportedEntryTypes + + +attribute +

      + + +
      +

      +Each + +global +object + +has +an +associated + +frozen +array +of +supported +entry +types +, +which +is +initialized +to +the + +FrozenArray + + +created + +from +the +sequence +of +strings +among +the + +registry + +that +are +supported +for +the +global +object, +in +alphabetical +order. +

      +

      +When + + +supportedEntryTypes + + +'s +attribute +getter +is +called, +run +the +following +steps: +

      +
        +
      1. +Let + +globalObject + +be +the + +environment +settings +object's +global +object +. +
      2. +
      3. +Return + +globalObject + +'s + +frozen +array +of +supported +entry +types +. +
      4. +
      +
      +
      + +Note + +
      +

      +This +attribute +allows +web +developers +to +easily +know +which +entry +types +are +supported +by +the +user +agent. +

      +
      +
      +
      +
      +

      + +6. + +Processing +

      + + +
      +
      +
      +

      + +6.1 + +Queue +a + +PerformanceEntry + +

      + + +
      +

      +To + +queue +a +PerformanceEntry + +( + +newEntry + +), +run +these +steps: +

      +
        +
      1. +Let + +interested +observers + +be +an +initially +empty +set +of + + +PerformanceObserver + + +objects. +
      2. +
      3. +Let + +entryType + +be + +newEntry + +’s + + +entryType + + +value. +
      4. +
      5. +Let + +relevantGlobal + +be + +newEntry + +'s + +relevant +global +object +. +
      6. +
      7. +For +each + +registered +performance +observer + + +regObs + +in + +relevantGlobal + +'s + +list +of +registered +performance +observer +objects +: +
          +
        1. +

          +If + +regObs + +'s + +options +list + +contains +a + + +PerformanceObserverInit + + + +options + +whose + + +entryTypes + + +member +includes + +entryType + +or +whose + + +type + + +member +equals +to + +entryType +: +

          +
            +
          1. +If + +should +add +entry + +with + +newEntry + +and + +options + +returns +true, +append + +regObs + +'s + +observer + +to + +interested +observers +. +
          2. +
          +
        2. +
        +
      8. +
      9. +For +each + +observer + +in + +interested +observers +: +
          +
        1. +Append + +newEntry + +to + +observer + +'s + +observer +buffer +. +
        2. +
        +
      10. +
      11. +Let + +tuple + +be +the + +relevant +performance +entry +tuple + +of + +entryType + +and + +relevantGlobal +. +
      12. +
      13. +Let + +isBufferFull + +be +the +return +value +of +the + +determine +if +a +performance +entry +buffer +is +full + +algorithm +with + +tuple + +as +input. +
      14. +
      15. +Let + +shouldAdd + +be +the +result +of + +should +add +entry + +with + +newEntry + +as +input. +
      16. +
      17. +If + +isBufferFull + +is +false +and + +shouldAdd + +is +true, + +append + + +newEntry + +to + +tuple + +'s + +performance +entry +buffer +. +
      18. +
      19. + +Queue +the +PerformanceObserver +task + +with + +relevantGlobal + +as +input. +
      20. +
      +
      +
      +
      +

      + +6.2 + +Queue +the +PerformanceObserver +task +

      + + +
      +

      +When +asked +to + +queue +the +PerformanceObserver +task +, +given + +relevantGlobal + +as +input, +run +the +following +steps: +

      +
        +
      1. +If + +relevantGlobal + +'s + +performance +observer +task +queued +flag + +is +set, +terminate +these +steps. +
      2. +
      3. +Set + +relevantGlobal + +'s + +performance +observer +task +queued +flag +. +
      4. +
      5. + +Queue +a +task + +that +consists +of +running +the +following +substeps. +The + +task +source + +for +the +queued +task +is +the + +performance +timeline +task +source +. +
          +
        1. +Unset + +performance +observer +task +queued +flag + +of + +relevantGlobal +. +
        2. +
        3. +Let + +notifyList + +be +a +copy +of + +relevantGlobal + +'s + +list +of +registered +performance +observer +objects +. +
        4. +
        5. +For +each + +registered +performance +observer + +object + +registeredObserver + +in + +notifyList +, +run +these +steps: +
            +
          1. +Let + +po + +be + +registeredObserver + +'s + +observer +. +
          2. +
          3. +Let + +entries + +be +a +copy +of + +po + +’s + +observer +buffer +. +
          4. +
          5. +If + +entries + +is +empty, +return. +
          6. +
          7. +Empty + +po + +’s + +observer +buffer +. +
          8. +
          9. +Let + +observerEntryList + +be +a +new + + +PerformanceObserverEntryList + +, +with +its + +entry +list + +set +to + +entries +. +
          10. +
          11. +Let + +droppedEntriesCount + +be +null. +
          12. +
          13. +If + +po + +'s + +requires +dropped +entries + +is +set, +perform +the +following +steps: +
              +
            1. +Set + +droppedEntriesCount + +to +0. +
            2. +
            3. +For +each + + +PerformanceObserverInit + + + +item + +in + +registeredObserver + +'s + +options +list +: +
                +
              1. +For +each + +DOMString + + +entryType + +that +appears +either +as + +item + +'s + + +type + + +or +in + +item + +'s + + +entryTypes + +: +
                  +
                1. +Let + +map + +be + +relevantGlobal + +'s + +performance +entry +buffer +map +. +
                2. +
                3. +Let + +tuple + +be +the +result +of + +getting +the +value +of +entry + +on + +map + +given + +entryType + +as + +key +. +
                4. +
                5. +Increase + +droppedEntriesCount + +by + +tuple + +'s + +dropped +entries +count +. +
                6. +
                +
              2. +
              +
            4. +
            5. +Set + +po + +'s + +requires +dropped +entries + +to +false. +
            6. +
            +
          14. +
          15. +Let + +callbackOptions + +be +a + + +PerformanceObserverCallbackOptions + + +with +its + + +droppedEntriesCount + + +set +to + +droppedEntriesCount + +if + +droppedEntriesCount + +is +not +null, +otherwise +unset. +
          16. +
          17. +Call + +po + +’s + +observer +callback + +with + +observerEntryList + +as +the +first +argument, +with + +po + +as +the +second +argument +and +as + +callback +this +value +, +and +with + +callbackOptions + +as +the +third +argument. +If +this + +throws + +an +exception, + +report +the +exception +. +
          18. +
          +
        6. +
        +
      6. +
      +

      +The + +performance +timeline + + +task +queue + +is +a +low +priority +queue +that, +if +possible, +should +be +processed +by +the +user +agent +during +idle +periods +to +minimize +impact +of +performance +monitoring +code. +

      +
      +
      +
      +

      + +6.3 + +Filter +buffer +map +by +name +and +type +

      + + +
      +

      +When +asked +to +run +the + +filter +buffer +map +by +name +and +type + +algorithm +with +optional + +name + +and + +type +, +run +the +following +steps: +

      +
        +
      1. +Let + +result + +be +an +initially +empty + +list +. +
      2. +
      3. +Let + +map + +be +the + +performance +entry +buffer +map + +associated +with +the + +relevant +global +object + +of + +this +. +
      4. +
      5. +Let + +tuple +list + +be +an +empty + +list +. +
      6. +
      7. +If + +type + +is +not +null, +append +the +result +of + +getting +the +value +of +entry + +on + +map + +given + +type + +as + +key + +to + +tuple +list +. +Otherwise, +assign +the +result +of + +get +the +values + +on + +map + +to + +tuple +list +. +
      8. +
      9. +For +each + +tuple + +in + +tuple +list +, +run +the +following +steps: +
          +
        1. +Let + +buffer + +be + +tuple + +'s + +performance +entry +buffer +. +
        2. +
        3. +If + +tuple + +'s + +availableFromTimeline + +is +false, +continue +to +the +next + +tuple +. +
        4. +
        5. +Let + +entries + +be +the +result +of +running + +filter +buffer +by +name +and +type + +with + +buffer +, + +name + +and + +type + +as +inputs. +
        6. +
        7. +For +each + +entry + +in + +entries +, + +append + + +entry + +to + +result +. +
        8. +
        +
      10. +
      11. +Sort + +results + +'s +entries +in +chronological +order +with +respect +to + + +startTime + + +
      12. +
      13. +Return + +result +. +
      14. +
      +
      +
      +
      +

      + +6.4 + +Filter +buffer +by +name +and +type +

      + + +
      +

      +When +asked +to +run +the + +filter +buffer +by +name +and +type + +algorithm, +with + +buffer +, + +name +, +and + +type + +as +inputs, +run +the +following +steps: +

      +
        +
      1. +Let + +result + +be +an +initially +empty + +list +. +
      2. +
      3. +For +each + + +PerformanceEntry + + + +entry + +in + +buffer +, +run +the +following +steps: +
          +
        1. +If + +type + +is +not +null +and +if + +type + +is +not + +identical +to + + +entry + +'s + +entryType + +attribute, +continue +to +next + +entry +. +
        2. +
        3. +If + +name + +is +not +null +and +if + +name + +is +not + +identical +to + + +entry + +'s + +name + +attribute, +continue +to +next + +entry +. +
        4. +
        5. + +append + + +entry + +to + +result +. +
        6. +
        +
      4. +
      5. +Sort + +results + +'s +entries +in +chronological +order +with +respect +to + + +startTime + + +
      6. +
      7. +Return + +result +. +
      8. +
      +
      +
      +
      +

      + +6.5 + +Determine +if +a +performance +entry +buffer +is +full +

      + + +
      +

      +To + +determine +if +a +performance +entry +buffer +is +full +, +with + +tuple + +as +input, +run +the +following +steps: +

      +
        +
      1. +Let + +num +current +entries + +be +the +size +of + +tuple + +'s + +performance +entry +buffer +. +
      2. +
      3. +If + +num +current +entries + +is +less +than + +tuples + +'s + +maxBufferSize +, +return +false. +
      4. +
      5. +Increase + +tuple + +'s + +dropped +entries +count + +by +1. +
      6. +
      7. +Return +true. +
      8. +
      +
      +
      +
      +
      +

      + +7. + +Privacy +Considerations +

      + + +
      +

      +This +specification +extends +the + + +Performance + + +interface +defined +by +[ + + +HR-TIME-3 + + +] +and +provides +methods +to +queue +and +retrieve +entries +from +the + +performance +timeline +. +Please +refer +to +[ + + +HR-TIME-3 + + +] +for +privacy +considerations +of +exposing +high-resoluting +timing +information. +Each +new +specification +introducing +new +performance +entries +should +have +its +own +privacy +considerations +as +well. +

      +
      +
      +
      +

      + +8. + +Security +Considerations +

      + + +
      +

      +This +specification +extends +the + + +Performance + + +interface +defined +by +[ + + +HR-TIME-3 + + +] +and +provides +methods +to +queue +and +retrieve +entries +from +the + +performance +timeline +. +Please +refer +to +[ + + +HR-TIME-3 + + +] +for +security +considerations +of +exposing +high-resoluting +timing +information. +Each +new +specification +introducing +new +performance +entries +should +have +its +own +security +considerations +as +well. +

      +
      +
      +
      +

      + +9. + +Dependencies +

      + + +
      +

      +The +[ + + +INFRA + + +] +specification +defines +the +following: + + +key + +, + + +getting +the +value +of +an +entry + +. +

      +
      +

      A. IDL Index

      WebIDLpartial interface Performance {
      +  PerformanceEntryList getEntries ();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +typedef sequence<PerformanceEntry> PerformanceEntryList;
      +[Exposed=(Window,Worker)]
      +interface PerformanceEntry {
      +  readonly    attribute DOMString           name;
      +  readonly    attribute DOMString           entryType;
      +  readonly    attribute DOMHighResTimeStamp startTime;
      +  readonly    attribute DOMHighResTimeStamp duration;
      +  [Default] object toJSON();
      +};
      +callback PerformanceObserverCallback = undefined (PerformanceObserverEntryList entries,
      +                                             PerformanceObserver observer,
      +                                             optional PerformanceObserverCallbackOptions options = {});
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserver {
      +  constructor(PerformanceObserverCallback callback);
      +  undefined observe (optional PerformanceObserverInit options = {});
      +  undefined disconnect ();
      +  PerformanceEntryList takeRecords();
      +  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
      +};
      +dictionary PerformanceObserverCallbackOptions {
      +  unsigned long long droppedEntriesCount;
      +};
      +dictionary PerformanceObserverInit {
      +  sequence<DOMString> entryTypes;
      +  DOMString type;
      +  boolean buffered;
      +};
      +[Exposed=(Window,Worker)]
      +interface PerformanceObserverEntryList {
      +  PerformanceEntryList getEntries();
      +  PerformanceEntryList getEntriesByType (DOMString type);
      +  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
      +};
      +
      +
      +
      +
      +
      +
      +

      + +B. + +Acknowledgments +

      + + +
      +

      +Thanks +to +Arvind +Jain, +Boris +Zbarsky, +Jatinder +Mann, +Nat +Duca, +Philippe +Le +Hegaret, +Ryosuke +Niwa, +Shubhie +Panicker, +Todd +Reifsteck, +Yoav +Weiss, +and +Zhiheng +Wang, +for +their +contributions +to +this +work. +

      +
      +
      +
      +

      + +C. + +References +

      + + +
      +
      +
      +

      + +C.1 + +Normative +references +

      + + +
      +
      +
      +[HR-TIME-3] +
      + + +High +Resolution +Time + +. +Yoav +Weiss. +W3C. +20 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/hr-time-3/ + +
      +[HTML] +
      + + +HTML +Standard + +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. +URL: + +https://html.spec.whatwg.org/multipage/ + +
      +[INFRA] +
      + + +Infra +Standard + +. +Anne +van +Kesteren; +Domenic +Denicola. +WHATWG. +Living +Standard. +URL: + +https://infra.spec.whatwg.org/ + +
      +[RFC2119] +
      + + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://www.rfc-editor.org/rfc/rfc2119 + +
      +[RFC8174] +
      + + +Ambiguity +of +Uppercase +vs +Lowercase +in +RFC +2119 +Key +Words + +. +B. +Leiba. +IETF. +May +2017. +Best +Current +Practice. +URL: + +https://www.rfc-editor.org/rfc/rfc8174 + +
      +[WebIDL] +
      + + +Web +IDL +Standard + +. +Edgar +Chen; +Timothy +Gu. +WHATWG. +Living +Standard. +URL: + +https://webidl.spec.whatwg.org/ + +
      +
      +
      +
      +

      + +C.2 + +Informative +references +

      + + +
      +
      +
      +[NAVIGATION-TIMING-2] +
      + + +Navigation +Timing +Level +2 + +. +Yoav +Weiss; +Noam +Rosenthal. +W3C. +7 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/navigation-timing-2/ + +
      +[PERFORMANCE-TIMELINE] +
      + + +Performance +Timeline + +. +Nicolas +Pena +Moreno. +W3C. +2 +December +2021. +W3C +Candidate +Recommendation. +URL: + +https://www.w3.org/TR/performance-timeline/ + +
      +[RESOURCE-TIMING-2] +
      + + +Resource +Timing +Level +2 + +. +Yoav +Weiss; +Noam +Rosenthal. +W3C. +29 +September +2022. +W3C +Working +Draft. +URL: + +https://www.w3.org/TR/resource-timing-2/ + +
      +[USER-TIMING-2] +
      + + +User +Timing +Level +2 + +. +Ilya +Grigorik. +W3C. +26 +February +2019. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/user-timing-2/ + +
      +[WORKERS] +
      + + +Web +Workers + +. +Ian +Hickson. +W3C. +28 +January +2021. +W3C +Working +Group +Note. +URL: + +https://www.w3.org/TR/workers/ + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +https://pr-preview.s3.amazonaws.com/w3c/performance-timeline/204/925ae5e...e1b67dc.html#dom-performanceobserver-takerecords + +/* +*** IMPORTANT *** +Update main.js and main.js.gz with Makefile when making modifications + */ + +var enquire = { + config : { + imgs : "/2008/site/images/" + }, + + init : function() { + var c = enquire; + appliedMedia = false; + var styleTag = document.getElementsByTagName('style')[0]; + document.addEventListener("DOMContentLoaded", function() { + document.body.classList.add("w3c_javascript"); + + var ua = window.navigator.userAgent; + var msie = ua.indexOf("MSIE "); + if (msie > 0) { + Array.prototype.forEach.call(document.querySelector("style"), function (el) { + el.setAttribute("media", "screen"); + }); + var ieversion = parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))); + if (ieversion <= 6) { + var stylesheet = document.createElement("link"); + stylesheet.setAttribute("rel", "stylesheet"); + stylesheet.setAttribute("href", "/2008/site/css/IE6.css'"); + document.head.appendChild(stylesheet); + } + } + + var header = document.createElement("p"); + header.style.marginLeft = "2.4%"; + header.style.paddingLeft = "10px"; + header.style.color = "#666"; + header.style.backgroundColor = "#eee"; + header.style.fontStyle = "italic"; + header.style.fontSize = "1.2em"; + header.innerText = "Leading the web to its full potential"; + document.querySelector("#w3c_nav div.w3c_sec_nav").appendChild(header); + detectAppliedMedia(); + }); + + // + function switchDisplayMode(media) { + // and disable the selected icon + if (media === 'handheld') { + document.body.classList.add("w3c_handheld"); + document.body.classList.remove("w3c_print"); + document.body.classList.remove("w3c_screen"); + } else if (media === 'print') { + document.body.classList.add("w3c_print"); + document.body.classList.remove("w3c_handheld"); + document.body.classList.remove("w3c_screen"); + } else { + document.body.classList.add("w3c_screen"); + document.body.classList.remove("w3c_handheld"); + document.body.classList.remove("w3c_print"); + } + // Adjusting expand/togglable sections + c.tree.init("expand_section", media); + c.toggableInclude.init(media); + } + + function detectAppliedMedia() { + // Detecting which media is being applied by looking up a specific style + var style = window.getComputedStyle(document.querySelector("#w3c_mast h1 a img")); + if (style.display === 'none') { + if (!appliedMedia || appliedMedia!='screen') { + switchDisplayMode("screen"); + appliedMedia = "screen"; + } + } else { + if (!appliedMedia || appliedMedia!='handheld') { + switchDisplayMode("handheld"); + appliedMedia = "handheld"; + } + } + } + }, + + /* + Expandable/collapsible list + */ + tree : { + init : function(sClass, media) { + /* for dynamic changes, don't change classes use style with class on body*/ + var c = enquire; + var t = c.tree; + Array.prototype.forEach.call(document.querySelectorAll(".hierarchy ." + sClass), function(el) { + var parents = Array.prototype.filter.call(t.parents(el), function (e) { + return (e.tagName === "DIV" || e.tagName === "LI") && e.classList.contains("expand_block"); + }); + /* Attach click handlers to each .expand_section elementexcept when expanded and not in print, mobile mode */ + if ((media!='print') && (media!='handheld')) { + if (el.classList.contains("closed") && parents) { + Array.prototype.forEach.call(parents, function (p) { + p.classList.add("closed"); + }); + } + if (!el.querySelector("img")) { + var isClosed = Array.prototype.some.call(parents, function(p) { + return p.classList.contains("closed"); + }); + var icon = document.createElement("img"); + icon.setAttribute("width", "9"); + icon.setAttribute("height", "9"); + + if (isClosed) { + icon.setAttribute("src", "/2008/site/images/ico-plus"); + icon.setAttribute("alt", "Expand"); + } else { + icon.setAttribute("src", "/2008/site/images/ico-minus"); + icon.setAttribute("alt", "Collapse"); + } + el.insertBefore(icon, el.firstChild); + var wrapper = document.createElement("a"); + wrapper.setAttribute("href", "#"); + el.appendChild(wrapper); + while (el.firstChild !== wrapper) { + wrapper.appendChild(el.firstChild); + } + } + + el.addEventListener("click", function(event) { + var target = el.querySelector("a[href]").getAttribute("href"); + var hash = target.substring(target.indexOf('#')); + if (hash !== "#") { + window.location.hash = hash; + } + event.preventDefault(); + t.toggle(el); + var isClosed = Array.prototype.some.call(parents, function(p) { + return p.classList.contains("closed"); + }); + var icon = el.querySelector("img"); + if (isClosed) { + icon.setAttribute("src", "/2008/site/images/ico-plus"); + icon.setAttribute("alt", "Expand"); + } else { + icon.setAttribute("src", "/2008/site/images/ico-minus"); + icon.setAttribute("alt", "Collapse"); + } + }); + } else { + // removes all the inner markup + el.textContent = el.innerText; + } + }); + }, + + parents: function(e) { + var result = []; + for (var p = e && e.parentElement; p; p = p.parentElement) { + result.push(p); + } + return result; + }, + + toggle : function(el) { + var t = enquire.tree; + var parents = Array.prototype.filter.call(t.parents(el), function (e) { + return (e.tagName === "DIV" || e.tagName === "LI") && e.classList.contains("expand_block"); + }); + Array.prototype.forEach.call(parents, function (p) { + p.classList.toggle("closed"); + }); + } + }, + /* + UI to toggle visibility of content in a page + */ + toggableInclude : { + init: function(media) { + var toggle = document.querySelector("#w3c_toggle_include"); + var c = enquire; + if ((media!='print') && (media!='handheld') && toggle) { + var startopen = toggle.classList.contains('default_open') || window.location.hash == '#w3c_all'; + if (!document.querySelector("#w3c_toggle_include_show")) { + var div = document.createElement('div'); + div.innerHTML = "
      "; + document.querySelector("#w3c_toggle_include").insertAdjacentElement('afterend', div); + } + document.querySelector("#w3c_toggle_include_hide").addEventListener("change", function() { + var elements = document.querySelectorAll("p.expand_description, div.expand_description, ul.expand_description"); + Array.prototype.forEach.call(elements, function(e) { + e.parentElement.classList.add("closed"); + }); + var img = document.querySelectorAll(".expand_section img"); + Array.prototype.forEach.call(img, function(i) { + i.setAttribute("src", "/2008/site/images/ico-plus"); + i.setAttribute("alt", "Expand"); + }); + if (window.location.hash == '#w3c_all') { + window.location.hash = ''; + } + }); + document.querySelector("#w3c_toggle_include_show").addEventListener("change", function() { + var elements = document.querySelectorAll("p.expand_description, div.expand_description, ul.expand_description"); + Array.prototype.forEach.call(elements, function(e) { + e.parentElement.classList.remove("closed"); + }); + var img = document.querySelectorAll(".expand_section img"); + Array.prototype.forEach.call(img, function(i) { + i.setAttribute("src", "/2008/site/images/ico-minus"); + i.setAttribute("alt", "Collapse"); + }); + if (window.location.hash == '#w3c_all') { + window.location.hash = ''; + } + }); + if (!startopen) { + document.querySelector("#w3c_toggle_include_hide").dispatchEvent(new Event("change")); + } else { + document.querySelector("#w3c_toggle_include_show").dispatchEvent(new Event("change")); + } + } else { + var t = enquire.tree; + var toggleForm = document.querySelector("#w3c_toggle_include"); + var f = document.querySelector("#w3c_toggle_include_show"); + var forms = Array.prototype.filter.call(t.parents(f), function(e) { + return e.tagName === "FORM" && Array.prototype.some.call(e.parentNode.children, function (c) { return c === toggleForm; }) && e !== toggleForm; + }); + Array.prototype.forEach.call(forms, function (f) { + f.remove(); + }); + } + } + } +}; + +enquire.init(); \ No newline at end of file diff --git a/OrgLink.tsx b/OrgLink.tsx new file mode 100644 index 0000000..3c9248e --- /dev/null +++ b/OrgLink.tsx @@ -0,0 +1,28 @@ +import {clsx} from 'clsx' +import {Link} from '@primer/react' +import {orgHovercardPath} from '@github-ui/paths' +import type {Author} from '../commit-attribution-types' +import styles from './OrgLink.module.css' + +/** + * Renders the author of a commit. + */ +export function OrgLink({org, className}: {org: Author; className?: string}) { + if (!org) return null + + return ( +
      + + {org.login!} + +
      + ) +} + +try{ OrgLink.displayName ||= 'OrgLink' } catch {} \ No newline at end of file diff --git a/Overlay-43cda449.css b/Overlay-43cda449.css new file mode 100644 index 0000000..50daf83 --- /dev/null +++ b/Overlay-43cda449.css @@ -0,0 +1,2 @@ +@layer primer-react { @keyframes prc-Overlay-overlay-appear-JpFey{0%{opacity:0}to{opacity:1}}.prc-Overlay-Overlay-jfs-T{background-color:var(--overlay-bgColor,var(--color-canvas-overlay));border-radius:var(--borderRadius-large,.75rem);bottom:var(--bottom,auto);box-shadow:var(--shadow-floating-small,var(--color-overlay-shadow));height:auto;left:var(--left,auto);max-height:100vh;max-width:calc(100vw - 2rem);min-width:192px;overflow:hidden;position:absolute;right:var(--right,auto);top:var(--top,auto);width:auto}.prc-Overlay-Overlay-jfs-T:focus{outline:none}@media (forced-colors:active){.prc-Overlay-Overlay-jfs-T{outline:1px solid transparent}}.prc-Overlay-Overlay-jfs-T:where([data-reflow-container=true]){max-width:calc(100vw - 2rem)}.prc-Overlay-Overlay-jfs-T:where([data-overflow-auto]){overflow:auto}.prc-Overlay-Overlay-jfs-T:where([data-overflow-hidden]){overflow:hidden}.prc-Overlay-Overlay-jfs-T:where([data-overflow-scroll]){overflow:scroll}.prc-Overlay-Overlay-jfs-T:where([data-overflow-visible]){overflow:visible}.prc-Overlay-Overlay-jfs-T:where([data-height-xsmall]){height:192px}.prc-Overlay-Overlay-jfs-T:where([data-height-small]){height:256px}.prc-Overlay-Overlay-jfs-T:where([data-height-medium]){height:320px}.prc-Overlay-Overlay-jfs-T:where([data-height-large]){height:432px}.prc-Overlay-Overlay-jfs-T:where([data-height-xlarge]){height:600px}.prc-Overlay-Overlay-jfs-T:where([data-height-auto]),.prc-Overlay-Overlay-jfs-T:where([data-height-initial]){height:auto}.prc-Overlay-Overlay-jfs-T:where([data-height-fit-content]){height:-moz-fit-content;height:fit-content}.prc-Overlay-Overlay-jfs-T:where([data-max-height-xsmall]){max-height:192px}.prc-Overlay-Overlay-jfs-T:where([data-max-height-small]){max-height:256px}.prc-Overlay-Overlay-jfs-T:where([data-max-height-medium]){max-height:320px}.prc-Overlay-Overlay-jfs-T:where([data-max-height-large]){max-height:432px}.prc-Overlay-Overlay-jfs-T:where([data-max-height-xlarge]){max-height:600px}.prc-Overlay-Overlay-jfs-T:where([data-max-height-fit-content]){max-height:-moz-fit-content;max-height:fit-content}.prc-Overlay-Overlay-jfs-T:where([data-width-small]){width:256px}.prc-Overlay-Overlay-jfs-T:where([data-width-medium]){width:320px}.prc-Overlay-Overlay-jfs-T:where([data-width-large]){width:480px}.prc-Overlay-Overlay-jfs-T:where([data-width-xlarge]){width:640px}.prc-Overlay-Overlay-jfs-T:where([data-width-xxlarge]){width:960px}.prc-Overlay-Overlay-jfs-T:where([data-width-auto]){width:auto}.prc-Overlay-Overlay-jfs-T:where([data-max-width-small]){max-width:256px}.prc-Overlay-Overlay-jfs-T:where([data-max-width-medium]){max-width:320px}.prc-Overlay-Overlay-jfs-T:where([data-max-width-large]){max-width:480px}.prc-Overlay-Overlay-jfs-T:where([data-max-width-xlarge]){max-width:640px}.prc-Overlay-Overlay-jfs-T:where([data-max-width-xxlarge]){max-width:960px}.prc-Overlay-Overlay-jfs-T:where([data-visibility-visible]){visibility:visible}.prc-Overlay-Overlay-jfs-T:where([data-visibility-hidden]){visibility:hidden}@media screen and (max-width:calc(48rem - 0.02px)){.prc-Overlay-Overlay-jfs-T:where([data-responsive=fullscreen]){border-radius:unset;height:100vh;left:0;margin:0;max-height:none;max-width:none;position:fixed;top:0;width:100vw}}@supports (height:100dvh){.prc-Overlay-Overlay-jfs-T:where([data-variant=fullscreen]){height:100dvh}}@media (prefers-reduced-motion:no-preference){.prc-Overlay-Overlay-jfs-T{animation:prc-Overlay-overlay-appear-JpFey .2s cubic-bezier(.33,1,.68,1)}} +/*# sourceMappingURL=Overlay-43cda449.css.map */ } \ No newline at end of file diff --git a/aclient-env.ts b/aclient-env.ts new file mode 100644 index 0000000..aac1701 --- /dev/null +++ b/aclient-env.ts @@ -0,0 +1,80 @@ +export interface ClientEnvironment { + readonly locale: string + readonly featureFlags: string[] + readonly login?: string + readonly copilotApiOverrideUrl: string | null +} + +let env: ClientEnvironment | undefined + +let getServerEnv: (() => ClientEnvironment | undefined) | null = null + +export function getEnv() { + const serverEnv = getServerEnv ? getServerEnv() : undefined + const targetEnv = serverEnv ?? env + + if (!targetEnv) { + throw new Error( + 'Client env was requested before it was loaded. This likely means you are attempting to use client env at the module level in SSR, which is not supported. Please move your client env usage into a function.', + ) + } + + return targetEnv +} + +export function getLocale() { + return getEnv().locale ?? 'en-US' +} + +export function isLoggedIn() { + return !!getEnv().login +} + +export function getCurrentUserLogin() { + return getEnv().login +} + +function loadEnv() { + if (typeof document !== 'undefined') { + const envTag = document.getElementById('client-env') + if (envTag) { + try { + env = JSON.parse(envTag.textContent || '') + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error parsing client-env', error) + } + } + } +} + +// Automatically load the env on initial page load +loadEnv() + +// This is a special helper method for setting the env in the SSR environment only +export function setClientEnvForSsr(clientEnv: ClientEnvironment | undefined) { + env = clientEnv +} + +export function setServerEnvGetter(getter: () => ClientEnvironment | undefined) { + getServerEnv = getter +} + +// This env object is used as a default for tests only and is not included in production builds +export const clientEnvForTests: ClientEnvironment = { + locale: 'en', + featureFlags: ['test_flag'], + copilotApiOverrideUrl: 'http://copilot-api.test', +} + +export function _resetForTests({loadNewEnv, forceUndefined}: {loadNewEnv: boolean; forceUndefined?: boolean}) { + // forget the current env + env = forceUndefined ? undefined : clientEnvForTests + // Note: we don't reset getServerEnv here because it's set once at module load time + // by client-env.server.ts and should persist across test resets + + if (loadNewEnv) { + // load the latest env + loadEnv() + } +} diff --git a/agentutils.ts b/agentutils.ts new file mode 100644 index 0000000..5e3820f --- /dev/null +++ b/agentutils.ts @@ -0,0 +1,12 @@ +import type {Author} from './commit-attribution-types' + +export function isBotOrApp(author: Author) { + const isApp = author.path?.startsWith('/apps/') ?? false + + // Copilot SWE agent should be rendered as circular, not square + if (isApp && author.login?.toLowerCase() === 'copilot-swe-agent') { + return false + } + + return isApp +} diff --git a/alive.ts b/alive.ts new file mode 100644 index 0000000..50bfc77 --- /dev/null +++ b/alive.ts @@ -0,0 +1,236 @@ +import type {AliveEvent, AliveSessionOptions, MetadataUpdate, Notifier, Subscription} from '@github/alive-client' +import {PresenceMetadataSet, SubscriptionSet, isPresenceChannel} from '@github/alive-client' +import {AliveSession} from './session' +import {debounce} from '@github/mini-throttle' +import {ready} from '@github-ui/document-ready' +import safeStorage from '@github-ui/safe-storage' +import {isSafari} from '@braintree/browser-detection' + +export interface Dispatchable { + dispatchEvent: (e: Event) => unknown +} + +function isSharedWorkerSupported(): boolean { + // There is currently a bug in safari that causes shared workers to stop working after a while + // see https://github.com/github/web-systems/issues/965 + if (isSafari()) return false + return 'SharedWorker' in window && safeStorage('localStorage').getItem('bypassSharedWorker') !== 'true' +} + +export function workerSrc(): string | null { + const url = document.head.querySelector(`link[rel=shared-web-socket-src]`)?.getAttribute('href') + + // ensure we have a valid URL, otherwise don't use the worker + if (!url || !url.startsWith('/')) { + return null + } + + return url +} + +function socketUrl(): string | null { + return document.head.querySelector('link[rel=shared-web-socket]')?.href ?? null +} + +function socketRefreshUrl(): string | null { + return ( + document.head.querySelector('link[rel=shared-web-socket]')?.getAttribute('data-refresh-url') ?? + null + ) +} + +function sessionIdentifier(): string | null { + return ( + document.head.querySelector('link[rel=shared-web-socket]')?.getAttribute('data-session-id') ?? null + ) +} + +/** + * dispatches events of type: 'socket:message' | 'socket:presence' + */ +function notify(subscribers: Iterable, {channel, type, data}: AliveEvent) { + for (const el of subscribers) { + el.dispatchEvent( + new CustomEvent(`socket:${type}`, { + bubbles: false, + cancelable: false, + detail: {name: channel, data}, + }), + ) + } +} + +class AliveSessionProxy { + #worker: SharedWorker + #subscriptions = new SubscriptionSet() + #presenceMetadata = new PresenceMetadataSet() + #notify: Notifier + + constructor( + src: string, + url: string, + refreshUrl: string, + sessionId: string, + notifier: Notifier, + options: AliveSessionOptions, + ) { + this.#notify = notifier + // eslint-disable-next-line ssr-friendly/no-dom-globals-in-constructor + this.#worker = new SharedWorker(`${src}?module=true`, { + name: `github-socket-worker-v3-${sessionId}`, + type: 'module', + }) + this.#worker.port.onmessage = ({data}) => this.#receive(data) + this.#worker.port.postMessage({connect: {url, refreshUrl, options}}) + } + + subscribe(subs: Array>) { + const added = this.#subscriptions.add(...subs) + if (added.length) { + this.#worker.port.postMessage({subscribe: added}) + } + + // We may be adding a subscription to a presence channel which is already subscribed. + // In this case, we need to explicitly ask the SharedWorker to send us the presence data. + const addedChannels = new Set(added.map(topic => topic.name)) + const redundantPresenceChannels = subs.reduce((redundantChannels, subscription) => { + const channel = subscription.topic.name + + if (isPresenceChannel(channel) && !addedChannels.has(channel)) { + redundantChannels.add(channel) + } + + return redundantChannels + }, new Set()) + + if (redundantPresenceChannels.size) { + this.#worker.port.postMessage({requestPresence: Array.from(redundantPresenceChannels)}) + } + } + + unsubscribeAll(...subscribers: Dispatchable[]) { + const removed = this.#subscriptions.drain(...subscribers) + if (removed.length) { + this.#worker.port.postMessage({unsubscribe: removed}) + } + + const updatedPresenceChannels = this.#presenceMetadata.removeSubscribers(subscribers) + this.sendPresenceMetadataUpdate(updatedPresenceChannels) + } + + updatePresenceMetadata(metadataUpdates: Array>) { + const updatedChannels = new Set() + + for (const update of metadataUpdates) { + // update the local metadata for this specific element + this.#presenceMetadata.setMetadata(update) + updatedChannels.add(update.channelName) + } + + // Send the full local metadata for these channels to the SharedWorker + this.sendPresenceMetadataUpdate(updatedChannels) + } + + sendPresenceMetadataUpdate(channelNames: Set) { + if (!channelNames.size) { + return + } + + const updatesForSharedWorker: Array, 'subscriber'>> = [] + + for (const channelName of channelNames) { + // get all metadata for this channel (from all elements) to send to the SharedWorker + updatesForSharedWorker.push({ + channelName, + metadata: this.#presenceMetadata.getChannelMetadata(channelName), + }) + } + + // Send the full metadata updates to the SharedWorker + this.#worker.port.postMessage({updatePresenceMetadata: updatesForSharedWorker}) + } + + online() { + this.#worker.port.postMessage({online: true}) + } + + offline() { + this.#worker.port.postMessage({online: false}) + } + + hangup() { + this.#worker.port.postMessage({hangup: true}) + } + + #notifyPresenceDebouncedByChannel = new Map>() + #receive(event: AliveEvent) { + const {channel} = event + + if (event.type === 'presence') { + // There are times when we get a flood of messages from the SharedWorker, such as a tab that has been idle for a long time and then comes back to the foreground. + // Since each presence message for a channel contains the full list of users, we can debounce the events and only notify subscribers with the last one + let debouncedNotify = this.#notifyPresenceDebouncedByChannel.get(channel) + if (!debouncedNotify) { + debouncedNotify = debounce((subscribers, debouncedEvent) => { + this.#notify(subscribers, debouncedEvent) + this.#notifyPresenceDebouncedByChannel.delete(channel) + }, 100) + this.#notifyPresenceDebouncedByChannel.set(channel, debouncedNotify) + } + + debouncedNotify(this.#subscriptions.subscribers(channel), event) + return + } + + // For non-presence messages, we can send them through immediately since they may contain different messages/data + this.#notify(this.#subscriptions.subscribers(channel), event) + } +} + +async function connect() { + const src = workerSrc() + if (!src) return + + const url = socketUrl() + if (!url) return + + const refreshUrl = socketRefreshUrl() + if (!refreshUrl) return + + const sessionId = sessionIdentifier() + if (!sessionId) return + + const createSession = () => { + const options: AliveSessionOptions = {} + + if (isSharedWorkerSupported()) { + try { + return new AliveSessionProxy(src, url, refreshUrl, sessionId, notify, options) + } catch { + // ignore errors. CSP will some times block SharedWorker creation. Fall back to standard AliveSession. + } + } + + return new AliveSession(url, refreshUrl, false, notify, options) + } + const session = createSession() + + window.addEventListener('online', () => session.online()) + window.addEventListener('offline', () => session.offline()) + window.addEventListener('pagehide', () => { + if ('hangup' in session) session.hangup() + }) + + return session +} + +async function connectWhenReady() { + await ready + return connect() +} + +let sessionPromise: undefined | ReturnType + +export function getSession() { + return (sessionPromise ||= connectWhenReady()) +} diff --git a/analytics-overrides.ts b/analytics-overrides.ts new file mode 100644 index 0000000..0cff533 --- /dev/null +++ b/analytics-overrides.ts @@ -0,0 +1,40 @@ +function queryLast(selector: string): T | undefined { + const list = document.querySelectorAll(selector) + if (list.length > 0) { + return list[list.length - 1] + } +} + +function pagePathname() { + const locationOverride = queryLast('meta[name=analytics-location]') + if (locationOverride) { + return locationOverride.content + } else { + return window.location.pathname + } +} + +function pageQuery() { + const stripParams = queryLast('meta[name=analytics-location-query-strip]') + let search = '' + + if (!stripParams) { + search = window.location.search + } + + const extraParams = queryLast('meta[name=analytics-location-params]') + if (extraParams) { + search += (search ? '&' : '?') + extraParams.content + } + + for (const meta of document.querySelectorAll('meta[name=analytics-param-rename]')) { + const names = meta.content.split(':', 2) + search = search.replace(new RegExp(`(^|[?&])${names[0]}($|=)`, 'g'), `$1${names[1]}$2`) + } + + return search +} + +export function requestUri() { + return `${window.location.protocol}//${window.location.host}${pagePathname() + pageQuery()}` +} diff --git a/apiinsights b/apiinsights new file mode 100644 index 0000000..b527393 --- /dev/null +++ b/apiinsights @@ -0,0 +1,91 @@ +// TODO: do not export those constants and instead provide functions to push and read data +export const TraceDataKey = 'GraphQLTraces' +export const TraceDataRefreshCallbackKey = 'GraphQLTracingRefresh' + +export const disabledClusters = getDisabledClusters() + +export function runsOnClient() { + return typeof window !== 'undefined' +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function reportTraceData(json: any) { + if (!runsOnClient()) return + if (!isTracingEnabled()) return + if (!json) return + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const rootWindowContent = window as {[key: string]: any} | undefined + + if (rootWindowContent && !rootWindowContent[TraceDataKey]) { + rootWindowContent[TraceDataKey] = [] + } + + if (rootWindowContent && json['__trace']) { + rootWindowContent[TraceDataKey].push(json['__trace']) + if (typeof rootWindowContent[TraceDataRefreshCallbackKey] === 'function') { + rootWindowContent[TraceDataRefreshCallbackKey]() + } + } +} + +export function isTracingEnabled() { + if (!runsOnClient()) return false + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const rootWindowContent = window as {[key: string]: any} | undefined + + return ( + new URLSearchParams(window.location.search).get('_tracing') === 'true' || + (rootWindowContent && rootWindowContent[TraceDataKey] !== undefined) + ) +} + +function clustersDisabled() { + return disabledClusters.length > 0 +} + +export function getInsightsUrl(url: string) { + if (!runsOnClient()) return url + if (!isTracingEnabled() && !clustersDisabled()) return url + + const urlObject = new URL(url, window.location.origin) + + if (isTracingEnabled()) { + urlObject.searchParams.set('_tracing', 'true') + } + + if (clustersDisabled()) { + urlObject.searchParams.set('disable_clusters', disabledClusters.join(',')) + } + + return urlObject.pathname + urlObject.search +} + +function getDisabledClusters() { + if (!runsOnClient()) return [] + + return decodeURIComponent(new URLSearchParams(window.location.search).get('disable_clusters') || '') + .split(',') + .filter(c => c !== '') +} + +export function isClusterDisabled(cluster: string) { + return disabledClusters.indexOf(cluster) > -1 +} + +export function toggleClusterState(cluster: string) { + if (!runsOnClient()) return + const index = disabledClusters.indexOf(cluster) + + if (index > -1) { + disabledClusters.splice(index, 1) + } else { + disabledClusters.push(cluster) + } + + const params = new URLSearchParams(window.location.search) + params.set('disable_clusters', disabledClusters.join(',')) + + window.location.search = params.toString() +} diff --git a/app-uuid.ts b/app-uuid.ts new file mode 100644 index 0000000..ac40a9d --- /dev/null +++ b/app-uuid.ts @@ -0,0 +1,38 @@ +import {currentState, updateCurrentState} from '@github-ui/history' +import {ssrSafeWindow} from '@github-ui/ssr-utils' + +// Use this mock interface to avoid importing ReactAppElement or ProjectsV2 here. +interface AppWithUuid extends Element { + uuid: string +} + +export const generateAppId = () => { + const historyAppId = currentState().appId + // When first loading an app, generate a new uuid to identify it + if (!historyAppId || historyAppId === 'rails') { + return crypto.randomUUID() + } + + // If the app is being restored from History, keep its uuid + return historyAppId +} + +export const registerAppId = (uuid: string) => { + updateCurrentState({appId: uuid}) +} + +export const currentAppId = () => { + const currentApp = + document.querySelector('react-app') || document.querySelector('projects-v2') + + return currentApp?.uuid || 'rails' +} + +// when the hash changes, we want to propagate the appId from the current state +ssrSafeWindow?.addEventListener( + 'hashchange', + () => { + updateCurrentState({appId: currentAppId()}) + }, + true, +) diff --git a/arianotify-polyfill.js b/arianotify-polyfill.js new file mode 100644 index 0000000..48db582 --- /dev/null +++ b/arianotify-polyfill.js @@ -0,0 +1,196 @@ +// @ts-check + +if (!("ariaNotify" in Element.prototype) || !("ariaNotify" in Document.prototype)) { + /** @type {string} */ + let uniqueId = `${Date.now()}`; + try { + uniqueId = crypto.randomUUID(); + } catch { } + + /** + * A unique symbol to prevent unauthorized access to the 'live-region' element. + * @type {Symbol} + */ + const passkey = Symbol(); + + /** @type {string} */ + const liveRegionCustomElementName = `live-region-${uniqueId}`; + + /** + * @param {number} ms + * @returns {Promise} + */ + function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + class Message { + /** @type {Element} */ + element; + + /** @type {string} */ + message; + + /** @type {"high" | "normal"} */ + priority = "normal"; + + /** + * @param {object} message + * @param {Element} message.element + * @param {string} message.message + * @param {"high" | "normal"} message.priority + */ + constructor({ element, message, priority = "normal" }) { + this.element = element; + this.message = message; + this.priority = priority; + } + + /** + * Whether this message can be announced. + * @returns {boolean} + */ + #canAnnounce() { + return ( + this.element.isConnected && + // Elements within inert containers should not be announced. + !this.element.closest("[inert]") && + // If there is a modal element on the page, everything outside of it is implicitly inert. + // This can be checked by seeing if the element is within the modal, if the modal is present. + (this.element.ownerDocument + .querySelector(":modal") + ?.contains(this.element) ?? + true) + ); + } + + /** @returns {Promise} */ + async announce() { + // Skip an unannounceable message. + if (!this.#canAnnounce()) { + return; + } + + // Get root element + let root = /** @type {Element} */ ( + this.element.closest("dialog") || this.element.closest("[role='dialog']") || this.element.getRootNode() + ); + if (!root || root instanceof Document) root = document.body; + + // Get 'live-region', if it already exists + /** @type {LiveRegionCustomElement | null} */ + let liveRegion = root.querySelector(liveRegionCustomElementName); + + // Create (or recreate) 'live-region', if it doesn’t exist + if (!liveRegion) { + liveRegion = /** @type {LiveRegionCustomElement} */ ( + document.createElement(liveRegionCustomElementName) + ); + root.append(liveRegion); + } + + await sleep(250); + liveRegion.handleMessage(passkey, this.message); + } + } + + const queue = new (class MessageQueue { + /** @type {Message[]} */ + #queue = []; + + /** @type {Message | undefined | null} */ + #currentMessage; + + /** + * Add the given message to the queue. + * @param {Message} message + * @returns {void} + */ + enqueue(message) { + const { priority } = message; + + if (priority === "high") { + // Insert after the last high-priority message, or at the beginning + // @ts-ignore: ts(2550) + const lastHighPriorityMessage = this.#queue.findLastIndex( + (message) => message.priority === "high" + ); + this.#queue.splice(lastHighPriorityMessage + 1, 0, message); + } else { + // Insert at the end + this.#queue.push(message); + } + + if (!this.#currentMessage) { + this.#processNext(); + } + } + + async #processNext() { + this.#currentMessage = this.#queue.shift(); + if (!this.#currentMessage) return; + await this.#currentMessage.announce(); + this.#processNext(); + } + })(); + + class LiveRegionCustomElement extends HTMLElement { + #shadowRoot = this.attachShadow({ mode: "closed" }); + + connectedCallback() { + this.ariaLive = "polite"; + this.ariaAtomic = "true"; + this.style.marginLeft = "-1px"; + this.style.marginTop = "-1px"; + this.style.position = "absolute"; + this.style.width = "1px"; + this.style.height = "1px"; + this.style.overflow = "hidden"; + this.style.clipPath = "rect(0 0 0 0)"; + this.style.overflowWrap = "normal"; + } + + /** + * @param {Symbol | null} key + * @param {string} message + */ + handleMessage(key = null, message = "") { + if (passkey !== key) return; + // This is a hack due to the way the aria live API works. A screen reader + // will not read a live region again if the text is the same. Adding a + // space character tells the browser that the live region has updated, + // which will cause it to read again, but with no audible difference. + if (this.#shadowRoot.textContent == message) message += "\u00A0"; + this.#shadowRoot.textContent = message; + } + } + customElements.define(liveRegionCustomElementName, LiveRegionCustomElement); + + if (!("ariaNotify" in Element.prototype)) { + /** + * @param {string} message + * @param {object} options + * @param {"high" | "normal"} [options.priority] + */ + Element.prototype["ariaNotify"] = function ( + message, + { priority = "normal" } = {} + ) { + queue.enqueue(new Message({ element: this, message, priority })); + }; + } + + if (!("ariaNotify" in Document.prototype)) { + /** + * @param {string} message + * @param {object} options + * @param {"high" | "normal"} [options.priority] + */ + Document.prototype["ariaNotify"] = function ( + message, + { priority = "normal" } = {} + ) { + queue.enqueue(new Message({ element: this.documentElement, message, priority })); + }; + } +} diff --git a/blob-anchor.ts b/blob-anchor.ts new file mode 100644 index 0000000..b34c586 --- /dev/null +++ b/blob-anchor.ts @@ -0,0 +1,271 @@ +export interface BlobOffset { + // Line number + // Lines start at 1. + line: number + + // Optional column number. + // Like lines, columns are 1-indexed. + column: number | null +} + +export interface BlobRange { + // Starting offset of range. + start: BlobOffset + + // End offset of range. + // End offset may be the same as the start. This indicates a collapsed range. + // Should always be initialized to a value that is equal or greater than the + // start range such the range is always in ascending order. Reversed ranges + // have undefined behavior. + end: BlobOffset +} + +// Inverse of `formatBlobRange`. +// +// Examples +// +// parseBlobRange("#L3") +// // => {start: {line: 3}} +// +// parseBlobRange("L3-L5") +// // => {start: {line: 3}, end: {line: 5}} +// +// parseBlobRange("") +// // => null +export function parseBlobRange(str: string): BlobRange | undefined { + const lines = str.match(/#?(?:L)(\d+)((?:C)(\d+))?/g) + if (!lines) { + return + } else if (lines.length === 1) { + const offset = parseBlobOffset(lines[0]) + if (!offset) return + return Object.freeze({start: offset, end: offset}) + } else if (lines.length === 2) { + const startOffset = parseBlobOffset(lines[0]) + const endOffset = parseBlobOffset(lines[1]) + if (!startOffset || !endOffset) return + + return ascendingBlobRange( + Object.freeze({ + start: startOffset, + end: endOffset, + }), + ) + } else { + return + } +} + +// Inverse of `parseBlobRange`. +// +// Examples +// +// formatBlobRange({start: {line: 3}}) +// // => "L3" +// +// formatBlobRange({start: {line: 3}, end: {line: 5}}) +// // => "L3-L5" +// +// formatBlobRange({start: {line: 3, column: 1}, end: {line: 5, column: 5}}) +// // => "L3C1-L5C5" +// +// formatBlobRange({start: {line: 3, column: 1}, end: {line: 5,}}) +// // => "L3C1-L5" +export function formatBlobRange(blobRange: BlobRange): string { + const {start, end} = ascendingBlobRange(blobRange) + + if (start.column != null && end.column != null) { + return `L${start.line}C${start.column}-L${end.line}C${end.column}` + } else if (start.column != null) { + return `L${start.line}C${start.column}-L${end.line}` + } else if (end.column != null) { + return `L${start.line}-L${end.line}C${end.column}` + } else if (start.line === end.line) { + return `L${start.line}` + } else { + return `L${start.line}-L${end.line}` + } +} + +// Returns a String containing the file prefix with trailing dash. +// +// Examples +// +// parseAnchorPrefix("#file-zshrc-L3") +// // => "file-zshrc-" +// +// parseAnchorPrefix("file-zshrc-L3-L5") +// // => "file-zshrc-" +// +// parseAnchorPrefix("") +// // => "" +function parseAnchorPrefix(str: string): string { + const match = str.length < 5000 && str.match(/(file-.+?-)L\d+?/i) + return match && match[1] ? match[1] : '' +} + +export type AnchorInfo = { + blobRange: BlobRange + anchorPrefix: string +} + +// Examples +// +// parseFileAnchor("#file-zshrc-L3") +// // => { blobRange: {start: {line: 3}}, anchorPrefix: "file-zshrc-" } +// +// parseFileAnchor("file-zshrc-L3-L5") +// // => { blobRange: {start: {line: 3}, end: {line: 5}}, anchorPrefix: "file-zshrc-" } +// +// parseFileAnchor("") +// // => { blobRange: null, anchorPrefix: undefined } +export function parseFileAnchor(str: string): AnchorInfo { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blobRange = parseBlobRange(str)! + const anchorPrefix = parseAnchorPrefix(str) + return {blobRange, anchorPrefix} +} + +// Formats line number range pair as an anchor String. +// +// Examples +// +// formatBlobRangeAnchor({blobRange: {start: {line: 3}}, anchorPrefix: ""}) +// // => "#L3" +// +// formatBlobRangeAnchor({blobRange: {start: {line: 3}}, anchorPrefix: "file-zshrc-"}) +// // => "#file-zshrc-L3" +// +// formatBlobRangeAnchor({blobRange: {start: {line: 3}, end: {line: 5}}, anchorPrefix: ""}) +// // => "#L3-L5" +// +// formatBlobRangeAnchor({blobRange: {start: {line: 3, column: 1}, end: {line: 5, column: 5}}, anchorPrefix: ""}) +// // => "#L3C1-L5C5" +// +// formatBlobRangeAnchor({blobRange: {start: {line: 3}, end: {line: 5}}, anchorPrefix: "file-zshrc-"}) +// // => "#file-zshrc-L3-L5" +// +// formatBlobRangeAnchor({blobRange: null, anchorPrefix: ""}) +// // => "#" +// +// formatBlobRangeAnchor({blobRange: null, anchorPrefix: "file-zshrc-"}) +// // => "#" +export function formatBlobRangeAnchor({anchorPrefix, blobRange}: AnchorInfo): string { + if (!blobRange) return '#' + return `#${anchorPrefix}${formatBlobRange(blobRange)}` +} + +function parseBlobOffset(str?: string): BlobOffset | null { + if (!str) return null + + const lineMatch = str.match(/L(\d+)/) + const columnMatch = str.match(/C(\d+)/) + if (lineMatch && lineMatch[1]) { + return Object.freeze({ + line: parseInt(lineMatch[1]), + column: columnMatch && columnMatch[1] ? parseInt(columnMatch[1]) : null, + }) + } else { + return null + } +} + +export function DOMRangeFromBlob( + blobRange: BlobRange, + getLineElement: (line: number) => Node | null, +): Range | undefined { + const [startContainer, _startOffset] = findRangeOffset(blobRange.start, true, getLineElement) + const [endContainer, _endOffset] = findRangeOffset(blobRange.end, false, getLineElement) + if (!startContainer || !endContainer) return + + // Treat -1 as full line selection + let startOffset = _startOffset + let endOffset = _endOffset + if (startOffset === -1) startOffset = 0 + if (endOffset === -1) endOffset = endContainer.childNodes.length + if (!startContainer.ownerDocument) throw new Error(`DOMRange needs to be inside document`) + + const range = startContainer.ownerDocument.createRange() + range.setStart(startContainer, startOffset) + range.setEnd(endContainer, endOffset) + return range +} + +function findRangeOffset( + offset: BlobOffset, + lookAhead: boolean, + getLineElement: (n: number) => Node | null, +): [Node | null, number] { + const error: [null, number] = [null, 0] + + const lineElement = getLineElement(offset.line) + if (!lineElement) return error + + if (offset.column == null) { + return [lineElement, -1] + } + + let column = offset.column - 1 + + const textNodes = getAllTextNodes(lineElement) + for (let i = 0; i < textNodes.length; i++) { + const textNode = textNodes[i] || null + + // TODO: length might be buggy with emoji + const nextC = column - (textNode?.textContent || '').length + + if (nextC === 0) { + const nextTextNode = textNodes[i + 1] + if (lookAhead && nextTextNode) { + return [nextTextNode, 0] + } else { + return [textNode, column] + } + } else if (nextC < 0) { + return [textNode, column] + } + + column = nextC + } + + return error +} + +// Get a flat list of text nodes in depth first order. +function getAllTextNodes(el: Node): Node[] { + if (el.nodeType === Node.TEXT_NODE) { + return [el] + } + if (!el.childNodes || !el.childNodes.length) return [] + let list: Node[] = [] + for (const node of el.childNodes) { + list = list.concat(getAllTextNodes(node)) + } + return list +} + +// Sorts range start and end offsets to be in ascending order. +function ascendingBlobRange(range: BlobRange): BlobRange { + const offsets: [BlobOffset, BlobOffset] = [range.start, range.end] + offsets.sort(compareBlobOffsets) + + if (offsets[0] === range.start && offsets[1] === range.end) { + return range + } else { + return Object.freeze({ + start: offsets[0], + end: offsets[1], + }) + } +} + +// Compare line offsets. May be used with Array.sort +function compareBlobOffsets(a: BlobOffset, b: BlobOffset): number { + if (a.line === b.line && a.column === b.column) { + return 0 + } else if (a.line === b.line && typeof a.column === 'number' && typeof b.column === 'number') { + return a.column - b.column + } else { + return a.line - b.line + } +} diff --git a/bootstrap b/bootstrap new file mode 100644 index 0000000..92490d3 --- /dev/null +++ b/bootstrap @@ -0,0 +1,30 @@ +// The module cache +var __webpack_module_cache__ = {}; + +// The require function +function __webpack_require__(moduleId) { + // Check if module is in cache + var cachedModule = __webpack_module_cache__[moduleId]; + if (cachedModule !== undefined) { + return cachedModule.exports; + } + // Create a new module (and put it into the cache) + var module = __webpack_module_cache__[moduleId] = { + id: moduleId, + loaded: false, + exports: {} + }; + + // Execute the module function + __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); + + // Flag the module as loaded + module.loaded = true; + + // Return the exports of the module + return module.exports; +} + +// expose the modules object (__webpack_modules__) +__webpack_require__.m = __webpack_modules__; + diff --git a/bootstrap.js b/bootstrap.js new file mode 100644 index 0000000..92490d3 --- /dev/null +++ b/bootstrap.js @@ -0,0 +1,30 @@ +// The module cache +var __webpack_module_cache__ = {}; + +// The require function +function __webpack_require__(moduleId) { + // Check if module is in cache + var cachedModule = __webpack_module_cache__[moduleId]; + if (cachedModule !== undefined) { + return cachedModule.exports; + } + // Create a new module (and put it into the cache) + var module = __webpack_module_cache__[moduleId] = { + id: moduleId, + loaded: false, + exports: {} + }; + + // Execute the module function + __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); + + // Flag the module as loaded + module.loaded = true; + + // Return the exports of the module + return module.exports; +} + +// expose the modules object (__webpack_modules__) +__webpack_require__.m = __webpack_modules__; + diff --git a/bsindex.js b/bsindex.js new file mode 100644 index 0000000..c96f5f6 --- /dev/null +++ b/bsindex.js @@ -0,0 +1,66 @@ +import * as clipboardItem from './clipboarditem.js'; +import * as elementCheckVisibility from './element-checkvisibility.js'; +import * as navigatorClipboard from './navigator-clipboard.js'; +import * as withResolvers from './promise-withResolvers.js'; +import * as requestIdleCallback from './requestidlecallback.js'; +import * as popover from '@oddbird/popover-polyfill/fn'; +import * as commandAndCommandFor from 'invokers-polyfill/fn'; +let supportsModalPseudo = false; +try { + // This will error in older browsers + supportsModalPseudo = document.body.matches(':modal') === false; +} +catch { + supportsModalPseudo = false; +} +export const baseSupport = typeof globalThis === 'object' && + // ES2019 + 'fromEntries' in Object && + 'flatMap' in Array.prototype && + 'trimEnd' in String.prototype && + // ES2020 + 'allSettled' in Promise && + 'matchAll' in String.prototype && + // ES2021 + 'replaceAll' in String.prototype && + 'any' in Promise && + // ES2022 + 'at' in String.prototype && + 'at' in Array.prototype && + 'hasOwn' in Object && + // ESNext + 'abort' in AbortSignal && + 'timeout' in AbortSignal && + // DOM / HTML and other specs + typeof queueMicrotask === 'function' && + typeof HTMLDialogElement === 'function' && + supportsModalPseudo && + typeof AggregateError === 'function' && + typeof BroadcastChannel === 'function' && + 'randomUUID' in crypto && + 'replaceChildren' in Element.prototype && + 'requestSubmit' in HTMLFormElement.prototype && + // 'requestIdleCallback' in window && // Polyfilled + true; +export const polyfills = { + clipboardItem, + elementCheckVisibility, + navigatorClipboard, + requestIdleCallback, + withResolvers, + popover, + commandAndCommandFor, +}; +export function isSupported() { + return baseSupport && Object.values(polyfills).every(polyfill => polyfill.isSupported()); +} +export function isPolyfilled() { + return Object.values(polyfills).every(polyfill => polyfill.isPolyfilled()); +} +export function apply() { + for (const polyfill of Object.values(polyfills)) { + if (!polyfill.isSupported()) + polyfill.apply(); + } +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/catalystbind.js b/catalystbind.js new file mode 100644 index 0000000..73de8c0 --- /dev/null +++ b/catalystbind.js @@ -0,0 +1,101 @@ +const controllers = new WeakSet(); +/* + * Bind `[data-action]` elements from the DOM to their actions. + * + */ +export function bind(controller) { + controllers.add(controller); + if (controller.shadowRoot) + bindShadow(controller.shadowRoot); + bindElements(controller); + listenForBind(controller.ownerDocument); +} +export function bindShadow(root) { + bindElements(root); + listenForBind(root); +} +const observers = new WeakMap(); +/** + * Set up observer that will make sure any actions that are dynamically + * injected into `el` will be bound to it's controller. + * + * This returns a Subscription object which you can call `unsubscribe()` on to + * stop further live updates. + */ +export function listenForBind(el = document) { + if (observers.has(el)) + return observers.get(el); + let closed = false; + const observer = new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && mutation.target instanceof Element) { + bindActions(mutation.target); + } + else if (mutation.type === 'childList' && mutation.addedNodes.length) { + for (const node of mutation.addedNodes) { + if (node instanceof Element) { + bindElements(node); + } + } + } + } + }); + observer.observe(el, { childList: true, subtree: true, attributeFilter: ['data-action'] }); + const subscription = { + get closed() { + return closed; + }, + unsubscribe() { + closed = true; + observers.delete(el); + observer.disconnect(); + } + }; + observers.set(el, subscription); + return subscription; +} +function bindElements(root) { + for (const el of root.querySelectorAll('[data-action]')) { + bindActions(el); + } + // Also bind the controller to itself + if (root instanceof Element && root.hasAttribute('data-action')) { + bindActions(root); + } +} +// Bind a single function to all events to avoid anonymous closure performance penalty. +function handleEvent(event) { + const el = event.currentTarget; + for (const binding of bindings(el)) { + if (event.type === binding.type) { + const controller = el.closest(binding.tag); + if (controllers.has(controller) && typeof controller[binding.method] === 'function') { + controller[binding.method](event); + } + const root = el.getRootNode(); + if (root instanceof ShadowRoot && controllers.has(root.host) && root.host.matches(binding.tag)) { + const shadowController = root.host; + if (typeof shadowController[binding.method] === 'function') { + shadowController[binding.method](event); + } + } + } + } +} +function* bindings(el) { + for (const action of (el.getAttribute('data-action') || '').trim().split(/\s+/)) { + const eventSep = action.lastIndexOf(':'); + const methodSep = Math.max(0, action.lastIndexOf('#')) || action.length; + yield { + type: action.slice(0, eventSep), + tag: action.slice(eventSep + 1, methodSep), + method: action.slice(methodSep + 1) || 'handleEvent' + } || 'handleEvent'; + } +} +function bindActions(el) { + for (const binding of bindings(el)) { + el.addEventListener(binding.type, handleEvent); + } +} +//# sourceMappingURL=bind.js.map \ No newline at end of file diff --git a/catalystcore.js b/catalystcore.js new file mode 100644 index 0000000..8d57656 --- /dev/null +++ b/catalystcore.js @@ -0,0 +1,76 @@ +import { register } from './register.js'; +import { bind, bindShadow } from './bind.js'; +import { autoShadowRoot } from './auto-shadow-root.js'; +import { defineObservedAttributes, initializeAttrs } from './attr.js'; +import { observe } from './lazy-define.js'; +const symbol = Symbol.for('catalyst'); +export class CatalystDelegate { + constructor(classObject) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const delegate = this; + const connectedCallback = classObject.prototype.connectedCallback; + classObject.prototype.connectedCallback = function () { + delegate.connectedCallback(this, connectedCallback); + }; + const disconnectedCallback = classObject.prototype.disconnectedCallback; + classObject.prototype.disconnectedCallback = function () { + delegate.disconnectedCallback(this, disconnectedCallback); + }; + const attributeChangedCallback = classObject.prototype.attributeChangedCallback; + classObject.prototype.attributeChangedCallback = function (name, oldValue, newValue) { + delegate.attributeChangedCallback(this, name, oldValue, newValue, attributeChangedCallback); + }; + let observedAttributes = classObject.observedAttributes || []; + Object.defineProperty(classObject, 'observedAttributes', { + configurable: true, + get() { + return delegate.observedAttributes(this, observedAttributes); + }, + set(attributes) { + observedAttributes = attributes; + } + }); + defineObservedAttributes(classObject); + register(classObject); + } + observedAttributes(instance, observedAttributes) { + return observedAttributes; + } + connectedCallback(instance, connectedCallback) { + instance.toggleAttribute('data-catalyst', true); + customElements.upgrade(instance); + autoShadowRoot(instance); + initializeAttrs(instance); + bind(instance); + connectedCallback?.call(instance); + if (instance.shadowRoot) { + bindShadow(instance.shadowRoot); + observe(instance.shadowRoot); + } + } + disconnectedCallback(element, disconnectedCallback) { + disconnectedCallback?.call(element); + } + attributeChangedCallback(instance, name, oldValue, newValue, attributeChangedCallback) { + initializeAttrs(instance); + if (name !== 'data-catalyst' && attributeChangedCallback) { + attributeChangedCallback.call(instance, name, oldValue, newValue); + } + } +} +export function meta(proto, name) { + if (!Object.prototype.hasOwnProperty.call(proto, symbol)) { + const parent = proto[symbol]; + const map = (proto[symbol] = new Map()); + if (parent) { + for (const [key, value] of parent) { + map.set(key, new Set(value)); + } + } + } + const map = proto[symbol]; + if (!map.has(name)) + map.set(name, new Set()); + return map.get(name); +} +//# sourceMappingURL=core.js.map \ No newline at end of file diff --git a/catalystfindtarget.js b/catalystfindtarget.js new file mode 100644 index 0000000..a3911a0 --- /dev/null +++ b/catalystfindtarget.js @@ -0,0 +1,41 @@ +/** + * findTarget will run `querySelectorAll` against the given controller, plus + * its shadowRoot, returning any the first child that: + * + * - Matches the selector of `[data-target~="tag.name"]` where tag is the + * tagName of the given HTMLElement, and `name` is the given `name` argument. + * + * - Closest ascendant of the element, that matches the tagname of the + * controller, is the specific instance of the controller itself - in other + * words it is not nested in other controllers of the same type. + * + */ +export function findTarget(controller, name) { + const tag = controller.tagName.toLowerCase(); + if (controller.shadowRoot) { + for (const el of controller.shadowRoot.querySelectorAll(`[data-target~="${tag}.${name}"]`)) { + if (!el.closest(tag)) + return el; + } + } + for (const el of controller.querySelectorAll(`[data-target~="${tag}.${name}"]`)) { + if (el.closest(tag) === controller) + return el; + } +} +export function findTargets(controller, name) { + const tag = controller.tagName.toLowerCase(); + const targets = []; + if (controller.shadowRoot) { + for (const el of controller.shadowRoot.querySelectorAll(`[data-targets~="${tag}.${name}"]`)) { + if (!el.closest(tag)) + targets.push(el); + } + } + for (const el of controller.querySelectorAll(`[data-targets~="${tag}.${name}"]`)) { + if (el.closest(tag) === controller) + targets.push(el); + } + return targets; +} +//# sourceMappingURL=findtarget.js.map \ No newline at end of file diff --git a/catalystlazy-define.js b/catalystlazy-define.js new file mode 100644 index 0000000..b7860ff --- /dev/null +++ b/catalystlazy-define.js @@ -0,0 +1,91 @@ +const dynamicElements = new Map(); +const ready = new Promise(resolve => { + if (document.readyState !== 'loading') { + resolve(); + } + else { + document.addEventListener('readystatechange', () => resolve(), { once: true }); + } +}); +const firstInteraction = new Promise(resolve => { + const controller = new AbortController(); + controller.signal.addEventListener('abort', () => resolve()); + const listenerOptions = { once: true, passive: true, signal: controller.signal }; + const handler = () => controller.abort(); + document.addEventListener('mousedown', handler, listenerOptions); + // eslint-disable-next-line github/require-passive-events + document.addEventListener('touchstart', handler, listenerOptions); + document.addEventListener('keydown', handler, listenerOptions); + document.addEventListener('pointerdown', handler, listenerOptions); +}); +const visible = (tagName) => new Promise(resolve => { + const observer = new IntersectionObserver(entries => { + for (const entry of entries) { + if (entry.isIntersecting) { + resolve(); + observer.disconnect(); + return; + } + } + }, { + // Currently the threshold is set to 256px from the bottom of the viewport + // with a threshold of 0.1. This means the element will not load until about + // 2 keyboard-down-arrow presses away from being visible in the viewport, + // giving us some time to fetch it before the contents are made visible + rootMargin: '0px 0px 256px 0px', + threshold: 0.01 + }); + for (const el of document.querySelectorAll(tagName)) { + observer.observe(el); + } +}); +const strategies = { + ready: () => ready, + firstInteraction: () => firstInteraction, + visible +}; +const timers = new WeakMap(); +function scan(element) { + cancelAnimationFrame(timers.get(element) || 0); + timers.set(element, requestAnimationFrame(() => { + for (const tagName of dynamicElements.keys()) { + const child = element instanceof Element && element.matches(tagName) ? element : element.querySelector(tagName); + if (customElements.get(tagName) || child) { + const strategyName = (child?.getAttribute('data-load-on') || 'ready'); + const strategy = strategyName in strategies ? strategies[strategyName] : strategies.ready; + // eslint-disable-next-line github/no-then + for (const cb of dynamicElements.get(tagName) || []) + strategy(tagName).then(cb); + dynamicElements.delete(tagName); + timers.delete(element); + } + } + })); +} +let elementLoader; +export function lazyDefine(tagNameOrObj, singleCallback) { + if (typeof tagNameOrObj === 'string' && singleCallback) { + tagNameOrObj = { [tagNameOrObj]: singleCallback }; + } + for (const [tagName, callback] of Object.entries(tagNameOrObj)) { + if (!dynamicElements.has(tagName)) + dynamicElements.set(tagName, new Set()); + dynamicElements.get(tagName).add(callback); + } + observe(document); +} +export function observe(target) { + elementLoader || (elementLoader = new MutationObserver(mutations => { + if (!dynamicElements.size) + return; + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (node instanceof Element) + scan(node); + } + } + })); + scan(target); + elementLoader.observe(target, { subtree: true, childList: true }); +} +//# sourceMappingURL=lazy-define.js.map \ No newline at end of file diff --git a/catalystregister.js b/catalystregister.js new file mode 100644 index 0000000..8a26592 --- /dev/null +++ b/catalystregister.js @@ -0,0 +1,25 @@ +import { dasherize } from './dasherize.js'; +/** + * Register the controller as a custom element. + * + * The classname is converted to a approriate tag name. + * + * Example: HelloController => hello-controller + */ +export function register(classObject) { + const name = dasherize(classObject.name).replace(/-element$/, ''); + try { + window.customElements.define(name, classObject); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + window[classObject.name] = customElements.get(name); + } + catch (e) { + // The only reason for window.customElements.define to throw a `NotSupportedError` + // is if the element has already been defined. + if (!(e instanceof DOMException && e.name === 'NotSupportedError')) + throw e; + } + return classObject; +} +//# sourceMappingURL=register.js.map \ No newline at end of file diff --git a/catalysttarget.js b/catalysttarget.js new file mode 100644 index 0000000..41a532e --- /dev/null +++ b/catalysttarget.js @@ -0,0 +1,35 @@ +import { findTarget, findTargets } from './findtarget.js'; +import { meta } from './core.js'; +/** + * Target is a decorator which - when assigned to a property field on the + * class - will override that class field, turning it into a Getter which + * returns a call to `findTarget(this, key)` where `key` is the name of the + * property field. In other words, `@target foo` becomes a getter for + * `findTarget(this, 'foo')`. + */ +export function target(proto, key) { + meta(proto, 'target').add(key); + Object.defineProperty(proto, key, { + configurable: true, + get() { + return findTarget(this, key); + } + }); +} +/** + * Targets is a decorator which - when assigned to a property field on the + * class - will override that class field, turning it into a Getter which + * returns a call to `findTargets(this, key)` where `key` is the name of the + * property field. In other words, `@targets foo` becomes a getter for + * `findTargets(this, 'foo')`. + */ +export function targets(proto, key) { + meta(proto, 'targets').add(key); + Object.defineProperty(proto, key, { + configurable: true, + get() { + return findTargets(this, key); + } + }); +} +//# sourceMappingURL=target.js.map \ No newline at end of file diff --git a/check-allindex.js b/check-allindex.js new file mode 100644 index 0000000..32972a8 --- /dev/null +++ b/check-allindex.js @@ -0,0 +1,101 @@ +export default function subscribe(container) { + let shiftKey = false; + let lastCheckbox = null; + container.addEventListener('mousedown', onMouseDown); + container.addEventListener('change', onChange); + function setChecked(target, input, checked, indeterminate = false) { + if (!(input instanceof HTMLInputElement)) + return; + input.indeterminate = indeterminate; + if (input.checked !== checked) { + input.checked = checked; + setTimeout(() => { + const event = new CustomEvent('change', { + bubbles: true, + cancelable: false, + detail: { relatedTarget: target } + }); + input.dispatchEvent(event); + }); + } + } + function onChange(event) { + const target = event.target; + if (!(target instanceof Element)) + return; + if (target.hasAttribute('data-check-all')) { + onCheckAll(event); + } + else if (target.hasAttribute('data-check-all-item')) { + onCheckAllItem(event); + } + } + function onCheckAll(event) { + if (event instanceof CustomEvent && event.detail) { + const { relatedTarget } = event.detail; + if (relatedTarget && relatedTarget.hasAttribute('data-check-all-item')) { + return; + } + } + const target = event.target; + if (!(target instanceof HTMLInputElement)) + return; + lastCheckbox = null; + for (const input of container.querySelectorAll('[data-check-all-item]')) { + setChecked(target, input, target.checked); + } + target.indeterminate = false; + updateCount(); + } + function onMouseDown(event) { + if (!(event.target instanceof Element)) + return; + const target = event.target instanceof HTMLLabelElement ? event.target.control || event.target : event.target; + if (target.hasAttribute('data-check-all-item')) { + shiftKey = event.shiftKey; + } + } + function onCheckAllItem(event) { + if (event instanceof CustomEvent && event.detail) { + const { relatedTarget } = event.detail; + if (relatedTarget && + (relatedTarget.hasAttribute('data-check-all') || relatedTarget.hasAttribute('data-check-all-item'))) { + return; + } + } + const target = event.target; + if (!(target instanceof HTMLInputElement)) + return; + const itemCheckboxes = Array.from(container.querySelectorAll('[data-check-all-item]')); + if (shiftKey && lastCheckbox) { + const [start, end] = [itemCheckboxes.indexOf(lastCheckbox), itemCheckboxes.indexOf(target)].sort(); + for (const input of itemCheckboxes.slice(start, +end + 1 || 9e9)) { + setChecked(target, input, target.checked); + } + } + shiftKey = false; + lastCheckbox = target; + const allCheckbox = container.querySelector('[data-check-all]'); + if (allCheckbox) { + const total = itemCheckboxes.length; + const count = itemCheckboxes.filter(checkbox => checkbox instanceof HTMLInputElement && checkbox.checked).length; + const checked = count === total; + const indeterminate = total > count && count > 0; + setChecked(target, allCheckbox, checked, indeterminate); + } + updateCount(); + } + function updateCount() { + const countContainer = container.querySelector('[data-check-all-count]'); + if (countContainer) { + const count = container.querySelectorAll('[data-check-all-item]:checked').length; + countContainer.textContent = count.toString(); + } + } + return { + unsubscribe: () => { + container.removeEventListener('mousedown', onMouseDown); + container.removeEventListener('change', onChange); + } + }; +} diff --git a/checkboxcheckallindex.js b/checkboxcheckallindex.js new file mode 100644 index 0000000..32972a8 --- /dev/null +++ b/checkboxcheckallindex.js @@ -0,0 +1,101 @@ +export default function subscribe(container) { + let shiftKey = false; + let lastCheckbox = null; + container.addEventListener('mousedown', onMouseDown); + container.addEventListener('change', onChange); + function setChecked(target, input, checked, indeterminate = false) { + if (!(input instanceof HTMLInputElement)) + return; + input.indeterminate = indeterminate; + if (input.checked !== checked) { + input.checked = checked; + setTimeout(() => { + const event = new CustomEvent('change', { + bubbles: true, + cancelable: false, + detail: { relatedTarget: target } + }); + input.dispatchEvent(event); + }); + } + } + function onChange(event) { + const target = event.target; + if (!(target instanceof Element)) + return; + if (target.hasAttribute('data-check-all')) { + onCheckAll(event); + } + else if (target.hasAttribute('data-check-all-item')) { + onCheckAllItem(event); + } + } + function onCheckAll(event) { + if (event instanceof CustomEvent && event.detail) { + const { relatedTarget } = event.detail; + if (relatedTarget && relatedTarget.hasAttribute('data-check-all-item')) { + return; + } + } + const target = event.target; + if (!(target instanceof HTMLInputElement)) + return; + lastCheckbox = null; + for (const input of container.querySelectorAll('[data-check-all-item]')) { + setChecked(target, input, target.checked); + } + target.indeterminate = false; + updateCount(); + } + function onMouseDown(event) { + if (!(event.target instanceof Element)) + return; + const target = event.target instanceof HTMLLabelElement ? event.target.control || event.target : event.target; + if (target.hasAttribute('data-check-all-item')) { + shiftKey = event.shiftKey; + } + } + function onCheckAllItem(event) { + if (event instanceof CustomEvent && event.detail) { + const { relatedTarget } = event.detail; + if (relatedTarget && + (relatedTarget.hasAttribute('data-check-all') || relatedTarget.hasAttribute('data-check-all-item'))) { + return; + } + } + const target = event.target; + if (!(target instanceof HTMLInputElement)) + return; + const itemCheckboxes = Array.from(container.querySelectorAll('[data-check-all-item]')); + if (shiftKey && lastCheckbox) { + const [start, end] = [itemCheckboxes.indexOf(lastCheckbox), itemCheckboxes.indexOf(target)].sort(); + for (const input of itemCheckboxes.slice(start, +end + 1 || 9e9)) { + setChecked(target, input, target.checked); + } + } + shiftKey = false; + lastCheckbox = target; + const allCheckbox = container.querySelector('[data-check-all]'); + if (allCheckbox) { + const total = itemCheckboxes.length; + const count = itemCheckboxes.filter(checkbox => checkbox instanceof HTMLInputElement && checkbox.checked).length; + const checked = count === total; + const indeterminate = total > count && count > 0; + setChecked(target, allCheckbox, checked, indeterminate); + } + updateCount(); + } + function updateCount() { + const countContainer = container.querySelector('[data-check-all-count]'); + if (countContainer) { + const count = container.querySelectorAll('[data-check-all-item]:checked').length; + countContainer.textContent = count.toString(); + } + } + return { + unsubscribe: () => { + container.removeEventListener('mousedown', onMouseDown); + container.removeEventListener('change', onChange); + } + }; +} diff --git a/chunk-EPOLDU6W.mjs b/chunk-EPOLDU6W.mjs new file mode 100644 index 0000000..f34ce5d --- /dev/null +++ b/chunk-EPOLDU6W.mjs @@ -0,0 +1,10994 @@ +/** + * react-router v7.12.0 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ +var __typeError = (msg) => { + throw TypeError(msg); +}; +var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); +var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); +var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); + +// lib/router/history.ts +var Action = /* @__PURE__ */ ((Action2) => { + Action2["Pop"] = "POP"; + Action2["Push"] = "PUSH"; + Action2["Replace"] = "REPLACE"; + return Action2; +})(Action || {}); +var PopStateEventType = "popstate"; +function createMemoryHistory(options = {}) { + let { initialEntries = ["/"], initialIndex, v5Compat = false } = options; + let entries; + entries = initialEntries.map( + (entry, index2) => createMemoryLocation( + entry, + typeof entry === "string" ? null : entry.state, + index2 === 0 ? "default" : void 0 + ) + ); + let index = clampIndex( + initialIndex == null ? entries.length - 1 : initialIndex + ); + let action = "POP" /* Pop */; + let listener = null; + function clampIndex(n) { + return Math.min(Math.max(n, 0), entries.length - 1); + } + function getCurrentLocation() { + return entries[index]; + } + function createMemoryLocation(to, state = null, key) { + let location = createLocation( + entries ? getCurrentLocation().pathname : "/", + to, + state, + key + ); + warning( + location.pathname.charAt(0) === "/", + `relative pathnames are not supported in memory history: ${JSON.stringify( + to + )}` + ); + return location; + } + function createHref2(to) { + return typeof to === "string" ? to : createPath(to); + } + let history = { + get index() { + return index; + }, + get action() { + return action; + }, + get location() { + return getCurrentLocation(); + }, + createHref: createHref2, + createURL(to) { + return new URL(createHref2(to), "http://localhost"); + }, + encodeLocation(to) { + let path = typeof to === "string" ? parsePath(to) : to; + return { + pathname: path.pathname || "", + search: path.search || "", + hash: path.hash || "" + }; + }, + push(to, state) { + action = "PUSH" /* Push */; + let nextLocation = createMemoryLocation(to, state); + index += 1; + entries.splice(index, entries.length, nextLocation); + if (v5Compat && listener) { + listener({ action, location: nextLocation, delta: 1 }); + } + }, + replace(to, state) { + action = "REPLACE" /* Replace */; + let nextLocation = createMemoryLocation(to, state); + entries[index] = nextLocation; + if (v5Compat && listener) { + listener({ action, location: nextLocation, delta: 0 }); + } + }, + go(delta) { + action = "POP" /* Pop */; + let nextIndex = clampIndex(index + delta); + let nextLocation = entries[nextIndex]; + index = nextIndex; + if (listener) { + listener({ action, location: nextLocation, delta }); + } + }, + listen(fn) { + listener = fn; + return () => { + listener = null; + }; + } + }; + return history; +} +function createBrowserHistory(options = {}) { + function createBrowserLocation(window2, globalHistory) { + let { pathname, search, hash } = window2.location; + return createLocation( + "", + { pathname, search, hash }, + // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, + globalHistory.state && globalHistory.state.key || "default" + ); + } + function createBrowserHref(window2, to) { + return typeof to === "string" ? to : createPath(to); + } + return getUrlBasedHistory( + createBrowserLocation, + createBrowserHref, + null, + options + ); +} +function createHashHistory(options = {}) { + function createHashLocation(window2, globalHistory) { + let { + pathname = "/", + search = "", + hash = "" + } = parsePath(window2.location.hash.substring(1)); + if (!pathname.startsWith("/") && !pathname.startsWith(".")) { + pathname = "/" + pathname; + } + return createLocation( + "", + { pathname, search, hash }, + // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, + globalHistory.state && globalHistory.state.key || "default" + ); + } + function createHashHref(window2, to) { + let base = window2.document.querySelector("base"); + let href = ""; + if (base && base.getAttribute("href")) { + let url = window2.location.href; + let hashIndex = url.indexOf("#"); + href = hashIndex === -1 ? url : url.slice(0, hashIndex); + } + return href + "#" + (typeof to === "string" ? to : createPath(to)); + } + function validateHashLocation(location, to) { + warning( + location.pathname.charAt(0) === "/", + `relative pathnames are not supported in hash history.push(${JSON.stringify( + to + )})` + ); + } + return getUrlBasedHistory( + createHashLocation, + createHashHref, + validateHashLocation, + options + ); +} +function invariant(value, message) { + if (value === false || value === null || typeof value === "undefined") { + throw new Error(message); + } +} +function warning(cond, message) { + if (!cond) { + if (typeof console !== "undefined") console.warn(message); + try { + throw new Error(message); + } catch (e) { + } + } +} +function createKey() { + return Math.random().toString(36).substring(2, 10); +} +function getHistoryState(location, index) { + return { + usr: location.state, + key: location.key, + idx: index + }; +} +function createLocation(current, to, state = null, key) { + let location = { + pathname: typeof current === "string" ? current : current.pathname, + search: "", + hash: "", + ...typeof to === "string" ? parsePath(to) : to, + state, + // TODO: This could be cleaned up. push/replace should probably just take + // full Locations now and avoid the need to run through this flow at all + // But that's a pretty big refactor to the current test suite so going to + // keep as is for the time being and just let any incoming keys take precedence + key: to && to.key || key || createKey() + }; + return location; +} +function createPath({ + pathname = "/", + search = "", + hash = "" +}) { + if (search && search !== "?") + pathname += search.charAt(0) === "?" ? search : "?" + search; + if (hash && hash !== "#") + pathname += hash.charAt(0) === "#" ? hash : "#" + hash; + return pathname; +} +function parsePath(path) { + let parsedPath = {}; + if (path) { + let hashIndex = path.indexOf("#"); + if (hashIndex >= 0) { + parsedPath.hash = path.substring(hashIndex); + path = path.substring(0, hashIndex); + } + let searchIndex = path.indexOf("?"); + if (searchIndex >= 0) { + parsedPath.search = path.substring(searchIndex); + path = path.substring(0, searchIndex); + } + if (path) { + parsedPath.pathname = path; + } + } + return parsedPath; +} +function getUrlBasedHistory(getLocation, createHref2, validateLocation, options = {}) { + let { window: window2 = document.defaultView, v5Compat = false } = options; + let globalHistory = window2.history; + let action = "POP" /* Pop */; + let listener = null; + let index = getIndex(); + if (index == null) { + index = 0; + globalHistory.replaceState({ ...globalHistory.state, idx: index }, ""); + } + function getIndex() { + let state = globalHistory.state || { idx: null }; + return state.idx; + } + function handlePop() { + action = "POP" /* Pop */; + let nextIndex = getIndex(); + let delta = nextIndex == null ? null : nextIndex - index; + index = nextIndex; + if (listener) { + listener({ action, location: history.location, delta }); + } + } + function push(to, state) { + action = "PUSH" /* Push */; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex() + 1; + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + try { + globalHistory.pushState(historyState, "", url); + } catch (error) { + if (error instanceof DOMException && error.name === "DataCloneError") { + throw error; + } + window2.location.assign(url); + } + if (v5Compat && listener) { + listener({ action, location: history.location, delta: 1 }); + } + } + function replace2(to, state) { + action = "REPLACE" /* Replace */; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex(); + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + globalHistory.replaceState(historyState, "", url); + if (v5Compat && listener) { + listener({ action, location: history.location, delta: 0 }); + } + } + function createURL(to) { + return createBrowserURLImpl(to); + } + let history = { + get action() { + return action; + }, + get location() { + return getLocation(window2, globalHistory); + }, + listen(fn) { + if (listener) { + throw new Error("A history only accepts one active listener"); + } + window2.addEventListener(PopStateEventType, handlePop); + listener = fn; + return () => { + window2.removeEventListener(PopStateEventType, handlePop); + listener = null; + }; + }, + createHref(to) { + return createHref2(window2, to); + }, + createURL, + encodeLocation(to) { + let url = createURL(to); + return { + pathname: url.pathname, + search: url.search, + hash: url.hash + }; + }, + push, + replace: replace2, + go(n) { + return globalHistory.go(n); + } + }; + return history; +} +function createBrowserURLImpl(to, isAbsolute = false) { + let base = "http://localhost"; + if (typeof window !== "undefined") { + base = window.location.origin !== "null" ? window.location.origin : window.location.href; + } + invariant(base, "No window.location.(origin|href) available to create URL"); + let href = typeof to === "string" ? to : createPath(to); + href = href.replace(/ $/, "%20"); + if (!isAbsolute && href.startsWith("//")) { + href = base + href; + } + return new URL(href, base); +} + +// lib/router/utils.ts +function createContext(defaultValue) { + return { defaultValue }; +} +var _map; +var RouterContextProvider = class { + /** + * Create a new `RouterContextProvider` instance + * @param init An optional initial context map to populate the provider with + */ + constructor(init) { + __privateAdd(this, _map, /* @__PURE__ */ new Map()); + if (init) { + for (let [context, value] of init) { + this.set(context, value); + } + } + } + /** + * Access a value from the context. If no value has been set for the context, + * it will return the context's `defaultValue` if provided, or throw an error + * if no `defaultValue` was set. + * @param context The context to get the value for + * @returns The value for the context, or the context's `defaultValue` if no + * value was set + */ + get(context) { + if (__privateGet(this, _map).has(context)) { + return __privateGet(this, _map).get(context); + } + if (context.defaultValue !== void 0) { + return context.defaultValue; + } + throw new Error("No value found for context"); + } + /** + * Set a value for the context. If the context already has a value set, this + * will overwrite it. + * + * @param context The context to set the value for + * @param value The value to set for the context + * @returns {void} + */ + set(context, value) { + __privateGet(this, _map).set(context, value); + } +}; +_map = new WeakMap(); +var unsupportedLazyRouteObjectKeys = /* @__PURE__ */ new Set([ + "lazy", + "caseSensitive", + "path", + "id", + "index", + "children" +]); +function isUnsupportedLazyRouteObjectKey(key) { + return unsupportedLazyRouteObjectKeys.has( + key + ); +} +var unsupportedLazyRouteFunctionKeys = /* @__PURE__ */ new Set([ + "lazy", + "caseSensitive", + "path", + "id", + "index", + "middleware", + "children" +]); +function isUnsupportedLazyRouteFunctionKey(key) { + return unsupportedLazyRouteFunctionKeys.has( + key + ); +} +function isIndexRoute(route) { + return route.index === true; +} +function convertRoutesToDataRoutes(routes, mapRouteProperties2, parentPath = [], manifest = {}, allowInPlaceMutations = false) { + return routes.map((route, index) => { + let treePath = [...parentPath, String(index)]; + let id = typeof route.id === "string" ? route.id : treePath.join("-"); + invariant( + route.index !== true || !route.children, + `Cannot specify children on an index route` + ); + invariant( + allowInPlaceMutations || !manifest[id], + `Found a route id collision on id "${id}". Route id's must be globally unique within Data Router usages` + ); + if (isIndexRoute(route)) { + let indexRoute = { + ...route, + id + }; + manifest[id] = mergeRouteUpdates( + indexRoute, + mapRouteProperties2(indexRoute) + ); + return indexRoute; + } else { + let pathOrLayoutRoute = { + ...route, + id, + children: void 0 + }; + manifest[id] = mergeRouteUpdates( + pathOrLayoutRoute, + mapRouteProperties2(pathOrLayoutRoute) + ); + if (route.children) { + pathOrLayoutRoute.children = convertRoutesToDataRoutes( + route.children, + mapRouteProperties2, + treePath, + manifest, + allowInPlaceMutations + ); + } + return pathOrLayoutRoute; + } + }); +} +function mergeRouteUpdates(route, updates) { + return Object.assign(route, { + ...updates, + ...typeof updates.lazy === "object" && updates.lazy != null ? { + lazy: { + ...route.lazy, + ...updates.lazy + } + } : {} + }); +} +function matchRoutes(routes, locationArg, basename = "/") { + return matchRoutesImpl(routes, locationArg, basename, false); +} +function matchRoutesImpl(routes, locationArg, basename, allowPartial) { + let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + let pathname = stripBasename(location.pathname || "/", basename); + if (pathname == null) { + return null; + } + let branches = flattenRoutes(routes); + rankRouteBranches(branches); + let matches = null; + for (let i = 0; matches == null && i < branches.length; ++i) { + let decoded = decodePath(pathname); + matches = matchRouteBranch( + branches[i], + decoded, + allowPartial + ); + } + return matches; +} +function convertRouteMatchToUiMatch(match, loaderData) { + let { route, pathname, params } = match; + return { + id: route.id, + pathname, + params, + data: loaderData[route.id], + loaderData: loaderData[route.id], + handle: route.handle + }; +} +function flattenRoutes(routes, branches = [], parentsMeta = [], parentPath = "", _hasParentOptionalSegments = false) { + let flattenRoute = (route, index, hasParentOptionalSegments = _hasParentOptionalSegments, relativePath) => { + let meta = { + relativePath: relativePath === void 0 ? route.path || "" : relativePath, + caseSensitive: route.caseSensitive === true, + childrenIndex: index, + route + }; + if (meta.relativePath.startsWith("/")) { + if (!meta.relativePath.startsWith(parentPath) && hasParentOptionalSegments) { + return; + } + invariant( + meta.relativePath.startsWith(parentPath), + `Absolute route path "${meta.relativePath}" nested under path "${parentPath}" is not valid. An absolute child route path must start with the combined path of all its parent routes.` + ); + meta.relativePath = meta.relativePath.slice(parentPath.length); + } + let path = joinPaths([parentPath, meta.relativePath]); + let routesMeta = parentsMeta.concat(meta); + if (route.children && route.children.length > 0) { + invariant( + // Our types know better, but runtime JS may not! + // @ts-expect-error + route.index !== true, + `Index routes must not have child routes. Please remove all child routes from route path "${path}".` + ); + flattenRoutes( + route.children, + branches, + routesMeta, + path, + hasParentOptionalSegments + ); + } + if (route.path == null && !route.index) { + return; + } + branches.push({ + path, + score: computeScore(path, route.index), + routesMeta + }); + }; + routes.forEach((route, index) => { + if (route.path === "" || !route.path?.includes("?")) { + flattenRoute(route, index); + } else { + for (let exploded of explodeOptionalSegments(route.path)) { + flattenRoute(route, index, true, exploded); + } + } + }); + return branches; +} +function explodeOptionalSegments(path) { + let segments = path.split("/"); + if (segments.length === 0) return []; + let [first, ...rest] = segments; + let isOptional = first.endsWith("?"); + let required = first.replace(/\?$/, ""); + if (rest.length === 0) { + return isOptional ? [required, ""] : [required]; + } + let restExploded = explodeOptionalSegments(rest.join("/")); + let result = []; + result.push( + ...restExploded.map( + (subpath) => subpath === "" ? required : [required, subpath].join("/") + ) + ); + if (isOptional) { + result.push(...restExploded); + } + return result.map( + (exploded) => path.startsWith("/") && exploded === "" ? "/" : exploded + ); +} +function rankRouteBranches(branches) { + branches.sort( + (a, b) => a.score !== b.score ? b.score - a.score : compareIndexes( + a.routesMeta.map((meta) => meta.childrenIndex), + b.routesMeta.map((meta) => meta.childrenIndex) + ) + ); +} +var paramRe = /^:[\w-]+$/; +var dynamicSegmentValue = 3; +var indexRouteValue = 2; +var emptySegmentValue = 1; +var staticSegmentValue = 10; +var splatPenalty = -2; +var isSplat = (s) => s === "*"; +function computeScore(path, index) { + let segments = path.split("/"); + let initialScore = segments.length; + if (segments.some(isSplat)) { + initialScore += splatPenalty; + } + if (index) { + initialScore += indexRouteValue; + } + return segments.filter((s) => !isSplat(s)).reduce( + (score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), + initialScore + ); +} +function compareIndexes(a, b) { + let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]); + return siblings ? ( + // If two routes are siblings, we should try to match the earlier sibling + // first. This allows people to have fine-grained control over the matching + // behavior by simply putting routes with identical paths in the order they + // want them tried. + a[a.length - 1] - b[b.length - 1] + ) : ( + // Otherwise, it doesn't really make sense to rank non-siblings by index, + // so they sort equally. + 0 + ); +} +function matchRouteBranch(branch, pathname, allowPartial = false) { + let { routesMeta } = branch; + let matchedParams = {}; + let matchedPathname = "/"; + let matches = []; + for (let i = 0; i < routesMeta.length; ++i) { + let meta = routesMeta[i]; + let end = i === routesMeta.length - 1; + let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/"; + let match = matchPath( + { path: meta.relativePath, caseSensitive: meta.caseSensitive, end }, + remainingPathname + ); + let route = meta.route; + if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) { + match = matchPath( + { + path: meta.relativePath, + caseSensitive: meta.caseSensitive, + end: false + }, + remainingPathname + ); + } + if (!match) { + return null; + } + Object.assign(matchedParams, match.params); + matches.push({ + // TODO: Can this as be avoided? + params: matchedParams, + pathname: joinPaths([matchedPathname, match.pathname]), + pathnameBase: normalizePathname( + joinPaths([matchedPathname, match.pathnameBase]) + ), + route + }); + if (match.pathnameBase !== "/") { + matchedPathname = joinPaths([matchedPathname, match.pathnameBase]); + } + } + return matches; +} +function generatePath(originalPath, params = {}) { + let path = originalPath; + if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) { + warning( + false, + `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".` + ); + path = path.replace(/\*$/, "/*"); + } + const prefix = path.startsWith("/") ? "/" : ""; + const stringify2 = (p) => p == null ? "" : typeof p === "string" ? p : String(p); + const segments = path.split(/\/+/).map((segment, index, array) => { + const isLastSegment = index === array.length - 1; + if (isLastSegment && segment === "*") { + const star = "*"; + return stringify2(params[star]); + } + const keyMatch = segment.match(/^:([\w-]+)(\??)(.*)/); + if (keyMatch) { + const [, key, optional, suffix] = keyMatch; + let param = params[key]; + invariant(optional === "?" || param != null, `Missing ":${key}" param`); + return encodeURIComponent(stringify2(param)) + suffix; + } + return segment.replace(/\?$/g, ""); + }).filter((segment) => !!segment); + return prefix + segments.join("/"); +} +function matchPath(pattern, pathname) { + if (typeof pattern === "string") { + pattern = { path: pattern, caseSensitive: false, end: true }; + } + let [matcher, compiledParams] = compilePath( + pattern.path, + pattern.caseSensitive, + pattern.end + ); + let match = pathname.match(matcher); + if (!match) return null; + let matchedPathname = match[0]; + let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1"); + let captureGroups = match.slice(1); + let params = compiledParams.reduce( + (memo2, { paramName, isOptional }, index) => { + if (paramName === "*") { + let splatValue = captureGroups[index] || ""; + pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1"); + } + const value = captureGroups[index]; + if (isOptional && !value) { + memo2[paramName] = void 0; + } else { + memo2[paramName] = (value || "").replace(/%2F/g, "/"); + } + return memo2; + }, + {} + ); + return { + params, + pathname: matchedPathname, + pathnameBase, + pattern + }; +} +function compilePath(path, caseSensitive = false, end = true) { + warning( + path === "*" || !path.endsWith("*") || path.endsWith("/*"), + `Route path "${path}" will be treated as if it were "${path.replace(/\*$/, "/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${path.replace(/\*$/, "/*")}".` + ); + let params = []; + let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace( + /\/:([\w-]+)(\?)?/g, + (_, paramName, isOptional) => { + params.push({ paramName, isOptional: isOptional != null }); + return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)"; + } + ).replace(/\/([\w-]+)\?(\/|$)/g, "(/$1)?$2"); + if (path.endsWith("*")) { + params.push({ paramName: "*" }); + regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$"; + } else if (end) { + regexpSource += "\\/*$"; + } else if (path !== "" && path !== "/") { + regexpSource += "(?:(?=\\/|$))"; + } else { + } + let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i"); + return [matcher, params]; +} +function decodePath(value) { + try { + return value.split("/").map((v) => decodeURIComponent(v).replace(/\//g, "%2F")).join("/"); + } catch (error) { + warning( + false, + `The URL path "${value}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${error}).` + ); + return value; + } +} +function stripBasename(pathname, basename) { + if (basename === "/") return pathname; + if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) { + return null; + } + let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length; + let nextChar = pathname.charAt(startIndex); + if (nextChar && nextChar !== "/") { + return null; + } + return pathname.slice(startIndex) || "/"; +} +function prependBasename({ + basename, + pathname +}) { + return pathname === "/" ? basename : joinPaths([basename, pathname]); +} +var ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i; +var isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX.test(url); +function resolvePath(to, fromPathname = "/") { + let { + pathname: toPathname, + search = "", + hash = "" + } = typeof to === "string" ? parsePath(to) : to; + let pathname; + if (toPathname) { + if (isAbsoluteUrl(toPathname)) { + pathname = toPathname; + } else { + if (toPathname.includes("//")) { + let oldPathname = toPathname; + toPathname = toPathname.replace(/\/\/+/g, "/"); + warning( + false, + `Pathnames cannot have embedded double slashes - normalizing ${oldPathname} -> ${toPathname}` + ); + } + if (toPathname.startsWith("/")) { + pathname = resolvePathname(toPathname.substring(1), "/"); + } else { + pathname = resolvePathname(toPathname, fromPathname); + } + } + } else { + pathname = fromPathname; + } + return { + pathname, + search: normalizeSearch(search), + hash: normalizeHash(hash) + }; +} +function resolvePathname(relativePath, fromPathname) { + let segments = fromPathname.replace(/\/+$/, "").split("/"); + let relativeSegments = relativePath.split("/"); + relativeSegments.forEach((segment) => { + if (segment === "..") { + if (segments.length > 1) segments.pop(); + } else if (segment !== ".") { + segments.push(segment); + } + }); + return segments.length > 1 ? segments.join("/") : "/"; +} +function getInvalidPathError(char, field, dest, path) { + return `Cannot include a '${char}' character in a manually specified \`to.${field}\` field [${JSON.stringify( + path + )}]. Please separate it out to the \`to.${dest}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`; +} +function getPathContributingMatches(matches) { + return matches.filter( + (match, index) => index === 0 || match.route.path && match.route.path.length > 0 + ); +} +function getResolveToMatches(matches) { + let pathMatches = getPathContributingMatches(matches); + return pathMatches.map( + (match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase + ); +} +function resolveTo(toArg, routePathnames, locationPathname, isPathRelative = false) { + let to; + if (typeof toArg === "string") { + to = parsePath(toArg); + } else { + to = { ...toArg }; + invariant( + !to.pathname || !to.pathname.includes("?"), + getInvalidPathError("?", "pathname", "search", to) + ); + invariant( + !to.pathname || !to.pathname.includes("#"), + getInvalidPathError("#", "pathname", "hash", to) + ); + invariant( + !to.search || !to.search.includes("#"), + getInvalidPathError("#", "search", "hash", to) + ); + } + let isEmptyPath = toArg === "" || to.pathname === ""; + let toPathname = isEmptyPath ? "/" : to.pathname; + let from; + if (toPathname == null) { + from = locationPathname; + } else { + let routePathnameIndex = routePathnames.length - 1; + if (!isPathRelative && toPathname.startsWith("..")) { + let toSegments = toPathname.split("/"); + while (toSegments[0] === "..") { + toSegments.shift(); + routePathnameIndex -= 1; + } + to.pathname = toSegments.join("/"); + } + from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/"; + } + let path = resolvePath(to, from); + let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); + let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/"); + if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) { + path.pathname += "/"; + } + return path; +} +var joinPaths = (paths) => paths.join("/").replace(/\/\/+/g, "/"); +var normalizePathname = (pathname) => pathname.replace(/\/+$/, "").replace(/^\/*/, "/"); +var normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search; +var normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; +var DataWithResponseInit = class { + constructor(data2, init) { + this.type = "DataWithResponseInit"; + this.data = data2; + this.init = init || null; + } +}; +function data(data2, init) { + return new DataWithResponseInit( + data2, + typeof init === "number" ? { status: init } : init + ); +} +var redirect = (url, init = 302) => { + let responseInit = init; + if (typeof responseInit === "number") { + responseInit = { status: responseInit }; + } else if (typeof responseInit.status === "undefined") { + responseInit.status = 302; + } + let headers = new Headers(responseInit.headers); + headers.set("Location", url); + return new Response(null, { ...responseInit, headers }); +}; +var redirectDocument = (url, init) => { + let response = redirect(url, init); + response.headers.set("X-Remix-Reload-Document", "true"); + return response; +}; +var replace = (url, init) => { + let response = redirect(url, init); + response.headers.set("X-Remix-Replace", "true"); + return response; +}; +var ErrorResponseImpl = class { + constructor(status, statusText, data2, internal = false) { + this.status = status; + this.statusText = statusText || ""; + this.internal = internal; + if (data2 instanceof Error) { + this.data = data2.toString(); + this.error = data2; + } else { + this.data = data2; + } + } +}; +function isRouteErrorResponse(error) { + return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error; +} +function getRoutePattern(matches) { + return matches.map((m) => m.route.path).filter(Boolean).join("/").replace(/\/\/*/g, "/") || "/"; +} +var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined"; +function parseToInfo(_to, basename) { + let to = _to; + if (typeof to !== "string" || !ABSOLUTE_URL_REGEX.test(to)) { + return { + absoluteURL: void 0, + isExternal: false, + to + }; + } + let absoluteURL = to; + let isExternal = false; + if (isBrowser) { + try { + let currentUrl = new URL(window.location.href); + let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to); + let path = stripBasename(targetUrl.pathname, basename); + if (targetUrl.origin === currentUrl.origin && path != null) { + to = path + targetUrl.search + targetUrl.hash; + } else { + isExternal = true; + } + } catch (e) { + warning( + false, + ` contains an invalid URL which will probably break when clicked - please update to a valid URL path.` + ); + } + } + return { + absoluteURL, + isExternal, + to + }; +} + +// lib/router/instrumentation.ts +var UninstrumentedSymbol = Symbol("Uninstrumented"); +function getRouteInstrumentationUpdates(fns, route) { + let aggregated = { + lazy: [], + "lazy.loader": [], + "lazy.action": [], + "lazy.middleware": [], + middleware: [], + loader: [], + action: [] + }; + fns.forEach( + (fn) => fn({ + id: route.id, + index: route.index, + path: route.path, + instrument(i) { + let keys = Object.keys(aggregated); + for (let key of keys) { + if (i[key]) { + aggregated[key].push(i[key]); + } + } + } + }) + ); + let updates = {}; + if (typeof route.lazy === "function" && aggregated.lazy.length > 0) { + let instrumented = wrapImpl(aggregated.lazy, route.lazy, () => void 0); + if (instrumented) { + updates.lazy = instrumented; + } + } + if (typeof route.lazy === "object") { + let lazyObject = route.lazy; + ["middleware", "loader", "action"].forEach((key) => { + let lazyFn = lazyObject[key]; + let instrumentations = aggregated[`lazy.${key}`]; + if (typeof lazyFn === "function" && instrumentations.length > 0) { + let instrumented = wrapImpl(instrumentations, lazyFn, () => void 0); + if (instrumented) { + updates.lazy = Object.assign(updates.lazy || {}, { + [key]: instrumented + }); + } + } + }); + } + ["loader", "action"].forEach((key) => { + let handler = route[key]; + if (typeof handler === "function" && aggregated[key].length > 0) { + let original = handler[UninstrumentedSymbol] ?? handler; + let instrumented = wrapImpl( + aggregated[key], + original, + (...args) => getHandlerInfo(args[0]) + ); + if (instrumented) { + if (key === "loader" && original.hydrate === true) { + instrumented.hydrate = true; + } + instrumented[UninstrumentedSymbol] = original; + updates[key] = instrumented; + } + } + }); + if (route.middleware && route.middleware.length > 0 && aggregated.middleware.length > 0) { + updates.middleware = route.middleware.map((middleware) => { + let original = middleware[UninstrumentedSymbol] ?? middleware; + let instrumented = wrapImpl( + aggregated.middleware, + original, + (...args) => getHandlerInfo(args[0]) + ); + if (instrumented) { + instrumented[UninstrumentedSymbol] = original; + return instrumented; + } + return middleware; + }); + } + return updates; +} +function instrumentClientSideRouter(router, fns) { + let aggregated = { + navigate: [], + fetch: [] + }; + fns.forEach( + (fn) => fn({ + instrument(i) { + let keys = Object.keys(i); + for (let key of keys) { + if (i[key]) { + aggregated[key].push(i[key]); + } + } + } + }) + ); + if (aggregated.navigate.length > 0) { + let navigate = router.navigate[UninstrumentedSymbol] ?? router.navigate; + let instrumentedNavigate = wrapImpl( + aggregated.navigate, + navigate, + (...args) => { + let [to, opts] = args; + return { + to: typeof to === "number" || typeof to === "string" ? to : to ? createPath(to) : ".", + ...getRouterInfo(router, opts ?? {}) + }; + } + ); + if (instrumentedNavigate) { + instrumentedNavigate[UninstrumentedSymbol] = navigate; + router.navigate = instrumentedNavigate; + } + } + if (aggregated.fetch.length > 0) { + let fetch2 = router.fetch[UninstrumentedSymbol] ?? router.fetch; + let instrumentedFetch = wrapImpl(aggregated.fetch, fetch2, (...args) => { + let [key, , href, opts] = args; + return { + href: href ?? ".", + fetcherKey: key, + ...getRouterInfo(router, opts ?? {}) + }; + }); + if (instrumentedFetch) { + instrumentedFetch[UninstrumentedSymbol] = fetch2; + router.fetch = instrumentedFetch; + } + } + return router; +} +function instrumentHandler(handler, fns) { + let aggregated = { + request: [] + }; + fns.forEach( + (fn) => fn({ + instrument(i) { + let keys = Object.keys(i); + for (let key of keys) { + if (i[key]) { + aggregated[key].push(i[key]); + } + } + } + }) + ); + let instrumentedHandler = handler; + if (aggregated.request.length > 0) { + instrumentedHandler = wrapImpl(aggregated.request, handler, (...args) => { + let [request, context] = args; + return { + request: getReadonlyRequest(request), + context: context != null ? getReadonlyContext(context) : context + }; + }); + } + return instrumentedHandler; +} +function wrapImpl(impls, handler, getInfo) { + if (impls.length === 0) { + return null; + } + return async (...args) => { + let result = await recurseRight( + impls, + getInfo(...args), + () => handler(...args), + impls.length - 1 + ); + if (result.type === "error") { + throw result.value; + } + return result.value; + }; +} +async function recurseRight(impls, info, handler, index) { + let impl = impls[index]; + let result; + if (!impl) { + try { + let value = await handler(); + result = { type: "success", value }; + } catch (e) { + result = { type: "error", value: e }; + } + } else { + let handlerPromise = void 0; + let callHandler = async () => { + if (handlerPromise) { + console.error("You cannot call instrumented handlers more than once"); + } else { + handlerPromise = recurseRight(impls, info, handler, index - 1); + } + result = await handlerPromise; + invariant(result, "Expected a result"); + if (result.type === "error" && result.value instanceof Error) { + return { status: "error", error: result.value }; + } + return { status: "success", error: void 0 }; + }; + try { + await impl(callHandler, info); + } catch (e) { + console.error("An instrumentation function threw an error:", e); + } + if (!handlerPromise) { + await callHandler(); + } + await handlerPromise; + } + if (result) { + return result; + } + return { + type: "error", + value: new Error("No result assigned in instrumentation chain.") + }; +} +function getHandlerInfo(args) { + let { request, context, params, unstable_pattern } = args; + return { + request: getReadonlyRequest(request), + params: { ...params }, + unstable_pattern, + context: getReadonlyContext(context) + }; +} +function getRouterInfo(router, opts) { + return { + currentUrl: createPath(router.state.location), + ..."formMethod" in opts ? { formMethod: opts.formMethod } : {}, + ..."formEncType" in opts ? { formEncType: opts.formEncType } : {}, + ..."formData" in opts ? { formData: opts.formData } : {}, + ..."body" in opts ? { body: opts.body } : {} + }; +} +function getReadonlyRequest(request) { + return { + method: request.method, + url: request.url, + headers: { + get: (...args) => request.headers.get(...args) + } + }; +} +function getReadonlyContext(context) { + if (isPlainObject(context)) { + let frozen = { ...context }; + Object.freeze(frozen); + return frozen; + } else { + return { + get: (ctx) => context.get(ctx) + }; + } +} +var objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0"); +function isPlainObject(thing) { + if (thing === null || typeof thing !== "object") { + return false; + } + const proto = Object.getPrototypeOf(thing); + return proto === Object.prototype || proto === null || Object.getOwnPropertyNames(proto).sort().join("\0") === objectProtoNames; +} + +// lib/router/router.ts +var validMutationMethodsArr = [ + "POST", + "PUT", + "PATCH", + "DELETE" +]; +var validMutationMethods = new Set( + validMutationMethodsArr +); +var validRequestMethodsArr = [ + "GET", + ...validMutationMethodsArr +]; +var validRequestMethods = new Set(validRequestMethodsArr); +var redirectStatusCodes = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]); +var redirectPreserveMethodStatusCodes = /* @__PURE__ */ new Set([307, 308]); +var IDLE_NAVIGATION = { + state: "idle", + location: void 0, + formMethod: void 0, + formAction: void 0, + formEncType: void 0, + formData: void 0, + json: void 0, + text: void 0 +}; +var IDLE_FETCHER = { + state: "idle", + data: void 0, + formMethod: void 0, + formAction: void 0, + formEncType: void 0, + formData: void 0, + json: void 0, + text: void 0 +}; +var IDLE_BLOCKER = { + state: "unblocked", + proceed: void 0, + reset: void 0, + location: void 0 +}; +var defaultMapRouteProperties = (route) => ({ + hasErrorBoundary: Boolean(route.hasErrorBoundary) +}); +var TRANSITIONS_STORAGE_KEY = "remix-router-transitions"; +var ResetLoaderDataSymbol = Symbol("ResetLoaderData"); +function createRouter(init) { + const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : void 0; + const isBrowser3 = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined"; + invariant( + init.routes.length > 0, + "You must provide a non-empty routes array to createRouter" + ); + let hydrationRouteProperties2 = init.hydrationRouteProperties || []; + let _mapRouteProperties = init.mapRouteProperties || defaultMapRouteProperties; + let mapRouteProperties2 = _mapRouteProperties; + if (init.unstable_instrumentations) { + let instrumentations = init.unstable_instrumentations; + mapRouteProperties2 = (route) => { + return { + ..._mapRouteProperties(route), + ...getRouteInstrumentationUpdates( + instrumentations.map((i) => i.route).filter(Boolean), + route + ) + }; + }; + } + let manifest = {}; + let dataRoutes = convertRoutesToDataRoutes( + init.routes, + mapRouteProperties2, + void 0, + manifest + ); + let inFlightDataRoutes; + let basename = init.basename || "/"; + if (!basename.startsWith("/")) { + basename = `/${basename}`; + } + let dataStrategyImpl = init.dataStrategy || defaultDataStrategyWithMiddleware; + let future = { + ...init.future + }; + let unlistenHistory = null; + let subscribers = /* @__PURE__ */ new Set(); + let savedScrollPositions2 = null; + let getScrollRestorationKey2 = null; + let getScrollPosition = null; + let initialScrollRestored = init.hydrationData != null; + let initialMatches = matchRoutes(dataRoutes, init.history.location, basename); + let initialMatchesIsFOW = false; + let initialErrors = null; + let initialized; + if (initialMatches == null && !init.patchRoutesOnNavigation) { + let error = getInternalRouterError(404, { + pathname: init.history.location.pathname + }); + let { matches, route } = getShortCircuitMatches(dataRoutes); + initialized = true; + initialMatches = matches; + initialErrors = { [route.id]: error }; + } else { + if (initialMatches && !init.hydrationData) { + let fogOfWar = checkFogOfWar( + initialMatches, + dataRoutes, + init.history.location.pathname + ); + if (fogOfWar.active) { + initialMatches = null; + } + } + if (!initialMatches) { + initialized = false; + initialMatches = []; + let fogOfWar = checkFogOfWar( + null, + dataRoutes, + init.history.location.pathname + ); + if (fogOfWar.active && fogOfWar.matches) { + initialMatchesIsFOW = true; + initialMatches = fogOfWar.matches; + } + } else if (initialMatches.some((m) => m.route.lazy)) { + initialized = false; + } else if (!initialMatches.some((m) => routeHasLoaderOrMiddleware(m.route))) { + initialized = true; + } else { + let loaderData = init.hydrationData ? init.hydrationData.loaderData : null; + let errors = init.hydrationData ? init.hydrationData.errors : null; + if (errors) { + let idx = initialMatches.findIndex( + (m) => errors[m.route.id] !== void 0 + ); + initialized = initialMatches.slice(0, idx + 1).every( + (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors) + ); + } else { + initialized = initialMatches.every( + (m) => !shouldLoadRouteOnHydration(m.route, loaderData, errors) + ); + } + } + } + let router; + let state = { + historyAction: init.history.action, + location: init.history.location, + matches: initialMatches, + initialized, + navigation: IDLE_NAVIGATION, + // Don't restore on initial updateState() if we were SSR'd + restoreScrollPosition: init.hydrationData != null ? false : null, + preventScrollReset: false, + revalidation: "idle", + loaderData: init.hydrationData && init.hydrationData.loaderData || {}, + actionData: init.hydrationData && init.hydrationData.actionData || null, + errors: init.hydrationData && init.hydrationData.errors || initialErrors, + fetchers: /* @__PURE__ */ new Map(), + blockers: /* @__PURE__ */ new Map() + }; + let pendingAction = "POP" /* Pop */; + let pendingPopstateNavigationDfd = null; + let pendingPreventScrollReset = false; + let pendingNavigationController; + let pendingViewTransitionEnabled = false; + let appliedViewTransitions = /* @__PURE__ */ new Map(); + let removePageHideEventListener = null; + let isUninterruptedRevalidation = false; + let isRevalidationRequired = false; + let cancelledFetcherLoads = /* @__PURE__ */ new Set(); + let fetchControllers = /* @__PURE__ */ new Map(); + let incrementingLoadId = 0; + let pendingNavigationLoadId = -1; + let fetchReloadIds = /* @__PURE__ */ new Map(); + let fetchRedirectIds = /* @__PURE__ */ new Set(); + let fetchLoadMatches = /* @__PURE__ */ new Map(); + let activeFetchers = /* @__PURE__ */ new Map(); + let fetchersQueuedForDeletion = /* @__PURE__ */ new Set(); + let blockerFunctions = /* @__PURE__ */ new Map(); + let unblockBlockerHistoryUpdate = void 0; + let pendingRevalidationDfd = null; + function initialize() { + unlistenHistory = init.history.listen( + ({ action: historyAction, location, delta }) => { + if (unblockBlockerHistoryUpdate) { + unblockBlockerHistoryUpdate(); + unblockBlockerHistoryUpdate = void 0; + return; + } + warning( + blockerFunctions.size === 0 || delta != null, + "You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL." + ); + let blockerKey = shouldBlockNavigation({ + currentLocation: state.location, + nextLocation: location, + historyAction + }); + if (blockerKey && delta != null) { + let nextHistoryUpdatePromise = new Promise((resolve) => { + unblockBlockerHistoryUpdate = resolve; + }); + init.history.go(delta * -1); + updateBlocker(blockerKey, { + state: "blocked", + location, + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: void 0, + reset: void 0, + location + }); + nextHistoryUpdatePromise.then(() => init.history.go(delta)); + }, + reset() { + let blockers = new Map(state.blockers); + blockers.set(blockerKey, IDLE_BLOCKER); + updateState({ blockers }); + } + }); + pendingPopstateNavigationDfd?.resolve(); + pendingPopstateNavigationDfd = null; + return; + } + return startNavigation(historyAction, location); + } + ); + if (isBrowser3) { + restoreAppliedTransitions(routerWindow, appliedViewTransitions); + let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions); + routerWindow.addEventListener("pagehide", _saveAppliedTransitions); + removePageHideEventListener = () => routerWindow.removeEventListener("pagehide", _saveAppliedTransitions); + } + if (!state.initialized) { + startNavigation("POP" /* Pop */, state.location, { + initialHydration: true + }); + } + return router; + } + function dispose() { + if (unlistenHistory) { + unlistenHistory(); + } + if (removePageHideEventListener) { + removePageHideEventListener(); + } + subscribers.clear(); + pendingNavigationController && pendingNavigationController.abort(); + state.fetchers.forEach((_, key) => deleteFetcher(key)); + state.blockers.forEach((_, key) => deleteBlocker(key)); + } + function subscribe(fn) { + subscribers.add(fn); + return () => subscribers.delete(fn); + } + function updateState(newState, opts = {}) { + if (newState.matches) { + newState.matches = newState.matches.map((m) => { + let route = manifest[m.route.id]; + let matchRoute = m.route; + if (matchRoute.element !== route.element || matchRoute.errorElement !== route.errorElement || matchRoute.hydrateFallbackElement !== route.hydrateFallbackElement) { + return { + ...m, + route + }; + } + return m; + }); + } + state = { + ...state, + ...newState + }; + let unmountedFetchers = []; + let mountedFetchers = []; + state.fetchers.forEach((fetcher, key) => { + if (fetcher.state === "idle") { + if (fetchersQueuedForDeletion.has(key)) { + unmountedFetchers.push(key); + } else { + mountedFetchers.push(key); + } + } + }); + fetchersQueuedForDeletion.forEach((key) => { + if (!state.fetchers.has(key) && !fetchControllers.has(key)) { + unmountedFetchers.push(key); + } + }); + [...subscribers].forEach( + (subscriber) => subscriber(state, { + deletedFetchers: unmountedFetchers, + newErrors: newState.errors ?? null, + viewTransitionOpts: opts.viewTransitionOpts, + flushSync: opts.flushSync === true + }) + ); + unmountedFetchers.forEach((key) => deleteFetcher(key)); + mountedFetchers.forEach((key) => state.fetchers.delete(key)); + } + function completeNavigation(location, newState, { flushSync } = {}) { + let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && location.state?._isRedirect !== true; + let actionData; + if (newState.actionData) { + if (Object.keys(newState.actionData).length > 0) { + actionData = newState.actionData; + } else { + actionData = null; + } + } else if (isActionReload) { + actionData = state.actionData; + } else { + actionData = null; + } + let loaderData = newState.loaderData ? mergeLoaderData( + state.loaderData, + newState.loaderData, + newState.matches || [], + newState.errors + ) : state.loaderData; + let blockers = state.blockers; + if (blockers.size > 0) { + blockers = new Map(blockers); + blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER)); + } + let restoreScrollPosition = isUninterruptedRevalidation ? false : getSavedScrollPosition(location, newState.matches || state.matches); + let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && location.state?._isRedirect !== true; + if (inFlightDataRoutes) { + dataRoutes = inFlightDataRoutes; + inFlightDataRoutes = void 0; + } + if (isUninterruptedRevalidation) { + } else if (pendingAction === "POP" /* Pop */) { + } else if (pendingAction === "PUSH" /* Push */) { + init.history.push(location, location.state); + } else if (pendingAction === "REPLACE" /* Replace */) { + init.history.replace(location, location.state); + } + let viewTransitionOpts; + if (pendingAction === "POP" /* Pop */) { + let priorPaths = appliedViewTransitions.get(state.location.pathname); + if (priorPaths && priorPaths.has(location.pathname)) { + viewTransitionOpts = { + currentLocation: state.location, + nextLocation: location + }; + } else if (appliedViewTransitions.has(location.pathname)) { + viewTransitionOpts = { + currentLocation: location, + nextLocation: state.location + }; + } + } else if (pendingViewTransitionEnabled) { + let toPaths = appliedViewTransitions.get(state.location.pathname); + if (toPaths) { + toPaths.add(location.pathname); + } else { + toPaths = /* @__PURE__ */ new Set([location.pathname]); + appliedViewTransitions.set(state.location.pathname, toPaths); + } + viewTransitionOpts = { + currentLocation: state.location, + nextLocation: location + }; + } + updateState( + { + ...newState, + // matches, errors, fetchers go through as-is + actionData, + loaderData, + historyAction: pendingAction, + location, + initialized: true, + navigation: IDLE_NAVIGATION, + revalidation: "idle", + restoreScrollPosition, + preventScrollReset, + blockers + }, + { + viewTransitionOpts, + flushSync: flushSync === true + } + ); + pendingAction = "POP" /* Pop */; + pendingPreventScrollReset = false; + pendingViewTransitionEnabled = false; + isUninterruptedRevalidation = false; + isRevalidationRequired = false; + pendingPopstateNavigationDfd?.resolve(); + pendingPopstateNavigationDfd = null; + pendingRevalidationDfd?.resolve(); + pendingRevalidationDfd = null; + } + async function navigate(to, opts) { + pendingPopstateNavigationDfd?.resolve(); + pendingPopstateNavigationDfd = null; + if (typeof to === "number") { + if (!pendingPopstateNavigationDfd) { + pendingPopstateNavigationDfd = createDeferred(); + } + let promise = pendingPopstateNavigationDfd.promise; + init.history.go(to); + return promise; + } + let normalizedPath = normalizeTo( + state.location, + state.matches, + basename, + to, + opts?.fromRouteId, + opts?.relative + ); + let { path, submission, error } = normalizeNavigateOptions( + false, + normalizedPath, + opts + ); + let currentLocation = state.location; + let nextLocation = createLocation(state.location, path, opts && opts.state); + nextLocation = { + ...nextLocation, + ...init.history.encodeLocation(nextLocation) + }; + let userReplace = opts && opts.replace != null ? opts.replace : void 0; + let historyAction = "PUSH" /* Push */; + if (userReplace === true) { + historyAction = "REPLACE" /* Replace */; + } else if (userReplace === false) { + } else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) { + historyAction = "REPLACE" /* Replace */; + } + let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : void 0; + let flushSync = (opts && opts.flushSync) === true; + let blockerKey = shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction + }); + if (blockerKey) { + updateBlocker(blockerKey, { + state: "blocked", + location: nextLocation, + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: void 0, + reset: void 0, + location: nextLocation + }); + navigate(to, opts); + }, + reset() { + let blockers = new Map(state.blockers); + blockers.set(blockerKey, IDLE_BLOCKER); + updateState({ blockers }); + } + }); + return; + } + await startNavigation(historyAction, nextLocation, { + submission, + // Send through the formData serialization error if we have one so we can + // render at the right error boundary after we match routes + pendingError: error, + preventScrollReset, + replace: opts && opts.replace, + enableViewTransition: opts && opts.viewTransition, + flushSync, + callSiteDefaultShouldRevalidate: opts && opts.unstable_defaultShouldRevalidate + }); + } + function revalidate() { + if (!pendingRevalidationDfd) { + pendingRevalidationDfd = createDeferred(); + } + interruptActiveLoads(); + updateState({ revalidation: "loading" }); + let promise = pendingRevalidationDfd.promise; + if (state.navigation.state === "submitting") { + return promise; + } + if (state.navigation.state === "idle") { + startNavigation(state.historyAction, state.location, { + startUninterruptedRevalidation: true + }); + return promise; + } + startNavigation( + pendingAction || state.historyAction, + state.navigation.location, + { + overrideNavigation: state.navigation, + // Proxy through any rending view transition + enableViewTransition: pendingViewTransitionEnabled === true + } + ); + return promise; + } + async function startNavigation(historyAction, location, opts) { + pendingNavigationController && pendingNavigationController.abort(); + pendingNavigationController = null; + pendingAction = historyAction; + isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; + saveScrollPosition(state.location, state.matches); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true; + let routesToUse = inFlightDataRoutes || dataRoutes; + let loadingNavigation = opts && opts.overrideNavigation; + let matches = opts?.initialHydration && state.matches && state.matches.length > 0 && !initialMatchesIsFOW ? ( + // `matchRoutes()` has already been called if we're in here via `router.initialize()` + state.matches + ) : matchRoutes(routesToUse, location, basename); + let flushSync = (opts && opts.flushSync) === true; + if (matches && state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) { + completeNavigation(location, { matches }, { flushSync }); + return; + } + let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname); + if (fogOfWar.active && fogOfWar.matches) { + matches = fogOfWar.matches; + } + if (!matches) { + let { error, notFoundMatches, route } = handleNavigational404( + location.pathname + ); + completeNavigation( + location, + { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error + } + }, + { flushSync } + ); + return; + } + pendingNavigationController = new AbortController(); + let request = createClientSideRequest( + init.history, + location, + pendingNavigationController.signal, + opts && opts.submission + ); + let scopedContext = init.getContext ? await init.getContext() : new RouterContextProvider(); + let pendingActionResult; + if (opts && opts.pendingError) { + pendingActionResult = [ + findNearestBoundary(matches).route.id, + { type: "error" /* error */, error: opts.pendingError } + ]; + } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) { + let actionResult = await handleAction( + request, + location, + opts.submission, + matches, + scopedContext, + fogOfWar.active, + opts && opts.initialHydration === true, + { replace: opts.replace, flushSync } + ); + if (actionResult.shortCircuited) { + return; + } + if (actionResult.pendingActionResult) { + let [routeId, result] = actionResult.pendingActionResult; + if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) { + pendingNavigationController = null; + completeNavigation(location, { + matches: actionResult.matches, + loaderData: {}, + errors: { + [routeId]: result.error + } + }); + return; + } + } + matches = actionResult.matches || matches; + pendingActionResult = actionResult.pendingActionResult; + loadingNavigation = getLoadingNavigation(location, opts.submission); + flushSync = false; + fogOfWar.active = false; + request = createClientSideRequest( + init.history, + request.url, + request.signal + ); + } + let { + shortCircuited, + matches: updatedMatches, + loaderData, + errors + } = await handleLoaders( + request, + location, + matches, + scopedContext, + fogOfWar.active, + loadingNavigation, + opts && opts.submission, + opts && opts.fetcherSubmission, + opts && opts.replace, + opts && opts.initialHydration === true, + flushSync, + pendingActionResult, + opts && opts.callSiteDefaultShouldRevalidate + ); + if (shortCircuited) { + return; + } + pendingNavigationController = null; + completeNavigation(location, { + matches: updatedMatches || matches, + ...getActionDataForCommit(pendingActionResult), + loaderData, + errors + }); + } + async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, initialHydration, opts = {}) { + interruptActiveLoads(); + let navigation = getSubmittingNavigation(location, submission); + updateState({ navigation }, { flushSync: opts.flushSync === true }); + if (isFogOfWar) { + let discoverResult = await discoverRoutes( + matches, + location.pathname, + request.signal + ); + if (discoverResult.type === "aborted") { + return { shortCircuited: true }; + } else if (discoverResult.type === "error") { + if (discoverResult.partialMatches.length === 0) { + let { matches: matches2, route } = getShortCircuitMatches(dataRoutes); + return { + matches: matches2, + pendingActionResult: [ + route.id, + { + type: "error" /* error */, + error: discoverResult.error + } + ] + }; + } + let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id; + return { + matches: discoverResult.partialMatches, + pendingActionResult: [ + boundaryId, + { + type: "error" /* error */, + error: discoverResult.error + } + ] + }; + } else if (!discoverResult.matches) { + let { notFoundMatches, error, route } = handleNavigational404( + location.pathname + ); + return { + matches: notFoundMatches, + pendingActionResult: [ + route.id, + { + type: "error" /* error */, + error + } + ] + }; + } else { + matches = discoverResult.matches; + } + } + let result; + let actionMatch = getTargetMatch(matches, location); + if (!actionMatch.route.action && !actionMatch.route.lazy) { + result = { + type: "error" /* error */, + error: getInternalRouterError(405, { + method: request.method, + pathname: location.pathname, + routeId: actionMatch.route.id + }) + }; + } else { + let dsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + request, + matches, + actionMatch, + initialHydration ? [] : hydrationRouteProperties2, + scopedContext + ); + let results = await callDataStrategy( + request, + dsMatches, + scopedContext, + null + ); + result = results[actionMatch.route.id]; + if (!result) { + for (let match of matches) { + if (results[match.route.id]) { + result = results[match.route.id]; + break; + } + } + } + if (request.signal.aborted) { + return { shortCircuited: true }; + } + } + if (isRedirectResult(result)) { + let replace2; + if (opts && opts.replace != null) { + replace2 = opts.replace; + } else { + let location2 = normalizeRedirectLocation( + result.response.headers.get("Location"), + new URL(request.url), + basename, + init.history + ); + replace2 = location2 === state.location.pathname + state.location.search; + } + await startRedirectNavigation(request, result, true, { + submission, + replace: replace2 + }); + return { shortCircuited: true }; + } + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + if ((opts && opts.replace) !== true) { + pendingAction = "PUSH" /* Push */; + } + return { + matches, + pendingActionResult: [ + boundaryMatch.route.id, + result, + actionMatch.route.id + ] + }; + } + return { + matches, + pendingActionResult: [actionMatch.route.id, result] + }; + } + async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync, pendingActionResult, callSiteDefaultShouldRevalidate) { + let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission); + let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation); + let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration; + if (isFogOfWar) { + if (shouldUpdateNavigationState) { + let actionData = getUpdatedActionData(pendingActionResult); + updateState( + { + navigation: loadingNavigation, + ...actionData !== void 0 ? { actionData } : {} + }, + { + flushSync + } + ); + } + let discoverResult = await discoverRoutes( + matches, + location.pathname, + request.signal + ); + if (discoverResult.type === "aborted") { + return { shortCircuited: true }; + } else if (discoverResult.type === "error") { + if (discoverResult.partialMatches.length === 0) { + let { matches: matches2, route } = getShortCircuitMatches(dataRoutes); + return { + matches: matches2, + loaderData: {}, + errors: { + [route.id]: discoverResult.error + } + }; + } + let boundaryId = findNearestBoundary(discoverResult.partialMatches).route.id; + return { + matches: discoverResult.partialMatches, + loaderData: {}, + errors: { + [boundaryId]: discoverResult.error + } + }; + } else if (!discoverResult.matches) { + let { error, notFoundMatches, route } = handleNavigational404( + location.pathname + ); + return { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error + } + }; + } else { + matches = discoverResult.matches; + } + } + let routesToUse = inFlightDataRoutes || dataRoutes; + let { dsMatches, revalidatingFetchers } = getMatchesToLoad( + request, + scopedContext, + mapRouteProperties2, + manifest, + init.history, + state, + matches, + activeSubmission, + location, + initialHydration ? [] : hydrationRouteProperties2, + initialHydration === true, + isRevalidationRequired, + cancelledFetcherLoads, + fetchersQueuedForDeletion, + fetchLoadMatches, + fetchRedirectIds, + routesToUse, + basename, + init.patchRoutesOnNavigation != null, + pendingActionResult, + callSiteDefaultShouldRevalidate + ); + pendingNavigationLoadId = ++incrementingLoadId; + if (!init.dataStrategy && !dsMatches.some((m) => m.shouldLoad) && !dsMatches.some( + (m) => m.route.middleware && m.route.middleware.length > 0 + ) && revalidatingFetchers.length === 0) { + let updatedFetchers2 = markFetchRedirectsDone(); + completeNavigation( + location, + { + matches, + loaderData: {}, + // Commit pending error if we're short circuiting + errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { [pendingActionResult[0]]: pendingActionResult[1].error } : null, + ...getActionDataForCommit(pendingActionResult), + ...updatedFetchers2 ? { fetchers: new Map(state.fetchers) } : {} + }, + { flushSync } + ); + return { shortCircuited: true }; + } + if (shouldUpdateNavigationState) { + let updates = {}; + if (!isFogOfWar) { + updates.navigation = loadingNavigation; + let actionData = getUpdatedActionData(pendingActionResult); + if (actionData !== void 0) { + updates.actionData = actionData; + } + } + if (revalidatingFetchers.length > 0) { + updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers); + } + updateState(updates, { flushSync }); + } + revalidatingFetchers.forEach((rf) => { + abortFetcher(rf.key); + if (rf.controller) { + fetchControllers.set(rf.key, rf.controller); + } + }); + let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((f) => abortFetcher(f.key)); + if (pendingNavigationController) { + pendingNavigationController.signal.addEventListener( + "abort", + abortPendingFetchRevalidations + ); + } + let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData( + dsMatches, + revalidatingFetchers, + request, + scopedContext + ); + if (request.signal.aborted) { + return { shortCircuited: true }; + } + if (pendingNavigationController) { + pendingNavigationController.signal.removeEventListener( + "abort", + abortPendingFetchRevalidations + ); + } + revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key)); + let redirect2 = findRedirect(loaderResults); + if (redirect2) { + await startRedirectNavigation(request, redirect2.result, true, { + replace: replace2 + }); + return { shortCircuited: true }; + } + redirect2 = findRedirect(fetcherResults); + if (redirect2) { + fetchRedirectIds.add(redirect2.key); + await startRedirectNavigation(request, redirect2.result, true, { + replace: replace2 + }); + return { shortCircuited: true }; + } + let { loaderData, errors } = processLoaderData( + state, + matches, + loaderResults, + pendingActionResult, + revalidatingFetchers, + fetcherResults + ); + if (initialHydration && state.errors) { + errors = { ...state.errors, ...errors }; + } + let updatedFetchers = markFetchRedirectsDone(); + let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId); + let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0; + return { + matches, + loaderData, + errors, + ...shouldUpdateFetchers ? { fetchers: new Map(state.fetchers) } : {} + }; + } + function getUpdatedActionData(pendingActionResult) { + if (pendingActionResult && !isErrorResult(pendingActionResult[1])) { + return { + [pendingActionResult[0]]: pendingActionResult[1].data + }; + } else if (state.actionData) { + if (Object.keys(state.actionData).length === 0) { + return null; + } else { + return state.actionData; + } + } + } + function getUpdatedRevalidatingFetchers(revalidatingFetchers) { + revalidatingFetchers.forEach((rf) => { + let fetcher = state.fetchers.get(rf.key); + let revalidatingFetcher = getLoadingFetcher( + void 0, + fetcher ? fetcher.data : void 0 + ); + state.fetchers.set(rf.key, revalidatingFetcher); + }); + return new Map(state.fetchers); + } + async function fetch2(key, routeId, href, opts) { + abortFetcher(key); + let flushSync = (opts && opts.flushSync) === true; + let routesToUse = inFlightDataRoutes || dataRoutes; + let normalizedPath = normalizeTo( + state.location, + state.matches, + basename, + href, + routeId, + opts?.relative + ); + let matches = matchRoutes(routesToUse, normalizedPath, basename); + let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath); + if (fogOfWar.active && fogOfWar.matches) { + matches = fogOfWar.matches; + } + if (!matches) { + setFetcherError( + key, + routeId, + getInternalRouterError(404, { pathname: normalizedPath }), + { flushSync } + ); + return; + } + let { path, submission, error } = normalizeNavigateOptions( + true, + normalizedPath, + opts + ); + if (error) { + setFetcherError(key, routeId, error, { flushSync }); + return; + } + let scopedContext = init.getContext ? await init.getContext() : new RouterContextProvider(); + let preventScrollReset = (opts && opts.preventScrollReset) === true; + if (submission && isMutationMethod(submission.formMethod)) { + await handleFetcherAction( + key, + routeId, + path, + matches, + scopedContext, + fogOfWar.active, + flushSync, + preventScrollReset, + submission, + opts && opts.unstable_defaultShouldRevalidate + ); + return; + } + fetchLoadMatches.set(key, { routeId, path }); + await handleFetcherLoader( + key, + routeId, + path, + matches, + scopedContext, + fogOfWar.active, + flushSync, + preventScrollReset, + submission + ); + } + async function handleFetcherAction(key, routeId, path, requestMatches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission, callSiteDefaultShouldRevalidate) { + interruptActiveLoads(); + fetchLoadMatches.delete(key); + let existingFetcher = state.fetchers.get(key); + updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), { + flushSync + }); + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest( + init.history, + path, + abortController.signal, + submission + ); + if (isFogOfWar) { + let discoverResult = await discoverRoutes( + requestMatches, + new URL(fetchRequest.url).pathname, + fetchRequest.signal, + key + ); + if (discoverResult.type === "aborted") { + return; + } else if (discoverResult.type === "error") { + setFetcherError(key, routeId, discoverResult.error, { flushSync }); + return; + } else if (!discoverResult.matches) { + setFetcherError( + key, + routeId, + getInternalRouterError(404, { pathname: path }), + { flushSync } + ); + return; + } else { + requestMatches = discoverResult.matches; + } + } + let match = getTargetMatch(requestMatches, path); + if (!match.route.action && !match.route.lazy) { + let error = getInternalRouterError(405, { + method: submission.formMethod, + pathname: path, + routeId + }); + setFetcherError(key, routeId, error, { flushSync }); + return; + } + fetchControllers.set(key, abortController); + let originatingLoadId = incrementingLoadId; + let fetchMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + fetchRequest, + requestMatches, + match, + hydrationRouteProperties2, + scopedContext + ); + let actionResults = await callDataStrategy( + fetchRequest, + fetchMatches, + scopedContext, + key + ); + let actionResult = actionResults[match.route.id]; + if (!actionResult) { + for (let match2 of fetchMatches) { + if (actionResults[match2.route.id]) { + actionResult = actionResults[match2.route.id]; + break; + } + } + } + if (fetchRequest.signal.aborted) { + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + return; + } + if (fetchersQueuedForDeletion.has(key)) { + if (isRedirectResult(actionResult) || isErrorResult(actionResult)) { + updateFetcherState(key, getDoneFetcher(void 0)); + return; + } + } else { + if (isRedirectResult(actionResult)) { + fetchControllers.delete(key); + if (pendingNavigationLoadId > originatingLoadId) { + updateFetcherState(key, getDoneFetcher(void 0)); + return; + } else { + fetchRedirectIds.add(key); + updateFetcherState(key, getLoadingFetcher(submission)); + return startRedirectNavigation(fetchRequest, actionResult, false, { + fetcherSubmission: submission, + preventScrollReset + }); + } + } + if (isErrorResult(actionResult)) { + setFetcherError(key, routeId, actionResult.error); + return; + } + } + let nextLocation = state.navigation.location || state.location; + let revalidationRequest = createClientSideRequest( + init.history, + nextLocation, + abortController.signal + ); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches; + invariant(matches, "Didn't find any matches after fetcher action"); + let loadId = ++incrementingLoadId; + fetchReloadIds.set(key, loadId); + let loadFetcher = getLoadingFetcher(submission, actionResult.data); + state.fetchers.set(key, loadFetcher); + let { dsMatches, revalidatingFetchers } = getMatchesToLoad( + revalidationRequest, + scopedContext, + mapRouteProperties2, + manifest, + init.history, + state, + matches, + submission, + nextLocation, + hydrationRouteProperties2, + false, + isRevalidationRequired, + cancelledFetcherLoads, + fetchersQueuedForDeletion, + fetchLoadMatches, + fetchRedirectIds, + routesToUse, + basename, + init.patchRoutesOnNavigation != null, + [match.route.id, actionResult], + callSiteDefaultShouldRevalidate + ); + revalidatingFetchers.filter((rf) => rf.key !== key).forEach((rf) => { + let staleKey = rf.key; + let existingFetcher2 = state.fetchers.get(staleKey); + let revalidatingFetcher = getLoadingFetcher( + void 0, + existingFetcher2 ? existingFetcher2.data : void 0 + ); + state.fetchers.set(staleKey, revalidatingFetcher); + abortFetcher(staleKey); + if (rf.controller) { + fetchControllers.set(staleKey, rf.controller); + } + }); + updateState({ fetchers: new Map(state.fetchers) }); + let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach((rf) => abortFetcher(rf.key)); + abortController.signal.addEventListener( + "abort", + abortPendingFetchRevalidations + ); + let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData( + dsMatches, + revalidatingFetchers, + revalidationRequest, + scopedContext + ); + if (abortController.signal.aborted) { + return; + } + abortController.signal.removeEventListener( + "abort", + abortPendingFetchRevalidations + ); + fetchReloadIds.delete(key); + fetchControllers.delete(key); + revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key)); + if (state.fetchers.has(key)) { + let doneFetcher = getDoneFetcher(actionResult.data); + state.fetchers.set(key, doneFetcher); + } + let redirect2 = findRedirect(loaderResults); + if (redirect2) { + return startRedirectNavigation( + revalidationRequest, + redirect2.result, + false, + { preventScrollReset } + ); + } + redirect2 = findRedirect(fetcherResults); + if (redirect2) { + fetchRedirectIds.add(redirect2.key); + return startRedirectNavigation( + revalidationRequest, + redirect2.result, + false, + { preventScrollReset } + ); + } + let { loaderData, errors } = processLoaderData( + state, + matches, + loaderResults, + void 0, + revalidatingFetchers, + fetcherResults + ); + abortStaleFetchLoads(loadId); + if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) { + invariant(pendingAction, "Expected pending action"); + pendingNavigationController && pendingNavigationController.abort(); + completeNavigation(state.navigation.location, { + matches, + loaderData, + errors, + fetchers: new Map(state.fetchers) + }); + } else { + updateState({ + errors, + loaderData: mergeLoaderData( + state.loaderData, + loaderData, + matches, + errors + ), + fetchers: new Map(state.fetchers) + }); + isRevalidationRequired = false; + } + } + async function handleFetcherLoader(key, routeId, path, matches, scopedContext, isFogOfWar, flushSync, preventScrollReset, submission) { + let existingFetcher = state.fetchers.get(key); + updateFetcherState( + key, + getLoadingFetcher( + submission, + existingFetcher ? existingFetcher.data : void 0 + ), + { flushSync } + ); + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest( + init.history, + path, + abortController.signal + ); + if (isFogOfWar) { + let discoverResult = await discoverRoutes( + matches, + new URL(fetchRequest.url).pathname, + fetchRequest.signal, + key + ); + if (discoverResult.type === "aborted") { + return; + } else if (discoverResult.type === "error") { + setFetcherError(key, routeId, discoverResult.error, { flushSync }); + return; + } else if (!discoverResult.matches) { + setFetcherError( + key, + routeId, + getInternalRouterError(404, { pathname: path }), + { flushSync } + ); + return; + } else { + matches = discoverResult.matches; + } + } + let match = getTargetMatch(matches, path); + fetchControllers.set(key, abortController); + let originatingLoadId = incrementingLoadId; + let dsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + fetchRequest, + matches, + match, + hydrationRouteProperties2, + scopedContext + ); + let results = await callDataStrategy( + fetchRequest, + dsMatches, + scopedContext, + key + ); + let result = results[match.route.id]; + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + if (fetchRequest.signal.aborted) { + return; + } + if (fetchersQueuedForDeletion.has(key)) { + updateFetcherState(key, getDoneFetcher(void 0)); + return; + } + if (isRedirectResult(result)) { + if (pendingNavigationLoadId > originatingLoadId) { + updateFetcherState(key, getDoneFetcher(void 0)); + return; + } else { + fetchRedirectIds.add(key); + await startRedirectNavigation(fetchRequest, result, false, { + preventScrollReset + }); + return; + } + } + if (isErrorResult(result)) { + setFetcherError(key, routeId, result.error); + return; + } + updateFetcherState(key, getDoneFetcher(result.data)); + } + async function startRedirectNavigation(request, redirect2, isNavigation, { + submission, + fetcherSubmission, + preventScrollReset, + replace: replace2 + } = {}) { + if (!isNavigation) { + pendingPopstateNavigationDfd?.resolve(); + pendingPopstateNavigationDfd = null; + } + if (redirect2.response.headers.has("X-Remix-Revalidate")) { + isRevalidationRequired = true; + } + let location = redirect2.response.headers.get("Location"); + invariant(location, "Expected a Location header on the redirect Response"); + location = normalizeRedirectLocation( + location, + new URL(request.url), + basename, + init.history + ); + let redirectLocation = createLocation(state.location, location, { + _isRedirect: true + }); + if (isBrowser3) { + let isDocumentReload = false; + if (redirect2.response.headers.has("X-Remix-Reload-Document")) { + isDocumentReload = true; + } else if (isAbsoluteUrl(location)) { + const url = createBrowserURLImpl(location, true); + isDocumentReload = // Hard reload if it's an absolute URL to a new origin + url.origin !== routerWindow.location.origin || // Hard reload if it's an absolute URL that does not match our basename + stripBasename(url.pathname, basename) == null; + } + if (isDocumentReload) { + if (replace2) { + routerWindow.location.replace(location); + } else { + routerWindow.location.assign(location); + } + return; + } + } + pendingNavigationController = null; + let redirectNavigationType = replace2 === true || redirect2.response.headers.has("X-Remix-Replace") ? "REPLACE" /* Replace */ : "PUSH" /* Push */; + let { formMethod, formAction, formEncType } = state.navigation; + if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) { + submission = getSubmissionFromNavigation(state.navigation); + } + let activeSubmission = submission || fetcherSubmission; + if (redirectPreserveMethodStatusCodes.has(redirect2.response.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) { + await startNavigation(redirectNavigationType, redirectLocation, { + submission: { + ...activeSubmission, + formAction: location + }, + // Preserve these flags across redirects + preventScrollReset: preventScrollReset || pendingPreventScrollReset, + enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0 + }); + } else { + let overrideNavigation = getLoadingNavigation( + redirectLocation, + submission + ); + await startNavigation(redirectNavigationType, redirectLocation, { + overrideNavigation, + // Send fetcher submissions through for shouldRevalidate + fetcherSubmission, + // Preserve these flags across redirects + preventScrollReset: preventScrollReset || pendingPreventScrollReset, + enableViewTransition: isNavigation ? pendingViewTransitionEnabled : void 0 + }); + } + } + async function callDataStrategy(request, matches, scopedContext, fetcherKey) { + let results; + let dataResults = {}; + try { + results = await callDataStrategyImpl( + dataStrategyImpl, + request, + matches, + fetcherKey, + scopedContext, + false + ); + } catch (e) { + matches.filter((m) => m.shouldLoad).forEach((m) => { + dataResults[m.route.id] = { + type: "error" /* error */, + error: e + }; + }); + return dataResults; + } + if (request.signal.aborted) { + return dataResults; + } + if (!isMutationMethod(request.method)) { + for (let match of matches) { + if (results[match.route.id]?.type === "error" /* error */) { + break; + } + if (!results.hasOwnProperty(match.route.id) && !state.loaderData.hasOwnProperty(match.route.id) && (!state.errors || !state.errors.hasOwnProperty(match.route.id)) && match.shouldCallHandler()) { + results[match.route.id] = { + type: "error" /* error */, + result: new Error( + `No result returned from dataStrategy for route ${match.route.id}` + ) + }; + } + } + } + for (let [routeId, result] of Object.entries(results)) { + if (isRedirectDataStrategyResult(result)) { + let response = result.result; + dataResults[routeId] = { + type: "redirect" /* redirect */, + response: normalizeRelativeRoutingRedirectResponse( + response, + request, + routeId, + matches, + basename + ) + }; + } else { + dataResults[routeId] = await convertDataStrategyResultToDataResult(result); + } + } + return dataResults; + } + async function callLoadersAndMaybeResolveData(matches, fetchersToLoad, request, scopedContext) { + let loaderResultsPromise = callDataStrategy( + request, + matches, + scopedContext, + null + ); + let fetcherResultsPromise = Promise.all( + fetchersToLoad.map(async (f) => { + if (f.matches && f.match && f.request && f.controller) { + let results = await callDataStrategy( + f.request, + f.matches, + scopedContext, + f.key + ); + let result = results[f.match.route.id]; + return { [f.key]: result }; + } else { + return Promise.resolve({ + [f.key]: { + type: "error" /* error */, + error: getInternalRouterError(404, { + pathname: f.path + }) + } + }); + } + }) + ); + let loaderResults = await loaderResultsPromise; + let fetcherResults = (await fetcherResultsPromise).reduce( + (acc, r) => Object.assign(acc, r), + {} + ); + return { + loaderResults, + fetcherResults + }; + } + function interruptActiveLoads() { + isRevalidationRequired = true; + fetchLoadMatches.forEach((_, key) => { + if (fetchControllers.has(key)) { + cancelledFetcherLoads.add(key); + } + abortFetcher(key); + }); + } + function updateFetcherState(key, fetcher, opts = {}) { + state.fetchers.set(key, fetcher); + updateState( + { fetchers: new Map(state.fetchers) }, + { flushSync: (opts && opts.flushSync) === true } + ); + } + function setFetcherError(key, routeId, error, opts = {}) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + deleteFetcher(key); + updateState( + { + errors: { + [boundaryMatch.route.id]: error + }, + fetchers: new Map(state.fetchers) + }, + { flushSync: (opts && opts.flushSync) === true } + ); + } + function getFetcher(key) { + activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1); + if (fetchersQueuedForDeletion.has(key)) { + fetchersQueuedForDeletion.delete(key); + } + return state.fetchers.get(key) || IDLE_FETCHER; + } + function resetFetcher(key, opts) { + abortFetcher(key, opts?.reason); + updateFetcherState(key, getDoneFetcher(null)); + } + function deleteFetcher(key) { + let fetcher = state.fetchers.get(key); + if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) { + abortFetcher(key); + } + fetchLoadMatches.delete(key); + fetchReloadIds.delete(key); + fetchRedirectIds.delete(key); + fetchersQueuedForDeletion.delete(key); + cancelledFetcherLoads.delete(key); + state.fetchers.delete(key); + } + function queueFetcherForDeletion(key) { + let count = (activeFetchers.get(key) || 0) - 1; + if (count <= 0) { + activeFetchers.delete(key); + fetchersQueuedForDeletion.add(key); + } else { + activeFetchers.set(key, count); + } + updateState({ fetchers: new Map(state.fetchers) }); + } + function abortFetcher(key, reason) { + let controller = fetchControllers.get(key); + if (controller) { + controller.abort(reason); + fetchControllers.delete(key); + } + } + function markFetchersDone(keys) { + for (let key of keys) { + let fetcher = getFetcher(key); + let doneFetcher = getDoneFetcher(fetcher.data); + state.fetchers.set(key, doneFetcher); + } + } + function markFetchRedirectsDone() { + let doneKeys = []; + let updatedFetchers = false; + for (let key of fetchRedirectIds) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, `Expected fetcher: ${key}`); + if (fetcher.state === "loading") { + fetchRedirectIds.delete(key); + doneKeys.push(key); + updatedFetchers = true; + } + } + markFetchersDone(doneKeys); + return updatedFetchers; + } + function abortStaleFetchLoads(landedId) { + let yeetedKeys = []; + for (let [key, id] of fetchReloadIds) { + if (id < landedId) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, `Expected fetcher: ${key}`); + if (fetcher.state === "loading") { + abortFetcher(key); + fetchReloadIds.delete(key); + yeetedKeys.push(key); + } + } + } + markFetchersDone(yeetedKeys); + return yeetedKeys.length > 0; + } + function getBlocker(key, fn) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + if (blockerFunctions.get(key) !== fn) { + blockerFunctions.set(key, fn); + } + return blocker; + } + function deleteBlocker(key) { + state.blockers.delete(key); + blockerFunctions.delete(key); + } + function updateBlocker(key, newBlocker) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + invariant( + blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", + `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}` + ); + let blockers = new Map(state.blockers); + blockers.set(key, newBlocker); + updateState({ blockers }); + } + function shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction + }) { + if (blockerFunctions.size === 0) { + return; + } + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); + if (blocker && blocker.state === "proceeding") { + return; + } + if (blockerFunction({ currentLocation, nextLocation, historyAction })) { + return blockerKey; + } + } + function handleNavigational404(pathname) { + let error = getInternalRouterError(404, { pathname }); + let routesToUse = inFlightDataRoutes || dataRoutes; + let { matches, route } = getShortCircuitMatches(routesToUse); + return { notFoundMatches: matches, route, error }; + } + function enableScrollRestoration(positions, getPosition, getKey) { + savedScrollPositions2 = positions; + getScrollPosition = getPosition; + getScrollRestorationKey2 = getKey || null; + if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) { + initialScrollRestored = true; + let y = getSavedScrollPosition(state.location, state.matches); + if (y != null) { + updateState({ restoreScrollPosition: y }); + } + } + return () => { + savedScrollPositions2 = null; + getScrollPosition = null; + getScrollRestorationKey2 = null; + }; + } + function getScrollKey(location, matches) { + if (getScrollRestorationKey2) { + let key = getScrollRestorationKey2( + location, + matches.map((m) => convertRouteMatchToUiMatch(m, state.loaderData)) + ); + return key || location.key; + } + return location.key; + } + function saveScrollPosition(location, matches) { + if (savedScrollPositions2 && getScrollPosition) { + let key = getScrollKey(location, matches); + savedScrollPositions2[key] = getScrollPosition(); + } + } + function getSavedScrollPosition(location, matches) { + if (savedScrollPositions2) { + let key = getScrollKey(location, matches); + let y = savedScrollPositions2[key]; + if (typeof y === "number") { + return y; + } + } + return null; + } + function checkFogOfWar(matches, routesToUse, pathname) { + if (init.patchRoutesOnNavigation) { + if (!matches) { + let fogMatches = matchRoutesImpl( + routesToUse, + pathname, + basename, + true + ); + return { active: true, matches: fogMatches || [] }; + } else { + if (Object.keys(matches[0].params).length > 0) { + let partialMatches = matchRoutesImpl( + routesToUse, + pathname, + basename, + true + ); + return { active: true, matches: partialMatches }; + } + } + } + return { active: false, matches: null }; + } + async function discoverRoutes(matches, pathname, signal, fetcherKey) { + if (!init.patchRoutesOnNavigation) { + return { type: "success", matches }; + } + let partialMatches = matches; + while (true) { + let isNonHMR = inFlightDataRoutes == null; + let routesToUse = inFlightDataRoutes || dataRoutes; + let localManifest = manifest; + try { + await init.patchRoutesOnNavigation({ + signal, + path: pathname, + matches: partialMatches, + fetcherKey, + patch: (routeId, children) => { + if (signal.aborted) return; + patchRoutesImpl( + routeId, + children, + routesToUse, + localManifest, + mapRouteProperties2, + false + ); + } + }); + } catch (e) { + return { type: "error", error: e, partialMatches }; + } finally { + if (isNonHMR && !signal.aborted) { + dataRoutes = [...dataRoutes]; + } + } + if (signal.aborted) { + return { type: "aborted" }; + } + let newMatches = matchRoutes(routesToUse, pathname, basename); + let newPartialMatches = null; + if (newMatches) { + if (Object.keys(newMatches[0].params).length === 0) { + return { type: "success", matches: newMatches }; + } else { + newPartialMatches = matchRoutesImpl( + routesToUse, + pathname, + basename, + true + ); + let matchedDeeper = newPartialMatches && partialMatches.length < newPartialMatches.length && compareMatches( + partialMatches, + newPartialMatches.slice(0, partialMatches.length) + ); + if (!matchedDeeper) { + return { type: "success", matches: newMatches }; + } + } + } + if (!newPartialMatches) { + newPartialMatches = matchRoutesImpl( + routesToUse, + pathname, + basename, + true + ); + } + if (!newPartialMatches || compareMatches(partialMatches, newPartialMatches)) { + return { type: "success", matches: null }; + } + partialMatches = newPartialMatches; + } + } + function compareMatches(a, b) { + return a.length === b.length && a.every((m, i) => m.route.id === b[i].route.id); + } + function _internalSetRoutes(newRoutes) { + manifest = {}; + inFlightDataRoutes = convertRoutesToDataRoutes( + newRoutes, + mapRouteProperties2, + void 0, + manifest + ); + } + function patchRoutes(routeId, children, unstable_allowElementMutations = false) { + let isNonHMR = inFlightDataRoutes == null; + let routesToUse = inFlightDataRoutes || dataRoutes; + patchRoutesImpl( + routeId, + children, + routesToUse, + manifest, + mapRouteProperties2, + unstable_allowElementMutations + ); + if (isNonHMR) { + dataRoutes = [...dataRoutes]; + updateState({}); + } + } + router = { + get basename() { + return basename; + }, + get future() { + return future; + }, + get state() { + return state; + }, + get routes() { + return dataRoutes; + }, + get window() { + return routerWindow; + }, + initialize, + subscribe, + enableScrollRestoration, + navigate, + fetch: fetch2, + revalidate, + // Passthrough to history-aware createHref used by useHref so we get proper + // hash-aware URLs in DOM paths + createHref: (to) => init.history.createHref(to), + encodeLocation: (to) => init.history.encodeLocation(to), + getFetcher, + resetFetcher, + deleteFetcher: queueFetcherForDeletion, + dispose, + getBlocker, + deleteBlocker, + patchRoutes, + _internalFetchControllers: fetchControllers, + // TODO: Remove setRoutes, it's temporary to avoid dealing with + // updating the tree while validating the update algorithm. + _internalSetRoutes, + _internalSetStateDoNotUseOrYouWillBreakYourApp(newState) { + updateState(newState); + } + }; + if (init.unstable_instrumentations) { + router = instrumentClientSideRouter( + router, + init.unstable_instrumentations.map((i) => i.router).filter(Boolean) + ); + } + return router; +} +function createStaticHandler(routes, opts) { + invariant( + routes.length > 0, + "You must provide a non-empty routes array to createStaticHandler" + ); + let manifest = {}; + let basename = (opts ? opts.basename : null) || "/"; + let _mapRouteProperties = opts?.mapRouteProperties || defaultMapRouteProperties; + let mapRouteProperties2 = _mapRouteProperties; + if (opts?.unstable_instrumentations) { + let instrumentations = opts.unstable_instrumentations; + mapRouteProperties2 = (route) => { + return { + ..._mapRouteProperties(route), + ...getRouteInstrumentationUpdates( + instrumentations.map((i) => i.route).filter(Boolean), + route + ) + }; + }; + } + let dataRoutes = convertRoutesToDataRoutes( + routes, + mapRouteProperties2, + void 0, + manifest + ); + async function query(request, { + requestContext, + filterMatchesToLoad, + skipLoaderErrorBubbling, + skipRevalidation, + dataStrategy, + generateMiddlewareResponse + } = {}) { + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); + requestContext = requestContext != null ? requestContext : new RouterContextProvider(); + if (!isValidMethod(method) && method !== "HEAD") { + let error = getInternalRouterError(405, { method }); + let { matches: methodNotAllowedMatches, route } = getShortCircuitMatches(dataRoutes); + let staticContext = { + basename, + location, + matches: methodNotAllowedMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {} + }; + return generateMiddlewareResponse ? generateMiddlewareResponse(() => Promise.resolve(staticContext)) : staticContext; + } else if (!matches) { + let error = getInternalRouterError(404, { pathname: location.pathname }); + let { matches: notFoundMatches, route } = getShortCircuitMatches(dataRoutes); + let staticContext = { + basename, + location, + matches: notFoundMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {} + }; + return generateMiddlewareResponse ? generateMiddlewareResponse(() => Promise.resolve(staticContext)) : staticContext; + } + if (generateMiddlewareResponse) { + invariant( + requestContext instanceof RouterContextProvider, + "When using middleware in `staticHandler.query()`, any provided `requestContext` must be an instance of `RouterContextProvider`" + ); + try { + await loadLazyMiddlewareForMatches( + matches, + manifest, + mapRouteProperties2 + ); + let renderedStaticContext; + let response = await runServerMiddlewarePipeline( + { + request, + unstable_pattern: getRoutePattern(matches), + matches, + params: matches[0].params, + // If we're calling middleware then it must be enabled so we can cast + // this to the proper type knowing it's not an `AppLoadContext` + context: requestContext + }, + async () => { + let res = await generateMiddlewareResponse( + async (revalidationRequest, opts2 = {}) => { + let result2 = await queryImpl( + revalidationRequest, + location, + matches, + requestContext, + dataStrategy || null, + skipLoaderErrorBubbling === true, + null, + "filterMatchesToLoad" in opts2 ? opts2.filterMatchesToLoad ?? null : filterMatchesToLoad ?? null, + skipRevalidation === true + ); + if (isResponse(result2)) { + return result2; + } + renderedStaticContext = { location, basename, ...result2 }; + return renderedStaticContext; + } + ); + return res; + }, + async (error, routeId) => { + if (isRedirectResponse(error)) { + return error; + } + if (isResponse(error)) { + try { + error = new ErrorResponseImpl( + error.status, + error.statusText, + await parseResponseBody(error) + ); + } catch (e) { + error = e; + } + } + if (isDataWithResponseInit(error)) { + error = dataWithResponseInitToErrorResponse(error); + } + if (renderedStaticContext) { + if (routeId in renderedStaticContext.loaderData) { + renderedStaticContext.loaderData[routeId] = void 0; + } + let staticContext = getStaticContextFromError( + dataRoutes, + renderedStaticContext, + error, + skipLoaderErrorBubbling ? routeId : findNearestBoundary(matches, routeId).route.id + ); + return generateMiddlewareResponse( + () => Promise.resolve(staticContext) + ); + } else { + let boundaryRouteId = skipLoaderErrorBubbling ? routeId : findNearestBoundary( + matches, + matches.find( + (m) => m.route.id === routeId || m.route.loader + )?.route.id || routeId + ).route.id; + let staticContext = { + matches, + location, + basename, + loaderData: {}, + actionData: null, + errors: { + [boundaryRouteId]: error + }, + statusCode: isRouteErrorResponse(error) ? error.status : 500, + actionHeaders: {}, + loaderHeaders: {} + }; + return generateMiddlewareResponse( + () => Promise.resolve(staticContext) + ); + } + } + ); + invariant(isResponse(response), "Expected a response in query()"); + return response; + } catch (e) { + if (isResponse(e)) { + return e; + } + throw e; + } + } + let result = await queryImpl( + request, + location, + matches, + requestContext, + dataStrategy || null, + skipLoaderErrorBubbling === true, + null, + filterMatchesToLoad || null, + skipRevalidation === true + ); + if (isResponse(result)) { + return result; + } + return { location, basename, ...result }; + } + async function queryRoute(request, { + routeId, + requestContext, + dataStrategy, + generateMiddlewareResponse + } = {}) { + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); + requestContext = requestContext != null ? requestContext : new RouterContextProvider(); + if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") { + throw getInternalRouterError(405, { method }); + } else if (!matches) { + throw getInternalRouterError(404, { pathname: location.pathname }); + } + let match = routeId ? matches.find((m) => m.route.id === routeId) : getTargetMatch(matches, location); + if (routeId && !match) { + throw getInternalRouterError(403, { + pathname: location.pathname, + routeId + }); + } else if (!match) { + throw getInternalRouterError(404, { pathname: location.pathname }); + } + if (generateMiddlewareResponse) { + invariant( + requestContext instanceof RouterContextProvider, + "When using middleware in `staticHandler.queryRoute()`, any provided `requestContext` must be an instance of `RouterContextProvider`" + ); + await loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties2); + let response = await runServerMiddlewarePipeline( + { + request, + unstable_pattern: getRoutePattern(matches), + matches, + params: matches[0].params, + // If we're calling middleware then it must be enabled so we can cast + // this to the proper type knowing it's not an `AppLoadContext` + context: requestContext + }, + async () => { + let res = await generateMiddlewareResponse( + async (innerRequest) => { + let result2 = await queryImpl( + innerRequest, + location, + matches, + requestContext, + dataStrategy || null, + false, + match, + null, + false + ); + let processed = handleQueryResult(result2); + return isResponse(processed) ? processed : typeof processed === "string" ? new Response(processed) : Response.json(processed); + } + ); + return res; + }, + (error) => { + if (isDataWithResponseInit(error)) { + return Promise.resolve(dataWithResponseInitToResponse(error)); + } + if (isResponse(error)) { + return Promise.resolve(error); + } + throw error; + } + ); + return response; + } + let result = await queryImpl( + request, + location, + matches, + requestContext, + dataStrategy || null, + false, + match, + null, + false + ); + return handleQueryResult(result); + function handleQueryResult(result2) { + if (isResponse(result2)) { + return result2; + } + let error = result2.errors ? Object.values(result2.errors)[0] : void 0; + if (error !== void 0) { + throw error; + } + if (result2.actionData) { + return Object.values(result2.actionData)[0]; + } + if (result2.loaderData) { + return Object.values(result2.loaderData)[0]; + } + return void 0; + } + } + async function queryImpl(request, location, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, skipRevalidation) { + invariant( + request.signal, + "query()/queryRoute() requests must contain an AbortController signal" + ); + try { + if (isMutationMethod(request.method)) { + let result2 = await submit( + request, + matches, + routeMatch || getTargetMatch(matches, location), + requestContext, + dataStrategy, + skipLoaderErrorBubbling, + routeMatch != null, + filterMatchesToLoad, + skipRevalidation + ); + return result2; + } + let result = await loadRouteData( + request, + matches, + requestContext, + dataStrategy, + skipLoaderErrorBubbling, + routeMatch, + filterMatchesToLoad + ); + return isResponse(result) ? result : { + ...result, + actionData: null, + actionHeaders: {} + }; + } catch (e) { + if (isDataStrategyResult(e) && isResponse(e.result)) { + if (e.type === "error" /* error */) { + throw e.result; + } + return e.result; + } + if (isRedirectResponse(e)) { + return e; + } + throw e; + } + } + async function submit(request, matches, actionMatch, requestContext, dataStrategy, skipLoaderErrorBubbling, isRouteRequest, filterMatchesToLoad, skipRevalidation) { + let result; + if (!actionMatch.route.action && !actionMatch.route.lazy) { + let error = getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: actionMatch.route.id + }); + if (isRouteRequest) { + throw error; + } + result = { + type: "error" /* error */, + error + }; + } else { + let dsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + request, + matches, + actionMatch, + [], + requestContext + ); + let results = await callDataStrategy( + request, + dsMatches, + isRouteRequest, + requestContext, + dataStrategy + ); + result = results[actionMatch.route.id]; + if (request.signal.aborted) { + throwStaticHandlerAbortedError(request, isRouteRequest); + } + } + if (isRedirectResult(result)) { + throw new Response(null, { + status: result.response.status, + headers: { + Location: result.response.headers.get("Location") + } + }); + } + if (isRouteRequest) { + if (isErrorResult(result)) { + throw result.error; + } + return { + matches: [actionMatch], + loaderData: {}, + actionData: { [actionMatch.route.id]: result.data }, + errors: null, + // Note: statusCode + headers are unused here since queryRoute will + // return the raw Response or value + statusCode: 200, + loaderHeaders: {}, + actionHeaders: {} + }; + } + if (skipRevalidation) { + if (isErrorResult(result)) { + let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id); + return { + statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500, + actionData: null, + actionHeaders: { + ...result.headers ? { [actionMatch.route.id]: result.headers } : {} + }, + matches, + loaderData: {}, + errors: { + [boundaryMatch.route.id]: result.error + }, + loaderHeaders: {} + }; + } else { + return { + actionData: { + [actionMatch.route.id]: result.data + }, + actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {}, + matches, + loaderData: {}, + errors: null, + statusCode: result.statusCode || 200, + loaderHeaders: {} + }; + } + } + let loaderRequest = new Request(request.url, { + headers: request.headers, + redirect: request.redirect, + signal: request.signal + }); + if (isErrorResult(result)) { + let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id); + let handlerContext2 = await loadRouteData( + loaderRequest, + matches, + requestContext, + dataStrategy, + skipLoaderErrorBubbling, + null, + filterMatchesToLoad, + [boundaryMatch.route.id, result] + ); + return { + ...handlerContext2, + statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500, + actionData: null, + actionHeaders: { + ...result.headers ? { [actionMatch.route.id]: result.headers } : {} + } + }; + } + let handlerContext = await loadRouteData( + loaderRequest, + matches, + requestContext, + dataStrategy, + skipLoaderErrorBubbling, + null, + filterMatchesToLoad + ); + return { + ...handlerContext, + actionData: { + [actionMatch.route.id]: result.data + }, + // action status codes take precedence over loader status codes + ...result.statusCode ? { statusCode: result.statusCode } : {}, + actionHeaders: result.headers ? { [actionMatch.route.id]: result.headers } : {} + }; + } + async function loadRouteData(request, matches, requestContext, dataStrategy, skipLoaderErrorBubbling, routeMatch, filterMatchesToLoad, pendingActionResult) { + let isRouteRequest = routeMatch != null; + if (isRouteRequest && !routeMatch?.route.loader && !routeMatch?.route.lazy) { + throw getInternalRouterError(400, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: routeMatch?.route.id + }); + } + let dsMatches; + if (routeMatch) { + dsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + request, + matches, + routeMatch, + [], + requestContext + ); + } else { + let maxIdx = pendingActionResult && isErrorResult(pendingActionResult[1]) ? ( + // Up to but not including the boundary + matches.findIndex((m) => m.route.id === pendingActionResult[0]) - 1 + ) : void 0; + let pattern = getRoutePattern(matches); + dsMatches = matches.map((match, index) => { + if (maxIdx != null && index > maxIdx) { + return getDataStrategyMatch( + mapRouteProperties2, + manifest, + request, + pattern, + match, + [], + requestContext, + false + ); + } + return getDataStrategyMatch( + mapRouteProperties2, + manifest, + request, + pattern, + match, + [], + requestContext, + (match.route.loader || match.route.lazy) != null && (!filterMatchesToLoad || filterMatchesToLoad(match)) + ); + }); + } + if (!dataStrategy && !dsMatches.some((m) => m.shouldLoad)) { + return { + matches, + loaderData: {}, + errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? { + [pendingActionResult[0]]: pendingActionResult[1].error + } : null, + statusCode: 200, + loaderHeaders: {} + }; + } + let results = await callDataStrategy( + request, + dsMatches, + isRouteRequest, + requestContext, + dataStrategy + ); + if (request.signal.aborted) { + throwStaticHandlerAbortedError(request, isRouteRequest); + } + let handlerContext = processRouteLoaderData( + matches, + results, + pendingActionResult, + true, + skipLoaderErrorBubbling + ); + return { + ...handlerContext, + matches + }; + } + async function callDataStrategy(request, matches, isRouteRequest, requestContext, dataStrategy) { + let results = await callDataStrategyImpl( + dataStrategy || defaultDataStrategy, + request, + matches, + null, + requestContext, + true + ); + let dataResults = {}; + await Promise.all( + matches.map(async (match) => { + if (!(match.route.id in results)) { + return; + } + let result = results[match.route.id]; + if (isRedirectDataStrategyResult(result)) { + let response = result.result; + throw normalizeRelativeRoutingRedirectResponse( + response, + request, + match.route.id, + matches, + basename + ); + } + if (isRouteRequest) { + if (isResponse(result.result)) { + throw result; + } else if (isDataWithResponseInit(result.result)) { + throw dataWithResponseInitToResponse(result.result); + } + } + dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result); + }) + ); + return dataResults; + } + return { + dataRoutes, + query, + queryRoute + }; +} +function getStaticContextFromError(routes, handlerContext, error, boundaryId) { + let errorBoundaryId = boundaryId || handlerContext._deepestRenderedBoundaryId || routes[0].id; + return { + ...handlerContext, + statusCode: isRouteErrorResponse(error) ? error.status : 500, + errors: { + [errorBoundaryId]: error + } + }; +} +function throwStaticHandlerAbortedError(request, isRouteRequest) { + if (request.signal.reason !== void 0) { + throw request.signal.reason; + } + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error( + `${method}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}` + ); +} +function isSubmissionNavigation(opts) { + return opts != null && ("formData" in opts && opts.formData != null || "body" in opts && opts.body !== void 0); +} +function normalizeTo(location, matches, basename, to, fromRouteId, relative) { + let contextualMatches; + let activeRouteMatch; + if (fromRouteId) { + contextualMatches = []; + for (let match of matches) { + contextualMatches.push(match); + if (match.route.id === fromRouteId) { + activeRouteMatch = match; + break; + } + } + } else { + contextualMatches = matches; + activeRouteMatch = matches[matches.length - 1]; + } + let path = resolveTo( + to ? to : ".", + getResolveToMatches(contextualMatches), + stripBasename(location.pathname, basename) || location.pathname, + relative === "path" + ); + if (to == null) { + path.search = location.search; + path.hash = location.hash; + } + if ((to == null || to === "" || to === ".") && activeRouteMatch) { + let nakedIndex = hasNakedIndexQuery(path.search); + if (activeRouteMatch.route.index && !nakedIndex) { + path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index"; + } else if (!activeRouteMatch.route.index && nakedIndex) { + let params = new URLSearchParams(path.search); + let indexValues = params.getAll("index"); + params.delete("index"); + indexValues.filter((v) => v).forEach((v) => params.append("index", v)); + let qs = params.toString(); + path.search = qs ? `?${qs}` : ""; + } + } + if (basename !== "/") { + path.pathname = prependBasename({ basename, pathname: path.pathname }); + } + return createPath(path); +} +function normalizeNavigateOptions(isFetcher, path, opts) { + if (!opts || !isSubmissionNavigation(opts)) { + return { path }; + } + if (opts.formMethod && !isValidMethod(opts.formMethod)) { + return { + path, + error: getInternalRouterError(405, { method: opts.formMethod }) + }; + } + let getInvalidBodyError = () => ({ + path, + error: getInternalRouterError(400, { type: "invalid-body" }) + }); + let rawFormMethod = opts.formMethod || "get"; + let formMethod = rawFormMethod.toUpperCase(); + let formAction = stripHashFromPath(path); + if (opts.body !== void 0) { + if (opts.formEncType === "text/plain") { + if (!isMutationMethod(formMethod)) { + return getInvalidBodyError(); + } + let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ? ( + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data + Array.from(opts.body.entries()).reduce( + (acc, [name, value]) => `${acc}${name}=${value} +`, + "" + ) + ) : String(opts.body); + return { + path, + submission: { + formMethod, + formAction, + formEncType: opts.formEncType, + formData: void 0, + json: void 0, + text + } + }; + } else if (opts.formEncType === "application/json") { + if (!isMutationMethod(formMethod)) { + return getInvalidBodyError(); + } + try { + let json = typeof opts.body === "string" ? JSON.parse(opts.body) : opts.body; + return { + path, + submission: { + formMethod, + formAction, + formEncType: opts.formEncType, + formData: void 0, + json, + text: void 0 + } + }; + } catch (e) { + return getInvalidBodyError(); + } + } + } + invariant( + typeof FormData === "function", + "FormData is not available in this environment" + ); + let searchParams; + let formData; + if (opts.formData) { + searchParams = convertFormDataToSearchParams(opts.formData); + formData = opts.formData; + } else if (opts.body instanceof FormData) { + searchParams = convertFormDataToSearchParams(opts.body); + formData = opts.body; + } else if (opts.body instanceof URLSearchParams) { + searchParams = opts.body; + formData = convertSearchParamsToFormData(searchParams); + } else if (opts.body == null) { + searchParams = new URLSearchParams(); + formData = new FormData(); + } else { + try { + searchParams = new URLSearchParams(opts.body); + formData = convertSearchParamsToFormData(searchParams); + } catch (e) { + return getInvalidBodyError(); + } + } + let submission = { + formMethod, + formAction, + formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded", + formData, + json: void 0, + text: void 0 + }; + if (isMutationMethod(submission.formMethod)) { + return { path, submission }; + } + let parsedPath = parsePath(path); + if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { + searchParams.append("index", ""); + } + parsedPath.search = `?${searchParams}`; + return { path: createPath(parsedPath), submission }; +} +function getMatchesToLoad(request, scopedContext, mapRouteProperties2, manifest, history, state, matches, submission, location, lazyRoutePropertiesToSkip, initialHydration, isRevalidationRequired, cancelledFetcherLoads, fetchersQueuedForDeletion, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, hasPatchRoutesOnNavigation, pendingActionResult, callSiteDefaultShouldRevalidate) { + let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : void 0; + let currentUrl = history.createURL(state.location); + let nextUrl = history.createURL(location); + let maxIdx; + if (initialHydration && state.errors) { + let boundaryId = Object.keys(state.errors)[0]; + maxIdx = matches.findIndex((m) => m.route.id === boundaryId); + } else if (pendingActionResult && isErrorResult(pendingActionResult[1])) { + let boundaryId = pendingActionResult[0]; + maxIdx = matches.findIndex((m) => m.route.id === boundaryId) - 1; + } + let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : void 0; + let shouldSkipRevalidation = actionStatus && actionStatus >= 400; + let baseShouldRevalidateArgs = { + currentUrl, + currentParams: state.matches[0]?.params || {}, + nextUrl, + nextParams: matches[0].params, + ...submission, + actionResult, + actionStatus + }; + let pattern = getRoutePattern(matches); + let dsMatches = matches.map((match, index) => { + let { route } = match; + let forceShouldLoad = null; + if (maxIdx != null && index > maxIdx) { + forceShouldLoad = false; + } else if (route.lazy) { + forceShouldLoad = true; + } else if (!routeHasLoaderOrMiddleware(route)) { + forceShouldLoad = false; + } else if (initialHydration) { + forceShouldLoad = shouldLoadRouteOnHydration( + route, + state.loaderData, + state.errors + ); + } else if (isNewLoader(state.loaderData, state.matches[index], match)) { + forceShouldLoad = true; + } + if (forceShouldLoad !== null) { + return getDataStrategyMatch( + mapRouteProperties2, + manifest, + request, + pattern, + match, + lazyRoutePropertiesToSkip, + scopedContext, + forceShouldLoad + ); + } + let defaultShouldRevalidate = false; + if (typeof callSiteDefaultShouldRevalidate === "boolean") { + defaultShouldRevalidate = callSiteDefaultShouldRevalidate; + } else if (shouldSkipRevalidation) { + defaultShouldRevalidate = false; + } else if (isRevalidationRequired) { + defaultShouldRevalidate = true; + } else if (currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search) { + defaultShouldRevalidate = true; + } else if (currentUrl.search !== nextUrl.search) { + defaultShouldRevalidate = true; + } else if (isNewRouteInstance(state.matches[index], match)) { + defaultShouldRevalidate = true; + } + let shouldRevalidateArgs = { + ...baseShouldRevalidateArgs, + defaultShouldRevalidate + }; + let shouldLoad = shouldRevalidateLoader(match, shouldRevalidateArgs); + return getDataStrategyMatch( + mapRouteProperties2, + manifest, + request, + pattern, + match, + lazyRoutePropertiesToSkip, + scopedContext, + shouldLoad, + shouldRevalidateArgs, + callSiteDefaultShouldRevalidate + ); + }); + let revalidatingFetchers = []; + fetchLoadMatches.forEach((f, key) => { + if (initialHydration || !matches.some((m) => m.route.id === f.routeId) || fetchersQueuedForDeletion.has(key)) { + return; + } + let fetcher = state.fetchers.get(key); + let isMidInitialLoad = fetcher && fetcher.state !== "idle" && fetcher.data === void 0; + let fetcherMatches = matchRoutes(routesToUse, f.path, basename); + if (!fetcherMatches) { + if (hasPatchRoutesOnNavigation && isMidInitialLoad) { + return; + } + revalidatingFetchers.push({ + key, + routeId: f.routeId, + path: f.path, + matches: null, + match: null, + request: null, + controller: null + }); + return; + } + if (fetchRedirectIds.has(key)) { + return; + } + let fetcherMatch = getTargetMatch(fetcherMatches, f.path); + let fetchController = new AbortController(); + let fetchRequest = createClientSideRequest( + history, + f.path, + fetchController.signal + ); + let fetcherDsMatches = null; + if (cancelledFetcherLoads.has(key)) { + cancelledFetcherLoads.delete(key); + fetcherDsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + fetchRequest, + fetcherMatches, + fetcherMatch, + lazyRoutePropertiesToSkip, + scopedContext + ); + } else if (isMidInitialLoad) { + if (isRevalidationRequired) { + fetcherDsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + fetchRequest, + fetcherMatches, + fetcherMatch, + lazyRoutePropertiesToSkip, + scopedContext + ); + } + } else { + let defaultShouldRevalidate; + if (typeof callSiteDefaultShouldRevalidate === "boolean") { + defaultShouldRevalidate = callSiteDefaultShouldRevalidate; + } else if (shouldSkipRevalidation) { + defaultShouldRevalidate = false; + } else { + defaultShouldRevalidate = isRevalidationRequired; + } + let shouldRevalidateArgs = { + ...baseShouldRevalidateArgs, + defaultShouldRevalidate + }; + if (shouldRevalidateLoader(fetcherMatch, shouldRevalidateArgs)) { + fetcherDsMatches = getTargetedDataStrategyMatches( + mapRouteProperties2, + manifest, + fetchRequest, + fetcherMatches, + fetcherMatch, + lazyRoutePropertiesToSkip, + scopedContext, + shouldRevalidateArgs + ); + } + } + if (fetcherDsMatches) { + revalidatingFetchers.push({ + key, + routeId: f.routeId, + path: f.path, + matches: fetcherDsMatches, + match: fetcherMatch, + request: fetchRequest, + controller: fetchController + }); + } + }); + return { dsMatches, revalidatingFetchers }; +} +function routeHasLoaderOrMiddleware(route) { + return route.loader != null || route.middleware != null && route.middleware.length > 0; +} +function shouldLoadRouteOnHydration(route, loaderData, errors) { + if (route.lazy) { + return true; + } + if (!routeHasLoaderOrMiddleware(route)) { + return false; + } + let hasData = loaderData != null && route.id in loaderData; + let hasError = errors != null && errors[route.id] !== void 0; + if (!hasData && hasError) { + return false; + } + if (typeof route.loader === "function" && route.loader.hydrate === true) { + return true; + } + return !hasData && !hasError; +} +function isNewLoader(currentLoaderData, currentMatch, match) { + let isNew = ( + // [a] -> [a, b] + !currentMatch || // [a, b] -> [a, c] + match.route.id !== currentMatch.route.id + ); + let isMissingData = !currentLoaderData.hasOwnProperty(match.route.id); + return isNew || isMissingData; +} +function isNewRouteInstance(currentMatch, match) { + let currentPath = currentMatch.route.path; + return ( + // param change for this match, /users/123 -> /users/456 + currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path + // e.g. /files/images/avatar.jpg -> files/finances.xls + currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"] + ); +} +function shouldRevalidateLoader(loaderMatch, arg) { + if (loaderMatch.route.shouldRevalidate) { + let routeChoice = loaderMatch.route.shouldRevalidate(arg); + if (typeof routeChoice === "boolean") { + return routeChoice; + } + } + return arg.defaultShouldRevalidate; +} +function patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties2, allowElementMutations) { + let childrenToPatch; + if (routeId) { + let route = manifest[routeId]; + invariant( + route, + `No route found to patch children into: routeId = ${routeId}` + ); + if (!route.children) { + route.children = []; + } + childrenToPatch = route.children; + } else { + childrenToPatch = routesToUse; + } + let uniqueChildren = []; + let existingChildren = []; + children.forEach((newRoute) => { + let existingRoute = childrenToPatch.find( + (existingRoute2) => isSameRoute(newRoute, existingRoute2) + ); + if (existingRoute) { + existingChildren.push({ existingRoute, newRoute }); + } else { + uniqueChildren.push(newRoute); + } + }); + if (uniqueChildren.length > 0) { + let newRoutes = convertRoutesToDataRoutes( + uniqueChildren, + mapRouteProperties2, + [routeId || "_", "patch", String(childrenToPatch?.length || "0")], + manifest + ); + childrenToPatch.push(...newRoutes); + } + if (allowElementMutations && existingChildren.length > 0) { + for (let i = 0; i < existingChildren.length; i++) { + let { existingRoute, newRoute } = existingChildren[i]; + let existingRouteTyped = existingRoute; + let [newRouteTyped] = convertRoutesToDataRoutes( + [newRoute], + mapRouteProperties2, + [], + // Doesn't matter for mutated routes since they already have an id + {}, + // Don't touch the manifest here since we're updating in place + true + ); + Object.assign(existingRouteTyped, { + element: newRouteTyped.element ? newRouteTyped.element : existingRouteTyped.element, + errorElement: newRouteTyped.errorElement ? newRouteTyped.errorElement : existingRouteTyped.errorElement, + hydrateFallbackElement: newRouteTyped.hydrateFallbackElement ? newRouteTyped.hydrateFallbackElement : existingRouteTyped.hydrateFallbackElement + }); + } + } +} +function isSameRoute(newRoute, existingRoute) { + if ("id" in newRoute && "id" in existingRoute && newRoute.id === existingRoute.id) { + return true; + } + if (!(newRoute.index === existingRoute.index && newRoute.path === existingRoute.path && newRoute.caseSensitive === existingRoute.caseSensitive)) { + return false; + } + if ((!newRoute.children || newRoute.children.length === 0) && (!existingRoute.children || existingRoute.children.length === 0)) { + return true; + } + return newRoute.children.every( + (aChild, i) => existingRoute.children?.some((bChild) => isSameRoute(aChild, bChild)) + ); +} +var lazyRoutePropertyCache = /* @__PURE__ */ new WeakMap(); +var loadLazyRouteProperty = ({ + key, + route, + manifest, + mapRouteProperties: mapRouteProperties2 +}) => { + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); + if (!routeToUpdate.lazy || typeof routeToUpdate.lazy !== "object") { + return; + } + let lazyFn = routeToUpdate.lazy[key]; + if (!lazyFn) { + return; + } + let cache = lazyRoutePropertyCache.get(routeToUpdate); + if (!cache) { + cache = {}; + lazyRoutePropertyCache.set(routeToUpdate, cache); + } + let cachedPromise = cache[key]; + if (cachedPromise) { + return cachedPromise; + } + let propertyPromise = (async () => { + let isUnsupported = isUnsupportedLazyRouteObjectKey(key); + let staticRouteValue = routeToUpdate[key]; + let isStaticallyDefined = staticRouteValue !== void 0 && key !== "hasErrorBoundary"; + if (isUnsupported) { + warning( + !isUnsupported, + "Route property " + key + " is not a supported lazy route property. This property will be ignored." + ); + cache[key] = Promise.resolve(); + } else if (isStaticallyDefined) { + warning( + false, + `Route "${routeToUpdate.id}" has a static property "${key}" defined. The lazy property will be ignored.` + ); + } else { + let value = await lazyFn(); + if (value != null) { + Object.assign(routeToUpdate, { [key]: value }); + Object.assign(routeToUpdate, mapRouteProperties2(routeToUpdate)); + } + } + if (typeof routeToUpdate.lazy === "object") { + routeToUpdate.lazy[key] = void 0; + if (Object.values(routeToUpdate.lazy).every((value) => value === void 0)) { + routeToUpdate.lazy = void 0; + } + } + })(); + cache[key] = propertyPromise; + return propertyPromise; +}; +var lazyRouteFunctionCache = /* @__PURE__ */ new WeakMap(); +function loadLazyRoute(route, type, manifest, mapRouteProperties2, lazyRoutePropertiesToSkip) { + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); + if (!route.lazy) { + return { + lazyRoutePromise: void 0, + lazyHandlerPromise: void 0 + }; + } + if (typeof route.lazy === "function") { + let cachedPromise = lazyRouteFunctionCache.get(routeToUpdate); + if (cachedPromise) { + return { + lazyRoutePromise: cachedPromise, + lazyHandlerPromise: cachedPromise + }; + } + let lazyRoutePromise2 = (async () => { + invariant( + typeof route.lazy === "function", + "No lazy route function found" + ); + let lazyRoute = await route.lazy(); + let routeUpdates = {}; + for (let lazyRouteProperty in lazyRoute) { + let lazyValue = lazyRoute[lazyRouteProperty]; + if (lazyValue === void 0) { + continue; + } + let isUnsupported = isUnsupportedLazyRouteFunctionKey(lazyRouteProperty); + let staticRouteValue = routeToUpdate[lazyRouteProperty]; + let isStaticallyDefined = staticRouteValue !== void 0 && // This property isn't static since it should always be updated based + // on the route updates + lazyRouteProperty !== "hasErrorBoundary"; + if (isUnsupported) { + warning( + !isUnsupported, + "Route property " + lazyRouteProperty + " is not a supported property to be returned from a lazy route function. This property will be ignored." + ); + } else if (isStaticallyDefined) { + warning( + !isStaticallyDefined, + `Route "${routeToUpdate.id}" has a static property "${lazyRouteProperty}" defined but its lazy function is also returning a value for this property. The lazy route property "${lazyRouteProperty}" will be ignored.` + ); + } else { + routeUpdates[lazyRouteProperty] = lazyValue; + } + } + Object.assign(routeToUpdate, routeUpdates); + Object.assign(routeToUpdate, { + // To keep things framework agnostic, we use the provided `mapRouteProperties` + // function to set the framework-aware properties (`element`/`hasErrorBoundary`) + // since the logic will differ between frameworks. + ...mapRouteProperties2(routeToUpdate), + lazy: void 0 + }); + })(); + lazyRouteFunctionCache.set(routeToUpdate, lazyRoutePromise2); + lazyRoutePromise2.catch(() => { + }); + return { + lazyRoutePromise: lazyRoutePromise2, + lazyHandlerPromise: lazyRoutePromise2 + }; + } + let lazyKeys = Object.keys(route.lazy); + let lazyPropertyPromises = []; + let lazyHandlerPromise = void 0; + for (let key of lazyKeys) { + if (lazyRoutePropertiesToSkip && lazyRoutePropertiesToSkip.includes(key)) { + continue; + } + let promise = loadLazyRouteProperty({ + key, + route, + manifest, + mapRouteProperties: mapRouteProperties2 + }); + if (promise) { + lazyPropertyPromises.push(promise); + if (key === type) { + lazyHandlerPromise = promise; + } + } + } + let lazyRoutePromise = lazyPropertyPromises.length > 0 ? Promise.all(lazyPropertyPromises).then(() => { + }) : void 0; + lazyRoutePromise?.catch(() => { + }); + lazyHandlerPromise?.catch(() => { + }); + return { + lazyRoutePromise, + lazyHandlerPromise + }; +} +function isNonNullable(value) { + return value !== void 0; +} +function loadLazyMiddlewareForMatches(matches, manifest, mapRouteProperties2) { + let promises = matches.map(({ route }) => { + if (typeof route.lazy !== "object" || !route.lazy.middleware) { + return void 0; + } + return loadLazyRouteProperty({ + key: "middleware", + route, + manifest, + mapRouteProperties: mapRouteProperties2 + }); + }).filter(isNonNullable); + return promises.length > 0 ? Promise.all(promises) : void 0; +} +async function defaultDataStrategy(args) { + let matchesToLoad = args.matches.filter((m) => m.shouldLoad); + let keyedResults = {}; + let results = await Promise.all(matchesToLoad.map((m) => m.resolve())); + results.forEach((result, i) => { + keyedResults[matchesToLoad[i].route.id] = result; + }); + return keyedResults; +} +async function defaultDataStrategyWithMiddleware(args) { + if (!args.matches.some((m) => m.route.middleware)) { + return defaultDataStrategy(args); + } + return runClientMiddlewarePipeline(args, () => defaultDataStrategy(args)); +} +function runServerMiddlewarePipeline(args, handler, errorHandler) { + return runMiddlewarePipeline( + args, + handler, + processResult, + isResponse, + errorHandler + ); + function processResult(result) { + return isDataWithResponseInit(result) ? dataWithResponseInitToResponse(result) : result; + } +} +function runClientMiddlewarePipeline(args, handler) { + return runMiddlewarePipeline( + args, + handler, + (r) => { + if (isRedirectResponse(r)) { + throw r; + } + return r; + }, + isDataStrategyResults, + errorHandler + ); + function errorHandler(error, routeId, nextResult) { + if (nextResult) { + return Promise.resolve( + Object.assign(nextResult.value, { + [routeId]: { type: "error", result: error } + }) + ); + } else { + let { matches } = args; + let maxBoundaryIdx = Math.min( + // Throwing route + Math.max( + matches.findIndex((m) => m.route.id === routeId), + 0 + ), + // or the shallowest route that needs to load data + Math.max( + matches.findIndex((m) => m.shouldCallHandler()), + 0 + ) + ); + let boundaryRouteId = findNearestBoundary( + matches, + matches[maxBoundaryIdx].route.id + ).route.id; + return Promise.resolve({ + [boundaryRouteId]: { type: "error", result: error } + }); + } + } +} +async function runMiddlewarePipeline(args, handler, processResult, isResult, errorHandler) { + let { matches, request, params, context, unstable_pattern } = args; + let tuples = matches.flatMap( + (m) => m.route.middleware ? m.route.middleware.map((fn) => [m.route.id, fn]) : [] + ); + let result = await callRouteMiddleware( + { + request, + params, + context, + unstable_pattern + }, + tuples, + handler, + processResult, + isResult, + errorHandler + ); + return result; +} +async function callRouteMiddleware(args, middlewares, handler, processResult, isResult, errorHandler, idx = 0) { + let { request } = args; + if (request.signal.aborted) { + throw request.signal.reason ?? new Error(`Request aborted: ${request.method} ${request.url}`); + } + let tuple = middlewares[idx]; + if (!tuple) { + let result = await handler(); + return result; + } + let [routeId, middleware] = tuple; + let nextResult; + let next = async () => { + if (nextResult) { + throw new Error("You may only call `next()` once per middleware"); + } + try { + let result = await callRouteMiddleware( + args, + middlewares, + handler, + processResult, + isResult, + errorHandler, + idx + 1 + ); + nextResult = { value: result }; + return nextResult.value; + } catch (error) { + nextResult = { value: await errorHandler(error, routeId, nextResult) }; + return nextResult.value; + } + }; + try { + let value = await middleware(args, next); + let result = value != null ? processResult(value) : void 0; + if (isResult(result)) { + return result; + } else if (nextResult) { + return result ?? nextResult.value; + } else { + nextResult = { value: await next() }; + return nextResult.value; + } + } catch (error) { + let response = await errorHandler(error, routeId, nextResult); + return response; + } +} +function getDataStrategyMatchLazyPromises(mapRouteProperties2, manifest, request, match, lazyRoutePropertiesToSkip) { + let lazyMiddlewarePromise = loadLazyRouteProperty({ + key: "middleware", + route: match.route, + manifest, + mapRouteProperties: mapRouteProperties2 + }); + let lazyRoutePromises = loadLazyRoute( + match.route, + isMutationMethod(request.method) ? "action" : "loader", + manifest, + mapRouteProperties2, + lazyRoutePropertiesToSkip + ); + return { + middleware: lazyMiddlewarePromise, + route: lazyRoutePromises.lazyRoutePromise, + handler: lazyRoutePromises.lazyHandlerPromise + }; +} +function getDataStrategyMatch(mapRouteProperties2, manifest, request, unstable_pattern, match, lazyRoutePropertiesToSkip, scopedContext, shouldLoad, shouldRevalidateArgs = null, callSiteDefaultShouldRevalidate) { + let isUsingNewApi = false; + let _lazyPromises = getDataStrategyMatchLazyPromises( + mapRouteProperties2, + manifest, + request, + match, + lazyRoutePropertiesToSkip + ); + return { + ...match, + _lazyPromises, + shouldLoad, + shouldRevalidateArgs, + shouldCallHandler(defaultShouldRevalidate) { + isUsingNewApi = true; + if (!shouldRevalidateArgs) { + return shouldLoad; + } + if (typeof callSiteDefaultShouldRevalidate === "boolean") { + return shouldRevalidateLoader(match, { + ...shouldRevalidateArgs, + defaultShouldRevalidate: callSiteDefaultShouldRevalidate + }); + } + if (typeof defaultShouldRevalidate === "boolean") { + return shouldRevalidateLoader(match, { + ...shouldRevalidateArgs, + defaultShouldRevalidate + }); + } + return shouldRevalidateLoader(match, shouldRevalidateArgs); + }, + resolve(handlerOverride) { + let { lazy, loader, middleware } = match.route; + let callHandler = isUsingNewApi || shouldLoad || handlerOverride && !isMutationMethod(request.method) && (lazy || loader); + let isMiddlewareOnlyRoute = middleware && middleware.length > 0 && !loader && !lazy; + if (callHandler && (isMutationMethod(request.method) || !isMiddlewareOnlyRoute)) { + return callLoaderOrAction({ + request, + unstable_pattern, + match, + lazyHandlerPromise: _lazyPromises?.handler, + lazyRoutePromise: _lazyPromises?.route, + handlerOverride, + scopedContext + }); + } + return Promise.resolve({ type: "data" /* data */, result: void 0 }); + } + }; +} +function getTargetedDataStrategyMatches(mapRouteProperties2, manifest, request, matches, targetMatch, lazyRoutePropertiesToSkip, scopedContext, shouldRevalidateArgs = null) { + return matches.map((match) => { + if (match.route.id !== targetMatch.route.id) { + return { + ...match, + shouldLoad: false, + shouldRevalidateArgs, + shouldCallHandler: () => false, + _lazyPromises: getDataStrategyMatchLazyPromises( + mapRouteProperties2, + manifest, + request, + match, + lazyRoutePropertiesToSkip + ), + resolve: () => Promise.resolve({ type: "data", result: void 0 }) + }; + } + return getDataStrategyMatch( + mapRouteProperties2, + manifest, + request, + getRoutePattern(matches), + match, + lazyRoutePropertiesToSkip, + scopedContext, + true, + shouldRevalidateArgs + ); + }); +} +async function callDataStrategyImpl(dataStrategyImpl, request, matches, fetcherKey, scopedContext, isStaticHandler) { + if (matches.some((m) => m._lazyPromises?.middleware)) { + await Promise.all(matches.map((m) => m._lazyPromises?.middleware)); + } + let dataStrategyArgs = { + request, + unstable_pattern: getRoutePattern(matches), + params: matches[0].params, + context: scopedContext, + matches + }; + let runClientMiddleware = isStaticHandler ? () => { + throw new Error( + "You cannot call `runClientMiddleware()` from a static handler `dataStrategy`. Middleware is run outside of `dataStrategy` during SSR in order to bubble up the Response. You can enable middleware via the `respond` API in `query`/`queryRoute`" + ); + } : (cb) => { + let typedDataStrategyArgs = dataStrategyArgs; + return runClientMiddlewarePipeline(typedDataStrategyArgs, () => { + return cb({ + ...typedDataStrategyArgs, + fetcherKey, + runClientMiddleware: () => { + throw new Error( + "Cannot call `runClientMiddleware()` from within an `runClientMiddleware` handler" + ); + } + }); + }); + }; + let results = await dataStrategyImpl({ + ...dataStrategyArgs, + fetcherKey, + runClientMiddleware + }); + try { + await Promise.all( + matches.flatMap((m) => [ + m._lazyPromises?.handler, + m._lazyPromises?.route + ]) + ); + } catch (e) { + } + return results; +} +async function callLoaderOrAction({ + request, + unstable_pattern, + match, + lazyHandlerPromise, + lazyRoutePromise, + handlerOverride, + scopedContext +}) { + let result; + let onReject; + let isAction = isMutationMethod(request.method); + let type = isAction ? "action" : "loader"; + let runHandler = (handler) => { + let reject; + let abortPromise = new Promise((_, r) => reject = r); + onReject = () => reject(); + request.signal.addEventListener("abort", onReject); + let actualHandler = (ctx) => { + if (typeof handler !== "function") { + return Promise.reject( + new Error( + `You cannot call the handler for a route which defines a boolean "${type}" [routeId: ${match.route.id}]` + ) + ); + } + return handler( + { + request, + unstable_pattern, + params: match.params, + context: scopedContext + }, + ...ctx !== void 0 ? [ctx] : [] + ); + }; + let handlerPromise = (async () => { + try { + let val = await (handlerOverride ? handlerOverride((ctx) => actualHandler(ctx)) : actualHandler()); + return { type: "data", result: val }; + } catch (e) { + return { type: "error", result: e }; + } + })(); + return Promise.race([handlerPromise, abortPromise]); + }; + try { + let handler = isAction ? match.route.action : match.route.loader; + if (lazyHandlerPromise || lazyRoutePromise) { + if (handler) { + let handlerError; + let [value] = await Promise.all([ + // If the handler throws, don't let it immediately bubble out, + // since we need to let the lazy() execution finish so we know if this + // route has a boundary that can handle the error + runHandler(handler).catch((e) => { + handlerError = e; + }), + // Ensure all lazy route promises are resolved before continuing + lazyHandlerPromise, + lazyRoutePromise + ]); + if (handlerError !== void 0) { + throw handlerError; + } + result = value; + } else { + await lazyHandlerPromise; + let handler2 = isAction ? match.route.action : match.route.loader; + if (handler2) { + [result] = await Promise.all([runHandler(handler2), lazyRoutePromise]); + } else if (type === "action") { + let url = new URL(request.url); + let pathname = url.pathname + url.search; + throw getInternalRouterError(405, { + method: request.method, + pathname, + routeId: match.route.id + }); + } else { + return { type: "data" /* data */, result: void 0 }; + } + } + } else if (!handler) { + let url = new URL(request.url); + let pathname = url.pathname + url.search; + throw getInternalRouterError(404, { + pathname + }); + } else { + result = await runHandler(handler); + } + } catch (e) { + return { type: "error" /* error */, result: e }; + } finally { + if (onReject) { + request.signal.removeEventListener("abort", onReject); + } + } + return result; +} +async function parseResponseBody(response) { + let contentType = response.headers.get("Content-Type"); + if (contentType && /\bapplication\/json\b/.test(contentType)) { + return response.body == null ? null : response.json(); + } + return response.text(); +} +async function convertDataStrategyResultToDataResult(dataStrategyResult) { + let { result, type } = dataStrategyResult; + if (isResponse(result)) { + let data2; + try { + data2 = await parseResponseBody(result); + } catch (e) { + return { type: "error" /* error */, error: e }; + } + if (type === "error" /* error */) { + return { + type: "error" /* error */, + error: new ErrorResponseImpl(result.status, result.statusText, data2), + statusCode: result.status, + headers: result.headers + }; + } + return { + type: "data" /* data */, + data: data2, + statusCode: result.status, + headers: result.headers + }; + } + if (type === "error" /* error */) { + if (isDataWithResponseInit(result)) { + if (result.data instanceof Error) { + return { + type: "error" /* error */, + error: result.data, + statusCode: result.init?.status, + headers: result.init?.headers ? new Headers(result.init.headers) : void 0 + }; + } + return { + type: "error" /* error */, + error: dataWithResponseInitToErrorResponse(result), + statusCode: isRouteErrorResponse(result) ? result.status : void 0, + headers: result.init?.headers ? new Headers(result.init.headers) : void 0 + }; + } + return { + type: "error" /* error */, + error: result, + statusCode: isRouteErrorResponse(result) ? result.status : void 0 + }; + } + if (isDataWithResponseInit(result)) { + return { + type: "data" /* data */, + data: result.data, + statusCode: result.init?.status, + headers: result.init?.headers ? new Headers(result.init.headers) : void 0 + }; + } + return { type: "data" /* data */, data: result }; +} +function normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename) { + let location = response.headers.get("Location"); + invariant( + location, + "Redirects returned/thrown from loaders/actions must have a Location header" + ); + if (!isAbsoluteUrl(location)) { + let trimmedMatches = matches.slice( + 0, + matches.findIndex((m) => m.route.id === routeId) + 1 + ); + location = normalizeTo( + new URL(request.url), + trimmedMatches, + basename, + location + ); + response.headers.set("Location", location); + } + return response; +} +function normalizeRedirectLocation(location, currentUrl, basename, historyInstance) { + let invalidProtocols = [ + "about:", + "blob:", + "chrome:", + "chrome-untrusted:", + "content:", + "data:", + "devtools:", + "file:", + "filesystem:", + // eslint-disable-next-line no-script-url + "javascript:" + ]; + if (isAbsoluteUrl(location)) { + let normalizedLocation = location; + let url = normalizedLocation.startsWith("//") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation); + if (invalidProtocols.includes(url.protocol)) { + throw new Error("Invalid redirect location"); + } + let isSameBasename = stripBasename(url.pathname, basename) != null; + if (url.origin === currentUrl.origin && isSameBasename) { + return url.pathname + url.search + url.hash; + } + } + try { + let url = historyInstance.createURL(location); + if (invalidProtocols.includes(url.protocol)) { + throw new Error("Invalid redirect location"); + } + } catch (e) { + } + return location; +} +function createClientSideRequest(history, location, signal, submission) { + let url = history.createURL(stripHashFromPath(location)).toString(); + let init = { signal }; + if (submission && isMutationMethod(submission.formMethod)) { + let { formMethod, formEncType } = submission; + init.method = formMethod.toUpperCase(); + if (formEncType === "application/json") { + init.headers = new Headers({ "Content-Type": formEncType }); + init.body = JSON.stringify(submission.json); + } else if (formEncType === "text/plain") { + init.body = submission.text; + } else if (formEncType === "application/x-www-form-urlencoded" && submission.formData) { + init.body = convertFormDataToSearchParams(submission.formData); + } else { + init.body = submission.formData; + } + } + return new Request(url, init); +} +function convertFormDataToSearchParams(formData) { + let searchParams = new URLSearchParams(); + for (let [key, value] of formData.entries()) { + searchParams.append(key, typeof value === "string" ? value : value.name); + } + return searchParams; +} +function convertSearchParamsToFormData(searchParams) { + let formData = new FormData(); + for (let [key, value] of searchParams.entries()) { + formData.append(key, value); + } + return formData; +} +function processRouteLoaderData(matches, results, pendingActionResult, isStaticHandler = false, skipLoaderErrorBubbling = false) { + let loaderData = {}; + let errors = null; + let statusCode; + let foundError = false; + let loaderHeaders = {}; + let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : void 0; + matches.forEach((match) => { + if (!(match.route.id in results)) { + return; + } + let id = match.route.id; + let result = results[id]; + invariant( + !isRedirectResult(result), + "Cannot handle redirect results in processLoaderData" + ); + if (isErrorResult(result)) { + let error = result.error; + if (pendingError !== void 0) { + error = pendingError; + pendingError = void 0; + } + errors = errors || {}; + if (skipLoaderErrorBubbling) { + errors[id] = error; + } else { + let boundaryMatch = findNearestBoundary(matches, id); + if (errors[boundaryMatch.route.id] == null) { + errors[boundaryMatch.route.id] = error; + } + } + if (!isStaticHandler) { + loaderData[id] = ResetLoaderDataSymbol; + } + if (!foundError) { + foundError = true; + statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500; + } + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } else { + loaderData[id] = result.data; + if (result.statusCode && result.statusCode !== 200 && !foundError) { + statusCode = result.statusCode; + } + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } + }); + if (pendingError !== void 0 && pendingActionResult) { + errors = { [pendingActionResult[0]]: pendingError }; + if (pendingActionResult[2]) { + loaderData[pendingActionResult[2]] = void 0; + } + } + return { + loaderData, + errors, + statusCode: statusCode || 200, + loaderHeaders + }; +} +function processLoaderData(state, matches, results, pendingActionResult, revalidatingFetchers, fetcherResults) { + let { loaderData, errors } = processRouteLoaderData( + matches, + results, + pendingActionResult + ); + revalidatingFetchers.filter((f) => !f.matches || f.matches.some((m) => m.shouldLoad)).forEach((rf) => { + let { key, match, controller } = rf; + if (controller && controller.signal.aborted) { + return; + } + let result = fetcherResults[key]; + invariant(result, "Did not find corresponding fetcher result"); + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, match?.route.id); + if (!(errors && errors[boundaryMatch.route.id])) { + errors = { + ...errors, + [boundaryMatch.route.id]: result.error + }; + } + state.fetchers.delete(key); + } else if (isRedirectResult(result)) { + invariant(false, "Unhandled fetcher revalidation redirect"); + } else { + let doneFetcher = getDoneFetcher(result.data); + state.fetchers.set(key, doneFetcher); + } + }); + return { loaderData, errors }; +} +function mergeLoaderData(loaderData, newLoaderData, matches, errors) { + let mergedLoaderData = Object.entries(newLoaderData).filter(([, v]) => v !== ResetLoaderDataSymbol).reduce((merged, [k, v]) => { + merged[k] = v; + return merged; + }, {}); + for (let match of matches) { + let id = match.route.id; + if (!newLoaderData.hasOwnProperty(id) && loaderData.hasOwnProperty(id) && match.route.loader) { + mergedLoaderData[id] = loaderData[id]; + } + if (errors && errors.hasOwnProperty(id)) { + break; + } + } + return mergedLoaderData; +} +function getActionDataForCommit(pendingActionResult) { + if (!pendingActionResult) { + return {}; + } + return isErrorResult(pendingActionResult[1]) ? { + // Clear out prior actionData on errors + actionData: {} + } : { + actionData: { + [pendingActionResult[0]]: pendingActionResult[1].data + } + }; +} +function findNearestBoundary(matches, routeId) { + let eligibleMatches = routeId ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) : [...matches]; + return eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || matches[0]; +} +function getShortCircuitMatches(routes) { + let route = routes.length === 1 ? routes[0] : routes.find((r) => r.index || !r.path || r.path === "/") || { + id: `__shim-error-route__` + }; + return { + matches: [ + { + params: {}, + pathname: "", + pathnameBase: "", + route + } + ], + route + }; +} +function getInternalRouterError(status, { + pathname, + routeId, + method, + type, + message +} = {}) { + let statusText = "Unknown Server Error"; + let errorMessage = "Unknown @remix-run/router error"; + if (status === 400) { + statusText = "Bad Request"; + if (method && pathname && routeId) { + errorMessage = `You made a ${method} request to "${pathname}" but did not provide a \`loader\` for route "${routeId}", so there is no way to handle the request.`; + } else if (type === "invalid-body") { + errorMessage = "Unable to encode submission body"; + } + } else if (status === 403) { + statusText = "Forbidden"; + errorMessage = `Route "${routeId}" does not match URL "${pathname}"`; + } else if (status === 404) { + statusText = "Not Found"; + errorMessage = `No route matches URL "${pathname}"`; + } else if (status === 405) { + statusText = "Method Not Allowed"; + if (method && pathname && routeId) { + errorMessage = `You made a ${method.toUpperCase()} request to "${pathname}" but did not provide an \`action\` for route "${routeId}", so there is no way to handle the request.`; + } else if (method) { + errorMessage = `Invalid request method "${method.toUpperCase()}"`; + } + } + return new ErrorResponseImpl( + status || 500, + statusText, + new Error(errorMessage), + true + ); +} +function findRedirect(results) { + let entries = Object.entries(results); + for (let i = entries.length - 1; i >= 0; i--) { + let [key, result] = entries[i]; + if (isRedirectResult(result)) { + return { key, result }; + } + } +} +function stripHashFromPath(path) { + let parsedPath = typeof path === "string" ? parsePath(path) : path; + return createPath({ ...parsedPath, hash: "" }); +} +function isHashChangeOnly(a, b) { + if (a.pathname !== b.pathname || a.search !== b.search) { + return false; + } + if (a.hash === "") { + return b.hash !== ""; + } else if (a.hash === b.hash) { + return true; + } else if (b.hash !== "") { + return true; + } + return false; +} +function dataWithResponseInitToResponse(data2) { + return Response.json(data2.data, data2.init ?? void 0); +} +function dataWithResponseInitToErrorResponse(data2) { + return new ErrorResponseImpl( + data2.init?.status ?? 500, + data2.init?.statusText ?? "Internal Server Error", + data2.data + ); +} +function isDataStrategyResults(result) { + return result != null && typeof result === "object" && Object.entries(result).every( + ([key, value]) => typeof key === "string" && isDataStrategyResult(value) + ); +} +function isDataStrategyResult(result) { + return result != null && typeof result === "object" && "type" in result && "result" in result && (result.type === "data" /* data */ || result.type === "error" /* error */); +} +function isRedirectDataStrategyResult(result) { + return isResponse(result.result) && redirectStatusCodes.has(result.result.status); +} +function isErrorResult(result) { + return result.type === "error" /* error */; +} +function isRedirectResult(result) { + return (result && result.type) === "redirect" /* redirect */; +} +function isDataWithResponseInit(value) { + return typeof value === "object" && value != null && "type" in value && "data" in value && "init" in value && value.type === "DataWithResponseInit"; +} +function isResponse(value) { + return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; +} +function isRedirectStatusCode(statusCode) { + return redirectStatusCodes.has(statusCode); +} +function isRedirectResponse(result) { + return isResponse(result) && isRedirectStatusCode(result.status) && result.headers.has("Location"); +} +function isValidMethod(method) { + return validRequestMethods.has(method.toUpperCase()); +} +function isMutationMethod(method) { + return validMutationMethods.has(method.toUpperCase()); +} +function hasNakedIndexQuery(search) { + return new URLSearchParams(search).getAll("index").some((v) => v === ""); +} +function getTargetMatch(matches, location) { + let search = typeof location === "string" ? parsePath(location).search : location.search; + if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) { + return matches[matches.length - 1]; + } + let pathMatches = getPathContributingMatches(matches); + return pathMatches[pathMatches.length - 1]; +} +function getSubmissionFromNavigation(navigation) { + let { formMethod, formAction, formEncType, text, formData, json } = navigation; + if (!formMethod || !formAction || !formEncType) { + return; + } + if (text != null) { + return { + formMethod, + formAction, + formEncType, + formData: void 0, + json: void 0, + text + }; + } else if (formData != null) { + return { + formMethod, + formAction, + formEncType, + formData, + json: void 0, + text: void 0 + }; + } else if (json !== void 0) { + return { + formMethod, + formAction, + formEncType, + formData: void 0, + json, + text: void 0 + }; + } +} +function getLoadingNavigation(location, submission) { + if (submission) { + let navigation = { + state: "loading", + location, + formMethod: submission.formMethod, + formAction: submission.formAction, + formEncType: submission.formEncType, + formData: submission.formData, + json: submission.json, + text: submission.text + }; + return navigation; + } else { + let navigation = { + state: "loading", + location, + formMethod: void 0, + formAction: void 0, + formEncType: void 0, + formData: void 0, + json: void 0, + text: void 0 + }; + return navigation; + } +} +function getSubmittingNavigation(location, submission) { + let navigation = { + state: "submitting", + location, + formMethod: submission.formMethod, + formAction: submission.formAction, + formEncType: submission.formEncType, + formData: submission.formData, + json: submission.json, + text: submission.text + }; + return navigation; +} +function getLoadingFetcher(submission, data2) { + if (submission) { + let fetcher = { + state: "loading", + formMethod: submission.formMethod, + formAction: submission.formAction, + formEncType: submission.formEncType, + formData: submission.formData, + json: submission.json, + text: submission.text, + data: data2 + }; + return fetcher; + } else { + let fetcher = { + state: "loading", + formMethod: void 0, + formAction: void 0, + formEncType: void 0, + formData: void 0, + json: void 0, + text: void 0, + data: data2 + }; + return fetcher; + } +} +function getSubmittingFetcher(submission, existingFetcher) { + let fetcher = { + state: "submitting", + formMethod: submission.formMethod, + formAction: submission.formAction, + formEncType: submission.formEncType, + formData: submission.formData, + json: submission.json, + text: submission.text, + data: existingFetcher ? existingFetcher.data : void 0 + }; + return fetcher; +} +function getDoneFetcher(data2) { + let fetcher = { + state: "idle", + formMethod: void 0, + formAction: void 0, + formEncType: void 0, + formData: void 0, + json: void 0, + text: void 0, + data: data2 + }; + return fetcher; +} +function restoreAppliedTransitions(_window, transitions) { + try { + let sessionPositions = _window.sessionStorage.getItem( + TRANSITIONS_STORAGE_KEY + ); + if (sessionPositions) { + let json = JSON.parse(sessionPositions); + for (let [k, v] of Object.entries(json || {})) { + if (v && Array.isArray(v)) { + transitions.set(k, new Set(v || [])); + } + } + } + } catch (e) { + } +} +function persistAppliedTransitions(_window, transitions) { + if (transitions.size > 0) { + let json = {}; + for (let [k, v] of transitions) { + json[k] = [...v]; + } + try { + _window.sessionStorage.setItem( + TRANSITIONS_STORAGE_KEY, + JSON.stringify(json) + ); + } catch (error) { + warning( + false, + `Failed to save applied view transitions in sessionStorage (${error}).` + ); + } + } +} +function createDeferred() { + let resolve; + let reject; + let promise = new Promise((res, rej) => { + resolve = async (val) => { + res(val); + try { + await promise; + } catch (e) { + } + }; + reject = async (error) => { + rej(error); + try { + await promise; + } catch (e) { + } + }; + }); + return { + promise, + //@ts-ignore + resolve, + //@ts-ignore + reject + }; +} + +// lib/context.ts +import * as React from "react"; +var DataRouterContext = React.createContext(null); +DataRouterContext.displayName = "DataRouter"; +var DataRouterStateContext = React.createContext(null); +DataRouterStateContext.displayName = "DataRouterState"; +var RSCRouterContext = React.createContext(false); +function useIsRSCRouterContext() { + return React.useContext(RSCRouterContext); +} +var ViewTransitionContext = React.createContext({ + isTransitioning: false +}); +ViewTransitionContext.displayName = "ViewTransition"; +var FetchersContext = React.createContext( + /* @__PURE__ */ new Map() +); +FetchersContext.displayName = "Fetchers"; +var AwaitContext = React.createContext(null); +AwaitContext.displayName = "Await"; +var AwaitContextProvider = (props) => React.createElement(AwaitContext.Provider, props); +var NavigationContext = React.createContext( + null +); +NavigationContext.displayName = "Navigation"; +var LocationContext = React.createContext( + null +); +LocationContext.displayName = "Location"; +var RouteContext = React.createContext({ + outlet: null, + matches: [], + isDataRoute: false +}); +RouteContext.displayName = "Route"; +var RouteErrorContext = React.createContext(null); +RouteErrorContext.displayName = "RouteError"; +var ENABLE_DEV_WARNINGS = true; + +// lib/hooks.tsx +import * as React2 from "react"; + +// lib/errors.ts +var ERROR_DIGEST_BASE = "REACT_ROUTER_ERROR"; +var ERROR_DIGEST_REDIRECT = "REDIRECT"; +var ERROR_DIGEST_ROUTE_ERROR_RESPONSE = "ROUTE_ERROR_RESPONSE"; +function decodeRedirectErrorDigest(digest) { + if (digest.startsWith(`${ERROR_DIGEST_BASE}:${ERROR_DIGEST_REDIRECT}:{`)) { + try { + let parsed = JSON.parse(digest.slice(28)); + if (typeof parsed === "object" && parsed && typeof parsed.status === "number" && typeof parsed.statusText === "string" && typeof parsed.location === "string" && typeof parsed.reloadDocument === "boolean" && typeof parsed.replace === "boolean") { + return parsed; + } + } catch { + } + } +} +function decodeRouteErrorResponseDigest(digest) { + if (digest.startsWith( + `${ERROR_DIGEST_BASE}:${ERROR_DIGEST_ROUTE_ERROR_RESPONSE}:{` + )) { + try { + let parsed = JSON.parse(digest.slice(40)); + if (typeof parsed === "object" && parsed && typeof parsed.status === "number" && typeof parsed.statusText === "string") { + return new ErrorResponseImpl( + parsed.status, + parsed.statusText, + parsed.data + ); + } + } catch { + } + } +} + +// lib/hooks.tsx +function useHref(to, { relative } = {}) { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of the + // router loaded. We can help them understand how to avoid that. + `useHref() may be used only in the context of a component.` + ); + let { basename, navigator } = React2.useContext(NavigationContext); + let { hash, pathname, search } = useResolvedPath(to, { relative }); + let joinedPathname = pathname; + if (basename !== "/") { + joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]); + } + return navigator.createHref({ pathname: joinedPathname, search, hash }); +} +function useInRouterContext() { + return React2.useContext(LocationContext) != null; +} +function useLocation() { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of the + // router loaded. We can help them understand how to avoid that. + `useLocation() may be used only in the context of a component.` + ); + return React2.useContext(LocationContext).location; +} +function useNavigationType() { + return React2.useContext(LocationContext).navigationType; +} +function useMatch(pattern) { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of the + // router loaded. We can help them understand how to avoid that. + `useMatch() may be used only in the context of a component.` + ); + let { pathname } = useLocation(); + return React2.useMemo( + () => matchPath(pattern, decodePath(pathname)), + [pathname, pattern] + ); +} +var navigateEffectWarning = `You should call navigate() in a React.useEffect(), not when your component is first rendered.`; +function useIsomorphicLayoutEffect(cb) { + let isStatic = React2.useContext(NavigationContext).static; + if (!isStatic) { + React2.useLayoutEffect(cb); + } +} +function useNavigate() { + let { isDataRoute } = React2.useContext(RouteContext); + return isDataRoute ? useNavigateStable() : useNavigateUnstable(); +} +function useNavigateUnstable() { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of the + // router loaded. We can help them understand how to avoid that. + `useNavigate() may be used only in the context of a component.` + ); + let dataRouterContext = React2.useContext(DataRouterContext); + let { basename, navigator } = React2.useContext(NavigationContext); + let { matches } = React2.useContext(RouteContext); + let { pathname: locationPathname } = useLocation(); + let routePathnamesJson = JSON.stringify(getResolveToMatches(matches)); + let activeRef = React2.useRef(false); + useIsomorphicLayoutEffect(() => { + activeRef.current = true; + }); + let navigate = React2.useCallback( + (to, options = {}) => { + warning(activeRef.current, navigateEffectWarning); + if (!activeRef.current) return; + if (typeof to === "number") { + navigator.go(to); + return; + } + let path = resolveTo( + to, + JSON.parse(routePathnamesJson), + locationPathname, + options.relative === "path" + ); + if (dataRouterContext == null && basename !== "/") { + path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]); + } + (!!options.replace ? navigator.replace : navigator.push)( + path, + options.state, + options + ); + }, + [ + basename, + navigator, + routePathnamesJson, + locationPathname, + dataRouterContext + ] + ); + return navigate; +} +var OutletContext = React2.createContext(null); +function useOutletContext() { + return React2.useContext(OutletContext); +} +function useOutlet(context) { + let outlet = React2.useContext(RouteContext).outlet; + return React2.useMemo( + () => outlet && /* @__PURE__ */ React2.createElement(OutletContext.Provider, { value: context }, outlet), + [outlet, context] + ); +} +function useParams() { + let { matches } = React2.useContext(RouteContext); + let routeMatch = matches[matches.length - 1]; + return routeMatch ? routeMatch.params : {}; +} +function useResolvedPath(to, { relative } = {}) { + let { matches } = React2.useContext(RouteContext); + let { pathname: locationPathname } = useLocation(); + let routePathnamesJson = JSON.stringify(getResolveToMatches(matches)); + return React2.useMemo( + () => resolveTo( + to, + JSON.parse(routePathnamesJson), + locationPathname, + relative === "path" + ), + [to, routePathnamesJson, locationPathname, relative] + ); +} +function useRoutes(routes, locationArg) { + return useRoutesImpl(routes, locationArg); +} +function useRoutesImpl(routes, locationArg, dataRouterState, onError, future) { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of the + // router loaded. We can help them understand how to avoid that. + `useRoutes() may be used only in the context of a component.` + ); + let { navigator } = React2.useContext(NavigationContext); + let { matches: parentMatches } = React2.useContext(RouteContext); + let routeMatch = parentMatches[parentMatches.length - 1]; + let parentParams = routeMatch ? routeMatch.params : {}; + let parentPathname = routeMatch ? routeMatch.pathname : "/"; + let parentPathnameBase = routeMatch ? routeMatch.pathnameBase : "/"; + let parentRoute = routeMatch && routeMatch.route; + if (ENABLE_DEV_WARNINGS) { + let parentPath = parentRoute && parentRoute.path || ""; + warningOnce( + parentPathname, + !parentRoute || parentPath.endsWith("*") || parentPath.endsWith("*?"), + `You rendered descendant (or called \`useRoutes()\`) at "${parentPathname}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .` + ); + } + let locationFromContext = useLocation(); + let location; + if (locationArg) { + let parsedLocationArg = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + invariant( + parentPathnameBase === "/" || parsedLocationArg.pathname?.startsWith(parentPathnameBase), + `When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${parentPathnameBase}" but pathname "${parsedLocationArg.pathname}" was given in the \`location\` prop.` + ); + location = parsedLocationArg; + } else { + location = locationFromContext; + } + let pathname = location.pathname || "/"; + let remainingPathname = pathname; + if (parentPathnameBase !== "/") { + let parentSegments = parentPathnameBase.replace(/^\//, "").split("/"); + let segments = pathname.replace(/^\//, "").split("/"); + remainingPathname = "/" + segments.slice(parentSegments.length).join("/"); + } + let matches = matchRoutes(routes, { pathname: remainingPathname }); + if (ENABLE_DEV_WARNINGS) { + warning( + parentRoute || matches != null, + `No routes matched location "${location.pathname}${location.search}${location.hash}" ` + ); + warning( + matches == null || matches[matches.length - 1].route.element !== void 0 || matches[matches.length - 1].route.Component !== void 0 || matches[matches.length - 1].route.lazy !== void 0, + `Matched leaf route at location "${location.pathname}${location.search}${location.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.` + ); + } + let renderedMatches = _renderMatches( + matches && matches.map( + (match) => Object.assign({}, match, { + params: Object.assign({}, parentParams, match.params), + pathname: joinPaths([ + parentPathnameBase, + // Re-encode pathnames that were decoded inside matchRoutes. + // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses + // `new URL()` internally and we need to prevent it from treating + // them as separators + navigator.encodeLocation ? navigator.encodeLocation( + match.pathname.replace(/\?/g, "%3F").replace(/#/g, "%23") + ).pathname : match.pathname + ]), + pathnameBase: match.pathnameBase === "/" ? parentPathnameBase : joinPaths([ + parentPathnameBase, + // Re-encode pathnames that were decoded inside matchRoutes + // Pre-encode `?` and `#` ahead of `encodeLocation` because it uses + // `new URL()` internally and we need to prevent it from treating + // them as separators + navigator.encodeLocation ? navigator.encodeLocation( + match.pathnameBase.replace(/\?/g, "%3F").replace(/#/g, "%23") + ).pathname : match.pathnameBase + ]) + }) + ), + parentMatches, + dataRouterState, + onError, + future + ); + if (locationArg && renderedMatches) { + return /* @__PURE__ */ React2.createElement( + LocationContext.Provider, + { + value: { + location: { + pathname: "/", + search: "", + hash: "", + state: null, + key: "default", + ...location + }, + navigationType: "POP" /* Pop */ + } + }, + renderedMatches + ); + } + return renderedMatches; +} +function DefaultErrorComponent() { + let error = useRouteError(); + let message = isRouteErrorResponse(error) ? `${error.status} ${error.statusText}` : error instanceof Error ? error.message : JSON.stringify(error); + let stack = error instanceof Error ? error.stack : null; + let lightgrey = "rgba(200,200,200, 0.5)"; + let preStyles = { padding: "0.5rem", backgroundColor: lightgrey }; + let codeStyles = { padding: "2px 4px", backgroundColor: lightgrey }; + let devInfo = null; + if (ENABLE_DEV_WARNINGS) { + console.error( + "Error handled by React Router default ErrorBoundary:", + error + ); + devInfo = /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("p", null, "\u{1F4BF} Hey developer \u{1F44B}"), /* @__PURE__ */ React2.createElement("p", null, "You can provide a way better UX than this when your app throws errors by providing your own ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "ErrorBoundary"), " or", " ", /* @__PURE__ */ React2.createElement("code", { style: codeStyles }, "errorElement"), " prop on your route.")); + } + return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", null, "Unexpected Application Error!"), /* @__PURE__ */ React2.createElement("h3", { style: { fontStyle: "italic" } }, message), stack ? /* @__PURE__ */ React2.createElement("pre", { style: preStyles }, stack) : null, devInfo); +} +var defaultErrorElement = /* @__PURE__ */ React2.createElement(DefaultErrorComponent, null); +var RenderErrorBoundary = class extends React2.Component { + constructor(props) { + super(props); + this.state = { + location: props.location, + revalidation: props.revalidation, + error: props.error + }; + } + static getDerivedStateFromError(error) { + return { error }; + } + static getDerivedStateFromProps(props, state) { + if (state.location !== props.location || state.revalidation !== "idle" && props.revalidation === "idle") { + return { + error: props.error, + location: props.location, + revalidation: props.revalidation + }; + } + return { + error: props.error !== void 0 ? props.error : state.error, + location: state.location, + revalidation: props.revalidation || state.revalidation + }; + } + componentDidCatch(error, errorInfo) { + if (this.props.onError) { + this.props.onError(error, errorInfo); + } else { + console.error( + "React Router caught the following error during render", + error + ); + } + } + render() { + let error = this.state.error; + if (this.context && typeof error === "object" && error && "digest" in error && typeof error.digest === "string") { + const decoded = decodeRouteErrorResponseDigest(error.digest); + if (decoded) error = decoded; + } + let result = error !== void 0 ? /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: this.props.routeContext }, /* @__PURE__ */ React2.createElement( + RouteErrorContext.Provider, + { + value: error, + children: this.props.component + } + )) : this.props.children; + if (this.context) { + return /* @__PURE__ */ React2.createElement(RSCErrorHandler, { error }, result); + } + return result; + } +}; +RenderErrorBoundary.contextType = RSCRouterContext; +var errorRedirectHandledMap = /* @__PURE__ */ new WeakMap(); +function RSCErrorHandler({ + children, + error +}) { + let { basename } = React2.useContext(NavigationContext); + if (typeof error === "object" && error && "digest" in error && typeof error.digest === "string") { + let redirect2 = decodeRedirectErrorDigest(error.digest); + if (redirect2) { + let existingRedirect = errorRedirectHandledMap.get(error); + if (existingRedirect) throw existingRedirect; + let parsed = parseToInfo(redirect2.location, basename); + if (isBrowser && !errorRedirectHandledMap.get(error)) { + if (parsed.isExternal || redirect2.reloadDocument) { + window.location.href = parsed.absoluteURL || parsed.to; + } else { + const redirectPromise = Promise.resolve().then( + () => window.__reactRouterDataRouter.navigate(parsed.to, { + replace: redirect2.replace + }) + ); + errorRedirectHandledMap.set(error, redirectPromise); + throw redirectPromise; + } + } + return /* @__PURE__ */ React2.createElement( + "meta", + { + httpEquiv: "refresh", + content: `0;url=${parsed.absoluteURL || parsed.to}` + } + ); + } + } + return children; +} +function RenderedRoute({ routeContext, match, children }) { + let dataRouterContext = React2.useContext(DataRouterContext); + if (dataRouterContext && dataRouterContext.static && dataRouterContext.staticContext && (match.route.errorElement || match.route.ErrorBoundary)) { + dataRouterContext.staticContext._deepestRenderedBoundaryId = match.route.id; + } + return /* @__PURE__ */ React2.createElement(RouteContext.Provider, { value: routeContext }, children); +} +function _renderMatches(matches, parentMatches = [], dataRouterState = null, onErrorHandler = null, future = null) { + if (matches == null) { + if (!dataRouterState) { + return null; + } + if (dataRouterState.errors) { + matches = dataRouterState.matches; + } else if (parentMatches.length === 0 && !dataRouterState.initialized && dataRouterState.matches.length > 0) { + matches = dataRouterState.matches; + } else { + return null; + } + } + let renderedMatches = matches; + let errors = dataRouterState?.errors; + if (errors != null) { + let errorIndex = renderedMatches.findIndex( + (m) => m.route.id && errors?.[m.route.id] !== void 0 + ); + invariant( + errorIndex >= 0, + `Could not find a matching route for errors on route IDs: ${Object.keys( + errors + ).join(",")}` + ); + renderedMatches = renderedMatches.slice( + 0, + Math.min(renderedMatches.length, errorIndex + 1) + ); + } + let renderFallback = false; + let fallbackIndex = -1; + if (dataRouterState) { + for (let i = 0; i < renderedMatches.length; i++) { + let match = renderedMatches[i]; + if (match.route.HydrateFallback || match.route.hydrateFallbackElement) { + fallbackIndex = i; + } + if (match.route.id) { + let { loaderData, errors: errors2 } = dataRouterState; + let needsToRunLoader = match.route.loader && !loaderData.hasOwnProperty(match.route.id) && (!errors2 || errors2[match.route.id] === void 0); + if (match.route.lazy || needsToRunLoader) { + renderFallback = true; + if (fallbackIndex >= 0) { + renderedMatches = renderedMatches.slice(0, fallbackIndex + 1); + } else { + renderedMatches = [renderedMatches[0]]; + } + break; + } + } + } + } + let onError = dataRouterState && onErrorHandler ? (error, errorInfo) => { + onErrorHandler(error, { + location: dataRouterState.location, + params: dataRouterState.matches?.[0]?.params ?? {}, + unstable_pattern: getRoutePattern(dataRouterState.matches), + errorInfo + }); + } : void 0; + return renderedMatches.reduceRight( + (outlet, match, index) => { + let error; + let shouldRenderHydrateFallback = false; + let errorElement = null; + let hydrateFallbackElement = null; + if (dataRouterState) { + error = errors && match.route.id ? errors[match.route.id] : void 0; + errorElement = match.route.errorElement || defaultErrorElement; + if (renderFallback) { + if (fallbackIndex < 0 && index === 0) { + warningOnce( + "route-fallback", + false, + "No `HydrateFallback` element provided to render during initial hydration" + ); + shouldRenderHydrateFallback = true; + hydrateFallbackElement = null; + } else if (fallbackIndex === index) { + shouldRenderHydrateFallback = true; + hydrateFallbackElement = match.route.hydrateFallbackElement || null; + } + } + } + let matches2 = parentMatches.concat(renderedMatches.slice(0, index + 1)); + let getChildren = () => { + let children; + if (error) { + children = errorElement; + } else if (shouldRenderHydrateFallback) { + children = hydrateFallbackElement; + } else if (match.route.Component) { + children = /* @__PURE__ */ React2.createElement(match.route.Component, null); + } else if (match.route.element) { + children = match.route.element; + } else { + children = outlet; + } + return /* @__PURE__ */ React2.createElement( + RenderedRoute, + { + match, + routeContext: { + outlet, + matches: matches2, + isDataRoute: dataRouterState != null + }, + children + } + ); + }; + return dataRouterState && (match.route.ErrorBoundary || match.route.errorElement || index === 0) ? /* @__PURE__ */ React2.createElement( + RenderErrorBoundary, + { + location: dataRouterState.location, + revalidation: dataRouterState.revalidation, + component: errorElement, + error, + children: getChildren(), + routeContext: { outlet: null, matches: matches2, isDataRoute: true }, + onError + } + ) : getChildren(); + }, + null + ); +} +function getDataRouterConsoleError(hookName) { + return `${hookName} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`; +} +function useDataRouterContext(hookName) { + let ctx = React2.useContext(DataRouterContext); + invariant(ctx, getDataRouterConsoleError(hookName)); + return ctx; +} +function useDataRouterState(hookName) { + let state = React2.useContext(DataRouterStateContext); + invariant(state, getDataRouterConsoleError(hookName)); + return state; +} +function useRouteContext(hookName) { + let route = React2.useContext(RouteContext); + invariant(route, getDataRouterConsoleError(hookName)); + return route; +} +function useCurrentRouteId(hookName) { + let route = useRouteContext(hookName); + let thisRoute = route.matches[route.matches.length - 1]; + invariant( + thisRoute.route.id, + `${hookName} can only be used on routes that contain a unique "id"` + ); + return thisRoute.route.id; +} +function useRouteId() { + return useCurrentRouteId("useRouteId" /* UseRouteId */); +} +function useNavigation() { + let state = useDataRouterState("useNavigation" /* UseNavigation */); + return state.navigation; +} +function useRevalidator() { + let dataRouterContext = useDataRouterContext("useRevalidator" /* UseRevalidator */); + let state = useDataRouterState("useRevalidator" /* UseRevalidator */); + let revalidate = React2.useCallback(async () => { + await dataRouterContext.router.revalidate(); + }, [dataRouterContext.router]); + return React2.useMemo( + () => ({ revalidate, state: state.revalidation }), + [revalidate, state.revalidation] + ); +} +function useMatches() { + let { matches, loaderData } = useDataRouterState( + "useMatches" /* UseMatches */ + ); + return React2.useMemo( + () => matches.map((m) => convertRouteMatchToUiMatch(m, loaderData)), + [matches, loaderData] + ); +} +function useLoaderData() { + let state = useDataRouterState("useLoaderData" /* UseLoaderData */); + let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */); + return state.loaderData[routeId]; +} +function useRouteLoaderData(routeId) { + let state = useDataRouterState("useRouteLoaderData" /* UseRouteLoaderData */); + return state.loaderData[routeId]; +} +function useActionData() { + let state = useDataRouterState("useActionData" /* UseActionData */); + let routeId = useCurrentRouteId("useLoaderData" /* UseLoaderData */); + return state.actionData ? state.actionData[routeId] : void 0; +} +function useRouteError() { + let error = React2.useContext(RouteErrorContext); + let state = useDataRouterState("useRouteError" /* UseRouteError */); + let routeId = useCurrentRouteId("useRouteError" /* UseRouteError */); + if (error !== void 0) { + return error; + } + return state.errors?.[routeId]; +} +function useAsyncValue() { + let value = React2.useContext(AwaitContext); + return value?._data; +} +function useAsyncError() { + let value = React2.useContext(AwaitContext); + return value?._error; +} +var blockerId = 0; +function useBlocker(shouldBlock) { + let { router, basename } = useDataRouterContext("useBlocker" /* UseBlocker */); + let state = useDataRouterState("useBlocker" /* UseBlocker */); + let [blockerKey, setBlockerKey] = React2.useState(""); + let blockerFunction = React2.useCallback( + (arg) => { + if (typeof shouldBlock !== "function") { + return !!shouldBlock; + } + if (basename === "/") { + return shouldBlock(arg); + } + let { currentLocation, nextLocation, historyAction } = arg; + return shouldBlock({ + currentLocation: { + ...currentLocation, + pathname: stripBasename(currentLocation.pathname, basename) || currentLocation.pathname + }, + nextLocation: { + ...nextLocation, + pathname: stripBasename(nextLocation.pathname, basename) || nextLocation.pathname + }, + historyAction + }); + }, + [basename, shouldBlock] + ); + React2.useEffect(() => { + let key = String(++blockerId); + setBlockerKey(key); + return () => router.deleteBlocker(key); + }, [router]); + React2.useEffect(() => { + if (blockerKey !== "") { + router.getBlocker(blockerKey, blockerFunction); + } + }, [router, blockerKey, blockerFunction]); + return blockerKey && state.blockers.has(blockerKey) ? state.blockers.get(blockerKey) : IDLE_BLOCKER; +} +function useNavigateStable() { + let { router } = useDataRouterContext("useNavigate" /* UseNavigateStable */); + let id = useCurrentRouteId("useNavigate" /* UseNavigateStable */); + let activeRef = React2.useRef(false); + useIsomorphicLayoutEffect(() => { + activeRef.current = true; + }); + let navigate = React2.useCallback( + async (to, options = {}) => { + warning(activeRef.current, navigateEffectWarning); + if (!activeRef.current) return; + if (typeof to === "number") { + await router.navigate(to); + } else { + await router.navigate(to, { fromRouteId: id, ...options }); + } + }, + [router, id] + ); + return navigate; +} +var alreadyWarned = {}; +function warningOnce(key, cond, message) { + if (!cond && !alreadyWarned[key]) { + alreadyWarned[key] = true; + warning(false, message); + } +} +function useRoute(...args) { + const currentRouteId = useCurrentRouteId( + "useRoute" /* UseRoute */ + ); + const id = args[0] ?? currentRouteId; + const state = useDataRouterState("useRoute" /* UseRoute */); + const route = state.matches.find(({ route: route2 }) => route2.id === id); + if (route === void 0) return void 0; + return { + handle: route.route.handle, + loaderData: state.loaderData[id], + actionData: state.actionData?.[id] + }; +} + +// lib/components.tsx +import * as React3 from "react"; + +// lib/server-runtime/warnings.ts +var alreadyWarned2 = {}; +function warnOnce(condition, message) { + if (!condition && !alreadyWarned2[message]) { + alreadyWarned2[message] = true; + console.warn(message); + } +} + +// lib/components.tsx +var USE_OPTIMISTIC = "useOptimistic"; +var useOptimisticImpl = React3[USE_OPTIMISTIC]; +var stableUseOptimisticSetter = () => void 0; +function useOptimisticSafe(val) { + if (useOptimisticImpl) { + return useOptimisticImpl(val); + } else { + return [val, stableUseOptimisticSetter]; + } +} +function mapRouteProperties(route) { + let updates = { + // Note: this check also occurs in createRoutesFromChildren so update + // there if you change this -- please and thank you! + hasErrorBoundary: route.hasErrorBoundary || route.ErrorBoundary != null || route.errorElement != null + }; + if (route.Component) { + if (ENABLE_DEV_WARNINGS) { + if (route.element) { + warning( + false, + "You should not include both `Component` and `element` on your route - `Component` will be used." + ); + } + } + Object.assign(updates, { + element: React3.createElement(route.Component), + Component: void 0 + }); + } + if (route.HydrateFallback) { + if (ENABLE_DEV_WARNINGS) { + if (route.hydrateFallbackElement) { + warning( + false, + "You should not include both `HydrateFallback` and `hydrateFallbackElement` on your route - `HydrateFallback` will be used." + ); + } + } + Object.assign(updates, { + hydrateFallbackElement: React3.createElement(route.HydrateFallback), + HydrateFallback: void 0 + }); + } + if (route.ErrorBoundary) { + if (ENABLE_DEV_WARNINGS) { + if (route.errorElement) { + warning( + false, + "You should not include both `ErrorBoundary` and `errorElement` on your route - `ErrorBoundary` will be used." + ); + } + } + Object.assign(updates, { + errorElement: React3.createElement(route.ErrorBoundary), + ErrorBoundary: void 0 + }); + } + return updates; +} +var hydrationRouteProperties = [ + "HydrateFallback", + "hydrateFallbackElement" +]; +function createMemoryRouter(routes, opts) { + return createRouter({ + basename: opts?.basename, + getContext: opts?.getContext, + future: opts?.future, + history: createMemoryHistory({ + initialEntries: opts?.initialEntries, + initialIndex: opts?.initialIndex + }), + hydrationData: opts?.hydrationData, + routes, + hydrationRouteProperties, + mapRouteProperties, + dataStrategy: opts?.dataStrategy, + patchRoutesOnNavigation: opts?.patchRoutesOnNavigation, + unstable_instrumentations: opts?.unstable_instrumentations + }).initialize(); +} +var Deferred = class { + constructor() { + this.status = "pending"; + this.promise = new Promise((resolve, reject) => { + this.resolve = (value) => { + if (this.status === "pending") { + this.status = "resolved"; + resolve(value); + } + }; + this.reject = (reason) => { + if (this.status === "pending") { + this.status = "rejected"; + reject(reason); + } + }; + }); + } +}; +function RouterProvider({ + router, + flushSync: reactDomFlushSyncImpl, + onError, + unstable_useTransitions +}) { + let unstable_rsc = useIsRSCRouterContext(); + unstable_useTransitions = unstable_rsc || unstable_useTransitions; + let [_state, setStateImpl] = React3.useState(router.state); + let [state, setOptimisticState] = useOptimisticSafe(_state); + let [pendingState, setPendingState] = React3.useState(); + let [vtContext, setVtContext] = React3.useState({ + isTransitioning: false + }); + let [renderDfd, setRenderDfd] = React3.useState(); + let [transition, setTransition] = React3.useState(); + let [interruption, setInterruption] = React3.useState(); + let fetcherData = React3.useRef(/* @__PURE__ */ new Map()); + let setState = React3.useCallback( + (newState, { deletedFetchers, newErrors, flushSync, viewTransitionOpts }) => { + if (newErrors && onError) { + Object.values(newErrors).forEach( + (error) => onError(error, { + location: newState.location, + params: newState.matches[0]?.params ?? {}, + unstable_pattern: getRoutePattern(newState.matches) + }) + ); + } + newState.fetchers.forEach((fetcher, key) => { + if (fetcher.data !== void 0) { + fetcherData.current.set(key, fetcher.data); + } + }); + deletedFetchers.forEach((key) => fetcherData.current.delete(key)); + warnOnce( + flushSync === false || reactDomFlushSyncImpl != null, + 'You provided the `flushSync` option to a router update, but you are not using the `` from `react-router/dom` so `ReactDOM.flushSync()` is unavailable. Please update your app to `import { RouterProvider } from "react-router/dom"` and ensure you have `react-dom` installed as a dependency to use the `flushSync` option.' + ); + let isViewTransitionAvailable = router.window != null && router.window.document != null && typeof router.window.document.startViewTransition === "function"; + warnOnce( + viewTransitionOpts == null || isViewTransitionAvailable, + "You provided the `viewTransition` option to a router update, but you do not appear to be running in a DOM environment as `window.startViewTransition` is not available." + ); + if (!viewTransitionOpts || !isViewTransitionAvailable) { + if (reactDomFlushSyncImpl && flushSync) { + reactDomFlushSyncImpl(() => setStateImpl(newState)); + } else if (unstable_useTransitions === false) { + setStateImpl(newState); + } else { + React3.startTransition(() => { + if (unstable_useTransitions === true) { + setOptimisticState((s) => getOptimisticRouterState(s, newState)); + } + setStateImpl(newState); + }); + } + return; + } + if (reactDomFlushSyncImpl && flushSync) { + reactDomFlushSyncImpl(() => { + if (transition) { + renderDfd?.resolve(); + transition.skipTransition(); + } + setVtContext({ + isTransitioning: true, + flushSync: true, + currentLocation: viewTransitionOpts.currentLocation, + nextLocation: viewTransitionOpts.nextLocation + }); + }); + let t = router.window.document.startViewTransition(() => { + reactDomFlushSyncImpl(() => setStateImpl(newState)); + }); + t.finished.finally(() => { + reactDomFlushSyncImpl(() => { + setRenderDfd(void 0); + setTransition(void 0); + setPendingState(void 0); + setVtContext({ isTransitioning: false }); + }); + }); + reactDomFlushSyncImpl(() => setTransition(t)); + return; + } + if (transition) { + renderDfd?.resolve(); + transition.skipTransition(); + setInterruption({ + state: newState, + currentLocation: viewTransitionOpts.currentLocation, + nextLocation: viewTransitionOpts.nextLocation + }); + } else { + setPendingState(newState); + setVtContext({ + isTransitioning: true, + flushSync: false, + currentLocation: viewTransitionOpts.currentLocation, + nextLocation: viewTransitionOpts.nextLocation + }); + } + }, + [ + router.window, + reactDomFlushSyncImpl, + transition, + renderDfd, + unstable_useTransitions, + setOptimisticState, + onError + ] + ); + React3.useLayoutEffect(() => router.subscribe(setState), [router, setState]); + React3.useEffect(() => { + if (vtContext.isTransitioning && !vtContext.flushSync) { + setRenderDfd(new Deferred()); + } + }, [vtContext]); + React3.useEffect(() => { + if (renderDfd && pendingState && router.window) { + let newState = pendingState; + let renderPromise = renderDfd.promise; + let transition2 = router.window.document.startViewTransition(async () => { + if (unstable_useTransitions === false) { + setStateImpl(newState); + } else { + React3.startTransition(() => { + if (unstable_useTransitions === true) { + setOptimisticState((s) => getOptimisticRouterState(s, newState)); + } + setStateImpl(newState); + }); + } + await renderPromise; + }); + transition2.finished.finally(() => { + setRenderDfd(void 0); + setTransition(void 0); + setPendingState(void 0); + setVtContext({ isTransitioning: false }); + }); + setTransition(transition2); + } + }, [ + pendingState, + renderDfd, + router.window, + unstable_useTransitions, + setOptimisticState + ]); + React3.useEffect(() => { + if (renderDfd && pendingState && state.location.key === pendingState.location.key) { + renderDfd.resolve(); + } + }, [renderDfd, transition, state.location, pendingState]); + React3.useEffect(() => { + if (!vtContext.isTransitioning && interruption) { + setPendingState(interruption.state); + setVtContext({ + isTransitioning: true, + flushSync: false, + currentLocation: interruption.currentLocation, + nextLocation: interruption.nextLocation + }); + setInterruption(void 0); + } + }, [vtContext.isTransitioning, interruption]); + let navigator = React3.useMemo(() => { + return { + createHref: router.createHref, + encodeLocation: router.encodeLocation, + go: (n) => router.navigate(n), + push: (to, state2, opts) => router.navigate(to, { + state: state2, + preventScrollReset: opts?.preventScrollReset + }), + replace: (to, state2, opts) => router.navigate(to, { + replace: true, + state: state2, + preventScrollReset: opts?.preventScrollReset + }) + }; + }, [router]); + let basename = router.basename || "/"; + let dataRouterContext = React3.useMemo( + () => ({ + router, + navigator, + static: false, + basename, + onError + }), + [router, navigator, basename, onError] + ); + return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DataRouterContext.Provider, { value: dataRouterContext }, /* @__PURE__ */ React3.createElement(DataRouterStateContext.Provider, { value: state }, /* @__PURE__ */ React3.createElement(FetchersContext.Provider, { value: fetcherData.current }, /* @__PURE__ */ React3.createElement(ViewTransitionContext.Provider, { value: vtContext }, /* @__PURE__ */ React3.createElement( + Router, + { + basename, + location: state.location, + navigationType: state.historyAction, + navigator, + unstable_useTransitions + }, + /* @__PURE__ */ React3.createElement( + MemoizedDataRoutes, + { + routes: router.routes, + future: router.future, + state, + onError + } + ) + ))))), null); +} +function getOptimisticRouterState(currentState, newState) { + return { + // Don't surface "current location specific" stuff mid-navigation + // (historyAction, location, matches, loaderData, errors, initialized, + // restoreScroll, preventScrollReset, blockers, etc.) + ...currentState, + // Only surface "pending/in-flight stuff" + // (navigation, revalidation, actionData, fetchers, ) + navigation: newState.navigation.state !== "idle" ? newState.navigation : currentState.navigation, + revalidation: newState.revalidation !== "idle" ? newState.revalidation : currentState.revalidation, + actionData: newState.navigation.state !== "submitting" ? newState.actionData : currentState.actionData, + fetchers: newState.fetchers + }; +} +var MemoizedDataRoutes = React3.memo(DataRoutes); +function DataRoutes({ + routes, + future, + state, + onError +}) { + return useRoutesImpl(routes, void 0, state, onError, future); +} +function MemoryRouter({ + basename, + children, + initialEntries, + initialIndex, + unstable_useTransitions +}) { + let historyRef = React3.useRef(); + if (historyRef.current == null) { + historyRef.current = createMemoryHistory({ + initialEntries, + initialIndex, + v5Compat: true + }); + } + let history = historyRef.current; + let [state, setStateImpl] = React3.useState({ + action: history.action, + location: history.location + }); + let setState = React3.useCallback( + (newState) => { + if (unstable_useTransitions === false) { + setStateImpl(newState); + } else { + React3.startTransition(() => setStateImpl(newState)); + } + }, + [unstable_useTransitions] + ); + React3.useLayoutEffect(() => history.listen(setState), [history, setState]); + return /* @__PURE__ */ React3.createElement( + Router, + { + basename, + children, + location: state.location, + navigationType: state.action, + navigator: history, + unstable_useTransitions + } + ); +} +function Navigate({ + to, + replace: replace2, + state, + relative +}) { + invariant( + useInRouterContext(), + // TODO: This error is probably because they somehow have 2 versions of + // the router loaded. We can help them understand how to avoid that. + ` may be used only in the context of a component.` + ); + let { static: isStatic } = React3.useContext(NavigationContext); + warning( + !isStatic, + ` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.` + ); + let { matches } = React3.useContext(RouteContext); + let { pathname: locationPathname } = useLocation(); + let navigate = useNavigate(); + let path = resolveTo( + to, + getResolveToMatches(matches), + locationPathname, + relative === "path" + ); + let jsonPath = JSON.stringify(path); + React3.useEffect(() => { + navigate(JSON.parse(jsonPath), { replace: replace2, state, relative }); + }, [navigate, jsonPath, relative, replace2, state]); + return null; +} +function Outlet(props) { + return useOutlet(props.context); +} +function Route(props) { + invariant( + false, + `A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .` + ); +} +function Router({ + basename: basenameProp = "/", + children = null, + location: locationProp, + navigationType = "POP" /* Pop */, + navigator, + static: staticProp = false, + unstable_useTransitions +}) { + invariant( + !useInRouterContext(), + `You cannot render a inside another . You should never have more than one in your app.` + ); + let basename = basenameProp.replace(/^\/*/, "/"); + let navigationContext = React3.useMemo( + () => ({ + basename, + navigator, + static: staticProp, + unstable_useTransitions, + future: {} + }), + [basename, navigator, staticProp, unstable_useTransitions] + ); + if (typeof locationProp === "string") { + locationProp = parsePath(locationProp); + } + let { + pathname = "/", + search = "", + hash = "", + state = null, + key = "default" + } = locationProp; + let locationContext = React3.useMemo(() => { + let trailingPathname = stripBasename(pathname, basename); + if (trailingPathname == null) { + return null; + } + return { + location: { + pathname: trailingPathname, + search, + hash, + state, + key + }, + navigationType + }; + }, [basename, pathname, search, hash, state, key, navigationType]); + warning( + locationContext != null, + ` is not able to match the URL "${pathname}${search}${hash}" because it does not start with the basename, so the won't render anything.` + ); + if (locationContext == null) { + return null; + } + return /* @__PURE__ */ React3.createElement(NavigationContext.Provider, { value: navigationContext }, /* @__PURE__ */ React3.createElement(LocationContext.Provider, { children, value: locationContext })); +} +function Routes({ + children, + location +}) { + return useRoutes(createRoutesFromChildren(children), location); +} +function Await({ + children, + errorElement, + resolve +}) { + let dataRouterContext = React3.useContext(DataRouterContext); + let dataRouterStateContext = React3.useContext(DataRouterStateContext); + let onError = React3.useCallback( + (error, errorInfo) => { + if (dataRouterContext && dataRouterContext.onError && dataRouterStateContext) { + dataRouterContext.onError(error, { + location: dataRouterStateContext.location, + params: dataRouterStateContext.matches[0]?.params || {}, + unstable_pattern: getRoutePattern(dataRouterStateContext.matches), + errorInfo + }); + } + }, + [dataRouterContext, dataRouterStateContext] + ); + return /* @__PURE__ */ React3.createElement( + AwaitErrorBoundary, + { + resolve, + errorElement, + onError + }, + /* @__PURE__ */ React3.createElement(ResolveAwait, null, children) + ); +} +var AwaitErrorBoundary = class extends React3.Component { + constructor(props) { + super(props); + this.state = { error: null }; + } + static getDerivedStateFromError(error) { + return { error }; + } + componentDidCatch(error, errorInfo) { + if (this.props.onError) { + this.props.onError(error, errorInfo); + } else { + console.error( + " caught the following error during render", + error, + errorInfo + ); + } + } + render() { + let { children, errorElement, resolve } = this.props; + let promise = null; + let status = 0 /* pending */; + if (!(resolve instanceof Promise)) { + status = 1 /* success */; + promise = Promise.resolve(); + Object.defineProperty(promise, "_tracked", { get: () => true }); + Object.defineProperty(promise, "_data", { get: () => resolve }); + } else if (this.state.error) { + status = 2 /* error */; + let renderError = this.state.error; + promise = Promise.reject().catch(() => { + }); + Object.defineProperty(promise, "_tracked", { get: () => true }); + Object.defineProperty(promise, "_error", { get: () => renderError }); + } else if (resolve._tracked) { + promise = resolve; + status = "_error" in promise ? 2 /* error */ : "_data" in promise ? 1 /* success */ : 0 /* pending */; + } else { + status = 0 /* pending */; + Object.defineProperty(resolve, "_tracked", { get: () => true }); + promise = resolve.then( + (data2) => Object.defineProperty(resolve, "_data", { get: () => data2 }), + (error) => { + this.props.onError?.(error); + Object.defineProperty(resolve, "_error", { get: () => error }); + } + ); + } + if (status === 2 /* error */ && !errorElement) { + throw promise._error; + } + if (status === 2 /* error */) { + return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children: errorElement }); + } + if (status === 1 /* success */) { + return /* @__PURE__ */ React3.createElement(AwaitContext.Provider, { value: promise, children }); + } + throw promise; + } +}; +function ResolveAwait({ + children +}) { + let data2 = useAsyncValue(); + let toRender = typeof children === "function" ? children(data2) : children; + return /* @__PURE__ */ React3.createElement(React3.Fragment, null, toRender); +} +function createRoutesFromChildren(children, parentPath = []) { + let routes = []; + React3.Children.forEach(children, (element, index) => { + if (!React3.isValidElement(element)) { + return; + } + let treePath = [...parentPath, index]; + if (element.type === React3.Fragment) { + routes.push.apply( + routes, + createRoutesFromChildren(element.props.children, treePath) + ); + return; + } + invariant( + element.type === Route, + `[${typeof element.type === "string" ? element.type : element.type.name}] is not a component. All component children of must be a or ` + ); + invariant( + !element.props.index || !element.props.children, + "An index route cannot have child routes." + ); + let route = { + id: element.props.id || treePath.join("-"), + caseSensitive: element.props.caseSensitive, + element: element.props.element, + Component: element.props.Component, + index: element.props.index, + path: element.props.path, + middleware: element.props.middleware, + loader: element.props.loader, + action: element.props.action, + hydrateFallbackElement: element.props.hydrateFallbackElement, + HydrateFallback: element.props.HydrateFallback, + errorElement: element.props.errorElement, + ErrorBoundary: element.props.ErrorBoundary, + hasErrorBoundary: element.props.hasErrorBoundary === true || element.props.ErrorBoundary != null || element.props.errorElement != null, + shouldRevalidate: element.props.shouldRevalidate, + handle: element.props.handle, + lazy: element.props.lazy + }; + if (element.props.children) { + route.children = createRoutesFromChildren( + element.props.children, + treePath + ); + } + routes.push(route); + }); + return routes; +} +var createRoutesFromElements = createRoutesFromChildren; +function renderMatches(matches) { + return _renderMatches(matches); +} +function useRouteComponentProps() { + return { + params: useParams(), + loaderData: useLoaderData(), + actionData: useActionData(), + matches: useMatches() + }; +} +function WithComponentProps({ + children +}) { + const props = useRouteComponentProps(); + return React3.cloneElement(children, props); +} +function withComponentProps(Component4) { + return function WithComponentProps2() { + const props = useRouteComponentProps(); + return React3.createElement(Component4, props); + }; +} +function useHydrateFallbackProps() { + return { + params: useParams(), + loaderData: useLoaderData(), + actionData: useActionData() + }; +} +function WithHydrateFallbackProps({ + children +}) { + const props = useHydrateFallbackProps(); + return React3.cloneElement(children, props); +} +function withHydrateFallbackProps(HydrateFallback) { + return function WithHydrateFallbackProps2() { + const props = useHydrateFallbackProps(); + return React3.createElement(HydrateFallback, props); + }; +} +function useErrorBoundaryProps() { + return { + params: useParams(), + loaderData: useLoaderData(), + actionData: useActionData(), + error: useRouteError() + }; +} +function WithErrorBoundaryProps({ + children +}) { + const props = useErrorBoundaryProps(); + return React3.cloneElement(children, props); +} +function withErrorBoundaryProps(ErrorBoundary) { + return function WithErrorBoundaryProps2() { + const props = useErrorBoundaryProps(); + return React3.createElement(ErrorBoundary, props); + }; +} + +// lib/dom/dom.ts +var defaultMethod = "get"; +var defaultEncType = "application/x-www-form-urlencoded"; +function isHtmlElement(object) { + return typeof HTMLElement !== "undefined" && object instanceof HTMLElement; +} +function isButtonElement(object) { + return isHtmlElement(object) && object.tagName.toLowerCase() === "button"; +} +function isFormElement(object) { + return isHtmlElement(object) && object.tagName.toLowerCase() === "form"; +} +function isInputElement(object) { + return isHtmlElement(object) && object.tagName.toLowerCase() === "input"; +} +function isModifiedEvent(event) { + return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); +} +function shouldProcessLinkClick(event, target) { + return event.button === 0 && // Ignore everything but left clicks + (!target || target === "_self") && // Let browser handle "target=_blank" etc. + !isModifiedEvent(event); +} +function createSearchParams(init = "") { + return new URLSearchParams( + typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo2, key) => { + let value = init[key]; + return memo2.concat( + Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]] + ); + }, []) + ); +} +function getSearchParamsForLocation(locationSearch, defaultSearchParams) { + let searchParams = createSearchParams(locationSearch); + if (defaultSearchParams) { + defaultSearchParams.forEach((_, key) => { + if (!searchParams.has(key)) { + defaultSearchParams.getAll(key).forEach((value) => { + searchParams.append(key, value); + }); + } + }); + } + return searchParams; +} +var _formDataSupportsSubmitter = null; +function isFormDataSubmitterSupported() { + if (_formDataSupportsSubmitter === null) { + try { + new FormData( + document.createElement("form"), + // @ts-expect-error if FormData supports the submitter parameter, this will throw + 0 + ); + _formDataSupportsSubmitter = false; + } catch (e) { + _formDataSupportsSubmitter = true; + } + } + return _formDataSupportsSubmitter; +} +var supportedFormEncTypes = /* @__PURE__ */ new Set([ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain" +]); +function getFormEncType(encType) { + if (encType != null && !supportedFormEncTypes.has(encType)) { + warning( + false, + `"${encType}" is not a valid \`encType\` for \`
      \`/\`\` and will default to "${defaultEncType}"` + ); + return null; + } + return encType; +} +function getFormSubmissionInfo(target, basename) { + let method; + let action; + let encType; + let formData; + let body; + if (isFormElement(target)) { + let attr = target.getAttribute("action"); + action = attr ? stripBasename(attr, basename) : null; + method = target.getAttribute("method") || defaultMethod; + encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType; + formData = new FormData(target); + } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) { + let form = target.form; + if (form == null) { + throw new Error( + `Cannot submit a

      9|?9Q0ZLZ6O3K5fK)NnOu)I?N zB6Y3XmKEJj4t^8Y>K3A>eVRRoz4jEVZYeX8NN%uyv5gS>C$6@mW38r#0R~T%6FKe_ zlck;b1Oo%g#OR=$D@+g&W50FDb|Zp_h+}n?(pe!xe>jzYwIGceqdl5xXd;U*s2l;X z788$?4i^hh%jK}2UTbwG803bCmfTI2uE!~B3G;xG@_S*v4$72V5!TT>JUEVKW`la* zO~IA|)vUo9T)>TOJx&~&Vi_WnHu7b|@fuX`dT2)|s~3IoK;!5(hs>$19yoVnC9(W* zdYWL~4yu2UOzGTTK|@{C0d$4uR^QhwLx5PAKD-(Acud|EvJO?CzN`r$_dlrT9vS25MjmTZU1gS%RQzsU%)5{an%%r|TU zD?(2C@%}7b36L(R-mKPv9$iqGTIMB~ir>|FHv%CfeVO@#_6b-HOke9H5@B)B8q$=r ze_+5C<9|1^=tCy`Odf#Z&J9uWV=vi-EEGU(3z^(Lg261z$BUkdV%?t`;6E&NE<8%&7uo3 zT*{a}F1RG`lUz7S0S6!#LL>eWC_Vai^!ky`@*lq6qU+*umFu}iw;zwGJR4n$9n@=ERo4Xku-hJ z^cy*i>sSbwkU+*vz>ry5ZCoR7SfYPGUZu;!p}vIc&NS3|ouP-_dY(B31^T#W_YWG2 zCfFG^ZAuyS-zW5);oR=oT)Gq+V%zb_`LJE(Zpl0~YgwZ@+LWrLsZ87KQd^@&d#`Dd zATUOsHw=xrINJXDC|!Gb#ER<t<*d z{h@_EhX=B%{8!W!175JYMn*t zoolar>&2mYS0uUAL%Sw#Sa!P@!~e&E15%1 z!w_n%`?AQ#w&ZaZ=AFdud49ObX|W9oZ&kR4>5i;9tr>pF>NW9cNVWxLG$V=_TW2YY z;pvc*#X56dbp({xu~E9wJ$9eLUGW^Ijuh(E`Cbjs1nos0UC$(LeadCyL#{8j$Vre3 zYuo4?M9HgHIO_M!mIgpXB{9eH<0WL2A^kslj-kOCd6 zb-RTD#(>Z-9HGDseC~k+VQ-IdVza<3$hr8+R0D^ZQ+!eKowp&ZH1GP>EJWHq4Jj%Rt5X*!dK)ilQ!!^6#F*yhU<$&3+35H+)WY*J464d<2lxkv+Eg7 zvw)N$=?Z08%}uM2h7pPOVDSMH0S2HXz4Q**q;NL}hT=T%6wHf@IgbT_{N_kz5A3=% z!99gZ4&M`7l5*d}X9-U8%(d)|$e5YotQArsir>HET`aKON-)ap31y5|Z>4$2gp>#U zS5dB5SLGk$Jvo-_6{+PFMxxwX;Uzj6w3Hj`;<3ccb`(`+(g z04p*i3HE=PPoSN<8JBLK|FH7sC=sCWmgj|b%vcC*4f-U#f<5AZ5x5|<<~Q)@az=-# z@!deY;M@L*JF=rAMNlwr!DcfU8~i2rO*HWT7<-2(+1jjYJ8hdMZQHhuleTT!wr$%w zY1__|w(T#Us=x8qJE~Eg*p1jDb|)gnyw_ZFUeO^>yvE}$J~UPs``+U2G%oFwD^><9 zI*~rcq+eiNnuElRlW#-flOxX!4^{Ylxv-<7G%jMB3|EuGs_vDW#?ma9C{|-vv-r9* zYh>Mwz7i~^VsO*TZVh#Bre36{S~kq|2i=BPq-EQN4G`4r@o(L8o0{AWt)60*r@FCz z!%eg{TJX_{Q+DPMaU_4ui!cuVCP;Nk73d4Aa3{9h?XQ;D+f0p1h@*v&hmnKdM(A+5 z*lE3UQ*{mI2k{i7QG&4`8b;Uzdb~~-A!FuOgtwNWM59>HB{GeQ_GOfill;XbOQvgP z@U|1J3z({2hj7LzTBqnQk=AT5{?kdVs@KB4q7?;Wfu-hi1dgj(g5fHPem}oToG@ds zo-M7t;TSGSyG%H|_^DGlp$s%+N+qk6O@rOEyz~fqYK2IYbJ+KT^uo(ri_64ZeeT7} z#ux>0k9+(3lI6OCXj^nkZ+$_awy*8BkOzzD$cmKaB55yoVa6Vv6JFrV_wQB;x*2S28;YbcbnKP! z>Y&yV*g}n&9XqtHY@KvsC*;fkwr6i_G40O2`Gy4;c4&&5Ep0CXBT3DKc>Rq51{Mekeuo z4%PhJU|8}y?R_nVcN&QQJ7IW%I?4L<0ZJ2xYjPVLlhR^_s@^-j7o9kVJOU4n4~G{g zPpK<)LGAVhkz*@$XL#Ud!fnsiQn%;+=JV9f_2cFAvbOf~`I`Iln$NbQ)3@vE^0IR! zce}@TW$W`{;_lCy-PTrZ!L#ST4#bZ^rUhplsag_idAvnzc}}TDgoPkOD46qujG!K{3hqun!iJ4_Yw& zC=<8Kp(+>=6L=+pfEf_+(58EP-+=ZMmj5jW&G^+<@<#aZrx@lg4Z<>uwA6M$QGvUc@5@MThTPA)CcYSD z?X^EiQV=t6!B%|m3O$?G_vh%(yO)2!w3fUd$NvV?dU$+%9+w_XWp?8IfN5>>+}~UN z@Zr9N4r~Rp1+l>Y`4x7U#$2HDinq7k7m#0~etE&yjhXn#IJ* zO}6eNcv3cUlDJ!B7XbVAlx@G4xGSK+7g$~aIHlZGt1#UCZcME}3~hXEt5;=VW+T%x zlD*Fc_s6-NPnrr(q3oliOvSy3G(A!=^Gp&2>n+-3NmWF4IXIKLID}AQn4^N+Q^us3 z<`%3M>>asl^h~A*)RKeb;wX17{qn(fd`c64mdljwrerP0>@R9JF?>+Hs~kg+#<_&3 zm8q<02hq%!kbE{j-S(Z16D{Cq0nhXWzswbXop(#dQ3G6%3-+IMsys?fq|yuf6fk-A zDDE*^%n4#qHVznMe>5Lgdr;!(MNMv1u_r_sU^O~*mAlj+f;Lm)E;ThUK5ZjTx;%0d zMd5Y&`*eCq4ROvw&`AB9IC@d3;$+m==jNvE2RCFY!GXs5c5CUWe==x{g!C=M%~$0V zH!yj*GE)jF!?alrz9vQvaIGi>tIy@u@q^75fgX$_G9zp{5OdXX+U`h2_0ECb+{KE3B`TjmA4j!&(|rSm zE>1x9G0ISy`dkWvs_NK$oAJ6M!aCl*_cR%qb5D~8!PkmmU)g~%i|mH?7OsC-J07T zhN3^tlBVYS(iDoe(`4H@=WakG6FRV?3=;zfgBz_ zdU&>UV*%lHh=|8XtAp7Be849N@8efuZK5!p!}hV4nv)#5*P%A%LvZ#%6F}(V^vgRW zuUnM2o&+6-zP=wbYPzrmGonj6Q~S4ZB_d)G>DQGfhyQq^f8fqG*k;^IA_OrMLaZH9 z*0m!!aAflrl)e8Em}|K>N5zLU6irqEDve{#?!E{ug6rWVzRVo?W{6vi7a^V+B&I1i zfo`WqQn{!UTDq*DpbMgp!W?)-v4~_ru6zI_ zQZTdzOu7muMM@WtoV34G8}M0t-$L=w=^Pu70oyW ztw~I3HDu2?pj#V5;xHiv2C;w{dq}QmhnAYG)sOlPHwFs`jy*?~58A=Ks^-Om(DGFu zc)Eg&Xr=L@*11q&v;hJg+?CI8BIh999&Pmug~YJx!rs)GeL-jZOHo-50>Q&PDaC@K z?ZY@^MW4bq!vxN;FxdiA88c(Kk+WW+X&4Yj<*TwBd>7lEjZu+=9VFsVMLlYx88$h( z3r4Nhs{-&go9z#O*b&_~oY<7tG=)|a(mYUYSrrS9q;kRjUl!jrMc!s0$%@l;k*1?)cf_4hXYZE<# zxBP;8!~T|6^?N@kqRTUwMDYZAmq}-t@r;fiYsOK z8lyn8Ge&>KrZm;xwuUNbW+@Nqk4&aGIpS2tiI{*q{pXrN2C?`|Hx1U(yMg5#9;?Z( zh$`OsAzj7KpsS4@fg&1y?i|^^H8F?}vDSk3W4SD|>Q+6dFpyWWP%4Pw>1>PvYC%CS zA~gno!G-!JI4`MQ%tIs*cl<7ta&vO-y1>~l8Gc1eu-CTU;@7tcl%FE6y<`+84>G8h zmi7r`GDddzOp`)_ouSGbvgCqBg8Gf!leRkC-apiahl}guZVk>aNPyDpb$~S15zksw zQ;(5iV$dBY)qWPpw~`jbB`J}~1-d7{*%D)Wg%T#TVslRa8nm|Fz3LLLMkW{Ezg%Qy zT@Vb19$>}lju8Qzx|)+6l%Lth65scSx-6&+RHdj6RM}Dz%Z=Vz4thWyCym%DhXQ76 z*kCWm2Gcv4t_lA>%_3ibs8Xp~oWO|0p#ZAh1YR2{?HC(}In2me5{+UK>Qst) z91;<{q<&i&F6w{1^0cz=3Tlz+r#vyuY*zdNse1$ZJ`|XmrC}GFqF=yl_y;z zROBTE*V=xK*$o~%->)8=y!a;60Zl~B!qJ*3-6-*XPsGpG_GkPY-+!>AvHy5Qrn5^TKuqlj~0PfHU@J!+$iCYRAcsblA8MDK8MLtK`3 zfkVd!PZCS;Madk0=i2$=+}sA4zMKQAB1jV?w735 zSTZLek9160q?ObPugP=K5%jbVQs?0yC?1Qvs8N-ev(FJC`8c4Z=U`60F$RphxT~Re zw~u)QN+H{s`4x~XiXsu8a3Io~ESgl``K#dBa!EE4=xiRMQg}^~vJ3?XFn7;FzTZY6 zyvT^0P^zdu65|tU29jS0^8zVih59yiCO7v+id#P)Og&~^8uP6M##=Ka#}-pjQjShY5LHmrgFrKcQL({JzY8Y#aim7{BmGWha(%&m?v9{Q zRyFSqNoTVE?xUMK(}>16tK5n+0+(77Dyq)P&YVgfEueT9v+0G8N%hp}zu89rV_Ogt zGYkFyv5ji5TW_^>>t{e4Ox?(Sx`I@X$^XIZaPa4D4KirqyIkgQKU_y1ded#<)~GfZ ztorHURC0c?HTz5n#@BWzL5y?m1sb%FLP4@4c%h*M_F z*usB*NZs$=oc3;l^Duue!@tJ>5b=w^BVF9*_SkM_{vdYXcN&j=5IgYyLhPjegV>qx z@_4-YLF~lBGS}+5#+C{_d%3aShtwUtwgTIqB#5#_Nr;%;|2S2s0CgXa9qwPxyQl5+ zNn@%QC4&e7XaJ&s7;t)T&x1W=1&;EtFEhjlw;*|#em)L#@9luIQ2bKw-t*t3Tt5It zdglJ~k&SvZ9r*LMsA{653c&mcA#&^T_;n?W5Tt4brtnLqp?sciLS1gYrvAwqS~Rnu zS?B_EKUC7k{xi%SlKl1Kzq!HBVoFq;*n7d{oT}tICHX^$)-`#GnZOo;1d?!br8E>AyMw#pdc9C!y7Zg zg9B4k-OfR#jKA|Zf#?1Xr}INU(tkSIN6?8ugU=2RU{CK1)ZKXGV9JH6p|EXR))WUD zkJ~rcQSWpW_%TcrB!sjIKWx*ZuT>bZLnf9<9g9RI3=-@UOMFr6F9z+2$hzHQS}HT6 z8n(|-0Vj9BkcqEKih4joaiu_AqZc|Ae^$Xrk^NFXt$;AK*Rq|Cr!zfBn+#s%a4%VE z2=zxKf)42zE-^#tvzu9KnjV!m11G9KBV=5TxTJT6h~^G%n5t{~?txEr@v{3B3y`Ns z4o7J?LN>B=KNq3%3;hLQaXC{kNC*&OA{$LKid%g@N=_;xi`qCHw9nN=;@nYcp7VaJ zZ#}@4w**FTq9~q->d^;TC<6w|LgKtC$Rr!IpFGT=wi>S3ReX$Kl$zokcgY@Hj07j^ z1fy8)rX&V5%;84VP8*_^gN$tjOD=R8l7h9^p?*qOSuedWq0IQ6JZ%t;5X{gIgveoy zKWenw1$;Tti#CG;rhT%3;Zz~(w~K*t)<%qysjW8I^EU=M#QmGP+1iW}8cN|y&5NF} zNkMUa5GU9A%GJdjx8Y3Gux1N&`JkK4zPD>CiMPYSeXLnBK2jnmrhK?D;2{!a$^q6G z9P>ezxeG)g^F)i0zAag;f{uX1}wV3fxyCr ztIFi1l6Y1_h`4HLx`QP~R=TGkn}Ltib(V&ZG*v?3>5~gHVb%1LfqyWAZE@ql#n@Y$ z-SZiP4&f2>9R)3hi$rpkl07EUo!0(2GE-&mUznp5jKC8ejg*u7!TKO56ht`;Mdm5R zcOl76#yI6@x8S?u&quCVRLwnX7GMAcUB*IrbimFKVSP~nuW1Lx0qqDZ^c1Df&i%St4J+im{YbueA{Z%z z{XY-pUP_V}b;0SkCdYr(aCGTbK8EznbgI?MC9K3^Z|Ue|T)I?N{YYFdqD_HPwTc;A zHk%G16u`^|;v~P{XIG{K6or&->@ijjW32wG7%She&*}A+yrC zxiw`jtTi6G)SO*~NF}_c=pn6tTQ`x3(wu`al*p@I1(z*dOWVoyp4;c>~cG(xrH8w)?dLMAFO23 zn3Q{snEJ=VwZ#{WV~j}{66+GVBAJs-Uu7`By4vBR16UnHz!6Y@i;X5aQ4-uIKk16K zqE9IzwYe+;W>-?W44P0UP{7R=y<)7Q4$TMaDo)g$FFXrtphpw+mA=0}t|O?eb;E*yVcSYEYF8sAe_WDKIy;CuRzc9Kdf{Y z?9+f~sc=5m0t=i-&BA^UvX6%h?~`bjYlnpI1@+`uISaIeW3fgA9688N_7B703nGLM_pxl~drH5qM_u_?tqM*^+(%WW9R zM%;vO0!33<)|4{U5PK0WoS@;Q4pfMV$TUfTT6vlkb5zxB$eIksl%%1kek*Pd##LY3 z-gRUoWh+{O@SF@=nI)iSGL5)_vH?`6hogV;!QM84G1-omDQDbc3Tz+o87cU}m}2(` z(h+u`U8kHppl8-Djs(Za0s~OAOHv96#mAz!PEi3WEYIYyQ(3%EUxPd&&lW@y;X;IC zw@LiZ;cs{SX}#7Fr!{vA|4u03ayL}*RXutmCm|FVR%|VTdir7-Fpy4|P=4iuMoWB5 z;~*)}AgQCXSZ15HKyn%`6&D9&Ft}yVzqF>#>rC2rB)jUygXZf{I^L@CiyCthwV8a~-+Bv5csr#|QV()ly!ffPkDEdZ{z zsJ}?o^*g&1Dq-KH4Kn6p?p1*K(GypL?=>%-hyxBWv4|397M(=#%31eqmOrt^Sd99# z&ZeZtLMB~79QG88-nWBHi#H9gHXtfkyt=y<%BEGpFhs+%S|(kxNJ%oH8c`}Y4LQ%b z2*mvd$|RPSNv+f8V||I>;HVn>F3f0)C}hznedu286v~ik>YOGBF-oCCb)U{?+upHv z6ho!WYW1E55*H~%;mXuQY&!#{y%b`tQk{{~D6O5itX%gG1IQQY!iVmNzk48BrD&5} zh+>yZ0MC>eQ)8{HuBHT|=MYz_C=;PPb_NWmXipapeUoc(eSMXHTwK0V#%8OB@y)I1 zr@<>5+ofd;21Q}c7>Y!D)5s-iDW?<33;35lYM#t zzI0&V_I~1hXS;1@#Qkf>cbgUd+wK19Gn9?)n$PDa-}1GuOZPPJr^oyLd}HQS?l>%j zpGxF=pVz}_MP#72({%62K*X{PEn*BT<5)NI%b%Rbt{HzFOTtK(S{-lh5?m7fS8qGO z_%+7Nq`sshcZz5dDIJn}R#rQB1qld5F(r>*z96VfgM~=AU4&!)Pn{?@6OHp0iGWnw z0|=u(rR7$k*^ zj&N%RiO4`ZsMO0C--+)Y2!t+KT^Oxe@K~hdBC>jp7oR(XDwYC>h-4BvY7KKiRp%q+ zoBD){2Jvi?C_CwRilRU<0>mSQXkfw>TDrJo0AT|N<#rhsAvYNStZ`i=RSo3raV(zh z4M9#_Tea%byvPy-FS&(>g2#}ZM%335+B*%*znA`6>76?1e*!V^LW1a8qF;IlAz*n% zyM631LofRUh=1lhkdZx6(5tO0rwQdbg3#6U2S|7CtP+}&9@#RE7Zfh^))e)EV8K!q z{TUId(Pd|T5;2SLYPkRH2=_nM2{1BnF#X37PE*1bn+>JsTy3(Qe>iqx9|#1HyCLZ* zuD}}R;eu2)4yYb`h2vodeZbpDVUG|SP7gT5*#70#+6$Y5$awt&hQ9a4Li&pYz~be` z`O#V=42uNr3f?#)TTN?d*$*G-lMJ_76p$h4(FLaph80s5GguJl0yGrSO$k6cYhUWC8f2B zo-p-=t48QItpC|25*$p~EdLN%8Gq@W`$bofTT%BQ5e>diO3mE6(MWXD5FGGozu!qp z4|#l#zF#`5Ve~3i%M#4G>EpWhak?V^kO+-Xg(i`O8c|5E3^QJ<<^(enQ+odU*R8p zb<7kqFdm+gHVlQ)zhP-Nv|PA6AzArdl2ZNJ!xo`=d<#!_LI^%sCs;HHc$Z`fDr|E( zlp<3*iC);_Q&c!j2_|(rA7d&$66II70*Je@ z;dzvVOxMYRg&8 zQ54Hrgu&&;V;IPnRN*m3)NccyV^;1B!yV9_VR2g?I_Z#!yqH|U@RK&rpAtKTHEV~a z={9U++Qw~JthFd5ydk^mC8-gp>SqPf(n-)&)WH+3 zkS?iRh<#3h;)=zuFcZU%X5`#spz3#76=9#N+8v@nL^7ilV8U>fs}}X0IMEO)!2?N2 z5gw--E{$+>QNaiaUYcX-730?2*9_`Dp9eT*(|;7mmh*ux??2k)X4kl39sj=MYzxqG za61|O&S8(Z@(~m!m%&Mv!&4M^i6~aT{Q)f_?kbn6vVe~c^@zIQp@{`0nvRm0raW1& z5IQ;4Skvy`7ZUb&ZlE9%Amseo$rTHjN|Oy6n$$&&dFoVh&5KX;4tSNUE@YRL8-y#RSfOl86|1JpH)5=b(R5k~Go zV{FOMb{v;xv1+CANvph?=zkZ1<~gz)kPEL7wb) zNUNXLt#Zi^3~Lj+G=(Ci?kRcIkg`R+yy%&oNx*F!*hI#|aRVg3*?al!NZK9%zq{T3 zCj?CA33gu-9aHqYNF`8aH4#jotL5Q-=Azx6XLcQ~`f~$ZD6@4<`raZVxLl^vBl{x* zPFK8cT(%vTqofxlsaV5PiR#6>w9Qu0oC*rH+4Xr6WPcx=-WA-qqr|kiqc&Doj8O`yU404Aa9lFY~M**Wu4nq3bZ)?P@jCW7lV0UhTD&LAvkvV-NQC%d`8` z%*uDVR zDMphKNKGLN=4xV-fv545jZv*gv^arL7S+N=amVapl>)4UD^P&@08>+SS(OSB)o~4N zqOuohg;2(#7u=?oYnbZY>;&yYjR&fc#GUpzg2Y~zU}-tJ*!x86-%snZ#rvq_7VEMcFX@uUTIP=KrH?q--}?5q^}- zi5C9)ZYD?+!24_oPmviGFi&SVauNTQ$Bo=?5W z4s-NJ+N?vYVcIDC-kfq&BqG5Ih8N>&N3pGPno}Wd6%k2ID5iXNNIjT&!3D+TWk(v(| zK}0=WWt8#Aw}VoG&Nkm-wV>5KW8qfyZh1es+OD0ZNI9w6Ykp^f@#P|2WlHY*P$?%> zwb%*MlS1xSHOoSE`XNDqsxIXqBH{#6(%XJ~i++U(W?E2*fpoI6OaLX=Prj2B5bo=w z846g-%gU=qffie43RQz52OP!MlcmrH<_YB~P6Gu3yn4_XWi4wE5C{*iq+3=Y57LfK?T8@J7z+1^gH$YaD%5}(H-e>V3 zPSE8v*zhb7v8FxQ)D|Nq(MX*vI-X&U)A8`#w>rO&?(Z5HzYMfy8zY^bE4_+rD|cBB zL)b5o4&d}xwkNzD?*%!+JVGHuHflK~GEYy0UdCDSyY9A|(QasCV%qN1>kcNx2h%7M(0=fL9L<^|+ zI34eo-@;BJ@T8e!#I;lz$LJPA+%<~!qm}};lx+pi7C4YbCC>Mfh~LX~f>ClDi4`IT z$u7IcJe9*imQ;*{$#;Uu)3)>?i;O!FhK^!?k}O!BPo}s7oPn+bb&-z z1jTiLq-GwQl7c}t-bNjnR?90V1>u3c;w_y-dtp1={ft;>SMY^nlHuc?ijHix+|x5?H9NW4SK%mrS? z%{Go`k>IGn;(zPw6x?ITut zk=&l$(GqAi1?(*q>k5`t*B^WflY$S`DOXS3& z4DwM%At^l_;7~H(M6~F^Tv7^kU+J>!VVRX&hkO?_KfY4gddXHq(xt$y$?*(s^6j)% zJr5nB%eDE?EL!>g^4_TN>3sb-ygIs__|)$7`2L&`d)}XEWy7<@yF-^2k;+T#?*XkG z8P1~##OKMw~F7$7E#=matT2r>G0 zKo#<)86Y97d{nMu+qJCg+?H~)k}`jwf*Z+r%s*2Y z(5pZb;7L~n5~N9aVFUU4Om-tTSpbc3y?A+UlA-JCYrF|1ZvERnNN&l(nn1X`oEQyw znNqW-+%5y%`B^C}4+$YU^AiViaZ5*TSjgz0C@;OF5K(y~Om=A@hM$VeK{{pIl!ISG zA|uw-xyJb1!G$VmI3TZ)g23Ayl(0va3>NH>AOwgQx|4pa- zkJ(E`1{TKuoWT6H-4I3aIj;Td=s(-|Op5>#XT3R3Q4W_HTho**a;7KKAjDx)r6)ST+5L@~fmDA49twsxz9d9mKz$1%(K|?D z)cvjZ-DkYv%-xCJO>`!<@3}-CqTcd+r}-4BRZSmHjt+QNywJ#0tB;pwyW9KAsq^>F zTHEW9;~6>~Yo87reXm;s?{>`Pm4P8tJV@+XKA1ssX;B_VxP;l;xBD9$fYpz8gRU>f z)t@!JB-usr>cM~{D5yL-z$PGiOMq&?pVE04e%;sWU}SxAKLr4f^PbFFK;VKU`ycPR z0&P9TeCmK0=3WvUP8lkXN{J|IA+UcU34z|+@Uug&n8S|%zywqnB(bXNwCInCUsy9L zlco0s9mb^@EO08b0brPVvbu~@ zC$$~EMk<7I=$0}8yrMZUt<&psUXfO zGnl7t`Zel92cZM`eK%ou9~y^zxna}Ft8RVbQuyH6f%D!$&(T)Nv5I?*5tD<+yr4vh zwjzFZ;+5HMvxu4z`?&ud)w|^_qn>eI`gJSZof{`t6T2|W11FVzTHy>OGNIXdp&4%B zoDIaq^SGFugs}O#CJ$05!n*43^s3Tlr4k6id#8GxiPvCHo}l$$TN)#u>knw$5oOCB z;rWKi#fG1!@u->5w(4oGRdym1In>FzjJJVe|Is^5ny(ZIK&W?!sBni*Gksn+X?e$E z>gBy2`n)$K^qxJ1iCo@hKmTnL?l0}?9*OfLsYV~7^Wi-HHiV^^Mp4rJ9#LeRZs68Q z>|+9>X#zEKfyK(ntKNJI3w8TE8$r$Z^7+e~J(eFIyG{BDAL0y=inQjQp#j4XRBb55 z4-gQYAjmqI#&+=SP%5iCdD1w{W`b}Hho(3GE)E#}@W#PlnRW-oqMGw&jq(fxEc>AZ`;zT(IsN1;i{$rW)wv8X4R@fiZM<&??h% z9Z6&7_5+B9a&dJG2i7pRd=I0ybzWL)t|qk9jP>4j6Ka!CavwU{(l*$e1van8Qy1xw z{|$vczePa`*D~!v67Y=n>+z6IR@-tzqbAdJGrkFiOvDo%Q34NqX1RPN;t9?ZA)EAf z3Y#2gBgVDx^}aJ^s2eGf64r=GjfqkSO&T57-rfW1sG%2XWE4&e?YyUU=-h9NGvyq> zWURkwT@L$UM?3{(9@4Q8TeK3nMr<1QAW7G7PD74*!Y-}64s&mV9J7c1iE^W&v}^mB zXgG~g8<6uDUa#gBF&yoP)NM6eW-NNiu-uLz`P&u@i;nnLejAs10dR-1Tl@NngGuaY z9E((rc3*zF!)FRSN|wo&fD<_zof~K~Sr>B?QA>%Yvb&fE>McV|AJiQ8zGWsPade%b zIN?ID(zqPrt+56s-rHBM!O-Ww0*K*Mpgry8l?u2S+0DmNdo5m(_$8JpjSS}VM2wd5 zKpC;j=K_Yotk2=YmC`PK)XH!f(aq;#M6j)0ko1%=KO~vi>f@WNh-%ld@5R>};$u-c ze8Y&O<@T%U_S!WHI%b5C!TA`pe{GKsC6c^0LK(|06}2jp!NJ2>^#fX+P|oj)x~&o8 zKA=&^Wn%Y;YoNt61y9+vj7f=lfyo^-h3cAkMvO|qrcwbZQ6cmFiV0A9Q|&eHd%BK z7eLMECq~5a8nZwVkEiP92S8c`RbGC-;`He;Q!zkEakTL%v)Z982>($m+J46T!Qu`2 zKi-l50;U>#5I7U^lB#qV6746@KZ>P^Kc-rX9lk;0AMeP?-vGtt&|`kwOyGBdf4a7w z24rwrw&7fiVwlBlkY2xnbEQlG=`@FQKid~j;{9(-UpN1<4lROy1TCW956zH zL?lFi>iqISslv5ZgY(1q;G$pB-=>f*6ttwha*&N7f`r)DgK5aD+nC2l$JrO4?SBM| z?2ll9{ztIT1sqPNSHI9zEBlE4H^K71W@DI{+5bbZXi5E8M*j>}F53B52A&ZhfW#X% zpJxAYjIv68`lltZR(O6KBd^2+a(jt2*#Hc6bq(6k`xkcjgvxYA>u=IDy*HQX9wdM) zoo-EUEyRFEq{Q!^SPT=~`nYUMruL96gV3Py2QaYingCHZLOU z)>k`Wj3MLhAiID}>4s~iDM0V!qgThLWpih>Q@&G)MgfwD8et0nIY1Ml_wkn{oN(F< z3IJOTZY`kv5bH+Fe6!`kG(a2|))B`7SXCtNA={IKlj|2|dUUN^q(yU~z@r73%O`iU z;Z^lk8kSckcB_J86Si9Yd1*C=#h=dilU$Zu=gJUuzLwSF0Geu^kRo53tqR<^SiIZc ze@jcUw-hp5xRq%#5=m;-nMV((neU;ZP^d@4)j-@t9nlecYZW`u_y>ohEv^x-1*6W@ zTOs^DOW?I3_g>@4YUi#x^}URs6oEnk)Q9Z~^l-^0aPp_A^9?){9K9qEqEZ-C!(-M<>Bmm5 zevi-N9suU6*c&a*hXdU)S4VDAlM@>Y!N3%c6f~yMk9(4P=r??hS-Rqf`N4q=OGmI(Wzt5VWqNw5t#;G;nDR z)>u;joz}!Et;F{x-HCi_J=}AiwsRmTV6eCp#F34r+-8ftl45cmME8jd;WtT%wo2Oj zv`@Vx#mJru6A-rnhI2xQ7-;-Om?)f)#C#_$=#IB%t@19R#Z@uBqhnP;FosJqeu@^1 z&_54rlyxO;%`bdZ5bd*Amg`4|fd-RXl9QSIY4Rlk-H$G06@kHa4!dZmYmC-6v06XqcY4znzt zwcp)vBqkNr7A>%A(Rn9E%?qin<$aarECT4`c?)XNmRP;EvWwT;FY+u}eT=lXOol4k zYQEiNWKeK}T4B`!y4yvfS8$_zW~~9?hyr>Y>SV8Z!;RHA*b{!9wmf?~Y-`h2jeC7E zc_s~+I27KM*xbm!x%5LFAaO0YF{-f^2OKzTW7m!Gy|R%R^)V$%ZEyaXXLIp(Yeh~m zTG}q?Luw@&Bfmik#Aol1gl0V$#YXg(4HgNj6JwSkY)@Wb1m(B+r5r@P?__ozekK zg+R0q)XToaw??Dpsob4X6QS+y(Wyd6JwF|pwq=Im)T*x-h@Nsri(45}G{3G1u9qZP z8_x5?Z032>h>PGz)NNd5>V)4c zsfo@zt0gm785z4{xcqaBx)ctK1cn`W`*w1xu5g(&Fr-;vr#NcY1>TK7 z@sq>=&BChH=J*tgH(Vi&?FH}%zUx)x|xJFq>J>Ax>5jEr_YfFw5|P53 zsB7;0;9+7#J2tx}U`!g=$#cA zlh4#-VE8k3Os1wiONxhD0Mdw(7c>0=+7Ue|FcaBJ82hPc2Mm-&J}!{ng?}p6D(Hh2 zPVG>wb{_CQ{!|>$;FJE9i^$1bE+3HfyAPH92iKRAu~9|X;EuLm=u7}1Y_hQ45oSH? zuHLW1Rh|Dly=-iaobxkcVM7ri_3%I~7OqhIUEpaW!`|M~0({*6O$=qR~P6+$s#*k)=sG2dt`dNXmBx-^0+ zoiN@1fi__Ujlz=3HzK%KTOTA>>f>$vyzk=N+|%j%{sUJ4rf&WI{PgH}dp*o-z1H3S z^LgXb;cDsrsuhExiuJcda9l2n$nazxW2O05b6+KpD!6Hlz!aEYQpF+wNghxF zbrm@x9D86JCop`85DAuie=+(`qC$-2Z1Ma?D<|SV2BzxU5`z zu??xBz(q&MvpH0qo1Nh2V=rh`C7k!TLnL38+33x+2>9sqlC^6n1Jy>F*Kzg3^-RZf(#E5vIxYO!Q1=X`IYKCwc2Lh@_%Pb@J! zy6A(-VnYf1QB&jDQ1r|2NvL4o^~s0v(4$|7mNIGT#q1dz8_Ux~@;o4FRrL=kCA^u( zOvc#<4A|G#e^37iJCS1zN_q5v!(j%E54;+)(Bl6l?Ec3%2MY`Pf5M+}H)=N8Znt!I zkAcpGZe{Ty@LwA)g(7u;9^5la`p{Ob*kthDo`Xj*9mM024)?P_HgI}x>S^FY9skHL zhC?5J$6SoY>|~FQ_%nEVy)W#h4$!YADu}u58^n>ZLO7zxP9QI6;qvuxeLS*_z=!I> z5qdEQ1^Vi*x&kXrQgVEMKa~RCr+&P?8@?RxzYi=t@4bBOgqHGseC*QY@_rp(mhM-o z$^GH`e~i6DcrHw|bsO8ZZQHhO?%1|%J8x{;Hg{~>cJk%!|Mt%FoW^OdW_7A&tvSZ; zt+UzqT7CKS2U9OM-_EfU(m3ZY7aZ`>fn|coKNa~=4gjHk-N-&xd+>b(Yb_lM9HPU2vmbYS z0`cH{hc6U*XGr#$9%C7bEc*fq#<>`_NETx&$Kzi%Esyns3Ku*!*o1lg?n)QkbuT;! zTsC8^pg2|ZxrT&$-%pNyOGYsouVf!aF0V`!s}Ud5+(!qGLdY0~1hj5{W(-hAEo8pb zWLF) zN&T>65S?E}E%#WkK9D6Z?o8_{r(;axa`L~}EweTzU4O!Q?tkI6#yIwaessb(QD_U+ zHY_@Lx$k1BaCz;L#Foq@@BbMz579n)Bu1<0GB~fSqU9gGQP`xoVY4N@$gV|F&CL=hr@2P=hMkAC>KKi_&<5*Ac{H;W!#}p2 z`-J+~J<-4M2XfAI26Bj$8iIZdwmHzGWxa5O;+_TASs?Uzq7Sh~c4E%R*WcNH&)~(B zx`{T|{Q3st4{!*@I%hP&besYi_w_v>?4}^?{_|!I&xn9@WdK<~T8zAWVXemqx`MMn zF`7^>NJ9|TO%+XeVy_uI;tQJ655601t*8W#dqFTloaL$V*gWd@XShcWtsf& zp9dL#(TqnEcgNSC77cWAv}OeW3AZ4%E46(F15`Le>FG8`S-`dHJ?X^SIW)jl$yt4C zFj|HMCj|~8YB^%O6`J%MrnU2+9Sur9rT{{K_tUE!*QLl&F}b5W>p>N9noIGc)Nqqa z{5eFsuk5a8vN!nBxMe`N6+d)XGtmv$04<|qNp1t#b(R8OXC&jxnBi!e*T~h&gIG@H zwTax;D^x=w)k>WnwQy5oUX38#jjNkr?9)x_{@i)^7|UNp0V^%3cIlK#uJXhV+0!DZ zv+ouBtXY85SlBn1qkz(DB6VLgOU-UXV>NfZpk-oxWm4bHGE}Z;SOMWie#g7SQt}f+ z-$PU6#Fm`dDGypUzk@!78mk<9KZzwayXBT42Ad-nEc9=bjh|dw&)~5RM}=&#!d2FB z`}6p3II-Wev3B$!ctwPIyvECvw1 z;^gs(;R~Z#o5JYotb7;UPTIBlHQ(`$HU(piEG9-=XPB| z86pfFxTLQACl64xDka5%4fca~h7T!M)abJF$i%<$xz{0%O^73tH=~syanVj)S;pp5 z2G6aY5H=!wNT1Yi$o=DOK(>r$C@WB*Re2qW7RaNct%RW)UxY5l9`!)U~3zIOO5RrC}@ zn3r9?w12+XR~ZT(X@vz?4fM0^Pp?;(vZwW!wdtAml@GeV3bH3$wu&`hTh|u1kePy) z#(D9i8xa5Yd3np2n9rYg{%GYz{S13INnio$F>9_>r`A7qugiAw*HUW3gJ}JB|F{~u zUpH`@s2)MQqKRJsgU{DB*ZJq=L|^ILGvw({=x$}!${xnUmwFpg8dRU2zBV+&GS6{3 z?>^2asZ8RZ96fG<9b(W`7ulQ0)+}$(EfD2a4|m^$NOI|go$bg`_C%VV+tBa3lT+zf z)OP))-YFK_*g;XAxD9feo^ZvCrCJwC@4oLCu{-q8Fz7>N=wIof2w+ zqmrdjj%2uuq#OW8jyK%W=F3Eh*IHajIm;!r%bV|xx_NTTq_yhX)c7T%VU{+pgeJC! z$@@E-cI&5}Y&Eq%@{P4G(=f=?UzSygPGS`Trv_Kgq2m{m)Ry2kTwBWq zVxQ3_m!4s#M}3D-*0nZ~`!Mln^6NmvLm*&F2;74xTe>cnk@9#=oEWl+{Hf>x3id3SrhYe?8I=Xjs zID8lkI)l~+%ZLUp6L#cL-DFRI>ar8uy-~9Ux1_lrxq+LzUR1}X8L6~F%5W%dl$%NU z+AUCXL>$ek9vL({UWv8q1qlv-t#o1`AsGs~BZ9T0mjas)e-bNpqxLTcy6nS3W?eGo z$UIXZEzB$COB2>9)_|^^^}b38P?;eia}jeWt+-yuL$4>Fh3K8O#6b|S!flJiRsSG? zFLh-{=m3v8U`n=YHXG=o?SVbnFgX0PG`E<7{mc<-MIUoBC*?zUlTxByzc^j2T5JT}QU{ z1>|@$7;!Q7gQS%zoPM|6I4jb^?}jKH)=ocYEkPF&*KQkEIqx+YF6p;F7pIg9tH6u< zifjyT68ZH)CNh{rIZ_JN9xaCY#6E{E@GAq!;%1dS5{H+Mq7WGq%-6=h7hJW}u^!3P z-kU@{CWjlOs<%FtUa?gVtr1eCv%ES}B1j|d)Z6MVj`C|aqS;>VYOTK1Tkpl>#(NDH2>dn*(8 zPr8hNR{h{zBweqRJXjk7P2!-~!hsU`fLPh>R=cG1>p?2NI zaGP>vw~Gdd95R-smU~fL*jv)mMDoMsx zWRc7oN6C-?TcKr=^Tokb@Lt-=g!mlwijo7Y1rVF=M~U&~o<h-*L|IV<4tb_LY zj!dsuaXLBqmF3O#Sz4he=pRWxl)Jtm@5{xGb|V)R?n7oa9iAd)3iZa-9%!E>s<#H@ zHwUE)#F9j?T9r$k^Xp1ZgJOr_2|7+5+9%H@m50lD;$qSPhM`kmpO^qu+srT+C2fHH ztSTdjy*)+#29-9CT~U6HIEOcMANu47J-+$jdL7W#aOkR)XTJvAj96?gi7krNktqf< z05fU;C11v$3TJ?vH@zEcMkTjVKbGFUhJjs_Qq);pL~=U>)x$7P`nT-}qG$uFL{xMY z)-gL#X-!!x6eR}3a;}O_x&W8gn#*#iYN%fwNBt@db!8xgql-3ArsWS7RaqhQQS zQk53_14f~jU44>l=OjHX#%43h-hVUGdsfg&i2oxom)w((yzJCxYlZ^b(ogsEisl>L z)K+Wt@6f!wCvTkNl&XBZPw?KbL@O6|VK02etidLa#`GWA?YXGC%+Dnj7Q>C#Q1%TM z;3Xt@0#zyy(=82gvh>t@y>(SJ#_u52hlddQG5eDaHnWt`b(`lT*)DgsDl%3w6?x?J zx$-FYF69!NQ@QXSOq_P~5BlJzMWU23q+5?Tfhx%Vzzs}2(>jmJ#I4ETm-kEv`nuF> zEwwXhulkTEZ$}@N9^gDjFm={LwvS!IkCD3u~bS>Q+$R&`NJ5IeQh6Xn6 zF)JJM=z-d02fO^za?S3YSSMQ%XqOv!*SQ+#RC+aR%A`T&(YNAy1)sHRl6g#>uJC-K zI>%D-9F7Gd&6jI1?zm%pXq3yCoPAKsW#Lq-$RE3_v_?LkuSb(aw_}=#CU*}tI9^cl zEu525%Va$mx4V?FO}r>36&Ox4E+P4LOSOW`XKj*`FJfNA!>4 z5X5^#laKY#4Mp4GN)wOMhX;9$l=v`q+!s@x1#D>G=J+eQUKYBvwqE;iabAjqXKInd zttjfM^XC_DR!q%(Sr4v^O*dmyt%B<0&?myF?@O~WPdHJ~{3dS47N+WMAY${$NLT|~ z6s}0OneFhjd#MqoQCoH6PkCR@SpTYx+eu)+0(8eeHdEA0khrhB?F*7Y?bkMX;x=3b z7|Xw;?6(5QJiMmc&x(daK)lnf&gG>aI%Iq5H_!o-cNp<&B?&I7$8ejTd)N{L$F>`r z4)0(gmmS2r>H>Qe*k@Dj!sI>~hHC=zMi~2Qds90ZnE!cxv#j}e*0-NGG{S<;c`p3L4~cjN-1t=weAX>5HY@`_ zIZrP2$K4XfI_kwu4^tWpEbYmbvd7k2$Mf8*@>mDoKy`=d#UOg*%C8?kTEltj{_^KLt(VL+n@%{#Nk8iI7C&}4Ezdg1K~Kk=NX&!TcCjAzjfA1sg!_A8>*8*S$Bjw|ql#-fR1LpWsv<4vX6akM80QKfq0J$pQ6l)VALZFZNyAo-lB12%#vr_qvTt+1;T^ zQmkOEY>Pr;j;sa%k3$=E12yA6*Y|%h94N1~zl!9+^Q54_bnf!QQTMQ6fXlbz`w7wa zK?&=~^WGK!VdnSg>@MK|kZ^~nxEFKu6+l?mFG!d_mH_bo9!GQ##5e5q_I}z6=;amo zd5Cxu^nX8CN)Qa-68Je04EQ?k|Gw!a{O`ZpqlcHP3ugoyrSYJ=7UwzcoLcewVk0Wf z!p<6ncwO^Qfu^IJe!^a%R(~iT{g25DVck()3AqGNb6mj&T~IW~3YG|)StqMFOZiGT#($%>s6L{XbZimq#FLS zEyzaRJK0;tYv=vDgYz{D@8=@AxBZus^V!*cLPyg>bc#a`;)mEp6q{=2z0g&3;TOz- z%#dpD`hj1fYRUJJ>qW>8bN3(SC$xt@2ZK_8&@Ekl+z0Xs)xt$X5wcw*=#`|2W%@v;n zZc>^rv{&@EZUZ0Nd>?FZwA|&+RHsmoA z91CHaCc`E4-x&~xa*H^NNYR8Qib>rdtAHI`L_)3EEcRb{5FjNl`%1pDiezrSx%tE* zi9m)nGzgwH-y}2?`^+H?p^8We0+5kehsrvmO{t=o0LU!zl%c8r32mKK9EU$`VV;#+ zHDn%L9XtqjM@R;4>qRR&MO!Jji(SpqWh^gGl5-AUIZDqTL?&hM}fHA4HK3J^R2J3(xvCl%?!LJwb}OYKAxCoGd;&2>c`FnL$lMBNHR1e?qc1#G8&^ zz(#a+@H_w~rF|IIM0mEN=*-RvK6gj#iV zR}{?+Ti*m*58^dO*4%8czpH%n{6(~aqbc#2l_qsTzOsp5KR`1zU5BXErCJWrmq)p496Bvh8*7FHe7a0tEysRlSc;ZXG&4x#oTdVE>QJ(7!@KR0Zisf; zI9wNFPUTbVw&7xKIb0Iyv47Ykx08oulOCIThkmSiSiyt{LWu(}tjL->$G<^ko&&@= zNYdq_8sfUUmuhFDY6r7gR$tZNc-ti(@Y^6ePN19)blf?#^%%)d^~o;clN(_1^tNaU z&O*lq@U2g>1sZ)o*7B*>u%hmM3XCECoaGoC;ro|2GfM4tl_~GyH;SN9 zVFIBkvd1N-<>t~>Ob^xfzv^Lz;em%YbQfJ-%SRWDI>7;_9`>xHxgw1)66=4G4cIUnCOwmw$U(BgwIVMcSn)h_oZ_5?HuK*m=M$jot?> z`t&eJT`1wcLSXg$Y*1xheY{(LuNO{^UG%9rkAG zop(_-Hl&l@HLr3+)T}YY#Smg_6l~zmcf}BJG(uWiHi3YCToaC%H^rg;uu=*3nyW|qP9A{+ugow}-vuS(0(yh=-720Q| zT-e;V21e;w9lp$1y@eI2)pwME|0oeZsdmx zwKryUMy^`Qe9^o(R8vx6hCzXUH6FYVt(q0msSj_ZxN9mH^ZY#6&O6l zO?IV00)yoa5ETsruD2qa-X{KI=Muez+?hB%WiUsS=qh0`%0W}cl7OKt0UNv2$>kNn z)y-TS2fs3*kwFqszSO-Xo}nJfoq4#Pah7RwwKi^BE$8#hj;yHWWY1G>6CHPSvXa?s z_K@zV_g(GV1F>>sW@5}5+XFsHC}+g^17A5uxKV0}=EB}DfGBP3D4oQX_#3M01Ds@< z=oE46(z1bWn90}JgSnM2(uW%dRM9`Xy$hhBIL?QRnuZnE+~09`W7mXXp#dYHoOanj z*h2mouKev;RSZW@{x`kM)*<% zQ#YvsY`Hw&$@i9sH};nlnJX&5dRz6))x} z?2_D~%(R@j8V_RTHNPu9Ii)-?dIpTzHRmOC8DW~b?uVDqwFIU1+@d2@-^5d)+72>J zEoZt?E9^1@>fmSzpP13A;6FJnkk&KPt9XRtv|$G{$~D5C+;tOXiVAxE5j(gPGzBel zLucoflSnp*qf35EilykB{T3s(KI(EJOdWK_qR3HEArx8tC*%BxKw6ooL0`-11et)E zgIoi8Z8KA@3CVDJ15A)~XaQO`_&5@~$(voS(MkL|CZrZd8jWAA&ASzNN_hNV+I9T?qsN3*&bi zH(iOg#rD@R%XneeaHpZA!9GW*qbDfK$TijdE4ceopIca#^x+VRZ(M4kD@n@Ot1T(f zjWkJwx8}$=hFNDlGDCtSt;7Zg8Zs;ftv%}~I_W+wQ8#{ctxn|7lWZMYgUl(%=p*v! zl!9uS@tK*P@Lp2_>iPxctDvDN27`f{x-c}BPuGByT?Y76uC}ClQ>WH(MXnMlfJUk3 zpB>{^4EAD##D{PSdbxc)^s939^}-^sLLwWfg8r4=5HT_K2-(G_T7pcSl&TzsioBPe ziC7#q_%$`#CiepJmS$XMqPh-h+hCw}s+HRg-b!;_M{PSOk>FL;glwTHm%=D zCM+3jnFl2PFI-Q6p_8wphT!fX!MVuk5*RTTpvrv=Z9x>Z zZ5Z=};Y#@`jq&B-i8kIR1`~T4YPq7ajIHJjQT24uYil}p+~UmW;Jwn|xGM-)Ad8&6UKTIgw2Cs`QhH?K2o~ItC%|T_-!gj2i?T8%S|16nuvvv38}KTR?X_u^ zEAq@hs^u}A)L@}2C6et!V5hU^^cMpKC1#r7li(J++zF7S|MEjc4(kS=vyJ|rz)6xgpb}h^3#y}lLp;9VCYR7o{l{!`{ zwTrdG7o^hGhVa=Uo6?oW)|x!gLD2pjX~W2hlg^`^`z+VgT%+jLw#dUpzh)H`68xZNmZUN0du5 zU4Cb@OS{?EpL#>f()TUByj`7`14QwX=BsLzsYPacgN`<$l$9AH6NnXPZg2 zC)G{wJ<;NjTM{uLoQPfG38%K>%o`$)|4-`pxGp(-$M)T&37!)n_*zTQY+8(T+dOqU z^5_+bnf*3%X$;>wl&r!9@vMm|`<%8sPhrYRbW%D;+lHQjVMPQBZ5FCTp^>6{IicTv z-tgDzlf=ssr)E^?jFj?*l_-dOd>XT`FwC!{orb0pts=WMv&UkFWgXK^;WFA@ei!@; zG;Q2JCbcsY+bK`BaI?Cwyl?X$iX7XEl2cAN%O3pn9m^oE5E<_vz53apa0qW^uja<= zTzb#h{>!D$_b}^jwSp(ONrACam##ED)sxma+i~ag_}l;O=k^H!en<_D+87qCJPA?p z&O^|T)py%(SNSNyN@iT~&VP^i=^%nLU%8Lw|({G{OQrB?4&(4KNqjTv(@85X348l36AKa=8w0m7-KMryw{T z?smKqQVSX9kt0x$)&|;);@s5Z&@pDBCKpQ$UyzA8qLvVP&$oRn(U6d(8wzMDu6815 z-VR8$^GIY}Ln1DH4&aaw(`QB`0$*N#N0?Ti?xDX^!UMweM%S;R&wUx!V0s0?I$9*r zNk|G{XYlvHwZNhJiIG?)Xc$VG2Yq%92iOvpL}+$J(LQqD4@>1|?x+c(dFtY_A%B4h z1EnB4A+uHgetO7WYqCDC!1=L@8qWT`nMq8ovJLM5QOLtBAP1O%ry{^UAo@i=F+N z<|6PH>bY%C6jCNf-5&hho;h?S{F~nPWlB5=e%kM;khCl|W%%NxtxNj*Zgmn82wdCm zKHd%kx^n`2Ki`)!BKrM57JI#1o_=oj?syjc-gZ1ax^eG3IL8Z%d%Az^BzK~%%6SE# zO4U4m$8X^aFQp<+L(fTx!%hUDA~DT; z$wJ{JMW~!iait@7yScCLd<5$npSBvqw9i>L**DIvpTe2EYy?}`m7J&&IQd~OmjC&} z0(ja8ZnzT87TD&O$9>m!etkST>LVp&7GO)M=f%XJ3~x`#tTO|0t0tIDBt#-zt5+fW zKL?e;I{#=^({tjrm$mWsTQ^Mr)7s4gbI!5#-_Og>Lyh|l^@4@!PcJh{d$sK8USRhd zu#8!hf8cZWg57kL7>@6sX2spH8Grr;8UZNsx7@Y0j1`CIR9X zxps))=mI^;LA$X~Yqj`y(?vsd=25S$mt}1^JZm~08KHnw#5J77@jnIzn;>wUNsv5_ zX%^V`Aw4{9%ywMQ6-iUhF(TLb*k$f+N8I6t)i`F=WwZF9Xs=7tUI!(A;7=b;OZlTg zRmL9at|wd)qR0gwTk!l1!3FG1&x|X1Bet9YeQITWo6U8a=g~;BNT9|*vYH}={;RGC zp#17pj1YF#$J|GTC`(6xbXM&f0dxu^AsmW&g8f+xZaH6@pF+wXoo$JnC1o8+1_Vlf zjFqLw(MPb(2ed-|@;PGhO5(RXOLr+3s6e5QM6GVg5LMV<52$rv=<|YjO)P+pCdipu z0&Mg;it%z4rJ7WJ3@oMo3XX9NaLH^2ycjQM@ z#QF6p+}YIlIp;zpa%!_b;{UtTX47tglcyFH>Y09@MWs5k)7gs9VZr>sB+W&WdNJf^ zF%I_(^a;Qf6i$iLQ{_5t$V7GOR`^1#<2~i(gl%J=6O` z(<1qGqFSplINZ#txq+kCUO-u4CQw$ZIib=6Gn0^yYnYHI7P@WO=v$c8gsh|yz%WpK z22NZCW24{DjB(90`EChRZXr~SmqDCnB+aK?Q;MclUm;5a#C%YKQ!V$Li2!DD7jS0e zRy>UO^#Jx)l)(=2)&-CC#qHHN?`rEXS6s4#gnP^z8_XiRjWkXii(Oc2n9Fbe=WTF3 z>STNH@HGcOIdI^{Ba9xpp2~j^`$9sAI1ayxH&tP-aG5!_;s&MogJr{W-Sz-*R$#ZY z#X=~Y@>4p>AN&~YB#*B3T{wm0rEM-nrE!_J3Uere?}O5|n6vX>McEak#)p66nJ%`2 z3b9PZ0*}Q8 zMk<^>_}WrYXVR~M`7`rpE7u{4l-DIaH1#YIsf-qCf|XR<3vt>Gd76y}tjxT=L=b1O zEErl^^>s%t7be2$RLU_bg&X(H1$+H8cf*i? z>b?a09lOn}k>`wib}B$oV!oBPWuPZHp*iO#sx*H=gj^-sVzsr=ICQL~0vn4JF`Dg_ z6)TB$Lfiyo!3XjQZKZ71ANWk7gR>Q@0Yn58TB4U@sS0iy$d3H)q_k<`E>Y*hvGyjw zM)VsjOU32De^nk`LboMMvjNHw2~>nfycw~UK$E6&6kRrW#3s&CHQ}a;wg_igvVRp* z2QLr>IrGk()w{*A$e3rQ*mP)m>P;+pk+iI341HkCZ1OUl#l`vUF=`U4} znaoVAv}6xA%<1U*4ekB29GOq*xV|5WBP16{DU7!aiCi@}Tvk1tNlhJST1$`sPj8(&{s`?PF$53MTNr)`U!?a)4+|79oo9N!=Nj(Bkt7g z_-YP(^qlbBgknJXbhHt3+CDasG_@3)G3*16P0dR50vnR~3&df`!oq;Pg%P8ZOKZK$5|hGZ&0GOwZPT8hbRZIorMzmex$is;;khpgdNCD@O z+w?T|az(lsQ|+CtVisr%K;7_4%!h}-DbS}h;G*=KTiNLs%8A6<0c+&!B?tGVg5hoc zsiH=3X(bM568jFetV?N);L(qAhs$}QYm!z4ug1CBO{|%Ue_$dJ88D_g9w#G06yl~~ zN&oX!-QZ@Qn`MA7auOWTrgvW;oTm#G155@HR$XG)a6wp}3j#(Oj*Usc`(Izxzqg;# zWFm$#E!aU-b{!AD=o~z!#ITZ#9ZM;MFe+5Aozpx4@^jtFD4-AF_?aK`VDn`c(;=NB z(^T3Qe)F3jJBAxxX--QCb9TL;c+Zv67F^Tln6Cnxuf9<$ zDtfBECc0=Ahdnab95OI2ZdaoME!s3HT;zEG{Wd+3^puOI48NV71pKWzW!cd{euV9T zmV_TPDLOS@U$ms)^aMSMB(H5^sge;rN`fWHhr`_7FzI|PLX6xvL#)V)ULQXwIEL1O zSZV#2oKz`mZ^d7{U_L^K+@c=p*%yq5k!=?*?9v};TOU5n&ZEJ+Cj{TnjC%~Fy&l7P z&Pw>GuV*iu%}9)NL3r(>Ntvl3{)QyS_k@&cO`)THpvq>@Gx)E7UR9c%W@)K+nCF&A zk2NsdCk&)S?7cnPZCiwvP=Sj+XEhSb5TER05^44xWJt%s-qr12VNmAaIHYJFM$o|R zus7n3&H*nJ``imluE#fEwe#o+AKMKjo-HNCxa!TO(sky<(@i$Z-j(2Ll$*=2yJqd`V$N;PaX8HmQ%8@vdDA=X zcgNARKUJOBdTSu7dIGY*HnNoi;!fF&@_TsF#v@41xr|`0{7ZA==3lFyBp!2C`Pf$y zoH7^&_|7cH+CKy4EeCuh&uAn9u++2S|EStC9|n_S|9v7SA859)Dj05kM8`r{g;z^T zJQmJef8R5%&NpF&k|vnt)cv5?jo*fEpWJ2sJTh=%^ZH+ep= z4?h9FPkr4VXWfYX0lsf1Z;FK7Ie`B@*D$|M_ICTfUVcD*g&WVQE=rlku=uM>@3^2D z9X!mri#X+AN6jU>z6`r7g_m(M?TmVp)D!|*e0#?|I}2S)gYalYKj^HD5ma-I>Q;+6 zywV0PkGI(?@>N92IU~m)l4;fcl2vQO!jy9*ELWqy?3Y<=DxkKQCFTpw#V)WQb1hS0 zDg^gnhAad}E)Q7qHj+tt4!&8Dd8v)0JQ;#o?uM%CrIZ+R*eyO;!?~dMWZOT)JW@{yg zk7}}zW1RvG%Gc}4KMn2 z+O_m7dZHM6s}O!3e$J2&gskemzoe$?$5#T#KjuFKUD@)4-_ZF;l+k)NxWL0KN9`+d zp<@0*CZh*${coAV{}JlM#>B$?KNt!4+6mijAAbH}`LO?($~}QZ1J=DMuf*b8bbl>4 zor2LKcRJ=ofBlGeQ$2lC*_tJcKtbm(i3I)M#OI_c7Jnhw3J$87KT%1^A_)C^zugD5 z;)CH|1w|g%NaRL^&;b%7(6|D9-QQ1&!(Y=5nAQw*#T)gnt@TWYVoWSe=1L`i_wn|S zkH?3z>EU+Q_mBSnmm_%o{*)*5|K3}@e_lo0<^T8iM`)OHZ^j{?;c5Ehfal-71f!sS z127h%b3uwwFdSpQL7#-w929kEq8U^rG%+<&vgXsTv%XVkmPjb;SO4}9O4x-BXb_yRaVp+l|Y2C-e zPqsy~fs=TsaWlk6ERzq1&EGraZi>=9-TdmIU4pNigOk0CvkaQf60Iaz_NU`LX0U43cw+`4(WY@2xS7~uW(lMr41%|Ig6X;XvmAc+-as^L+i7I; zLf}GN-Al9+@hAHcA%r-bV`^{4h*uEHNtA;-w4A4aDk(9?oEeBv)o0e7UP;zd)^rA4ah$amhLJEe70;Tx+?*6rxdqIkf?LQ z;ixyoP=M^oqC8G}U)X3EzTyWnVq#=Uq!k>1>l`5sh zx>qhkGF|M|tjuT?W5D>To+SNaAaydXpP$?wvWUSn*(e!UW}&!ahpppboRPkhXB^&` zM2(bk+#i~nKz3fy38}niDr7KhU3}AWJ4khMSVa-rzOMS(djGW|5p65!5-|uxq2i6? zJ~Pl=&QfQ1K}((32+HeAU#`Duo6|W5F^jgxST<$UfB?5MNyNO_fxWp-Ya z@~*(+N;APfJpph(b;Q_s?$$He;d|h7Ld&M7fV~2P=5f;8(AN(V*qjGqv(!1dIw9@! zO<073H4G{0cKWVsDoR>yJlu)Ns$N3o~HY+`2Sa%w5J9=_u3JIV{7 zL{wR~lMUE5M<);H*gEsS*>bbgglV~!GAKl<&4Mth^`{dq(zak}ClEFrcA0V=E~cix z#m1SXHLz)oN=VL;*+Lh_G$1Fp^>9b8eZKrb%8z`;Q4fvtAdv#bNft1&a<#h9vT{xp z;0?+wvBs3His7@KR`vG4cwGi5m8h`$(jcan(7(!=U1q>244uv3ktF&BLJMRYJldym z5nfGe>Lc6LUyDVe7`quuKj0MM2Ney+_sGRRRMjW<(C8A(@}$COOQE?!#<_DyV|cAW za+`%8AN<%WR{zcZX#V}SaotJJ@?jIaGv#nX{iDi>F^X{gH!40FCcOqD5>NB-`IKzh zyBYXEv9j_H>njI1dPjrAdipSDA_C)nKGFRRo12rVJOOgJxsG zwv)_?rJ^2k7idhX8JMotowNK8wk9t$wam7ZDw`Qk48rW4X!ik&ZKv39GLEMQ9|qr*wsjp`jPfvX-3#>F!$MLNOj?)JcLEo6Xng8~=-^ zSX5-pKkVJgLPo!o_(YIU@o5sjANUzRW~=0sEn!QZ{3czp%~ixMJ>AP}5k|_U{7Ps@j9nd{%9zh%U}Sm|x7^ z$1JU^I%W~&96t%1>X3}bDfB^+>`=gG-|^0;tT4C#n6~GO%8-CE?-x}tOqCt)XwEPo zz@^aJnwLeT!noFEh4I|*mcpyEHk}K*^vkej!N-0%vCvR27U$e#MX;;+dpg58s`0(~ zl8&VqR^9uH$M>Vt{L26nN)yq1yXAgAc^S@Sl2t5VmGoIie#c<7?>1{SZAPaw`>{M# z)?&tFI>*YQtad*eV&B5QNMpyv(Z#gZ06_ZD-aFjhpmX zXIh=x$dA_+ymKbx$1z8DTlGKfekCRwX+%w@%KEyEeE}gYuGkt%-I55?Cj-b{)l1j9 zY|-%AYcSu$JK6>7T9Gm@?6ZI0?8CIpFZ|Z;5U~FJGk30Kb>?OCMj(gY z6UPE?F_Wn+(q&;&Od4r9rpJ}&VCoOEu%REa;>-ys3Y(+Kw-$R|4w^eOmb4wDp|Ntn zzXOpaS9pCxh?%br%+vL{4=GOzVfo%g?vV0I2g; z&y*GG$ytn54MrMyUNOyb(JTDe{bN)hV1xl=>JdWy#AyJF4TzsuN$ZPs#T`@&GV(>pl3p$s^iXT`kJ z%s3lo^J~}xOLv1Kl-~9bTH_CJAAZXzi$LClmvo=L(WO*>)v79oAu-0MH}`$Du16%g z-gQ{+mXEk|<^F$+y+e>F0k>vbwr$(C?NhdG+qP}nwr!lUPT97rUfu539r1VE!5w8} z4&#iRcXMSBeKUxG((V>g9A3KTWufw|SlLMjy7W8F@j!4Oa zN|!)^`N_Cfrw%SH?GY14&7@a=FU_eLrav2u$q`BKv!0u`*MYOMz3rxM$BfETNu5+) zX%6hOSEujRtq^#EPl~0yWi54Xm~Nu1^-l~}uV#W1?W#nlgyV|8FmO-YT+Jv6;D*E~ z(5evf&1~87y&D~q?KBYmq3Z&G$M#%TK5`IU%mL{^<_jJ*Om+mv8n@S%f-;2h4O4&9 z4O(!|y^LHKv%mXo@Gid;NRe;O}8FsEwJ5Z-oPaJN$D4`Iqu9 zNJ7h)WBFP+b=uVF|Qg~$kFrzs4mdSLW&0CQ%S{{WK^r*jov;zL+En5gE z9fvI)@cbC`IrgpLt!K)UH5HNIt-R?llQ@J4QSAwV7S76BhR=kVs~Dkm z7UZJ7AO`N8g-Gel!0D*FPPv%*>&UFMs-E8O6 zgrds3p`;PIw7X@54Pe--V!iu3C ztEF#V9bPbnD{Fb^+YF16*K&0$Uz`TY%iQooFYtj3iH-F!GD}vy9exmffV`@nK_5+T zZh=emJls-SrWbOq+UA2t<_OV|2|pMRHBLWMZT6bj|9AwchjB1U3vIz|Aj@@imnG+% z<%%KJmx76X%Y~Vl8~ftID9ej+<3Sy4p#fhQ8lS-A6|IxbEEdxsez#}51pe2*gst8DBbV-Lwsg8P z6fl%4@_J0xx0ZEWoD-^DxjRn!T$q|G6!cwBSZ8u`n$)~-=%2uQf*iROCBHsl@axCX zP1+8f`R)|FgwlxkS1!ilPVVS;S=n~mhMg?G-;49_Z^GBJw7h?rd0D=1zj7^Dct5X? z2l|_x-@(Dq$KKw@&d-yi-seMC8-MQy#t#xJHUk!?mM^VVDY;}~08!iWxO`4bqy!lS z{`~FzLH(9~3AV@%LD7CXy-n*C`|(3)VhHxBCdOnU2Xh$J%w6fDn8p1*P*jqVlW;T! zad$iJH<%RWq(h=9bzp`;c98e7K76J2+pNRH@D&iHg4BI|e?_ySDTRbM8|4H7G`qwZ zY?C9WQ~?Pw%d~`_trc~&D2(}gT;ZhaxVlLHr0=cl;{4{kv3^wnI}FnyYKz&(+{p)DP^#fH@TQaA4rU>+H_56l45>}lHQHEx&$Q*UOsj{%3kotuO6yhAUdh{C#k zNf&7tXS3Gd&s(Fw+e@XIfKU0Pt^QIM1lM`LV#=Ci?Q>KUW+8V610r7z?* zNVOiczsB3U{qi4M?clz!c$@7qotJ*XU8thsIfr4SF8MhDSNTB|`Vgz$Re& zLtw|8_Eo@{*H2CYUe2k_?JObFKj2wu02iQ|feU7@xKL4j_gkjy-n(8x?|;AysF%>E zoa-y=j+(RoHuYH;n)_1#Yv;dkzH9-~85e(o!zET|ehSTFw@#9T>D(`QmH|WjD_gEN zm^3j(wCTdigDHS7(K#U*CeZN=u!y=fV#OBl5Lr*srn(lYK5lb36WTx}7<_25287rU zVI`;H9tu&Or$J!I0=(lWaO(M{i>hXoA;vmka0L@;X{% zuCwU~zaJh9-?T>^9B}2b^p;*f?%7coBsb`i{F;He)RpaJXZyPPjAn~PmYJQ5ftp~CD|SO;pD6tL zAa3tCVy8}Y%QfBNHHMPGqdv_5n;CeWR!fOoVaRHN@@=;TO<|R!S$yMPE3vpDv0*m8 z@N#gG-DR{*D`wY@5hJm1Hj?&)nfAZJxpf+B=b|}SSDz`|D*2$&k$kB*WG8h@5DKNpGFs>pgEy~#t-*7r*sd663pMUY4?nu#~ENs&hWAOAuXjkcl6z`Vh>M|R$gCNO- zisNK86l~AVoe0s3A;VG`2{1D73)32Ewgu@!nE|LG5sy=3_LEf)F2X=}ShaHKjlwFoyXfNo&W=%3mISKSJV|?+sdP&t|1rz6 z--nYq{ex~UfS==nzIf&2t0*2_MGiM5El>i*wps_@5G2(l7^;+LfIdvoqJu;5qeBv; z(y%SRbERi5z?ZJwxC6~6?t32%xyZLx$fo2)r<0t(9j zf)GC?Yh__;KdaU-7eOh{=q(fILA+{1d{lj0lnfefuILwOg7%hp$n>e$15>=te!|qLth5 zOo6&o0Mes`%<;wS)!njiRDyRiliOTB|JO}E|xQKe1~ zXX+vkDaYlVyl05PSvWqKKg5~gYoI~H88kn{STDkbtzi~fXEEt((Y-7la_v21MP#TM z!KsMKN9LpWZg?H2_OKKRXBXWAF88uE%Xm;`+hQ!GS~&o@kg_NqykFy81JABMg+~+c zwB6Fgqm~^UpsWpJ_^MTy;4l0foaoj^80_EOPJP&rMI7ykXjK0as%N?{Y5nWt>Pchb zvu$QHbow-})b^7d_6HZ+SQanY@R5}`&N-~lVGfgO?_~{sLe(fhQ73g)FY;{~&koVV zv)W?FXd)z)B{!65AbOcf->t9qkLDn`JG?PB`{!%lZF;?-iG3}OvOg!fT^=t(25wD$ z-kv|3*gwZJVLxAQtzB=cS#CG{-5#DlcfxKD4|+cyj(Xo;S6O;He5Le9!?A*O_TCQV z8t&xoj za*N{fPZczS{2xGbyN0}MJ&S4t=}d7s*BH%E&tWc^(yrFI>(x1pIFB@(q6jD8vaJM& z;P(RMjlfgVaHlh=UBo<8#XEvLjy6YtMXzJ4DN-MJvg|v!?>n?|3)@QSAF6}c+`_;W zp0bJ6!h;_tT!XZ)O$CiR1Q=70L*}@m@1aEbdojw?pTRrNlf97DCYqm5&D>*ib&=Zp7}T zE@Y){7LdH!2LEu$_lDfext&`?5CL}nFV|OR0+BW;mhWF{YMVg1WqLw4sHEt_ z4$5?dSV-FYKg@ z-`CUjH_&}tKh}MKWvs)XpNT?fJ3dKv>{cVh_FY zg3nK}Df+bL*H6Zt^0WI;&)j|Aa6L0u$4mdp!A^SH;TPd+iR4-TCb3AX)j`O|%~Ok9 ztW(r@pIK~TqFv4QkcAi4lEp655P8Rulg%YhcCc2jVkt0`8OU79Dqxqj50Gp!VW`WO znK_ykhw6b(pM_3%k9_2Fr!mOBu6dFuShcQm@sY#0@i#xp;P-@vAlP?)@+x$R6|i=b z27y`$;dvm7AuzMc0k=c+FsS%u-|%IsA#rU}%=d>hIe~HmTE96&3pl)1O>|Oi+*u$g zZ6q1ZZPk>%v8@ppAY(kQVIo1=J4u9+q!#1A4SABJR-$O?8UX@LVyd_g4Dkb-cldsj zkR)-!R6-yq%sS(T`x2N&#rF`DNb2DwkUtH9e)#LI);0*^q+%+v@%Eh|wAjN-B3~~Q zwlO=rm`d#G z+5{N1DqVq*o-UX*1F%Cx&@oZ0)ba6Jw+OW~I|5W#WklOAtqcX&%S$HTpIS8TKw4E^ zw%3*d&gOrqmpfdQBHH_%)r#u>Kl#WtAUKG(5mV{XDV#ahXp& zix4_7(A{|L`rnBB&EJVm5mJO%^dg>KY!c+q-$jjj7zH9?{UZQLQ+|SpT>+#&skTh# z>#Z5XbdyraloQtiO8NB=c8}99@IyeGLb(4L!s}3~n=%lf>eQIUrNg9PgLBYO=j#$y zLV8>x31wOpAN?JrxE7Z<|5l6Cvq_QWvj!s4qv?pCJryUMbn}?$&;h9K>!^(26C37v zL?GGc-gP&K9)tGA&GaOiL;o4&Q)5q?5Jhbl*=KUl5BAr?~5oDwLS_q$4gL zIG~StinQ4#!gg_}9c19NRExYJ*X-VQ1q zomPO?h(KFW{c||Ld~ zREov1L~{|gs<<&wrxIn=bx0& zm_1toKZcoGrSt%mW;plCW3`YrlX&K@;dA-6(Hlk%G>FTA)OKkG0Ie!otX4tt&;b20 z_zFb9G!jddE+J0xu{d#=osi0!oTEuyB_K{iq@;0@t$@aw9HUX)1u=41K6N9v70ttd z9mqAcy)ooeK-fEktm#6g zO29)-{sfVV0t(-2VgjZw@I2Xx-{KGjkh=*+tG)-S#0l-_8*F}FK-dKJpS@C%S*iG& zU=Gtr)O)i-Vv&_S^P62O9Y=Jb*Dmpjx?E=D$nt2QT2#(^Mh{|(Zh%~Bbf%Gikcu>D zS<{!k*Iq=zB!v=&! zO=J#z$KVV_d83S`c6(}Vk2`dZk4cC26CT!LDUnh45t`0JHzSXltv64wPQ~EtM0p2C z{qX#YTDT*{Iv_>7YuNWaMj06lG1P*9@lWV;gqlXfEa*-yw5Kd`9UO~X#(IUIZVQVN zeM;3aY*};|Fk}SAud3zJk6@Vk%MGYMLM0EH?#-{^X@+;6xLzca_A1b~lBc+;D4S3= zI|tRTf%bR`Wpi!g{E@{-hf~QHp=>2x5P^F&hI+-dKZAIB&$49}2`)}P$q?P)?G9Uo z1x?jgzjzR5_lV52iTntg{RYi*SflkQ2cT*}GjHv}T1gG8LM^ILimH7MovK@J2u-ii zuI*uRB&q|6QB^V0uef%0PFEQ)Rd{~-5FA++8i+=ZNSz)5q!UtJAWbBGG!#))W&i^6 z1|}f8(|;z?gNx3RcjN0sz^gyXmZY=C(7@%&m)j`v4T0orjpnaFhYfekPTuQ zFWtWqkz?be{$jX(jz+Dj>XdUv+iQfhg#&exw(f4<2m%V*%*OF=_6AReV)|0j+wb-J z_6#7VxaL&vX+zUltL31rC-Js%bC9De36r{(o--S=&-&Cb{NBf0log#|>D^8ID;Ji$Dg4W@fCe6ijf_E*QUF7WW` zw8#!o9k2nmfhAdt#!@7%W=9dj(vOKbx#?oZ)xjHN6Mfgq(~?cX2_ zn`^usiL{4fR-{MU4$e&LQp@iSnWifs7PG(vHO@E@(nMe-`tweY&=6qAn|;{1{9iVf z;(!VreQn5)@*JaovCjx2!;k~vMVDw*AUPcL1xUX4urkjj*m`IPCTY~c98yKv0@?1o zUJ#*A0%8B#AIEFIL+iHiq4>Z2aZmPA$+RVbQiM!f;4@(9H-%Cp=>_4#p-5?%xyb&Z zOyx+C(u$vN2V*CnD1Y{QkpGuGj_v>2U6G=FU@#EvX&P1ckQ zgJL-iiU8<=C8K98ujoFHY0v*%9{nGpS(rFE{~sHRR-ASl>~DL?As70P#w874sDJv} zdLs-)wn-pwdzexC{};%GTyvShnU!~Jx&WBDi4#YDN+h7TV0PH=^#Oum^kQf6WBTLz ze%m~KL^5(?u@>WNGjIYSnjHi@A z?NR&v_=fj+d$xJL>cZT7H+jBZjKTB!d_RuO<%Ox$;rY6MPAviqU94u6jV&LWJl)cO zlZB?~snIx2gKG>|YHebfe2!P?vK@}mG;zAYJGySSh6tjgFFX#zp% z0_A=`_i@u-8PH+&H)g)KFIyV3nb#1Ss|fMkU83B=0=(>K2;>pO-AE@yT#5JUl?pM8 z6D6gDPdYVr&fA(KZU(nfJbWK97%URH_?yNXRfFFh5oQQ@|Ufne_W2llNIr_$r=YPWNEK~nKPX`T`(d?Gu19; z%X;Jem5#S+gI7Rvvh^_u)V|ArM|JoH`IbG1N~B@)l}luO1()zi{1&*L2VavhM`m>R zc#@8zNI{`YX9hD{5hKJP%9Pcmb#K4Cqg;q`$Q)UGWwuRLjT|;0#NC&_{}?&O_QQER z{o7Zrr5ygt zQ2VvzhK|3uXkaP55J^`t84#a5%t3{t^XG7Q$Vt}j(lzs);A%kTZ=WcpF#pesk@LVy ziI|pYzf%BjBX(1f#dDb7NvwgnX)Dc@Qb+3M91XH4Zf%Z=88SaEx=AwZ*=7({nhHIP})t*9uUR z!1NABpL%y)u~O<)3{lsm#qp%#uy$H_2MkB)ur&ggNdwuE7!XO#U9n0IKCm8UIurk$ z2Tkcy?x)+UuC_|ym$2?S)&ti<;BXsNXxkQlUAYJ2zv3&rnyIKG$rR@m_uVBHm(-Ez z%=EoGV9=54>b%uPB9rBT1f+e=c;;>mzve1Iv#jOHjAGPL*X*{l!;qH^F*@YUsAud+v#uNMO+3*nJ7Y7IWM%CQ7V9iHg{6Zbi!A z?F57b>n&1)if52cqp*Wt(SXE-O{73a_o#JOM`Dxm3dpwdUswwareeFPCaSd79Ld7r zr;|ib(M$q6>cBteL4LUu34s;pe|wN4bz*Kw6QfAR~lCfIX4zGa|C5VX6ha+GjR{|zU_}4dAE1u*?ez78^*HzlXIDMt0gzldHHDQ7g=bwur&<4^K|OZ zGkYVZn<@mkwqdSn?8Y^b$e+8*1tqV?T@A+DMiZE!05LX1EnPjLH+!(qHEyL)n+J6- zS5sTssA131bO0Sm$m8@R%%U+RLa|)oU&}l6IEBEB;>*UrC2MQEtGhH8BfgIIPOt1; zkZcG`<&wZ}QGw1b#Cw-41qmGr%j!+QiJvfUzO<&9id5$l`I~@aBpdXj z*a9veS8)KKN1Pw)NnoR|Cos0vMaZ++$Z056r zyGSw-g(6z3J}aTt?xtsz*=lb-lG{)1*X#JSd@&tY@IQg0G~o@B(q^iJjin?9cg_CR zrv0r3I>aZ!w(*p+wmsT&TaK}U4wap{HSNL_X5bUGPzI9g8;wFu6^Sye_mBqD6KB=y zmqp7ME$P`51~ZB-ou8Mvtn3PU!6nJqrttvGUMAg2V=@Xw*37d;1y+B;wU<4-ZQwla zSXf14Iwv?T?k2fahGg?~+LN4hqA4tC+%m3lXB$0;&ohFf&{wVpA1N%IuWCl=)E5`x z96yCi_v-2wy)H%scE?yhE0s0dCD!xu#ggW95s=onW5^d_Zfebr9U3wUM;&JmEK{@F zG@M3^7QUA&_oCge)DSr9he7t=&k5iq{`cY%|iWi1Aem=>;*qhn&Z*prW95U z-xO{euMxeZaT{glfl6j4gfoT(Tch|3n^D;!EPfr7NSn1K{^um=(jsha=t`wavcX5% zOC@}L9e40chXcQ3@eE1q3@fp<+i`X)sBcrOVomdq5Buv}s6gH>dD8U#d^DC}bFJ7* zM)bu&^UrlOeq&AdS5}jz#_{hk|18xlZy^LstH?h{JL3XCJOj=iYO!NDx$f^XfHTY& zt>;BIaJ5n%L=}p;euro0q$qrPz&#$l=O$~4$03#;_=9Wh84{*TkY%U%X3@ekn^Qz% z#_WBMSLX_jqel##d&#`281PU=gDfh>`fTND<6^fQV<5%wWvEsdHm#1u%inB1Uy^OK zY}10U>w4V#WW}&SnY6)76Fv_v&O@6bII@eUQcmD2Vw*-uj56^2N&uVTaXS`-GH~$2 z3X(>FRl1oBTnIT8q^RJw9Qj{D0t<*K|qhG3gC930+9e0;?qv9)p^%o zC7t4ioET=Gs8V2nL(XzIfZz;Z2KXS2T`{Gj{yRJZ&!NhYgR>k{(eWx}T!KnmYA&OF z7Z};j+xN8*!7HgqOPsAcV$LA(md^Se7G_GF;(Rfl*|iEWc}i`neTUF)u*Crqeva)n z*=>LJi9E_bNdM|so0QNqVMFlz(Pp7`7$wT+IIy8gSg6U{l*l|3BCIPRFjwRZY;%Ez z9TCm|_LoMCg$veA!>2dMuvjgC9Wye=>v=aqm^P29Ik`QH|F*1Zgh4fLB%@TO(z#S% z1-BJQ>8Uk>WhR}B6O%fJs6mmC_qo-)9h{FX-%w+);HUVZ_`(2WI=s{IP|ppX>^$=V z_kHa-Jk@_czJ1l%?MvU%|KbZa_x9}U{`LIa9{*SN4-L!vemyz4-OJnQeLK1;droj? zWx!~;r(fTs1o1|Q2Qh0fuM``rVG@F8=>BAS1q)#v{t)+e&a|lFC>T5TE~fblFb7d# z3=eI@VI56g4bH~#E01muhcz{Z8Qiof0W1Yep`}bmHKW3sjc|48=LyF4@Rp*|idd2q z7|3brgrZ=aP+7{yNO4vTsD#D2KqPG|Vx6U;JIBDdggTJI1aXbf;NB2+fuF@-KAZ_dR)b4L8YC8hg+2A#wC#xGc^aIQ z`@>xz3N8_!L|TWtbYiK+C3HST`3}WUTW>%;) zXipQ91-B8P#a+h3l3O_4;Wg?DDX=p*)xvm33#~;Dt#+9*kkA-5X@*T=U?D6?2=&0A zx+51O_9%HGBYnoG7`>gfL=Lz`=pDr>74NuPXvXM>ACwC{Seo@bBuGzp9#sU?hFG8) zD|+Q06ZR+nZ{k1e{}5il#LoDi&K_;8xXpG{-`^Djr+{Ugf06_c`W}}y_^qd|;HOTV zS+I)wNv2#M^L~1_a_d}3q#L=;2>@a|sqXG{_;WGIo|DlZtAgO$Za#P9fb-jPeOJAg z5DPs>zv~4|gI)wOF4GeKf{F{heEUAe@;d)?(Q_aB)h`XMGF);4Nl6oVQPHT_w|#zn z%=&qJ*L%I@y5N5|dA(ko{NeB6`T2g3emR~Qf)DHCah>n+;pV|}9a_BJ8|EJDEYouv zc9P-RW)!T*-(IxqVh8wrXK!Ag>2)0-GbK;xVw4W22QmV90?Z@zO91qM6M=~*NWm&Y z{j6gX81nN6naNcmIz0$eTva4+*`tOb)mWJ_ZJI?2M{od`1LkA;@5#Z-`2quka^xVm z2wih`#w}<3=mhuG@csE_w|T1aH@CNzTPXNE!lU;>2(n~FvR2n9Md z(s!5G9fty<*GJ{R*tTwDX@&hQqWk@_Lo7llq}U4*gc*$y3D6xSG5PE$xiV zt8$!=6%Vn-qlESDLP}HvfY^*mkTF<| z4R0_wPjJh~P}?)O#oLWAOr;D83JbdjT%d6^0AdwWkuit`+Tj)IANsXgTinEDHq#j? zOs!V`k537QtFJIHSG$+7T0^oFlOkeJwn=1N+s_z^RdQMu8K$F0F5%)F<-ZP2E>L*L z&gu<>i*!C8G=XNLDufzrtK9c|PqEguZpJD-%=f=0Pb_iPRgT|a_ye7DvH>?r|{Y zyWhTTJTC$xyU)}R+)L#Mlz%Q#EB$q`+cuRF3xze#muR$Nmi#Z;6AH-(Y>WdLCpl@~ zTyAIwm<_v8Enh`ivsxcAAmm<&<}MJtL!nYx0bwnf5;bl&btqvKC{tR%2{#Z?y*PSdmJ6d*|nih*U zYzvA6&Q@SKl)l9$aMrvD>da!6iW*R;*_@{S0sGSLB8YTXsH(!|#{`r<$tSj`F@#$v@G zw=boSe8cF^sbJumjb^%`?RXQ0y=;}AE`DQQ{MDGozD!7R`i{>;q-%q4l&t7XXh{`5 zo0M4>n1cRg78>cuvC>cAt}NK4_slaHGf`>aZ9r>d!BSKrHZ`k|WGEhWU=r9TzP1S& zZ45PGW$X@y`k;<;f1Zv^|yUCFlczbjYl7PqAo)b1{$jRh~tr z&}!l-Y%wK^z7sV=JFJdf=qeyH0R3@^;ypKG@Qi)QnAOyvV$6>_2}EhBK1uU5tA?#; zL`%~q(zWAi;V+)HWii@=Cx6VF+VtD`WbDhK4d*D;UhR}Ds{IM+lw8BuT z=A)pr>XHYdi1c8^+8l+}+j=3N7BA=qspIm9P-M)O=3|}U*ws<>yObOBxa)Ik>+AbqjGveu}z9sR1Q+%+SWgGqev{58qAB~(qF<* z?B6q{$=LVH2F5omiVQ`y2CrsJ(xh))lUy+q(W)DA>xq}Vl1a)*yNTawKs4kcK7s9) zZYvgZT#^24C-x(XEjch7Edyb>t<=x%UWfJ zSVCshgL*nWkwJ8E1Etk)DXElVoU)0$s<~H9%cg?s+;uA5v;xa0dF5CtS?`Sx%pSm0 z!?ih5k(rnIQyJKUyj$)bQA!Pu_5?*^k#bL166K*%8)B%iV#ZDygP=|G{-JF{UILue zXo_ks0H0}iYFuu+xMWP$5LXKmj7r|8NwZ53wbD4biaMb@9hKPJJc`Zq-N9Sjzs5U6 z85LTI3&Ix}18YKu1)1qFyT+R-A&`NY-b4p6P0TrzN<3nU*p?OM3AVa@mge&%cq7LT z879KJ`cue@FL0$9FvThu<3T3O!GGo{0Wud{vnX^J9B8ruiO;V+@IktEu3 zc;ZH4ci4$xZn3m@6*`=~at=6}HCdF_D%yeNn3NZAgKc~(n!k-1EY;vz_g;r`1K+)N zhcC$lnaGWxgcYx0v$WYjp5QR>OJ3!r;yUlW`a3K-;tIwzMjHyNB!}P_@G0QcmfiRn zYT;DsgIo^zVW}4)`ju2<`F<}9uCK>15SZVn!^rrM2z1D*JImhxXy{s zgS}H#Zj$lmV|5QiXEwTbn_HV*vHUo$@E<2>aeciH^tYbxH+?&9zx%W=dk1B1^!WUK z=Xk#FUwQP`WBh%7FH;{U_uIOK#PiYydIF_mR0X&}`4IcuxP|P>&?Cm++l%x$Jp}d8 zOFH>I2_hThw5j4StHdP<(Dp(Spx!dm2KAhH4Tx)p<^HFK(|Yo}gaX#$q&ohL`9z60 zzh+82j+k~$e{g2rW!ubO+jx+FG**!bTD(yrw4LAzv~4p$0=>L-aGLguCMGS#l#{+C zI)<7Mq2&q2#sZ?@(_yfFQqg6tDrBeq_3wNe0zG{R2I7Cuw~Za0W1oQbll12B0u6}e z6+x14KylcB#;!fX`D#_TML}8CAnHWcH`7F<2&r~|BQ8u=ITGZrn37S^!iYl5T@HY2 za+j*sT{ir82>YpszYi&0LU3K8aGH-UUtF{zJVc50rB=80fAVc_NWn)4Va<#)1`?J7 z=23_O23A7ic*p}o@_t;L*r(i+sqC+B{BcWlOB7^K_|=z>V5}1_Pqs0aY4*{aOOspu z`PWNXG@wr94?Q4tpicV@-)uBJ{@-QX|6!SyiGiK%KUOZZr0urY{!2K1s!ecz%jgXt z2vAca>m{+k0{wVNCKnIXfW6B3YaCCcNYuQkrkvRjgu+%=r@r#eMn4f$j8XP|tttq8 z7ftd(1*rA?DS6j~+{21;c_mMohlTjX#>d$9OH|v{Rr32*)>YM|VA(yI?=i*qAncNG ztxH@g7`#s0)Lq=|KP$OBYcA(~SIqkMbojcteO!I%eBB?dXFcfAS(fYdY-nezW$C!I zF1N@(T^o^##fn~8hCsE{xan1<0p!2WRe8RsEnh((QDUFPG;t84&f=0|i#J|~XG(zP z0&{@aL-kt$&;xXX-hS~y?{dX^a(nkr-MP&Ix5N5}378GKG5!Mv9b89(?9P^yCyQW$ z^+W}UfZ$c?0pKN`_3x*HWQ8ac*fqr|kVgox2|xg&Q3?;x0Lf_p)x+w&%hAx5Myn$v`LmXzUt@sPS4bUY7miuiRK99mMm)ICzm;AcF=;#o5ptkKFer;*WMlm^ zZ8U&|!&g&pGT+3Ck;pwyh7%+|bt>D)ik@gVAF-L8WcJo4GSwFQ^9BWR8BnbWa&O@A z)?5gp78Gd^VNlzcfb4XycMd~UP@S2F+E}@v1sCxd6L%1$l!NCeSMWhe-3s`Cu4=}4 zTY2_P2QNHM9Ug4f6X<}K zIOeT#Q}OV8gP^f2MV%`8TS9Yn&g}(ungo?XXotb#mIIX&VTQ`-!&2I@PW}@cDr&>v zPAF$r8_Qm5b(8zp3>2b4y3)V0LQV*VchtT%O^S4W9PLRE5%X+(RWLL8>dIgRON(9C zD98eHF!OjTGXWx69LUwUU~=nirM(5y4u;}ruOlP1>qxBjFWpdq*7pu^7jY;bncR!A z*%Af-tKH{NOrZvXFic&=Jsx$KWK#m#_AirA`AYxOSzofp%4=O{Te}Rx_}Zl!%~ywU0t!=a+gKaH zgZSS@EaAyzV$r`zD;P~BwH56Bs4XFfw&5laTN^}E$|i6G9ly}%24^sSSG@HONgAn2?Rj;UL`D* zM60LZ+XIN1?fDsmNXxKik(MCMK1&42DNFF9mAFGZ6Q4n2t9##@@%kSG>&O5HUlL*Ga=g`^DMYmLdSg&V|-|sPP96YV*R&d8(<0!!)G#k zjAJf7DkLt!b1fr9wvDSS6`L@t;xK35bBnk%BU3`ToxL!r`dT97+ zN)vR($bx<_LQ3C_~^6kny+`u{=HjVp4HHvEaToyNnx9HZb3+cN@O8&j3VzxFNlTQ zq()k=6LP}%vJiEcMmJle!JoVK@HKo5WGbw+) zhN~ttu0wuFRg9CIMl4OE8o9pBZ+CoRg&4NoCn34jHp~RVt|2>GYeJ?kF%5clX!F$i zt|@3^9Q2iyJ0mZ>Vfx)z7JlO?r#ANQ>hfQSrR~2QqEX3WmwA_1P0!Clo5&!tL!JZ5-B5j zOYunR=HLz1qbm|nIy`L%OZ&v_5h_CRS*3E3yfE;|$0(k613*dF7E&7wQUil8q1h1-5(T5!Olz=moT?P1q4uU635!P=v zscFxcvcZCcqQG=mnNk3{!13Tw^An!3fZFT73mN~zt`0LZ`+q7e5dD za<4uBKmbWZxjgI<#-I;18cYPiXf!6@34i!byF58~m7MHL0I2l~bl|$WI?t=R#&aDm zeq4%)x7~POlaLHM^ZfX|`Q$A*LEJZRE8Dis_4{Z zMa${OM*BovKSfQcqYMOMNXBdgYKVqpgeu5}YgXCt4g|8=?=W?w9Ww|jFsS)R?F9qs*$NxcZHn7zOSRCN2T-O997annOwo&*{s65@c^ zSLA~GLpM_?&r(JgGG#nO5Y0h0Bz0GN5s%u)e$GGj!3OOmW&h!>cyO42kZQ ztA;f6BL(Y`Pvj*fJ5-rD-rdni?L0P-@;)&)M;T(4<3NvEEtuLK;Nsa`>3t9p(esG< zcTBk&ojh%hAl@X}Am9u=x|g1i{Un4|f2gGUu==~LLE;B0_^_cdB-h0H{c*QKcofRQ z@1>jNSu}CR;;p(RnDW5DVI*J0y5L+fh*_lPY6<0PU3yF?ky=c@B#*7Q-^?Myc|%X! zlQ(7t+mr_LM9&Z*L8RI$mDUa1k`-Gw_K!+9k`+6?NjfH5ODSg1{FX(|Dqfk$%~_x- z{?Tl814kq9+%a+i7nsCi@i1+d?C68`u!4bcPlu)}DFB74x3c1aaTl*qI#O53hr&(V zt)3%@GIgeOnSc{Bi35{3k8H>5$BR3(lK04tAQiru&{XXm1Vw z{h}uTMZSBHj*U-{LCPXcbE{|5I`)4%U?MXf3F{!ei>JNmQKj4rjIxyl?uR?ZkTr4q z9!vk@%bd2HRZ{t+2+Rb76{?C@1ZH$$kep0JnSgna+oeCe4r+&eE7O>TXkcKN?xGA^ z+_7Zu(5T{R5(Yvz*MJ0BO%PcV+xVcUT|B&M2Iq0+Bq~+XjmSz;7oh^+Ofs@;T2S>v zozhb+uVLF-X}u1JbQFZ=MhU!ii^?E`#zKl-RmV7IpCZ?Fh~(-*7N54yB3V6Wd#_lT z<4=T-Q>1tbdrmcw5kh58cYc&PHE|VC;Oe54Poq=%LaEOckWUR}3kkVf3b+E6%=kwI zGf66{bKurStn zo=o0W&VC9mDNUvX2$>#np`Jy3j7k5ThsQ~kJ$X_w+b^E7uVky`9OsxAIU-Y)bgV1e zjtm?j2av`r6UpZAM0q4S;`mFdd0%WOeaA9`?znlIZets&X76y;IijvkZ6e9fctzw$iBLKqj0L%PPJVrwx4;s_^;# zf<@m)r+3o`UT7ABF;!JZ$9>8YZ{b2w?1g5jL5l_p9s%OWMDNGTuqf8+PXlg~S>*uc zVQzCe5yU_!M@F$Ia1$gqaE)S!TB2O|rKc5cI9Nk3ZvRy01Eb-zk2H+s=sjJf?HbM+ zg_#I()Pl4TAnO}M<`NFH>pYlB)J5nq0hnF66BQeB45gu`ZNz>Ggek9lygFrRxDLfj z%n$bLn(^NtmOqBS#!vR-6`9S0fTeOEDU>+}sdEePBzj>j3wIg&Am@i0vFVRMsUkI~(j4 zgzv3cPZAl$A~g-LN?cV`G3Ab8wn{SOQELjWKa-IC(#cOj$-S3V0bCII$DQSo7aJW& z5yi5aQn)-Jc+)+h9lp6*5+tJsNnKE5D>XDf))AoQ8&{C{jd7?0_4zQ8w+alY$sClh z;V`F^+6H%>P7KCLQr*D!VyjcpRGAN8xX3juf^2-jD&o|pEN$aFfU(rq5s2cHy|ui2 zrTS#E3??5SW*I^bY#{a(T{M7$g}C<;>taD2J&f~qn zziN_&@kN5Jz1|kS2-Hm^R1RMwPeu+p5_IGgn z6M2&LGVDHy=x|w(=DHnTv?6X}SY1RN-(?wiL@Zf_RAjK*D^jUFUcJ2U(K0P_2}MM{ zq!K2Yfzzqfoq@>&NeFtQuIGm!Dwg^h5 z(X5s{`_73kb$aHl_<4+vWTsh?Wt<`&qDFgy;X_)}+6tKUq+<1NqFKJ2Bq#$BMP962 zl3pQ3%mmY;a~6+w37rGFqFJagH7#q<4fPr#TnF!=MTTkGe6Q z4mp5d*`}vtqB%BQKW#7x$-;{D|Hs%nMQ0LlYqzm&qhoe#t7AKPV<#Qkwr$(CZQC|G z_Q|*Z|D19582e&h)u_6tx~p1i)tb-joOJs;{)@vnj;j=-h;*bU8Hf0;LrDnt8SEwC z1hi3~Yz(!b8FA193pp9X#xi?%`q+!)9doM6mh2tOsSWPDO+|c+t+g?jiY<8S`OuC4 z$f~o1@lTL`h5kUc_BrU_jRSTgamBW_wdk36I>>d|+{k?q8tindv>0+warzdqS=MOE zy>h^y#V;$lYv%_d*(#-%Ad>tsucG`dwGtZ!4A?E2W}s3iQ5jCUoZ`nCV;1~~Ut$66 zCvG0Hm@CMV={pMSH#91x?V8CXu|r$!Jj&{U{!G*1iS(8S-6W082f(f;oF&c#%6GJ} zEp*Vmir9zeJ1}^u?x#Crb|2Nw47oK9fMXNHAd~>TiJ@J-_m=B&3i(XYY;Zn@26Zyk z`LXDd2LK~c5;!P@^Dw8lgol_gCT=ZO2^NYN9s4k45qTdvg!MLv!6FutE2sjR-k|)V z`4}bSeu#4|OEeXow-~>;J;gwV8%YGA6}pl62ZJInV>EI>wf_S&hOBX;M2f@A-{Ge! zBu4HgGxf7S_5i#I0|YZxtkbC%Qfd#X#Ihk@Wj;{I&^X1r9JLW!yCe_<-nT@T1@OwY z{ZdH7J12A|H$*IlkQka%G#`>xF=&uW_NFTZ=cqzdUzN7*%y>(OGD&XTs_Dzs9E&N~ zwH&=h!zy=m-{H_&&pDKQ)vL7~ac^i5v$A*6&)`yB?Ni|o#5Xr-XAxFH|-%lonGI22OA}b zIegBD{GYEk6yN*0J6)egTbM6^k@|u{wRtb%hB8>($^+82H(Q%EEtA6Ia+0ls-&r0+ zT8ODWz3vsIO!363nNJ(zECjKZh82`~am-d1k?d9IRRbBARs_=npj%3kl!om*M69_e z@jR7SNx&SqcC4U?)*cw-aj24k;h2Y$ng!$Fq8GLg*bi0YQ2t!-yf&00J z9ofK066nYaaSe~r7rTZ<^mxBL1iIWcdJ1Z8NV4ZGc+QHrE4j9TpcPm4OG&hvkn5el2TRy8u>9xih{c*|4(h#{}QKTVP^mDI3502 z^ycv6w(i^sP_czBP@jN{bf;L*{_fF=1NvtcIVF{$A; z!?En0O$pY0I<$lS{-nu`t(W=sfjgdy$t36S6?5uEW_HXC?r^8%f#(}`PQxvGO35ur zq{%+5xr1%OcEa8LoekgD)Ici7a^Vh7o+Ed!()f8#lj{<&cO%R7h(ho26^tP7#mny~Onz6oi@GIJA zqKk=d)4lh0ALZXpaoP-i)5+pj?R>#3k3r6BWlZnz)EBrvC<++fN~@>;=pRm69b=&g zi+;tn1_&u&sI);q&y(yZ8^o16)SZOKv+s4qeV)GaNSMnHQ|x15j<&yTgN;0WHj-!u zws;-Gqz#N{!4=7W5#!zB4KQSC?$D`VOg=Ha>d@nx1YVttFM0&j)9{$nXL~g> z2SrUcBP%h06Laa8=KLeN#Z8^98ykEaZo2GJR$~L-XGP0hB^-+%9LYU?TK3Wyw_+-R zh{W%*S1O|6@hK-A%a%x+!NBB6Agfmp?V0JYm`;lXKE!eh%p94dfV&atWa%Xf13^9! zC()bWCXhv8g^6%|k`<$p-7Sy>*!tT`TWRv*d>ykgF*4<2h-Z;T7IEn00GH8I7XdInw@++$F1WU|e_3pL9JmDt*){++h6e&$ zT^D0|vj+j@Y6}z>ez(h&*ee10IG(&_yNXoBUYm^K%^BiXI9TQ|>+=rc(-K&c!V4dtlejuUSf0A$iszIzAWK8mB z_CNb)no44KWSNmPe!jaKLQe`?!Kv(}I*5x!5M|=*J}YfAG2mn6I}s1Fb|m$E5nWch zM5aNpd}T^_WC`l=`RSSap&cPW-3IdE@&)|5Am`+9mrkPaVbm}qGR)l<;Y`ee8x$*S z;GS5O1jQh7M7tA$=isr{eV_2j*U9&+U;9j!k#hmf(G$UgBs+ZHV%GjQX;$ zDxFVT#x-nj@I$!pt8Xu~9*ki`Odr9h0ed-3Uar4 z@U%-0ndLo7%R{$0y{IU!Wt#_^5d4L;F{6LilzrdO)~<-{jv-9&W5O(&s+vnB|IS^k zEtghHNi`mkK9+H-VWWm-0ZOz36?(zPjex5aqIX#tI7Ck^hDeTEkzA$3rO+P^=Zz1- z_msn3de!A3Pf@PP#KIY+H8L<}N)@#xIddCJBCfnxIK%lEaM!5&xS8Vi!H#RXN4IR5 z%NSAsTf4^=yJFc1H-_ao2|4H#dX}CAi$tl?s)JS=okgT)_7L*GQ7!QA*CruvRDY6< zBhM_|eCXFd`Q}%i$_Hh9c)t!dS)o9zi6cjvZI{*gTUT!tutg6nso0#IH6{;Da;V+l zCVi=~Xm0lE=vaqRQTa;BPxaO?G+Nrns-xr?Jng$@)ZE$#o|+ygLFAG%m~{Vjue(57 zEp}3o&#o=2PS9Y@ok`MZwjjNdaqFlLhdZEyj=SY?KqO$TVZhArLBum6N*IDq(Oc;2 ze|BNgJvt{<{!IIA7;g&##LtQc{&_ou6&r^&p(M~U5?6-qUY#(syuqL}kSn3eoW7de z2R#+R!%(0h$ZjMm-*K4>at1{;#cmGYOdJ)D1yipbanpp6Cls)|d)6K&@bd90g)Vih zV-uPur90!E$HUcCAMJALS!Vh7L33ph4ua{S)fj>V(N6ChnU|BVB#ODjb|yMYsVaij z*Wu9m!$8pmm|;y4B|j*Z7oCw+ElEr;f{JkXv4>e^paJZp9NcMU&{qgnP>$hkn=r(` zZCh^UNzH`*vElNk(8=>Z6HU`lwT|L!AFc}0Q^l6$6!a%&Esr*nJ7sLLj8a=Opg2tR zB+39T#$ybrj1p@V9i8IWws^;+wJws!_GnQ~&Jh#mPYR8YMf4TZgSu5otTAAD*b7Og zn&(TYisqn2SQR!Ea@GPKs3cHOMi3UiDZnXKHdE1xP9oyH zHR-KT)6XeBVUnz}MicH8Cu_oPUW0K+qUQV6#KSan?KcR5l=JQItf#shc*U6@HtKWW zu-HSfoYd}s8UM91j1c~M9pa&y-RaY;(+sMpp;gr@tVPD4N||69jdnFNH$xD96p~KA z;6cui`~vLPm*3bVL*>;<{VpVj;g*~>%V3#m2UjpQc>nAOHAUfuXy`}&3%Zuvsrn3n zzfF5UdFIJlYN|2cLtsnk7h51LPeJWl3Y45>8>Q&D*;a_%kUQr+<1X4F>a;_(kIToq zz-Y&{RwB}(vZ6~wOXhBENv7~z3gfg8-n~X^@O|e85Q+%1bT#U9XbTiLGC3<2vx}8H z^<4$si;%k&SPG^r(yn$27P3ZER-cR4ZcKM^bsHri$xhAK9b5gj5&lrVs)2Nq-LhNZ z#AP;&)LI2U)8I@+f zR*wv>_W2D>5B|4HbxdNC7*@x;a+}z(;?>#W`HuBE_%>i_edaF>Cf7TXOTo>|&R<-< z#=E%mZTlv$w%G0Q{tkC!kS^>1G>krRhODjZAaUy>pr7^qk<5FRKWO5?q(b2_{8g!k zW~+W843+%BZd8y~UP=g8M=o{orx=O_eQevSeHp-6s zZ`mnY`Kp=?7+MA5o*E&zmSB|zvt1=(K?`Mj4$J zR!U;voB3$X(mCi8r64=Ee5ZR1DWq%}++oTT(PiW|DltzJj##F1c?GfFUEb6yg1%Lp z4JIL**`RBKVQZ5|O(|P`+`YWKEnSvdIwV@W{0dj5(Bf29nM(k{6ai%uw*^ykzZ)uB zvSf&GKTNcWMf$|G8mTW70A9S%-PB)$mf9rmq`)MH`wTs6kuRr3IxXI}HzHZlg;&Vf zoK5;QhyIn7HsXrGhghcz{Jc3*&Ng@&!D-@clIx<)orTX!xg+`2)QjGGw%qBy3f{As zE6A#OMu4l4#$Qf8ModEC+YY*gsUz%9raK)J+Si4NwF8F?4+$4iIx4>=&5@-QaSfAd z`gd9mJ}r(eB}r%eyM$%LVS9FBV6xJNN`h@^p@%=ZXPk@=pNTZ~pLIXg4>M=(G!cD+Zc~~SFUTO3QZm4ITe}WLNB_U-FMmz_+1fj zrrj&SSpuAPju)V}x1K`Agi~DhTcvwmSac;RHJm9;KAuaM3X#5u;#y&8_qR^NoGLFEwsgxrZec>kD zgyuwS^t-p%=NjYmp6f%8+m+$*D#v6b7RC04*>L`OR(+zPu`Ms;=Y}=mIZdB1)bFeR zN~@j^!OzRqj_9$fz5yRNEdRJx%i&2;)Pi={RQkNEe#LR65zyleiV_223%(T|PK=Zt z0g&!>&{x*7&Mm#?`BcefQG0r539{hRW$R$;gjS{(wBIp(Z%)lQ7cMd4OsYhLO)h~- z7hXVA-Wni#;GjnmxOU=I%5vlZ17nOObJoF=UqBuyTQP$uQB-Y;{Sy}!EZB?7jrwKp&b4V z@P7SSn#0%qytGXL&OF_JespECXMxl+4 zKZ+D`BzfEo!d<$I!`JoZiAH33B7)F2xDCcF0oNaVbyng$1pcuqNcPWZ3>aE=_KE35 z6hP%iOuY0WWHR%47Z|$rYWj`GqYX;h;)9<^wrL_GowOQNual zb5cT9buLJ+K!V^RGr9ycY?~8b;9#w>LL@aqt)Y`&okDfF*-h6CDcG_nfNgQa5QViD zLe588C{>Y!`d84_bF>dTgWV0;j3Cn0A)hMa4d9`3Sb@=ZY=}Ngsn)}y3C2W)im(JA zX<}7D?+0jtN;@n3vX4~Q)Kf~zV5|>P%d9Jiy(BMpjR^Dk`pKZ&8oW>E?rmbB<~jvc zo>#ceJ4S2z%5b^-fAc4Qq9_k0V;#C}f*XaEAv|YO^Gv7%cv92z41Drg6%oVPshUTq zc>~RG)rmF(b7~>4WL91*#1Mq2&(e>;oN6UjMtb{FX?#hDi5A%e%J_PY78TR6fbynaWknuSNBz=E>lkppOSbC$3{A1UD3?uav zN59ER&|!(EYv<$Q_f*MLO4KdkLqU-4fZ+~fts>582$;)f&JO!mN(o{{$BpRy9)Cth zkI&b`!u>)HKR>(8_U32p`-U*+)JDrj$d<`_Ya91yaM;8 zJ9Bz}Hv3&Tx7tCQv;0p{@3Dk`-`R`oFQ!$g-zZs^CEuIpI+DuVXY{5N0Bee9cXUc4 zzkyGov(q_7n%0(-2GofehnuQR2Ud?Jv_c@gTb=cC1zSd~-n`Fp1;6pXFQ58;HM10k z$Zba~TXKj+DihMXj0mGG@k~9fnT-dto;3bfR{?})SJLe>8YRQk3Y2P=QnGglhvtwxbEkT5}^Uv!JCIjo3{?A4oZd7+?B<+t=&#R5{J++5{& zl>5584vbb>i>d~4+lT>a$z$MeX%xAfiv=^2++SJCTUQtmviL0mTah^uS9p;t$254ws~SW0 z2L8-+RmEkA>5vJaZ7XBq*BqTayGWh+?cff){9N%C6nAYB<{?h=F$c9U=4x{w`}}cy zqi9~ql?*nnEaq^fG-8z$Q~=piYrGL!qiUG^6fu08+3>2p;X!*Gw7MgKKKH`{n`=4N z-6XM!Gq^&DG7AqZ*V3!sCLn zE_88q8&>-@lu#P@m1C0cDK)`Jb}oOArvIQn@xHrdz1|D;QD<2om|9~F%cGjg^oTT) z8k^|2$jd(zMOD*@=aqRcoil3|oZB#kPBb=ZsYhbMLB*_J)W1}{!@%`)w9~vvk5tC( z8<5&`f9bz3B_27G?Ro_#&M#IZ9--4bQX98*ZFK|5%Fs+)kp7{W2r;DpJ#Z!I>LVi- z<}e?xQ(;|V%i00Queg|Bzfm2@i%P~w*%23PlYdE{G`%?QQEAm9zV_D!(*IyFV*Gl$ z0I)Go$f-uv0Z%L9Pm_*5uifx23O5<3S`yNnFC#LHow~Z04;|qvM1-tf#MW2{T!O3V zYC$_#Xk8SH0ScQpM~#aukb4-6f%880ef(-iu>PQckl^{!KE>eZ9(G|s2GuZ*>O_$| zroF!WEdqNHy$1gaI4cZF=$)pOsb^KPD~Xurxaj9sHEgg9_Vw5#MQIxkTi^xtENR13 zusjnZ<8DCN`z1jZFD7Hdc~Uba5gQHU5nZ>4J2CqQU$o~PDep8LfE}7W^~FLB2uMSSJAe(f zGB$E+9wpa5o|FMT)|k7B1S&lYWd{lWg{J_dJeGe%Gce~MI#E(*-cK;*W~Vq9hts*T zZO;jy>=p7I@Kqn(w(AoSa4}wgBU2^}{%MnX zuucT?>EiYxAG|lu_PXGTJl{jz_BNnqQWW1F);MxW0nA5a}$7- zyhPin;#*Qq5`f?}q>EM3g8^`t4mq%H+0bhuRn~ucsTOZ^V(LR0ge=)xxS3~-XvDouBm0e4f0~X4lneSXl)|21hI)w;|#XUSQ-fZze!%PZ&& z#wsad^{p!kuv2vphFOlK5sg9~`{Ys)*vadN`@iRc-Q5Go8hp4aC__zMU8l^Kp!)c@ zMkpuYqnK=PPU6Bsy~VGELwsfbRzrBR?Sz^9tdO-mps5}0Uht}R{KLI)gcS}L^9fNY zJ>fy(1#l3M|B=XFl&cE((+^U4?L;4sEJ`Tk;9mk(%yh_DxVkSUJLRVasJztXK3HE& z(}IkmNDsBu?=}fNaV19dCOYXAv%8yPT5;yz)f`d6?pfWuO>6M*|7;7nekAuYzR~Bo zUlzLd%Ao6>D0N^DtGROpIH)G0u@*mf(mF{R{@$LD_1IB8>BVQY?{vh#3 z$D%Xxgtk8GAcH8)$;L>=fR!dg9^v9uiL)$E-?v$DF?GA*VC*r!C9U9+J5}abV1Nx+ zgeKk`wr^_$)WaY)EUR?F*b}vK^7l8T)j{w|(`r|%(=d3~)G6QJ5bOxhR6D?yCWRro zXp}wJbE{CZkS)}oU(OCE&xD{DYH079|J<{ssVsgvJrRV1t@z`kqf>{slm(FV`@2>TOX7Ri#|rL0bGRyT#843#WviP&HY5oT0dgTSBQ34fDLj zob&vMB(x=<(wrDuLA7(F1%s%`T=?D7M`iiky-28?*8C-0s?1BYsqIv`XYMV`RbO&6wCWS`s44pl*tqS zC7a8$+zg?Q*GZ4*@m-Hkr_J@(-SxnT+)XyW_t)a)=fg=)&Q^$z*Y|bGv)rrNY-zAy zg~~S>r^#yMATF>U@NtzyQ!?%n^wv+nl+=Q*d=V_)-AUDw^z-jLuJ1wTt~}{I5Ih)R zaQLW6eJKZ?#B53#9iv)~wp+~hWJWzN7akqoJV8+@dy}EGf58p2)zhgVwRF#29&?g~ z2yiggRdZp28vELA@ZqWwmT0Apeks|vnHkHD%aruC;q8%unzj0>XxsgOIG$f0(ujA` zyJbi9DfH>GcS3XX5$iO;3kDB0I(0Srr>t;Y!FekTj$I5!k@$$h<7nDq-ug(v5W;8u zK?e+hcO!p(U~~5b6c4U4&F3pS4KV7E+xIirI)dLb#iA2G;inAvC47}y2>xMx14YWY zlY>Cur$sOPevL>H|3gQ?_P?ghIsQ9sj<*qw+wus|Wt;(L@^Ga99`F^bka>^IH^(?_ z$lwSD9gJ?t2>J5r+aTt|iRKVCzCvT8tyIM$$bL_%h+{hVf@kQxol5Bih^qv{1FItLEr*n_2&_K0SS#>n4$ynXrkAKWU*SCZ|yFJIQsOGx~| z_;#s-0WPwWNA3&d08jTENw$==Cr+}5jj>w>IH^9^@l9F&B8$%MdMfIAIUD4SxpaHN zegsmEl@^I3z_<0k?Qony#$FmN?@in@8>(IrC4(mntA&V*fb(qL0SWqN+Y4M1={$AfWbdon?&LRsw^TR| zd)-~OuJj=bx(k*MYsX=o#$m@+q6uaUDx)#Po&J*VNoj>vnms8EIbogTZ92r_FeLLt z6d>x&?c zZh;VwaUM-FmD&p|lFj$cX*zWl+n<(Z0vXwRGN*pEQE?InvXX_M?dBJ3&=|q?&i?+> zs#t*>3RPUpo|X>r)>edzzlbff_0?Hb7&8`kj`WN1ebihg9U}Ml3-E0$UiH{?%!$6Z zb}ad|{%I;ey|X%q&VbacaHT7L0?djfxxwntq23e&(Ie^}wy;h#60SmOqh| zW~{Vfn9LbTg*+asQZB;no9DH`^!=eE<|^#>ie>P0gXZ990P9<(u^5wy{yk4Sol>OR zgChM^7QI~bqKGMMAM`TQW;)lHWOos&tWx&-ec@x;xvFJYGSJ?O!HOI~vQ@Yx3Y|H> zIkNGu;vjpP;p$Q%ThsMf9*EWF$-SMl(tmr+r8X z?Jr%jaACGsH*4NUA;uzT;_qnLL~n?weMcQtA=%lD>D4G&IvTPiob#B9G*2NPYJuK? zb;UzNy{E+fK5KKB{y6Ig&46&hvf_*h!_h5Uy-q{*3oy8-r~GJ&is&B7$SaME6JnSW zO}a*+f_KYK8FIC;Q{X7yn($4LoE>X6EC!=K4RHZ<21e>$nXus7N0^3)^{#~8Bfg$+ z4F0-yoROp96{!J6Wy~>`Nt7th8b&Rw5QDmbC->RpuxlUK6P~a!;n1Z#p!y{ks$pn@ zHMr14B&>=w3RX^M;#R4q8hCT%;GktNaO({E_GrQ2BBaGFrq7c5MH->8-c?Yj+qzsJ zwRJEWz@rKxB8_O$!;Yu{Nc8b-;;V_omCX2@&BW%uvwWn?P-gE+W}CvX0%fb)h|+2L zr4e8q$ZqRndvN}IWEGQIY|#TJ8mCkn-0Z)CU8F#WwM+Xsm56m#1>-0V14U|ZGmyKb zEr~@OrH%}!_uEOBSk`#r-O}Y^iqScjri=q~g}b8hqGjH5zo+5HbpoB(*_9GJOK2wZ z(+I7u9jn?^f}kEGsRT=nPzWTDJw5TNGHG;ZnfB}D*2R&|k_`N7lZYmX#b0P~+=v#} zuwbEE%*aBorqJhA?f<&&%EiCS#s6eE;FA5C#j|X)0x1(hIG$XW)5&1Q6jpBWT|y{1 zL5eI;Jt;alP)QCdBkxPMUSJmWsMsRj&c=f2Qj|c-EVIj@oXo=4p@~glM58HN7V(|m zf{D@Ekd7E$53No3-62kiE?B)x15{G4nr6WNsJ*Ndjm!s4H6fO^Ea5#QMux?h;ZK{E zCMQat4#FU1-Os=&&}6R8rbECx~LGq%|!cH5X($ByDvw z(n@PRBjt+h$ zfWcfWR^~?l;+^}PQyQWBPmrx#!Y0B|o<%+6J3EwRkZy%ACKV@Ki8)=%wQ-u(J8v&w zZDpLpNZ`>lp|0tTQ3I(B*2F)_1CMX_O%X-QoBe<*wf3!K_Q`b&w5rpenDZf?GeuuZ zjooYnt@ROZmJtHw9f=2chh(JH*L|kv`%~#07Qs4Xk3K)X1Yq~-wP@y>V##LOb);Gt zjbJx>DKm>H9M*ahudAVccl;XZPbhi9ppzUPOceJW!-;Q1cWdZCI5APer+-rWXl-KO zsWq>W^D=y$V!X4N5e2(I|ItflMcf*_)qPo`bRu;XXA)gPpLHetA#oom#SWw+ZYQ+c znsVDh)qICO&3ZLKdJ^%o1~GC;N+r^x&k9OhiqM2j5P#T>gO(9-oC!h=Y$7ep+1O&< z0n=Z$cvzbG7_YcIvU;{+7wmm+?Y#7PB3=c+Q9!AHHQbRyP^l~@%ABndyqqk8&8$2O z1UE`MV{Sr&6zebvkA73hrr$TpqN}(tW)bZ=^66YZvl35?Q zPohShF-xF@ba01oQ&L&!U(X@3Y=YB{B=VNRKsD-AcUT$2Zmw_kmYXMa%04N|lA3Ey zZW1}iE*lJ>FqsMWZI1Hcj$15AYy8-%6E<>qAo@_z9R|@KFx>1L0L0kL+3zndb{5Adcmv4QETiZ4& znhSt)GAJMF-QiTM4Frkg)pJ}z9F_&M1--yg$1qVoqn zJ|5hgp9fPN&xG4NJ>M_-t?zr!KKva&70=U@oK4O@8#xqEKLwcgPuX@O7JMwQ^{}2K zVlm++d1(X&o-dYFa0RVgYrkkQ6mycrNBo5=fwOTC9%TXWKKe|33)9UN=S74X6m{Or zS8!GokU+&Gj9lf?QVH2AN@N{7uE+CmcLrv~tLQMzeq*9o1;a*Zuzxs5{Zg?}{<#EjLT_$2DAf%Ga8ZjyHT3G{g6fV9l?QK{4f7-crH#Eb%0H6eNkS~8 za;!LujxFONil}IDtnx3AYmEI4APn*l>~=$1LLUPoF*8@h*$j9@D_xE%PUWyFGBuJl zIIT0yKfB>Y#cY)TRG@$UOs zT$mqTSjdQn$bc0!TCJw$^{6LR6+8XS@-umt(fW)4YJNRynJR(L{~KkoPe@#630!1e zxB!6FEImHEI`;WC=HGMFv%|JGw9qlN)l%>F{5`eR z^M9)4n4Ij4|5VExpBLSJ$B!33VKrxj>@J9afO@wN;{ZVeD=QLKU!O`x^-z8651z_lp77C;sK9@efmeLDdbhf#F6c6lX29})IVGv>pqa4?nqreZ<#esQTG->8I!Py3D4B*0{sJ}H$I3ufcIu_a! z%~uF-vQ?y{jS{P=rMEm$eP$1nq{1|peOZ=YNNk>zapEdao1)gAYv}9+q)Gcr~Jz-L5<)%D#|$#bE$Yw z`gv4tv)0xK8VtJ)a{JP!OrF4TnBB_DtDcXk+KqNG(umy9+xtHsd#VbA_+6Aqg<9tk zrXZrih<^AE=Ntf?c1N1x#QR8RB4i=8lLV#901_^EuIHai2I) zJW5I)=hzDGP3m-mLPcsYOf1hg%1LSzVN}+56>SX;aXlg{EFP-UT7L23e4PcQLdQf; zL8;3~zI*FGg|mFBX6%xIw|SDot6Kw0pxLBw3Es)MY@>f0NL~n=X={a-Mi~Wp=USY@ zQ~>QB&C|Zv5ePdXw0M%BJ0@95G18o?&*Vk_1x9Vx^%5CAzd(Mg0t`AJB?edbJ(hkLpyp z%H#Q{-|URioZKr32-s1pU7E4iU(7t6b<4G5b(-!FQ@ycZk|t_$!S-kz>g$ScD}Ws` zJ5qz!j4lsWDzEfY^dQQo*YTl#&6YO>n^=jBSuJPWDKo=EaX}Q?$m2Ll&2-hCsmMof zTz(}XWu?l2uqT`@_$IO> zR7wluzOZ+v>1(&eI*_WNhA)o4{m1MP{TI+>Y_zn#KxO)utg5`a5+^dds?ad$!@ijL zHFQv!@!O!7dqJ;oKVr!PcmHD$q;tGb#HSbll^I5Su)jJ3CcLICQ^Ayuy2`p2X`JZ- zBc-}Olt!_XXKlO|pXx&2P-gcxrK3%nOUvnShAJmzJk3x=_x2fOwv;4YIx39#%>ITk z>Dj1_8gYNjI80&JppB_7v8|NaYjLlVQcKu{vE{msV+QnO4YaRWj}{_#tW!vT(42+V zF7cq>0A_BSXMv7qEdA_dk+#OVey}gPqFgE3UmF`iE|skJwh4i{glmtoltU{|x3|HO zSGk;l?XPgPJ?BE8KE9mFJ&2B4allet&?3BApR)2W6yO;Z|HE7p_|0U~$G`&Uu1=GB zD7Dz>_pWH#$(;I2dNI#SU~l6qRvv-fyh|u49(-U*1N42D%o=?;KCiW9*``dBYIUmoYWg?3(!yC&;@JkdL8U9cF*? ze6!`o*qYcn_36=d!knV&^rL2RzG`Md!Gws00r_#t?vwiq*=9nS@HKZi2?^*Sq|xsi z9zQH(A4%*^fZda{P~G6SBhX-k-3P0QT6&liz8&SUGL7V?gceR#l(qs5SJpz zⅇ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 z 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