@internetarchive/bookreader 5.0.0-118 → 5.0.0-119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BookReader/474.js.map +1 -1
- package/BookReader/BookReader.css +1 -1
- package/BookReader/ia-bookreader.js +1886 -0
- package/BookReader/{BookReader.js.LICENSE.txt → ia-bookreader.js.LICENSE.txt} +6 -0
- package/BookReader/ia-bookreader.js.map +1 -0
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +2 -2
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.experiments.js +1 -1
- package/BookReader/plugins/plugin.experiments.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -1
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +1 -1
- package/BookReader/plugins/plugin.iiif.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -63
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.translate.js +1 -197
- package/BookReader/plugins/plugin.translate.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/plugins/translator-worker.js.map +1 -1
- package/BookReader/webcomponents-bundle.js.map +1 -1
- package/dist/esm/ia-bookreader.js +3 -0
- package/{BookReader/ia-bookreader-bundle.js.LICENSE.txt → dist/esm/ia-bookreader.js.LICENSE.txt} +1 -3
- package/dist/esm/ia-bookreader.js.map +1 -0
- package/dist/esm/plugins/plugin.archive_analytics.js +2 -0
- package/dist/esm/plugins/plugin.archive_analytics.js.map +1 -0
- package/dist/esm/plugins/plugin.autoplay.js +2 -0
- package/dist/esm/plugins/plugin.autoplay.js.map +1 -0
- package/dist/esm/plugins/plugin.chapters.js +2 -0
- package/dist/esm/plugins/plugin.chapters.js.map +1 -0
- package/dist/esm/plugins/plugin.experiments.js +2 -0
- package/dist/esm/plugins/plugin.experiments.js.map +1 -0
- package/dist/esm/plugins/plugin.iframe.js +2 -0
- package/dist/esm/plugins/plugin.iframe.js.map +1 -0
- package/dist/esm/plugins/plugin.iiif.js +2 -0
- package/dist/esm/plugins/plugin.iiif.js.map +1 -0
- package/dist/esm/plugins/plugin.resume.js +2 -0
- package/dist/esm/plugins/plugin.resume.js.map +1 -0
- package/dist/esm/plugins/plugin.search.js +2 -0
- package/dist/esm/plugins/plugin.search.js.map +1 -0
- package/dist/esm/plugins/plugin.text_selection.js +2 -0
- package/dist/esm/plugins/plugin.text_selection.js.map +1 -0
- package/dist/esm/plugins/plugin.translate.js +2 -0
- package/dist/esm/plugins/plugin.translate.js.map +1 -0
- package/dist/esm/plugins/plugin.tts.js +2 -0
- package/dist/esm/plugins/plugin.tts.js.map +1 -0
- package/dist/esm/plugins/plugin.url.js +2 -0
- package/dist/esm/plugins/plugin.url.js.map +1 -0
- package/dist/esm/plugins/plugin.vendor-fullscreen.js +2 -0
- package/dist/esm/plugins/plugin.vendor-fullscreen.js.map +1 -0
- package/package.json +19 -13
- package/src/BookReader/options.js +1 -1
- package/src/BookReader/utils/SelectionObserver.js +19 -2
- package/src/ia-bookreader/ia-bookreader.js +12 -3
- package/src/plugins/search/view.js +1 -1
- package/src/plugins/translate/plugin.translate.js +3 -2
- package/BookReader/BookReader.js +0 -3
- package/BookReader/BookReader.js.map +0 -1
- package/BookReader/ia-bookreader-bundle.js +0 -1886
- package/BookReader/ia-bookreader-bundle.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins/plugin.tts.js","mappings":"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","sources":["webpack://@internetarchive/bookreader/./node_modules/core-js/internals/string-trim-forced.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/string-trim.js","webpack://@internetarchive/bookreader/./node_modules/core-js/internals/whitespaces.js","webpack://@internetarchive/bookreader/./node_modules/core-js/modules/es.string.trim.js","webpack://@internetarchive/bookreader/./src/BookReaderPlugin.js","webpack://@internetarchive/bookreader/./src/plugins/tts/PageChunk.js","webpack://@internetarchive/bookreader/./src/plugins/tts/PageChunkIterator.js","webpack://@internetarchive/bookreader/./src/plugins/tts/AbstractTTSEngine.js","webpack://@internetarchive/bookreader/./src/plugins/tts/FestivalTTSEngine.js","webpack://@internetarchive/bookreader/./src/plugins/tts/WebTTSEngine.js","webpack://@internetarchive/bookreader/./src/plugins/tts/tooltip_dict.js","webpack://@internetarchive/bookreader/./src/plugins/tts/plugin.tts.js","webpack://@internetarchive/bookreader/./src/plugins/tts/utils.js","webpack://@internetarchive/bookreader/./src/util/strings.js"],"sourcesContent":["'use strict';\nvar PROPER_FUNCTION_NAME = require('../internals/function-name').PROPER;\nvar fails = require('../internals/fails');\nvar whitespaces = require('../internals/whitespaces');\n\nvar non = '\\u200B\\u0085\\u180E';\n\n// check that a method works with the correct list\n// of whitespaces and has a correct name\nmodule.exports = function (METHOD_NAME) {\n return fails(function () {\n return !!whitespaces[METHOD_NAME]()\n || non[METHOD_NAME]() !== non\n || (PROPER_FUNCTION_NAME && whitespaces[METHOD_NAME].name !== METHOD_NAME);\n });\n};\n","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar toString = require('../internals/to-string');\nvar whitespaces = require('../internals/whitespaces');\n\nvar replace = uncurryThis(''.replace);\nvar ltrim = RegExp('^[' + whitespaces + ']+');\nvar rtrim = RegExp('(^|[^' + whitespaces + '])[' + whitespaces + ']+$');\n\n// `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation\nvar createMethod = function (TYPE) {\n return function ($this) {\n var string = toString(requireObjectCoercible($this));\n if (TYPE & 1) string = replace(string, ltrim, '');\n if (TYPE & 2) string = replace(string, rtrim, '$1');\n return string;\n };\n};\n\nmodule.exports = {\n // `String.prototype.{ trimLeft, trimStart }` methods\n // https://tc39.es/ecma262/#sec-string.prototype.trimstart\n start: createMethod(1),\n // `String.prototype.{ trimRight, trimEnd }` methods\n // https://tc39.es/ecma262/#sec-string.prototype.trimend\n end: createMethod(2),\n // `String.prototype.trim` method\n // https://tc39.es/ecma262/#sec-string.prototype.trim\n trim: createMethod(3)\n};\n","'use strict';\n// a string of all valid unicode whitespaces\nmodule.exports = '\\u0009\\u000A\\u000B\\u000C\\u000D\\u0020\\u00A0\\u1680\\u2000\\u2001\\u2002' +\n '\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';\n","'use strict';\nvar $ = require('../internals/export');\nvar $trim = require('../internals/string-trim').trim;\nvar forcedStringTrimMethod = require('../internals/string-trim-forced');\n\n// `String.prototype.trim` method\n// https://tc39.es/ecma262/#sec-string.prototype.trim\n$({ target: 'String', proto: true, forced: forcedStringTrimMethod('trim') }, {\n trim: function trim() {\n return $trim(this);\n }\n});\n","// @ts-check\n/** @typedef {import(\"./BookReader.js\").default} BookReader */\n\n/**\n * @template TOptions\n */\nexport class BookReaderPlugin {\n /**\n * @param {BookReader} br\n */\n constructor(br) {\n /** @type {BookReader} */\n this.br = br;\n /** @type {TOptions} */\n this.options;\n }\n\n /**\n * @abstract\n * @param {TOptions} options\n **/\n setup(options) {\n this.options = Object.assign({}, this.options, options);\n }\n\n /** @abstract */\n init() {}\n\n /**\n * @abstract\n * @protected\n * @param {import (\"./BookReader/PageContainer.js\").PageContainer} pageContainer\n */\n _configurePageContainer(pageContainer) {\n }\n\n /**\n * @abstract\n * @protected\n * @param {JQuery<HTMLElement>} $toolbarElement\n */\n _configureToolbar($toolbarElement) {\n }\n\n /** @abstract @protected */\n _bindNavigationHandlers() {}\n\n /**\n * @param {JQuery<HTMLElement>} $navBar\n */\n extendNavBar($navBar) {}\n}\n","import { applyVariables } from \"../../util/strings.js\";\n\n/** A chunk ends at the first sentence end after this many words */\nconst MIN_WORDS_IN_CHUNK = 25;\n/** A chunk with no sentence end is cut at the first line end after this many words */\nconst MAX_WORDS_IN_CHUNK = 50;\n\n/**\n * Class to manage a 'chunk' (approximately a paragraph) of text on a page.\n */\nexport default class PageChunk {\n /**\n * @param {number} leafIndex\n * @param {number} chunkIndex\n * @param {string} text\n * @param {DJVURect[]} lineRects\n */\n constructor(leafIndex, chunkIndex, text, lineRects) {\n this.leafIndex = leafIndex;\n this.chunkIndex = chunkIndex;\n this.text = text;\n this.lineRects = lineRects;\n }\n\n /**\n * @param {import('@/src/util/strings.js').StringWithVars} pageChunkUrl\n * @param {number} leafIndex\n * @return {Promise<PageChunk[]>}\n */\n static async fetch(pageChunkUrl, leafIndex) {\n if (window.br.plugins.translate?.translationManager.active) {\n const translateLayers = await window.br.plugins.translate.getTranslateLayers(leafIndex);\n const paragraphs = Array.from(translateLayers[0].childNodes);\n\n const pageChunks = [];\n for (const [idx, item] of paragraphs.entries()) {\n // Should not read paragraphs w/ header or footer roles\n if (!item.classList.contains('ocr-role-header-footer')) {\n const translatedChunk = new PageChunk(leafIndex, idx, item.textContent, []);\n pageChunks.push(translatedChunk);\n }\n }\n if (pageChunks.length === 0) {\n const placeholder = new PageChunk(leafIndex, 0, \"\", []);\n pageChunks.push(placeholder);\n }\n return pageChunks;\n }\n\n const ocrPage = await PageChunk._getTextSelectionOcrPage(leafIndex);\n if (ocrPage) {\n return PageChunk._fromTextWrapperResponse(leafIndex, PageChunk._chunkOcrPage(ocrPage));\n }\n\n const chunks = await $.ajax({\n type: 'GET',\n url: applyVariables(pageChunkUrl, { pageIndex: leafIndex }),\n cache: true,\n xhrFields: {\n withCredentials: window.br.protected,\n },\n });\n return PageChunk._fromTextWrapperResponse(leafIndex, chunks);\n }\n\n /**\n * The text selection plugin's OCR for the page, if it has any. It's cached\n * and shared with the text layer, so using it avoids requesting the page's\n * text a second time.\n * @param {number} leafIndex\n * @return {Promise<Element | undefined>}\n */\n static async _getTextSelectionOcrPage(leafIndex) {\n const textSelection = window.br.plugins.textSelection;\n if (!textSelection?.options.enabled) return undefined;\n try {\n return await textSelection.getPageText(leafIndex);\n } catch (e) {\n return undefined;\n }\n }\n\n /**\n * Convert the response from BookReaderGetTextWrapper.php into a {@link PageChunk} instance\n * @param {number} leafIndex\n * @param {Array<[String, ...DJVURect[]]>} chunksResponse\n * @return {PageChunk[]}\n */\n static _fromTextWrapperResponse(leafIndex, chunksResponse) {\n return chunksResponse.map((c, i) => {\n const correctedLineRects = PageChunk._fixChunkRects(c.slice(1));\n const correctedText = PageChunk._removeDanglingHyphens(c[0]);\n return new PageChunk(leafIndex, i, correctedText, correctedLineRects);\n });\n }\n\n /**\n * Split a page of djvu xml OCR into roughly paragraph-sized chunks, in the\n * same shape as BookReaderGetTextWrapper.php's response: each chunk is its\n * text followed by a box per line (or part of a line) it covers. Running\n * headers/footers are skipped.\n * @param {Element} ocrPage djvu xml `OBJECT` element\n * @return {Array<[String, ...DJVURect[]]>}\n */\n static _chunkOcrPage(ocrPage) {\n /** @type {Array<[String, ...DJVURect[]]>} */\n const chunks = [];\n /** @type {string[]} */\n let words = [];\n /** @type {DJVURect[]} */\n let rects = [];\n /** @type {DJVURect | null} bounds of the current line's words in this chunk */\n let lineRect = null;\n\n const endChunk = () => {\n if (lineRect) rects.push(lineRect);\n chunks.push([words.join(' '), ...rects]);\n words = [];\n rects = [];\n lineRect = null;\n };\n\n for (const line of ocrPage.querySelectorAll('LINE')) {\n if (line.closest('PARAGRAPH')?.getAttribute('x-role') === 'header-footer') continue;\n\n for (const word of line.querySelectorAll('WORD')) {\n const [left, bottom, right, top] = (word.getAttribute('coords') ?? '').split(',').map(parseFloat);\n const text = word.textContent.trim();\n // Same words the text layer drops as unpositionable\n if (!text || isNaN(top) || (left === 0 && top === 0)) continue;\n\n lineRect = lineRect ? [\n Math.min(lineRect[0], left),\n Math.max(lineRect[1], bottom),\n Math.max(lineRect[2], right),\n Math.min(lineRect[3], top),\n ] : [left, bottom, right, top];\n words.push(text);\n\n if (text.endsWith('.') && words.length > MIN_WORDS_IN_CHUNK) endChunk();\n }\n\n if (lineRect) rects.push(lineRect);\n lineRect = null;\n if (words.length > MAX_WORDS_IN_CHUNK) endChunk();\n }\n\n if (words.length) endChunk();\n return chunks;\n }\n\n /**\n * @private\n * Sometimes the first rectangle will be ridiculously wide/tall. Find those and fix them\n * *NOTE*: Modifies the original array and returns it.\n * *NOTE*: This should probably be fixed on the petabox side, and then removed here\n * Has 2 problems:\n * - If the rect is the last rect on the page (and hence the only rect in the array),\n * the rect's size isn't fixed\n * - Because this relies on the second rect, there's a chance it won't be the right\n * width\n * @param {DJVURect[]} rects\n * @return {DJVURect[]}\n */\n static _fixChunkRects(rects) {\n if (rects.length < 2) return rects;\n\n const [firstRect, secondRect] = rects;\n const [left, bottom, right] = firstRect;\n const width = right - left;\n const secondHeight = secondRect[1] - secondRect[3];\n const secondWidth = secondRect[2] - secondRect[0];\n const secondRight = secondRect[2];\n\n if (width > secondWidth * 30) {\n // Set the end to be the same\n firstRect[2] = secondRight;\n // And the top to be the same height\n firstRect[3] = bottom - secondHeight;\n }\n\n return rects;\n }\n\n /**\n * Remove \"dangling\" hyphens from read aloud text to avoid TTS stuttering\n * @param {string} text\n * @return {string}\n */\n static _removeDanglingHyphens(text) {\n // Some books mis-OCR a dangling hyphen as a ¬ (mathematical not sign) . Since in math\n // the not sign should not appear followed by a space, we think we can safely assume\n // this should be replaced.\n return text.replace(/[-¬]\\s+/g, '');\n }\n}\n\n/**\n * @typedef {[number, number, number, number]} DJVURect\n * coords are in l,b,r,t order\n */\n","import PageChunk from './PageChunk.js';\n\n/**\n * Class that iterates over the page chunks of a book; caching/buffering\n * as much as possible to try to ensure a smooth experience.\n */\nexport default class PageChunkIterator {\n /**\n * @param {number} pageCount total number of pages\n * @param {number} start page to start on\n * @param {PageChunkIteratorOptions} opts\n */\n constructor(pageCount, start, opts) {\n this.pageCount = pageCount;\n this.opts = Object.assign({}, DEFAULT_OPTS, opts);\n /** Position in the chunk sequence */\n this._cursor = { page: start, chunk: 0 };\n /** @type {Object<number, PageChunk[]>} leaf index -> chunks*/\n this._bufferedPages = {};\n /** @type {Object<number, PromiseLike<PageChunk[]>} leaf index -> chunks*/\n this._bufferingPages = {};\n /**\n * @type {Promise} promise that manages cursor modifications so that they\n * happen in order triggered as opposed to order the server responds\n **/\n this._cursorLock = Promise.resolve();\n }\n\n /**\n * Get the next chunk\n * @return {PromiseLike<\"__PageChunkIterator.AT_END__\" | PageChunk>}\n */\n next() {\n return this._cursorLock = this._cursorLock\n .then(() => this._nextUncontrolled());\n }\n\n /**\n * Sends the cursor back 1\n * @return {Promise}\n **/\n decrement() {\n return this._cursorLock = this._cursorLock\n .then(() => this._decrementUncontrolled());\n }\n\n /**\n * Gets without ensuring synchronization. Since this iterator has a lot of async\n * code, calling e.g. \"next\" twice (before the first call to next has finished)\n * would cause the system to be in a weird state. To avoid that, we make sure calls\n * to next and decrement (functions that modify the cursor) are synchronized,\n * so that regardless how long it takes for one to respond, they'll always be executed\n * in the correct order.\n * @return {PromiseLike<\"__PageChunkIterator.AT_END__\" | PageChunk>}\n */\n async _nextUncontrolled() {\n if (this._cursor.page == this.pageCount) {\n return Promise.resolve(PageChunkIterator.AT_END);\n }\n this._recenterBuffer(this._cursor.page);\n const chunks = await this._fetchPageChunks(this._cursor.page);\n if (this._cursor.chunk == chunks.length) {\n this._cursor.page++;\n this._cursor.chunk = 0;\n return this._nextUncontrolled();\n }\n return chunks[this._cursor.chunk++];\n }\n\n /**\n * Decrements without ensuring synchronization. (See {@link PageChunkIterator._nextUncontrolled});\n * @return {Promise}\n */\n _decrementUncontrolled() {\n let cursorChangePromise = Promise.resolve();\n\n if (this._cursor.chunk > 0) {\n this._cursor.chunk--;\n } else if (this._cursor.page > 0) {\n this._cursor.page--;\n // Go back possibly multiple pages, because pages can be blank\n cursorChangePromise = this._fetchPageChunks(this._cursor.page)\n .then(prevPageChunks => {\n if (prevPageChunks.length == 0) return this._decrementUncontrolled();\n else this._cursor.chunk = prevPageChunks.length - 1;\n });\n }\n\n return cursorChangePromise\n .then(() => this._fetchPageChunks(this._cursor.page));\n }\n\n /**\n * Recenter the buffer around the provided page index\n * @param {number} index\n */\n _recenterBuffer(index) {\n const start = Math.max(0, index - this.opts.pageBufferSize);\n const end = Math.min(this.pageCount, index + this.opts.pageBufferSize + 1);\n for (let i = start; i < end; i++) {\n this._fetchPageChunks(i);\n }\n\n this._removePageFromBuffer(start - 1);\n this._removePageFromBuffer(end + 1);\n }\n\n /**\n * @param {number} index\n */\n _removePageFromBuffer(index) {\n delete this._bufferingPages[index];\n delete this._bufferedPages[index];\n }\n\n /**\n * Fetches the chunks on a page; checks the buffer, so it won't make unnecessary\n * requests if it's called multiple times for the same index.\n * @param {number} index\n * @return {Promise<PageChunk[]>}\n */\n _fetchPageChunks(index) {\n if (index in this._bufferingPages) return this._bufferingPages[index];\n if (index in this._bufferedPages) return Promise.resolve(this._bufferedPages[index]);\n\n this._bufferingPages[index] = this._fetchPageChunksDirect(index)\n .then(chunks => {\n delete this._bufferingPages[index];\n this._bufferedPages[index] = chunks;\n return chunks;\n });\n\n return this._bufferingPages[index];\n }\n\n /**\n * Fetches a page without checking buffer\n * @param {number} index\n */\n _fetchPageChunksDirect(index) {\n return PageChunk.fetch(this.opts.pageChunkUrl, index);\n }\n}\n\nPageChunkIterator.AT_END = \"__PageChunkIterator.AT_END__\";\n\n/** @type {PageChunkIteratorOptions} */\nconst DEFAULT_OPTS = {\n pageChunkUrl: null,\n pageBufferSize: 2,\n};\n\n/**\n * @typedef {Object} PageChunkIteratorOptions\n * @property {import('@/src/util/strings.js').StringWithVars} pageChunkUrl\n * @property {number} [pageBufferSize] number of pages to buffer before/after the current page\n */\n","import PageChunkIterator from './PageChunkIterator.js';\nimport { hasLocalStorage } from './utils.js';\n/** @typedef {import('./utils.js').ISO6391} ISO6391 */\n/** @typedef {import('./PageChunk.js')} PageChunk */\n\n/**\n * @export\n * @typedef {Object} TTSEngineOptions\n * @property {import('@/src/util/strings.js').StringWithVars} pageChunkUrl\n * @property {ISO6391} bookLanguage\n * @property {Function} onLoadingStart\n * @property {Function} onLoadingComplete\n * @property {Function} onDone called when the entire book is done\n * @property {function(PageChunk): PromiseLike} beforeChunkPlay will delay the playing of the chunk\n * @property {function(PageChunk): void} afterChunkPlay fires once a chunk has fully finished\n */\n\n/**\n * @typedef {Object} AbstractTTSSound\n * @property {PageChunk} chunk\n * @property {boolean} loaded\n * @property {number} rate\n * @property {SpeechSynthesisVoice} voice\n * @property {(callback: Function) => void} load\n * @property {() => PromiseLike} play\n * @property {() => Promise} stop\n * @property {() => void} pause\n * @property {() => void} resume\n * @property {() => void} finish force the sound to 'finish'\n * @property {number => void} setPlaybackRate\n * @property {SpeechSynthesisVoice => void} setVoice\n **/\n\n/** Handling bookreader's text-to-speech */\nexport default class AbstractTTSEngine {\n /**\n * @protected\n * @param {TTSEngineOptions} options\n */\n constructor(options) {\n this.playing = false;\n this.paused = false;\n /** @type {TTSEngineOptions} */\n this.opts = options;\n /** @type {PageChunkIterator} */\n this._chunkIterator = null;\n /** @type {AbstractTTSSound} */\n this.activeSound = null;\n this.playbackRate = 1;\n /** Events we can bind to */\n this.events = $({});\n /** @type {SpeechSynthesisVoice} */\n this.voice = null;\n // Listen for voice changes (fired by subclasses)\n this.events.on('voiceschanged', this.updateBestVoice);\n this.events.trigger('voiceschanged');\n }\n\n /**\n * @abstract\n * @return {boolean}\n */\n static isSupported() { throw new Error(\"Unimplemented abstract class\"); }\n\n /**\n * @abstract\n * @return {SpeechSynthesisVoice[]}\n */\n getVoices() { throw new Error(\"Unimplemented abstract class\"); }\n\n /** @abstract */\n init() { return null; }\n\n updateBestVoice = () => {\n this.voice = AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);\n }\n\n /**\n * @param {number} leafIndex\n * @param {number} numLeafs total number of leafs in the current book\n */\n start(leafIndex, numLeafs) {\n this.playing = true;\n this.paused = false;\n this.opts.onLoadingStart();\n\n this._chunkIterator = new PageChunkIterator(numLeafs, leafIndex, {\n pageChunkUrl: this.opts.pageChunkUrl,\n pageBufferSize: 3,\n });\n this.step();\n this.events.trigger('start');\n }\n\n stop() {\n if (this.activeSound) this.activeSound.stop();\n this.playing = false;\n this.paused = true;\n this._chunkIterator = null;\n this.activeSound = null;\n this.events.trigger('stop');\n }\n\n /** @public */\n pause() {\n const fireEvent = !this.paused && this.activeSound;\n this.paused = true;\n if (this.activeSound) this.activeSound.pause();\n if (fireEvent) this.events.trigger('pause');\n }\n\n /** @public */\n resume() {\n const fireEvent = this.paused && this.activeSound;\n this.paused = false;\n if (this.activeSound) this.activeSound.resume();\n if (fireEvent) this.events.trigger('resume');\n }\n\n togglePlayPause() {\n if (this.paused) this.resume();\n else this.pause();\n }\n\n /** @public */\n jumpForward() {\n if (this.activeSound) this.activeSound.finish();\n }\n\n /** @public */\n async jumpBackward() {\n await Promise.all([\n this.activeSound.stop(),\n this._chunkIterator.decrement()\n .then(() => this._chunkIterator.decrement()),\n ]);\n this.step();\n }\n\n /** @param {string} voiceURI */\n setVoice(voiceURI) {\n // if the user actively selects a voice, don't re-choose best voice anymore\n // MS Edge fires voices changed randomly very often\n this.events.off('voiceschanged', this.updateBestVoice);\n this.voice = this.getVoices().find(voice => voice.voiceURI === voiceURI);\n // if the current book has a language set, store the selected voice with the book language as a suffix\n if (this.opts.bookLanguage && hasLocalStorage()) {\n localStorage.setItem(`BRtts-voice-${this.opts.bookLanguage}`, this.voice.voiceURI);\n }\n if (this.activeSound) this.activeSound.setVoice(this.voice);\n }\n\n /** @param {number} newRate */\n setPlaybackRate(newRate) {\n this.playbackRate = newRate;\n if (this.activeSound) this.activeSound.setPlaybackRate(newRate);\n }\n\n /** @private */\n async step() {\n const chunk = await this._chunkIterator.next();\n if (chunk == PageChunkIterator.AT_END) {\n this.stop();\n this.opts.onDone();\n return;\n }\n this.opts.onLoadingStart();\n const sound = this.createSound(chunk);\n sound.chunk = chunk;\n sound.rate = this.playbackRate;\n sound.voice = this.voice;\n sound.load(() => this.opts.onLoadingComplete());\n\n this.opts.onLoadingComplete();\n\n await this.opts.beforeChunkPlay(chunk);\n\n if (!this.playing) return;\n\n const playPromise = await this.playSound(sound)\n .then(()=> this.opts.afterChunkPlay(sound.chunk));\n\n if (this.paused) this.pause();\n await playPromise;\n\n if (this.playing) return this.step();\n }\n\n /**\n * @abstract\n * @param {PageChunk} chunk\n * @return {AbstractTTSSound}\n */\n createSound(chunk) { throw new Error(\"Unimplemented abstract class\"); }\n\n /**\n * @param {AbstractTTSSound} sound\n * @return {PromiseLike} promise called once playing finished\n */\n playSound(sound) {\n this.activeSound = sound;\n if (!this.activeSound.loaded) this.opts.onLoadingStart();\n return this.activeSound.play();\n }\n\n /** Convenience wrapper for {@see AbstractTTSEngine.getBestVoice} */\n getBestVoice(languageOverride) {\n return AbstractTTSEngine.getBestBookVoice(this.getVoices(), languageOverride || this.opts.bookLanguage);\n }\n\n /**\n * @private\n * Find the best voice to use given the available voices, the book language, and the user's\n * languages.\n * @param {SpeechSynthesisVoice[]} voices\n * @param {ISO6391} bookLanguage\n * @param {string[]} userLanguages languages in BCP47 format (e.g. en-US). Ordered by preference.\n * @return {SpeechSynthesisVoice | undefined}\n */\n static getBestBookVoice(voices, bookLanguage, userLanguages = navigator.languages) {\n const bookLangVoices = voices.filter(v => v.lang.startsWith(bookLanguage));\n // navigator.languages browser support isn't great yet, so get just 1 language otherwise\n // Sample navigator.languages: [\"en-CA\", \"fr-CA\", \"fr\", \"en-US\", \"en\", \"de-DE\", \"de\"]\n userLanguages = userLanguages || (navigator.language ? [navigator.language] : []);\n\n // user languages that match the book language\n const matchingUserLangs = userLanguages.filter(lang => lang.startsWith(bookLanguage));\n\n // First try to find the last chosen voice from localStorage for the current book language\n return AbstractTTSEngine.getMatchingStoredVoice(bookLangVoices, bookLanguage)\n // Try to find voices that intersect these two sets\n || AbstractTTSEngine.getMatchingVoice(matchingUserLangs, bookLangVoices)\n // no user languages match the books; let's return the best voice for the book language\n || (bookLangVoices.find(v => v.default) || bookLangVoices[0])\n // No voices match the book language? let's find a voice in the user's language\n // and ignore book lang\n || AbstractTTSEngine.getMatchingVoice(userLanguages, voices)\n // C'mon! Ok, just read with whatever we got!\n || (voices.find(v => v.default) || voices[0]);\n }\n\n /**\n * @private\n * Get the voice last selected by the user for the book language from localStorage.\n * Returns undefined if no voice is stored or found.\n * @param {SpeechSynthesisVoice[]} voices browser voices to choose from\n * @param {ISO6391} bookLanguage book language to look for\n * @return {SpeechSynthesisVoice | undefined}\n */\n static getMatchingStoredVoice(voices, bookLanguage) {\n const storedVoice = hasLocalStorage() && localStorage.getItem(`BRtts-voice-${bookLanguage}`);\n return (storedVoice ? voices.find(v => v.voiceURI === storedVoice) : undefined);\n }\n\n /**\n * @private\n * Get the best voice that matches one of the BCP47 languages (order by preference)\n * @param {string[]} languages in BCP 47 format (e.g. 'en-US', or 'en'); ordered by preference\n * @param {SpeechSynthesisVoice[]} voices voices to choose from\n * @return {SpeechSynthesisVoice | undefined}\n */\n static getMatchingVoice(languages, voices) {\n for (const lang of languages) {\n // Chrome Android was returning voice languages like `en_US` instead of `en-US`\n const matchingVoices = voices.filter(v => v.lang.replace('_', '-').startsWith(lang));\n if (matchingVoices.length) {\n return matchingVoices.find(v => v.default) || matchingVoices[0];\n }\n }\n }\n}\n","import AbstractTTSEngine from './AbstractTTSEngine.js';\nimport { sleep } from '../../BookReader/utils.js';\nimport { applyVariables } from '../../util/strings.js';\n/* global soundManager */\nimport 'soundmanager2';\nimport 'jquery.browser';\n\n/** @typedef {import(\"./AbstractTTSEngine.js\").TTSEngineOptions} TTSEngineOptions */\n/** @typedef {import(\"./AbstractTTSEngine.js\").AbstractTTSSound} AbstractTTSSound */\n\n/**\n * @extends AbstractTTSEngine\n * TTS using Festival endpoint\n **/\nexport default class FestivalTTSEngine extends AbstractTTSEngine {\n /** @override */\n static isSupported() {\n return typeof(soundManager) !== 'undefined' && soundManager.supported();\n }\n\n /** @param {TTSEngineOptions | { festivalUrl: import('@/src/util/strings.js').StringWithVars }} options */\n constructor(options) {\n super(options);\n // $.browsers is sometimes undefined on some Android browsers :/\n // Likely related to when $.browser was moved to npm\n /** @type {'mp3' | 'ogg'} format of audio to get */\n this.audioFormat = $.browser?.mozilla ? 'ogg' : 'mp3'; //eslint-disable-line no-jquery/no-browser\n /** @type {import('@/src/util/strings.js').StringWithVars} */\n this.festivalUrl = options.festivalUrl;\n }\n\n /** @override */\n getVoices() {\n return [\n { default: true, lang: \"en-US\", localService: false, name: \"Festival - English (US)\", voiceURI: null },\n ];\n }\n\n /** @override */\n init() {\n // setup sound manager\n soundManager.setup({\n debugMode: false,\n // Note, there's a bug in Chrome regarding range requests.\n // Flash is used as a workaround.\n // See https://bugs.chromium.org/p/chromium/issues/detail?id=505707\n preferFlash: true,\n url: '/bookreader/BookReader/soundmanager/swf',\n useHTML5Audio: true,\n //flash 8 version of swf is buggy when calling play() on a sound that is still loading\n flashVersion: 9,\n });\n }\n\n /**\n * @override\n * @param {number} leafIndex\n * @param {number} numLeafs total number of leafs in the current book\n */\n start(leafIndex, numLeafs) {\n let promise = null;\n\n // Hack for iOS\n if (navigator.userAgent.match(/mobile/i)) {\n promise = this.iOSCaptureUserIntentHack();\n }\n\n promise = promise || Promise.resolve();\n promise.then(() => super.start(leafIndex, numLeafs));\n }\n\n /** @override */\n createSound(chunk) {\n return new FestivalTTSSound(applyVariables(this.festivalUrl, { text: chunk.text, format: this.audioFormat }));\n }\n\n /**\n * @private\n * Security restrictions require playback to be triggered\n * by a user click/touch. This intention gets lost in the async calls\n * on iOS, but, for some reason, if we start the audio here, it works.\n * See https://stackoverflow.com/questions/12206631/html5-audio-cant-play-through-javascript-unless-triggered-manually-once\n * @return {PromiseLike}\n */\n async iOSCaptureUserIntentHack() {\n const sound = soundManager.createSound({ url: SILENCE_1MS[this.audioFormat] });\n await new Promise(res => sound.play({onfinish: res}));\n sound.destruct();\n }\n}\n\n/** @extends AbstractTTSSound */\nclass FestivalTTSSound {\n /** @param {string} soundUrl **/\n constructor(soundUrl) {\n this.soundUrl = soundUrl;\n /** @type {SMSound} */\n this.sound = null;\n this.rate = 1;\n /** @type {function} calling this resolves the \"play\" promise */\n this._finishResolver = null;\n }\n\n get loaded() {\n return this.sound && this.sound.loaded;\n }\n\n load(onload) {\n this.sound = soundManager.createSound({\n url: this.soundUrl,\n // API recommended, but only fires once play started on safari\n onload: () => {\n if (this.rate != 1) this.sound.setPlaybackRate(this.rate);\n onload();\n },\n onresume: async () => {\n await sleep(25);\n if (this.rate != 1) this.sound.setPlaybackRate(this.rate);\n },\n });\n return this.sound.load();\n }\n\n async play() {\n await new Promise(res => {\n this._finishResolver = res;\n this.sound.play({ onfinish: res });\n });\n this.sound.destruct();\n }\n\n /** @override */\n stop() {\n this.sound.stop();\n return Promise.resolve();\n }\n\n /** @override */\n pause() { this.sound.pause(); }\n /** @override */\n resume() { this.sound.resume(); }\n /** @override */\n setPlaybackRate(rate) {\n this.rate = rate;\n this.sound.setPlaybackRate(rate);\n }\n\n /** @override */\n finish() {\n this.sound.stop();\n this._finishResolver();\n }\n}\n\n/** Needed to capture the audio context for iOS hack. Generated using Audacity. */\nconst SILENCE_1MS = {\n mp3: 'data:audio/mp3;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA//////////////////////////////////////////////////////////////////8AAAAeTEFNRTMuOTlyBJwAAAAAAAAAADUgJAaUQQABrgAAAnHIf8sZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxAADwlwBKGAAACAAAD/AAAAEAAAAH///////////////+UBAMExBTUUzLjk5LjOqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+xDEIAPAAAGkAAAAIAAANIAAAASqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg==',\n ogg: 'data:audio/ogg;base64,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',\n};\n","/* global br */\nimport { isChrome, isFirefox, isAndroid } from '../../util/browserSniffing.js';\nimport { DEBUG_READ_ALOUD } from './utils.js';\nimport { promisifyEvent, sleep } from '../../BookReader/utils.js';\nimport AbstractTTSEngine from './AbstractTTSEngine.js';\n/** @typedef {import(\"./AbstractTTSEngine.js\").PageChunk} PageChunk */\n/** @typedef {import(\"./AbstractTTSEngine.js\").AbstractTTSSound} AbstractTTSSound */\n/** @typedef {import(\"./AbstractTTSEngine.js\").TTSEngineOptions} TTSEngineOptions */\n\n/**\n * @extends AbstractTTSEngine\n * TTS using Web Speech APIs\n **/\nexport default class WebTTSEngine extends AbstractTTSEngine {\n static isSupported() {\n return typeof(window.speechSynthesis) !== 'undefined';\n }\n\n /** @param {TTSEngineOptions} options */\n constructor(options) {\n super(options);\n\n // SAFARI doesn't have addEventListener on speechSynthesis\n if (speechSynthesis.addEventListener) {\n speechSynthesis.addEventListener('voiceschanged', () => this.events.trigger('voiceschanged'));\n }\n }\n\n /** @override */\n start(leafIndex, numLeafs) {\n // Need to run in this function to capture user intent to start playing audio\n if ('mediaSession' in navigator) {\n /**\n * According to https://developers.google.com/web/updates/2017/02/media-session#implementation_notes , it needs to be at least 5 seconds\n * long to allow usage of the media sessions api\n */\n const audio = new Audio(br.options.imagesBaseURL + '../silence.mp3');\n audio.loop = true;\n\n this.events.on('pause', () => audio.pause());\n this.events.on('resume', () => audio.play());\n // apparently this is what you need to do to make the media session notification go away\n // See https://developers.google.com/web/updates/2017/02/media-session#implementation_notes\n this.events.on('stop', () => audio.src = '');\n audio.play().then(() => {\n navigator.mediaSession.metadata = new MediaMetadata({\n title: br.bookTitle,\n artist: br.options.metadata.filter(m => m.label == 'Author').map(m => m.value)[0],\n // album: 'The Ultimate Collection (Remastered)',\n artwork: [\n { src: br.options.thumbnail, type: 'image/jpg' },\n ],\n });\n\n navigator.mediaSession.setPositionState({\n duration: Infinity,\n });\n\n navigator.mediaSession.setActionHandler('play', () => {\n audio.play();\n this.resume();\n });\n navigator.mediaSession.setActionHandler('pause', () => {\n audio.pause();\n this.pause();\n });\n\n // navigator.mediaSession.setActionHandler('seekbackward', () => this.jumpBackward());\n // navigator.mediaSession.setActionHandler('seekforward', () => this.jumpForward());\n // Some devices only support the previoustrack/nexttrack (e.g. Win10), so show those.\n // Android devices do support the seek actions, but we don't want to show both buttons\n // and have them do the same thing.\n navigator.mediaSession.setActionHandler('previoustrack', () => this.jumpBackward());\n navigator.mediaSession.setActionHandler('nexttrack', () => this.jumpForward());\n });\n }\n\n return super.start(leafIndex, numLeafs);\n }\n\n /** @override */\n getVoices() {\n const voices = speechSynthesis.getVoices();\n if (voices.filter(v => v.default).length != 1) {\n // iOS bug where the default system voice is sometimes\n // missing from the list\n voices.unshift({\n voiceURI: 'bookreader.SystemDefault',\n name: 'System Default',\n // Not necessarily true, but very likely\n lang: navigator.language,\n default: true,\n localService: true,\n });\n }\n return voices;\n }\n\n /** @override */\n createSound(chunk) {\n return new WebTTSSound(chunk.text);\n }\n}\n\n/** @extends AbstractTTSSound */\nexport class WebTTSSound {\n /** @param {string} text **/\n constructor(text) {\n this.text = text;\n this.loaded = false;\n this.paused = false;\n this.started = false;\n /** Whether the audio was stopped with a .stop() call */\n this.stopped = false;\n this.rate = 1;\n\n /** @type {SpeechSynthesisUtterance} */\n this.utterance = null;\n\n /** @type {SpeechSynthesisVoice} */\n this.voice = null;\n\n this._lastEvents = {\n /** @type {SpeechSynthesisEvent} */\n pause: null,\n /** @type {SpeechSynthesisEvent} */\n boundary: null,\n /** @type {SpeechSynthesisEvent} */\n start: null,\n };\n\n /** Store where we are in the text. Only works on some browsers. */\n this._charIndex = 0;\n\n /** @type {Function} resolve function called when playback finished */\n this._finishResolver = null;\n\n /** @type {Promise} promise resolved by _finishResolver */\n this._finishPromise = null;\n }\n\n /** @override **/\n load(onload) {\n this.loaded = false;\n this.started = false;\n\n this.utterance = new SpeechSynthesisUtterance(this.text.slice(this._charIndex));\n // iOS bug where the default system voice is sometimes\n // missing from the list\n if (this.voice?.voiceURI !== 'bookreader.SystemDefault') {\n this.utterance.voice = this.voice;\n }\n // Need to also set lang (for some reason); won't set voice on Chrome@Android otherwise\n if (this.voice) this.utterance.lang = this.voice.lang;\n this.utterance.rate = this.rate;\n\n // Useful for debugging things\n if (DEBUG_READ_ALOUD) {\n this.utterance.addEventListener('pause', () => console.log('pause'));\n this.utterance.addEventListener('resume', () => console.log('resume'));\n this.utterance.addEventListener('start', () => console.log('start'));\n this.utterance.addEventListener('end', () => console.log('end'));\n this.utterance.addEventListener('error', ev => console.log('error', ev));\n this.utterance.addEventListener('boundary', () => console.log('boundary'));\n this.utterance.addEventListener('mark', () => console.log('mark'));\n this.utterance.addEventListener('finish', () => console.log('finish'));\n }\n\n // Keep track of the speech synthesis events that come in; they have useful info\n // about progress (like charIndex)\n this.utterance.addEventListener('start', ev => this._lastEvents.start = ev);\n this.utterance.addEventListener('boundary', ev => this._lastEvents.boundary = ev);\n this.utterance.addEventListener('pause', ev => this._lastEvents.pause = ev);\n\n // Update our state\n this.utterance.addEventListener('start', () => {\n this.started = true;\n this.stopped = false;\n this.paused = false;\n });\n this.utterance.addEventListener('pause', () => this.paused = true);\n this.utterance.addEventListener('resume', () => this.paused = false);\n this.utterance.addEventListener('end', ev => {\n if (!this.paused && !this.stopped) {\n // Trigger a new event, finish, which only fires when audio fully completed\n this.utterance.dispatchEvent(new CustomEvent('finish', ev));\n }\n });\n this.loaded = true;\n onload && onload();\n }\n\n /**\n * Run whenever properties have changed. Tries to restart in the same spot it\n * left off.\n * @return {Promise<void>}\n */\n async reload() {\n // We'll restore the pause state, so copy it here\n const wasPaused = this.paused;\n // Use recent event to determine where we'll restart from\n // Browser support for this is mixed, but it degrades to restarting the chunk\n // and that's ok\n const recentEvent = this._lastEvents.boundary || this._lastEvents.pause;\n if (recentEvent) {\n this._charIndex = this.text.indexOf(recentEvent.target.text) + recentEvent.charIndex;\n }\n\n // We can't modify the utterance object, so we have to make a new one\n await this.stop();\n this.load();\n // Instead of playing and immediately pausing, we don't start playing. Note\n // this is a requirement because pause doesn't work consistently across\n // browsers.\n if (!wasPaused) this.play();\n }\n\n play() {\n this._finishPromise = this._finishPromise || new Promise(res => this._finishResolver = res);\n this.utterance.addEventListener('finish', this._finishResolver);\n\n // clear the queue\n speechSynthesis.cancel();\n // reset pause state\n speechSynthesis.resume();\n // Speak\n speechSynthesis.speak(this.utterance);\n\n const isLocalVoice = this.utterance.voice && this.utterance.voice.localService;\n if (isChrome() && !isLocalVoice) this._chromePausingBugFix();\n\n return this._finishPromise;\n }\n\n /** @return {Promise} */\n stop() {\n // 'end' won't fire if already stopped\n let endPromise = Promise.resolve();\n if (!this.stopped) {\n endPromise = Promise.race([\n promisifyEvent(this.utterance, 'end'),\n // Safari triggers an error when you call cancel mid-sound\n promisifyEvent(this.utterance, 'error'),\n ]);\n }\n this.stopped = true;\n speechSynthesis.cancel();\n return endPromise;\n }\n\n async finish() {\n await this.stop();\n this.utterance.dispatchEvent(new Event('finish'));\n }\n\n /**\n * @override\n * Will fire a pause event unless already paused\n **/\n async pause() {\n if (this.paused) return;\n\n const pausePromise = promisifyEvent(this.utterance, 'pause');\n speechSynthesis.pause();\n\n // There are a few awful browser cases:\n // 1. Pause works and fires\n // 2. Pause doesn't work and doesn't fire\n // 3. Pause works but doesn't fire\n const pauseMightNotWork = (isFirefox() && isAndroid());\n\n // Pause sometimes works, but doesn't fire the event, so wait to see if it fires\n const winner = await Promise.race([pausePromise, sleep(100).then(() => 'timeout')]);\n\n // We got our pause event; nothing to do!\n if (winner != 'timeout') return;\n\n if (DEBUG_READ_ALOUD) {\n console.log('TTS: Firing pause event manually');\n }\n\n this.utterance.dispatchEvent(new CustomEvent('pause', this._lastEvents.start));\n\n // if pause might not work, then we'll stop entirely and restart later\n if (pauseMightNotWork) this.stop();\n }\n\n async resume() {\n if (!this.started || this.stopped) {\n this.play();\n return;\n }\n\n if (!this.paused) return;\n\n // Browser cases:\n // 1. Resume works + fires\n // 2. Resume works + doesn't fire (Chrome Desktop)\n // 3. Resume doesn't work + doesn't fire (Chrome/FF Android)\n const resumeMightNotWork = (isChrome() && isAndroid()) || (isFirefox() && isAndroid());\n\n // Try resume\n const resumePromise = promisifyEvent(this.utterance, 'resume');\n speechSynthesis.resume();\n\n const winner = await Promise.race([resumePromise, sleep(100).then(() => 'timeout')]);\n // We got resume! All is good\n if (winner != 'timeout') return;\n\n if (DEBUG_READ_ALOUD) {\n console.log('TTS: Firing resume event manually');\n }\n\n // Fake it\n this.utterance.dispatchEvent(new CustomEvent('resume', {}));\n if (resumeMightNotWork) {\n await this.reload();\n this.play();\n }\n }\n\n setPlaybackRate(rate) {\n this.rate = rate;\n this.reload();\n }\n\n /** @param {SpeechSynthesisVoice} voice */\n setVoice(voice) {\n this.voice = voice;\n this.reload();\n }\n /**\n * @private\n * Chrome has a bug where it only plays 15 seconds of TTS and then\n * suddenly stops (see https://bugs.chromium.org/p/chromium/issues/detail?id=679437 )\n * We avoid this (as described here: https://bugs.chromium.org/p/chromium/issues/detail?id=679437#c15 )\n * by pausing after 14 seconds and ~instantly resuming.\n */\n async _chromePausingBugFix() {\n if (DEBUG_READ_ALOUD) {\n console.log('CHROME-PAUSE-HACK: starting');\n }\n\n const result = await Promise.race([\n sleep(14000).then(() => 'timeout'),\n promisifyEvent(this.utterance, 'pause').then(() => 'pause'),\n promisifyEvent(this.utterance, 'end').then(() => 'end'),\n // Some browsers (Edge) trigger error when the utterance is interrupted/stopped\n promisifyEvent(this.utterance, 'error').then(() => 'error'),\n ]);\n\n if (DEBUG_READ_ALOUD) {\n console.log(`CHROME-PAUSE-HACK: ${result}`);\n }\n if (result == 'end' || result == 'error') {\n // audio was stopped/finished; nothing to do\n if (DEBUG_READ_ALOUD) {\n console.log('CHROME-PAUSE-HACK: stopped (end/error)');\n }\n } else if (result == 'pause') {\n // audio was paused; wait for resume\n // Chrome won't let you resume the audio if 14s have passed 🤷\n // We could do the same as before (but resume+pause instead of pause+resume),\n // but that means we'd _constantly_ be running in the background. So in that\n // case, let's just restart the chunk\n const result2 = await Promise.race([\n promisifyEvent(this.utterance, 'resume').then(() => 'resume'),\n sleep(14000).then(() => 'timeout'),\n ]);\n if (result2 == 'timeout') {\n if (DEBUG_READ_ALOUD) {\n console.log('CHROME-PAUSE-HACK: stopped (timed out while paused)');\n }\n // We hit Chrome's secret cut off time while paused, and\n // won't be able to resume normally, so trigger a stop.\n this.stop();\n } else {\n // The user resumed before the cut off! Continue as normal\n this._chromePausingBugFix();\n }\n } else if (result == 'timeout') {\n // We hit Chrome's secret cut off time while playing.\n // To be able to keep TTS-ing, quickly pause/resume.\n speechSynthesis.pause();\n await sleep(25);\n speechSynthesis.resume();\n\n // Listen for more\n this._chromePausingBugFix();\n }\n }\n}\n","export const en = {\n advance: 'Advance 10 seconds',\n play: 'Play',\n playbackSpeed: 'Playback speed',\n readAloud: 'Read this book aloud',\n review: 'Review 10 seconds',\n};\n\nexport const es = {\n advance: 'Avance 10 segundos',\n play: 'Jugar',\n playbackSpeed: 'Velocidad de reproducción',\n readAloud: 'Lee este libro en voz alta',\n review: 'Revisar 10 segundos',\n};\n","// @ts-check\n\nimport FestivalTTSEngine from './FestivalTTSEngine.js';\nimport WebTTSEngine from './WebTTSEngine.js';\nimport { toISO6391 } from './utils.js';\nimport { en as tooltips } from './tooltip_dict.js';\nimport { renderBoxesInPageContainerLayer } from '../../BookReader/PageContainer.js';\nimport { BookReaderPlugin } from '../../BookReaderPlugin.js';\nimport { applyVariables, countWords } from '../../util/strings.js';\n/** @typedef {import('./PageChunk.js').default} PageChunk */\n/** @typedef {import(\"./AbstractTTSEngine.js\").default} AbstractTTSEngine */\n\nconst BookReader = /** @type {typeof import('../../BookReader').default} */(window.BookReader);\n\n/**\n * Plugin for Text to Speech in BookReader\n */\nexport class TtsPlugin extends BookReaderPlugin {\n options = {\n enabled: true,\n /**\n * @type {import('@/src/util/strings.js').StringWithVars}\n * The URL where to get PageChunk objects for a given page. Expects a var `pageIndex`\n **/\n pageChunkUrl: 'https://{{server}}/BookReader/BookReaderGetTextWrapper.php?path={{bookPath|urlencode}}_djvu.xml&page={{pageIndex}}&callback=false',\n /**\n * @type {import('@/src/util/strings.js').StringWithVars}\n * The URL for converting text to audio if the web SpeechSynthesis API is not supported.\n * Provided variables:\n * - `text` -- the text to convert to audio\n * - `format` -- the format of the audio, 'mp3' or 'ogg';\n */\n remoteTtsUrl: 'https://{{server}}/BookReader/BookReaderGetTTS.php?string={{text|urlencode}}&format={{format}}',\n }\n\n /**\n * @override\n * @param {Partial<TtsPlugin['options']>} options\n **/\n setup(options) {\n super.setup(Object.assign({\n // @deprecated support options specified in global options\n server: this.br.options.server,\n bookPath: this.br.options.bookPath,\n }, options));\n\n if (!this.options.enabled) return;\n\n /** @type { {[pageIndex: number]: Array<{ l: number, r: number, t: number, b: number }>} } */\n this._ttsBoxesByIndex = {};\n\n let TTSEngine = WebTTSEngine.isSupported() ? WebTTSEngine :\n FestivalTTSEngine.isSupported() ? FestivalTTSEngine :\n null;\n\n if (/_forceTTSEngine=(festival|web)/.test(location.toString())) {\n const engineName = location.toString().match(/_forceTTSEngine=(festival|web)/)[1];\n TTSEngine = { festival: FestivalTTSEngine, web: WebTTSEngine }[engineName];\n }\n\n if (TTSEngine) {\n /** @type {AbstractTTSEngine} */\n this.ttsEngine = new TTSEngine({\n pageChunkUrl: applyVariables(this.options.pageChunkUrl, this.br.options.vars),\n bookLanguage: toISO6391(this.br.options.bookLanguage),\n onLoadingStart: this.br.showProgressPopup.bind(this.br, 'Loading audio...'),\n onLoadingComplete: this.br.removeProgressPopup.bind(this.br),\n onDone: this.stop.bind(this),\n beforeChunkPlay: this.beforeChunkPlay.bind(this),\n afterChunkPlay: this.sendChunkFinishedAnalyticsEvent.bind(this),\n ...(TTSEngine === FestivalTTSEngine ? {\n festivalUrl: applyVariables(this.options.remoteTtsUrl, this.br.options.vars),\n } : {}),\n });\n }\n }\n\n /** @override */\n init() {\n if (!this.options.enabled) return;\n\n this.br.bind(BookReader.eventNames.PostInit, () => {\n this.br.$('.BRicon.read').click(() => {\n this.toggle();\n return false;\n });\n if (this.ttsEngine) {\n this.ttsEngine.init();\n if (/[?&]_autoReadAloud=show/.test(location.toString())) {\n this.start(false); // false flag is to initiate read aloud controls\n }\n }\n });\n\n // This is fired when the hash changes by one of the other plugins!\n // i.e. it will fire every time the page changes -_-\n // this.br.bind(BookReader.eventNames.stop, function(e, br) {\n // this.ttsStop();\n // }.bind(this));\n }\n\n /**\n * @override\n * @param {import (\"@/src/BookReader/PageContainer.js\").PageContainer} pageContainer\n */\n _configurePageContainer(pageContainer) {\n if (this.options.enabled && pageContainer.page && pageContainer.page.index in this._ttsBoxesByIndex) {\n const pageIndex = pageContainer.page.index;\n renderBoxesInPageContainerLayer('ttsHiliteLayer', this._ttsBoxesByIndex[pageIndex], pageContainer.page, pageContainer.$container[0]);\n }\n }\n\n /**\n * @override\n * @param {JQuery<HTMLElement>} $navBar\n */\n extendNavBar($navBar) {\n if (!this.options.enabled || !this.ttsEngine) return;\n\n this.br.refs.$BRReadAloudToolbar = $(`\n <ul class=\"read-aloud\">\n <li>\n <select class=\"playback-speed\" name=\"playback-speed\" title=\"${tooltips.playbackSpeed}\">\n <option value=\"0.25\">0.25x</option>\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1.0\" selected>1.0x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"1.75\">1.75x</option>\n <option value=\"2\">2x</option>\n </select>\n </li>\n <li>\n <button type=\"button\" name=\"review\" title=\"${tooltips.review}\">\n <div class=\"icon icon-review\"></div>\n </button>\n </li>\n <li>\n <button type=\"button\" name=\"play\" title=\"${tooltips.play}\">\n <div class=\"icon icon-play\"></div>\n <div class=\"icon icon-pause\"></div>\n </button>\n </li>\n <li>\n <button type=\"button\" name=\"advance\" title=\"${tooltips.advance}\">\n <div class=\"icon icon-advance\"></div>\n </button>\n </li>\n <li>\n <select class=\"playback-voices\" name=\"playback-voice\" style=\"display: none\" title=\"Change read aloud voices\">\n </select>\n </li>\n </ul>\n `);\n\n $navBar.find('.BRcontrols').prepend(this.br.refs.$BRReadAloudToolbar);\n\n const renderVoiceOption = (voices) => {\n return voices.map(voice =>\n `<option value=\"${voice.voiceURI}\">${voice.lang} - ${voice.name}</option>`).join('');\n };\n\n const voiceSortOrder = (a,b) => `${a.lang} - ${a.name}`.localeCompare(`${b.lang} - ${b.name}`);\n\n const renderVoicesMenu = (voicesMenu) => {\n voicesMenu.empty();\n let bookLanguage = this.ttsEngine.opts.bookLanguage;\n if (this.br.plugins.translate?.translationManager?.active) {\n bookLanguage = this.br.plugins.translate.langFromCode;\n }\n\n const bookLanguages = this.ttsEngine.getVoices().filter(v => v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);\n const otherLanguages = this.ttsEngine.getVoices().filter(v => !v.lang.startsWith(bookLanguage)).sort(voiceSortOrder);\n\n if (this.ttsEngine.getVoices().length > 1) {\n if (this.br.plugins.translate?.translationManager?.active) {\n // Separate out Other Languages when translation active, not sure if too much / unwieldy\n const toLang = this.br.plugins.translate.langToCode;\n const translatedLanguages = this.ttsEngine.getVoices().filter(v => v.lang.startsWith(toLang)).sort(voiceSortOrder);\n voicesMenu.append($(`<optgroup label=\"Book Language, Translated From (${bookLanguage})\"> ${renderVoiceOption(bookLanguages)} </optgroup>`));\n voicesMenu.append($(`<optgroup label=\"Book Language, Translated To (${toLang})\"> ${renderVoiceOption(translatedLanguages)} </optgroup>`));\n voicesMenu.append($(`<optgroup label=\"Other Languages\"> ${renderVoiceOption(otherLanguages.filter(v => !v.lang.startsWith(toLang)).sort(voiceSortOrder))}`));\n } else {\n voicesMenu.append($(`<optgroup label=\"Book Language (${bookLanguage})\"> ${renderVoiceOption(bookLanguages)} </optgroup>`));\n voicesMenu.append($(`<optgroup label=\"Other Languages\"> ${renderVoiceOption(otherLanguages)} </optgroup>`));\n }\n\n voicesMenu.val(this.ttsEngine.voice.voiceURI);\n voicesMenu.show();\n } else {\n voicesMenu.hide();\n }\n };\n\n const voicesMenu = this.br.refs.$BRReadAloudToolbar.find('[name=playback-voice]');\n renderVoicesMenu(voicesMenu);\n voicesMenu.on(\"change\", ev => this.ttsEngine.setVoice(voicesMenu.val()));\n this.ttsEngine.events.on('pause resume start', () => this.updateState());\n this.ttsEngine.events.on('voiceschanged', () => renderVoicesMenu(voicesMenu));\n this.br.on('translationEnabled', () => renderVoicesMenu(voicesMenu));\n this.br.on('translationDisabled', () => renderVoicesMenu(voicesMenu));\n this.br.refs.$BRReadAloudToolbar.find('[name=play]').on(\"click\", this.playPause.bind(this));\n this.br.refs.$BRReadAloudToolbar.find('[name=advance]').on(\"click\", this.jumpForward.bind(this));\n this.br.refs.$BRReadAloudToolbar.find('[name=review]').on(\"click\", this.jumpBackward.bind(this));\n const $rateSelector = this.br.refs.$BRReadAloudToolbar.find('select[name=\"playback-speed\"]');\n $rateSelector.on(\"change\", ev => this.ttsEngine.setPlaybackRate(parseFloat($rateSelector.val())));\n $(`<li>\n <button class=\"BRicon read js-tooltip\" title=\"${tooltips.readAloud}\">\n <div class=\"icon icon-read-aloud\"></div>\n <span class=\"BRtooltip\">${tooltips.readAloud}</span>\n </button>\n </li>`).insertBefore($navBar.find('.BRcontrols .BRicon.zoom_out').closest('li'));\n }\n\n toggle() {\n this.br.plugins.autoplay?.stop();\n if (this.ttsEngine.playing) {\n this.stop();\n } else {\n this.start();\n }\n }\n\n start(startTTSEngine = true) {\n const checkVoice = this.br.plugins.translate?.translationManager?.active ? toISO6391(this.br.plugins.translate.langToCode) : \"\";\n const bookVoice = this.ttsEngine.getBestVoice(checkVoice);\n\n const voicesMenu = this.br.refs.$BRReadAloudToolbar.find('[name=playback-voice');\n this.ttsEngine.setVoice(bookVoice.voiceURI);\n voicesMenu.val(bookVoice.voiceURI);\n if (this.br.constModeThumb == this.br.mode)\n this.br.switchMode(this.br.constMode1up);\n\n this.br.refs.$BRReadAloudToolbar.addClass('visible');\n this.br.$('.BRicon.read').addClass('unread active');\n this.sendAnalyticsEvent('Start');\n if (startTTSEngine)\n this.ttsEngine.start(this.br.currentIndex(), this.br.book.getNumLeafs());\n }\n\n jumpForward() {\n if (this.ttsEngine.paused) {\n this.ttsEngine.resume();\n }\n this.ttsEngine.jumpForward();\n }\n\n jumpBackward() {\n if (this.ttsEngine.paused) {\n this.ttsEngine.resume();\n }\n this.ttsEngine.jumpBackward();\n }\n\n updateState() {\n const isPlaying = !(this.ttsEngine.paused || !this.ttsEngine.playing);\n this.br.$('.read-aloud [name=play]').toggleClass('playing', isPlaying);\n }\n\n playPause() {\n if (!this.ttsEngine.playing) {\n this.toggle();\n } else {\n this.ttsEngine.togglePlayPause();\n this.updateState();\n }\n }\n\n\n stop() {\n this.br.refs.$BRReadAloudToolbar.removeClass('visible');\n this.br.$('.BRicon.read').removeClass('unread active');\n this.sendAnalyticsEvent('Stop');\n this.ttsEngine.stop();\n this.removeHilites();\n this.br.removeProgressPopup();\n }\n\n /**\n * @param {PageChunk} chunk\n * Returns once the flip is done\n */\n async beforeChunkPlay(chunk) {\n await this.maybeFlipToIndex(chunk.leafIndex);\n this.highlightChunk(chunk);\n this.scrollToChunk(chunk);\n }\n\n /**\n * @param {PageChunk} chunk\n */\n sendChunkFinishedAnalyticsEvent(chunk) {\n this.sendAnalyticsEvent('ChunkFinished-Words', countWords(chunk.text));\n }\n\n /**\n * Flip the page if the provided leaf index is not visible\n * @param {Number} leafIndex\n */\n async maybeFlipToIndex(leafIndex) {\n if (!this.br._isIndexDisplayed(leafIndex)) {\n // Don't interrupt the read aloud with the page flip update?\n this.br.jumpToIndex(leafIndex, { ariaLive: false });\n }\n }\n\n /**\n * @param {PageChunk} chunk\n */\n highlightChunk(chunk) {\n // The poorly-named variable leafIndex\n const pageIndex = chunk.leafIndex;\n\n this.removeHilites();\n if (this.br.plugins.translate?.translationManager.active) {\n const pageContainers = this.br.getActivePageContainerElementsForIndex(pageIndex);\n const paragraphIndex = chunk.chunkIndex;\n pageContainers.forEach(container => {\n const translateElement = container.querySelector('.BRtranslateLayer');\n const containerChildren = Array.from(translateElement.childNodes);\n const paragraphEle = containerChildren[paragraphIndex];\n if (!paragraphEle) { return; }\n const [pOffHeight, pOffTop, pOffWidth, pOffLeft] = [paragraphEle.offsetHeight, paragraphEle.offsetTop, paragraphEle.offsetWidth, paragraphEle.offsetLeft];\n const boxes = {pageIndex: [\n {l: pOffLeft, r: pOffLeft + pOffWidth, b: pOffTop + pOffHeight, t: pOffTop},\n ]};\n renderBoxesInPageContainerLayer('ttsHiliteLayer', boxes.pageIndex, this.br.book.getPage(pageIndex), translateElement);\n });\n return;\n }\n // group by index; currently only possible to have chunks on one page :/\n this._ttsBoxesByIndex = {\n [pageIndex]: chunk.lineRects.map(([l, b, r, t]) => ({l, r, b, t})),\n };\n\n // update any already created pages\n for (const [pageIndexString, boxes] of Object.entries(this._ttsBoxesByIndex)) {\n const pageIndex = parseFloat(pageIndexString);\n const page = this.br.book.getPage(pageIndex);\n const pageContainers = this.br.getActivePageContainerElementsForIndex(pageIndex);\n pageContainers.forEach(container => renderBoxesInPageContainerLayer('ttsHiliteLayer', boxes, page, container));\n }\n }\n\n /**\n * @param {PageChunk} chunk\n */\n scrollToChunk(chunk) {\n // It behaves weird if used in thumb mode\n if (this.br.constModeThumb == this.br.mode) return;\n\n const highlightRect = $(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0];\n this.br.scrollIntoView(highlightRect, {\n block: 'center',\n inline: 'center',\n behavior: 'smooth',\n });\n }\n\n removeHilites() {\n $(this.br.getActivePageContainerElements()).find('.ttsHiliteLayer').remove();\n this._ttsBoxesByIndex = {};\n }\n\n /**\n * @private\n * Send an analytics event with an optional value. Also attaches the book's language.\n * @param {string} action\n * @param {number} [value]\n */\n sendAnalyticsEvent(action, value) {\n if (this.br.plugins.archiveAnalytics) {\n const extraValues = {};\n const mediaLanguage = this.ttsEngine.opts.bookLanguage;\n if (mediaLanguage) extraValues.mediaLanguage = mediaLanguage;\n this.br.plugins.archiveAnalytics.sendEvent('BRReadAloud', action, value, extraValues);\n }\n }\n}\n\nBookReader?.registerPlugin('tts', TtsPlugin);\n","// @ts-check\nimport langs from 'iso-language-codes';\n\n/** @type {{[lang: string]: string}} */\n// Handle odd one-off language pairs that might show up over time\nconst specialLangs = {\n \"zh-hans\": \"中文 (Zhōngwén)\",\n};\n\n/**\n * @typedef {string} ISO6391\n * Language code in ISO 639-1 format. e.g. en, fr, zh\n **/\n\n/**\n * @param {string} language in some format\n * @return {ISO6391?}\n */\nexport function toISO6391(language) {\n if (!language) return null;\n language = language.toLocaleLowerCase();\n if (specialLangs[language]) {\n return language;\n }\n const codeObj = (\n findLanguage(language, ['iso639_1']) ||\n findLanguage(language, ['iso639_2T']) ||\n findLanguage(language, ['iso639_2B', 'name', 'nativeName'])\n );\n if (codeObj) return codeObj.iso639_1;\n return null;\n}\n\n/**\n *\n * @param {string} language\n * @returns {string | null}\n */\nexport function toNativeName(language) {\n if (!language) return null;\n language = language.toLocaleLowerCase();\n if (specialLangs[language]) {\n return specialLangs[language];\n }\n const codeObj = (\n findLanguage(language, ['iso639_1']) ||\n findLanguage(language, ['iso639_2T']) ||\n findLanguage(language, ['iso639_2B', 'name', 'nativeName'])\n );\n if (codeObj?.nativeName) return codeObj.nativeName.split(\", \")[0];\n return null;\n}\n\n/** @typedef {import('iso-language-codes').Code} Code */\n\n/**\n * @param {string} language\n * @param {Array<'iso639_1' | 'iso639_2T' | 'iso639_2B' | 'nativeName' | 'name'>} fields\n * @returns {Code | null}\n */\nfunction findLanguage(language, fields) {\n if (!language) return null;\n language = language.toLowerCase();\n for (const lang of langs) {\n for (const codeType of fields) {\n if (lang[codeType]?.toLowerCase().split(\", \").includes(language)) {\n return lang;\n }\n }\n }\n return null;\n}\n\n/**\n * Checks whether the current browser supports localStorage or\n * if the current context has access to it.\n * @return {boolean}\n */\nexport function hasLocalStorage() {\n try {\n return !!window.localStorage;\n } catch (e) {\n // Will throw in sandboxed iframe\n // DOMException: Window.localStorage getter: Forbidden in a sandboxed document without the 'allow-same-origin' flag.\n return false;\n }\n}\n\nexport const DEBUG_READ_ALOUD = location.toString().indexOf('_debugReadAloud=true') != -1;\n\nexport async function checkIfFiresPause() {\n // Pick some random text so that if it accidentally speaks, it's not too annoying\n const u = new SpeechSynthesisUtterance(\"Loading\");\n let calledPause = false;\n u.addEventListener('pause', () => calledPause = true);\n speechSynthesis.speak(u);\n await new Promise(res => setTimeout(res, 10));\n speechSynthesis.pause();\n return calledPause;\n}\n","/**\n * @typedef {String} StringWithVars\n * A template string with {{foo}} style variables\n * Also supports filters, like {{bookPath|urlencode}} (See APPLY_FILTERS for the\n * supported list of filters)\n **/\n\n/**\n * Count whitespace-delimited words in a string.\n * @param {string} text\n * @return {number}\n */\nexport function countWords(text) {\n const matches = text.match(/\\S+/g);\n return matches ? matches.length : 0;\n}\n\n/**\n * @param {StringWithVars|String} template\n * @param { {[varName: string]: { toString: () => string} } } vars\n * @param { {[varName: string]: { toString: () => string} } } [overrides]\n * @returns {StringWithVars|string}\n */\nexport function applyVariables(template, vars, overrides = {}, possibleFilters = APPLY_FILTERS) {\n return template?.replace(/\\{\\{([^}]*?)\\}\\}/g, ($0, $1) => {\n if (!$1) return $0;\n /** @type {string} */\n const expression = $1;\n const [varName, ...filterNames] = expression.split('|').map(x => x.trim());\n const defined = varName in overrides || varName in vars;\n\n // If it's not defined, don't expand it at all\n if (!defined) return $0;\n\n const value = varName in overrides ? overrides[varName]\n : varName in vars ? vars[varName] : null;\n const filters = filterNames.map(n => possibleFilters[n]);\n return filters.reduce((acc, cur) => cur(acc), value && value.toString());\n });\n}\n\n/** @type { {[filterName: String]:( string => string)} } */\nexport const APPLY_FILTERS = {\n urlencode: encodeURIComponent,\n};\n"],"names":["PROPER_FUNCTION_NAME","__webpack_require__","fails","whitespaces","module","exports","METHOD_NAME","name","uncurryThis","requireObjectCoercible","toString","replace","ltrim","RegExp","rtrim","createMethod","TYPE","$this","string","start","end","Bq","$","$trim","target","proto","forced","forcedStringTrimMethod","trim","this","BookReaderPlugin","constructor","br","options","setup","Object","assign","init","_configurePageContainer","pageContainer","_configureToolbar","$toolbarElement","_bindNavigationHandlers","extendNavBar","$navBar","PageChunk","leafIndex","chunkIndex","text","lineRects","fetch","pageChunkUrl","_window$br$plugins$tr","window","plugins","translate","translationManager","active","translateLayers","getTranslateLayers","paragraphs","Array","from","childNodes","pageChunks","_ref","entries","_ref2","_slicedToArray","idx","item","classList","contains","translatedChunk","textContent","push","length","placeholder","ocrPage","_getTextSelectionOcrPage","_fromTextWrapperResponse","_chunkOcrPage","chunks","ajax","type","url","applyVariables","pageIndex","cache","xhrFields","withCredentials","protected","textSelection","enabled","getPageText","e","chunksResponse","map","c","i","correctedLineRects","_fixChunkRects","slice","correctedText","_removeDanglingHyphens","words","rects","lineRect","endChunk","join","line","querySelectorAll","_line$closest","closest","getAttribute","word","_word$getAttribute","_split$map2","split","parseFloat","left","bottom","right","top","isNaN","Math","min","max","endsWith","_rects","firstRect","secondRect","_firstRect","width","secondHeight","secondWidth","secondRight","PageChunkIterator","pageCount","opts","DEFAULT_OPTS","_cursor","page","chunk","_bufferedPages","_bufferingPages","_cursorLock","Promise","resolve","next","then","_nextUncontrolled","decrement","_decrementUncontrolled","AT_END","_recenterBuffer","_fetchPageChunks","cursorChangePromise","prevPageChunks","index","pageBufferSize","_removePageFromBuffer","_fetchPageChunksDirect","AbstractTTSEngine","voice","getBestBookVoice","getVoices","bookLanguage","playing","paused","_chunkIterator","activeSound","playbackRate","events","on","updateBestVoice","trigger","isSupported","Error","numLeafs","onLoadingStart","step","stop","pause","fireEvent","resume","togglePlayPause","jumpForward","finish","jumpBackward","all","setVoice","voiceURI","off","find","hasLocalStorage","localStorage","setItem","concat","setPlaybackRate","newRate","onDone","sound","createSound","rate","load","onLoadingComplete","beforeChunkPlay","playPromise","playSound","afterChunkPlay","loaded","play","getBestVoice","languageOverride","voices","userLanguages","arguments","undefined","navigator","languages","bookLangVoices","filter","v","lang","startsWith","language","matchingUserLangs","getMatchingStoredVoice","getMatchingVoice","default","storedVoice","getItem","matchingVoices","FestivalTTSEngine","soundManager","supported","_$$browser","super","audioFormat","browser","mozilla","festivalUrl","localService","debugMode","preferFlash","useHTML5Audio","flashVersion","promise","userAgent","match","iOSCaptureUserIntentHack","FestivalTTSSound","format","SILENCE_1MS","res","onfinish","destruct","soundUrl","_finishResolver","onload","onresume","async","sleep","mp3","ogg","WebTTSEngine","speechSynthesis","addEventListener","audio","Audio","imagesBaseURL","loop","src","mediaSession","metadata","MediaMetadata","title","bookTitle","artist","m","label","value","artwork","thumbnail","setPositionState","duration","Infinity","setActionHandler","unshift","WebTTSSound","started","stopped","utterance","_lastEvents","boundary","_charIndex","_finishPromise","_this$voice","SpeechSynthesisUtterance","DEBUG_READ_ALOUD","console","log","ev","dispatchEvent","CustomEvent","reload","wasPaused","recentEvent","indexOf","charIndex","cancel","speak","isLocalVoice","isChrome","_chromePausingBugFix","endPromise","race","promisifyEvent","Event","pausePromise","pauseMightNotWork","isFirefox","isAndroid","resumeMightNotWork","resumePromise","result","en","BookReader","TtsPlugin","_defineProperty","remoteTtsUrl","server","bookPath","_ttsBoxesByIndex","TTSEngine","test","location","engineName","festival","web","ttsEngine","_objectSpread","vars","toISO6391","showProgressPopup","bind","removeProgressPopup","sendChunkFinishedAnalyticsEvent","eventNames","PostInit","click","toggle","renderBoxesInPageContainerLayer","$container","refs","$BRReadAloudToolbar","prepend","renderVoiceOption","voiceSortOrder","a","b","localeCompare","renderVoicesMenu","voicesMenu","_this$br$plugins$tran","empty","langFromCode","bookLanguages","sort","otherLanguages","_this$br$plugins$tran2","toLang","langToCode","translatedLanguages","append","val","show","hide","updateState","playPause","$rateSelector","tooltips","insertBefore","_this$br$plugins$auto","autoplay","_this$br$plugins$tran3","startTTSEngine","checkVoice","bookVoice","constModeThumb","mode","switchMode","constMode1up","addClass","sendAnalyticsEvent","currentIndex","book","getNumLeafs","isPlaying","toggleClass","removeClass","removeHilites","maybeFlipToIndex","highlightChunk","scrollToChunk","countWords","_isIndexDisplayed","jumpToIndex","ariaLive","_this$br$plugins$tran4","pageContainers","getActivePageContainerElementsForIndex","paragraphIndex","forEach","container","translateElement","querySelector","paragraphEle","offsetHeight","offsetTop","offsetWidth","offsetLeft","pOffTop","pOffLeft","boxes","l","r","t","getPage","_ref3","_ref4","_ref5","pageIndexString","_$$last","highlightRect","last","scrollIntoView","block","inline","behavior","getActivePageContainerElements","remove","action","archiveAnalytics","extraValues","mediaLanguage","sendEvent","registerPlugin","specialLangs","toLocaleLowerCase","codeObj","findLanguage","iso639_1","toNativeName","nativeName","fields","toLowerCase","langs","codeType","_lang$codeType","includes","matches","template","overrides","possibleFilters","APPLY_FILTERS","$0","$1","_expression$split$map2","x","varName","filterNames","_arrayLikeToArray","n","reduce","acc","cur","urlencode","encodeURIComponent"],"sourceRoot":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const __webpack_esm_ids__=[479];export const __webpack_esm_modules__={7916:(t,e,r)=>{var n=r(6080),o=r(9565),a=r(8981),i=r(6319),s=r(4209),l=r(3517),h=r(6198),u=r(4659),c=r(4527),f=r(8563),p=r(3085),d=r(9539),m=r(6837),g=Array;t.exports=function(t){var e=l(this),r=arguments.length,v=r>1?arguments[1]:void 0,y=void 0!==v;y&&(v=n(v,r>2?arguments[2]:void 0));var w,b,S,P,k,R,U=a(t),B=p(U),H=0;if(!B||this===g&&s(B))for(w=h(U),b=e?new this(w):g(w);w>H;H++)R=y?v(U[H],H):U[H],u(b,H,R);else for(b=e?new this:[],k=(P=f(U,B)).next;!(S=o(k,P)).done;H++){try{m(H)}catch(t){d(P,"throw",t)}R=y?i(P,v,[S.value,H],!0):S.value;try{u(b,H,R)}catch(t){d(P,"throw",t)}}return c(b,H),b}},4527:(t,e,r)=>{var n=r(3724),o=r(4376),a=TypeError,i=Object.getOwnPropertyDescriptor,s=n&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}();t.exports=s?function(t,e){if(o(t)&&!i(t,"length").writable)throw new a("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e}},6319:(t,e,r)=>{var n=r(8551),o=r(9539);t.exports=function(t,e,r,a){try{return a?e(n(r)[0],r[1]):e(r)}catch(e){o(t,"throw",e)}}},4124:(t,e,r)=>{var n=r(4576);t.exports=function(t,e){var r=n[t],o=r&&r.prototype;return o&&o[e]}},4213:(t,e,r)=>{var n=r(3724),o=r(9504),a=r(9565),i=r(9039),s=r(1072),l=r(3717),h=r(8773),u=r(8981),c=r(7055),f=Object.assign,p=Object.defineProperty,d=o([].concat);t.exports=!f||i(function(){if(n&&1!==f({b:1},f(p({},"a",{enumerable:!0,get:function(){p(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},r=Symbol("assign detection"),o="abcdefghijklmnopqrst";return t[r]=7,o.split("").forEach(function(t){e[t]=t}),7!==f({},t)[r]||s(f({},e)).join("")!==o})?function(t,e){for(var r=u(t),o=arguments.length,i=1,f=l.f,p=h.f;o>i;)for(var m,g=c(arguments[i++]),v=f?d(s(g),f(g)):s(g),y=v.length,w=0;y>w;)m=v[w++],n&&!a(p,g,m)||(r[m]=g[m]);return r}:f},6098:(t,e,r)=>{var n=r(9504),o=2147483647,a=/[^\0-\u007E]/,i=/[.\u3002\uFF0E\uFF61]/g,s="Overflow: input needs wider integers to process",l=RangeError,h=n(i.exec),u=Math.floor,c=String.fromCharCode,f=n("".charCodeAt),p=n([].join),d=n([].push),m=n("".replace),g=n("".split),v=n("".toLowerCase),y=function(t){return t+22+75*(t<26)},w=function(t,e,r){var n=0;for(t=r?u(t/700):t>>1,t+=u(t/e);t>455;)t=u(t/35),n+=36;return u(n+36*t/(t+38))},b=function(t){var e=[];t=function(t){for(var e=[],r=0,n=t.length;r<n;){var o=f(t,r++);if(o>=55296&&o<=56319&&r<n){var a=f(t,r++);56320==(64512&a)?d(e,((1023&o)<<10)+(1023&a)+65536):(d(e,o),r--)}else d(e,o)}return e}(t);var r,n,a=t.length,i=128,h=0,m=72;for(r=0;r<t.length;r++)(n=t[r])<128&&d(e,c(n));var g=e.length,v=g;for(g&&d(e,"-");v<a;){var b=o;for(r=0;r<t.length;r++)(n=t[r])>=i&&n<b&&(b=n);var S=v+1;if(b-i>u((o-h)/S))throw new l(s);for(h+=(b-i)*S,i=b,r=0;r<t.length;r++){if((n=t[r])<i&&++h>o)throw new l(s);if(n===i){for(var P=h,k=36;;){var R=k<=m?1:k>=m+26?26:k-m;if(P<R)break;var U=P-R,B=36-R;d(e,c(y(R+U%B))),P=u(U/B),k+=36}d(e,c(y(P))),m=w(h,S,v===g),h=0,v++}}h++,i++}return p(e,"")};t.exports=function(t){var e,r,n=[],o=g(m(v(t),i,"."),".");for(e=0;e<o.length;e++)r=o[e],d(n,h(a,r)?"xn--"+b(r):r);return p(n,".")}},706:(t,e,r)=>{var n=r(350).PROPER,o=r(9039),a=r(7452);t.exports=function(t){return o(function(){return!!a[t]()||"
"!=="
"[t]()||n&&a[t].name!==t})}},3802:(t,e,r)=>{var n=r(9504),o=r(7750),a=r(655),i=r(7452),s=n("".replace),l=RegExp("^["+i+"]+"),h=RegExp("(^|[^"+i+"])["+i+"]+$"),u=function(t){return function(e){var r=a(o(e));return 1&t&&(r=s(r,l,"")),2&t&&(r=s(r,h,"$1")),r}};t.exports={start:u(1),end:u(2),Bq:u(3)}},7452:t=>{t.exports="\t\n\v\f\r \u2028\u2029\ufeff"},3921:(t,e,r)=>{var n=r(6518),o=r(2652),a=r(4659);n({target:"Object",stat:!0},{fromEntries:function(t){var e={};return o(t,function(t,r){a(e,t,r)},{AS_ENTRIES:!0}),e}})},2762:(t,e,r)=>{var n=r(6518),o=r(3802).Bq;n({target:"String",proto:!0,forced:r(706)("trim")},{trim:function(){return o(this)}})},3679:(t,e,r)=>{r.d(e,{Z:()=>g,A:()=>v});var n,o=()=>r(6518),a=()=>r(1181),i=()=>r(8183),s=()=>r(655),l=r.cw(function(t,e){var n=i().o,o=s(),l=a(),h=r(1088),u=r(2529),c="String Iterator",f=l.set,p=l.getterFor(c);h(String,"String",function(t){f(this,{type:c,string:o(t),index:0})},function(){var t,e=p(this),r=e.string,o=e.index;return o>=r.length?u(void 0,!0):(t=n(r,o),e.index+=t.length,u(t,!1))})}),h=r.cw(function(t,e){l();var n,h=o(),u=r(3724),c=r(7416),f=r(4576),p=r(6080),d=r(9504),m=r(6840),g=r(2106),v=r(679),y=r(9297),w=r(4213),b=r(7916),S=r(7680),P=i().L,k=r(6098),R=r(918),U=s(),B=r(687),H=r(2812),L=r(8406),_=a(),O=_.set,q=_.getterFor("URL"),I=L.URLSearchParams,x=L.getState,A=R.decode,j=R.encode,F=f.URL,T=f.TypeError,C=f.parseInt,M=Math.floor,E=Math.pow,$=String.fromCharCode,z=d("".charAt),N=d(/./.exec),J=d([].join),W=d(1.1.toString),Z=d([].pop),D=d([].push),Q=d("".replace),G=d([].shift),K=d("".split),V=d("".indexOf),X=d("".slice),Y=d("".toLowerCase),tt=d([].unshift),et="Invalid scheme",rt="Invalid host",nt="Invalid port",ot=/[a-z]/i,at=/[\d+\-.a-z]/i,it=/\d/,st=/^0x/i,lt=/^[0-7]+$/,ht=/^\d+$/,ut=/^[\da-f]+$/i,ct=/[\u0000-\u0020#%/:<>?@[\\\]^|\u007F]/,ft=/[\0\t\n\r #/:<>?@[\\\]^|]/,pt=/^[\u0000-\u0020]+/,dt=/(^|[^\u0000-\u0020])[\u0000-\u0020]+$/,mt=/[\t\n\r]/g,gt=/[^\u0000-\u007F]/,vt=function(t){return 173===t||847===t||8203===t||12644===t||65279===t||65440===t||t>=4447&&t<=4448||t>=6068&&t<=6069||t>=6155&&t<=6159||t>=8288&&t<=8292||t>=8298&&t<=8303||t>=65024&&t<=65039||t>=917760&&t<=917999},yt=function(t){return 65533===t||t>=55296&&t<=57343||t>=128&&t<=159||t>=8206&&t<=8207||t>=8232&&t<=8233||t>=8234&&t<=8238||t>=8293&&t<=8297||t>=64976&&t<=65007||!(65534&~t)||t>=57344&&t<=63743||t>=983040&&t<=1114109},wt=function(t){return t>=65281&&t<=65374?t-65248:160===t||5760===t||8239===t||8287===t||12288===t||t>=8192&&t<=8202||t<=65535&&V("¨¯´¸˘˙˚˛˜˝ͺ΄΅᾽᾿῀῁῍῎῏῝῞῟῭΅´῾‗‾⁇⁈⁉℀℁℅℆⩴゛゜ﱞﱟﱠﱡﱢﱣﷺﷻ︓︖﹇﹈﹉﹊﹋﹌﹕﹖﹟﹤﹥﹨﹪﹫ﹰﹲﹴﹶﹸﹺﹼﹾ ̄",$(t))>-1?32:t},bt=function(t){var e,r,n,o;if("number"==typeof t){for(e=[],r=0;r<4;r++)tt(e,t%256),t=M(t/256);return J(e,".")}if("object"==typeof t){for(e="",n=function(t){for(var e=null,r=1,n=null,o=0,a=0;a<8;a++)0!==t[a]?(o>r&&(e=n,r=o),n=null,o=0):(null===n&&(n=a),++o);return o>r?n:e}(t),r=0;r<8;r++)o&&0===t[r]||(o&&(o=!1),n===r?(e+=r?":":"::",o=!0):(e+=W(t[r],16),r<7&&(e+=":")));return"["+e+"]"}return t},St={},Pt=w({},St,{" ":1,'"':1,"#":1,"<":1,">":1}),kt=w({},Pt,{"'":1}),Rt=w({},St,{" ":1,'"':1,"<":1,">":1,"`":1}),Ut=w({},Rt,{"#":1,"?":1,"{":1,"}":1,"^":1}),Bt=w({},Ut,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),Ht=function(t,e){var r=P(t,0);return r>=32&&r<127&&!y(e,t)?t:"'"===t&&y(e,t)?"%27":j(t)},Lt={ftp:21,file:null,http:80,https:443,ws:80,wss:443},_t=function(t,e){var r;return 2===t.length&&N(ot,z(t,0))&&(":"===(r=z(t,1))||!e&&"|"===r)},Ot=function(t){var e;return t.length>1&&_t(X(t,0,2))&&(2===t.length||"/"===(e=z(t,2))||"\\"===e||"?"===e||"#"===e)},qt=function(t){return"."===t||"%2e"===Y(t)},It=function(t){return".."===(t=Y(t))||"%2e."===t||".%2e"===t||"%2e%2e"===t},xt={},At={},jt={},Ft={},Tt={},Ct={},Mt={},Et={},$t={},zt={},Nt={},Jt={},Wt={},Zt={},Dt={},Qt={},Gt={},Kt={},Vt={},Xt={},Yt={},te=function(t,e,r){var n,o,a,i=U(t);if(e){if(o=this.parse(i))throw new T(o);this.searchParams=null}else{if(void 0!==r&&(n=new te(r,!0)),o=this.parse(i,null,n))throw new T(o);(a=x(new I)).bindURL(this),this.searchParams=a}};te.prototype={type:"URL",parse:function(t,e,r){var o,a,i,s,l=this,h=e||xt,u=0,c="",f=!1,p=!1,d=!1;for(t=U(t),e||(l.scheme="",l.username="",l.password="",l.host=null,l.port=null,l.path=[],l.query=null,l.fragment=null,l.cannotBeABaseURL=!1,t=Q(t,pt,""),t=Q(t,dt,"$1")),t=Q(t,mt,""),o=b(t);u<=o.length;){switch(a=o[u],h){case xt:if(!a||!N(ot,a)){if(e)return et;h=jt;continue}c+=Y(a),h=At;break;case At:if(a&&N(at,a))c+=Y(a);else{if(":"!==a){if(e)return et;c="",h=jt,u=0;continue}if(e&&(l.isSpecial()!==y(Lt,c)||"file"===c&&(l.includesCredentials()||null!==l.port)||"file"===l.scheme&&""===l.host))return;if(l.scheme=c,e)return void(l.isSpecial()&&Lt[l.scheme]===l.port&&(l.port=null));c="","file"===l.scheme?h=Zt:l.isSpecial()&&r&&r.scheme===l.scheme?h=Ft:l.isSpecial()?h=Et:"/"===o[u+1]?(h=Tt,u++):(l.cannotBeABaseURL=!0,D(l.path,""),h=Vt)}break;case jt:if(!r||r.cannotBeABaseURL&&"#"!==a)return et;if(r.cannotBeABaseURL&&"#"===a){l.scheme=r.scheme,l.path=S(r.path),l.query=r.query,l.fragment="",l.cannotBeABaseURL=!0,h=Yt;break}h="file"===r.scheme?Zt:Ct;continue;case Ft:if("/"!==a||"/"!==o[u+1]){h=Ct;continue}h=$t,u++;break;case Tt:if("/"===a){h=zt;break}h=Kt;continue;case Ct:if(l.scheme=r.scheme,a===n)l.username=r.username,l.password=r.password,l.host=r.host,l.port=r.port,l.path=S(r.path),l.query=r.query;else if("/"===a||"\\"===a&&l.isSpecial())h=Mt;else if("?"===a)l.username=r.username,l.password=r.password,l.host=r.host,l.port=r.port,l.path=S(r.path),l.query="",h=Xt;else{if("#"!==a){l.username=r.username,l.password=r.password,l.host=r.host,l.port=r.port,l.path=S(r.path),l.path.length&&l.path.length--,h=Kt;continue}l.username=r.username,l.password=r.password,l.host=r.host,l.port=r.port,l.path=S(r.path),l.query=r.query,l.fragment="",h=Yt}break;case Mt:if(!l.isSpecial()||"/"!==a&&"\\"!==a){if("/"!==a){l.username=r.username,l.password=r.password,l.host=r.host,l.port=r.port,h=Kt;continue}h=zt}else h=$t;break;case Et:if(h=$t,"/"!==a||"/"!==o[u+1])continue;u++;break;case $t:if("/"!==a&&"\\"!==a){h=zt;continue}break;case zt:if("@"===a){f&&(c="%40"+c),f=!0,i=b(c);for(var m=0;m<i.length;m++){var g=i[m];if(":"!==g||d){var v=Ht(g,Bt);d?l.password+=v:l.username+=v}else d=!0}c=""}else if(a===n||"/"===a||"?"===a||"#"===a||"\\"===a&&l.isSpecial()){if(f&&""===c)return"Invalid authority";u-=b(c).length+1,c="",h=Nt}else c+=a;break;case Nt:case Jt:if(e&&"file"===l.scheme){h=Qt;continue}if(":"!==a||p){if(a===n||"/"===a||"?"===a||"#"===a||"\\"===a&&l.isSpecial()){if(l.isSpecial()&&""===c)return rt;if(e&&""===c&&(l.includesCredentials()||null!==l.port))return;if(s=l.parseHost(c))return s;if(c="",h=Gt,e)return;continue}"["===a?p=!0:"]"===a&&(p=!1),c+=a}else{if(""===c)return rt;if(e===Jt)return;if(s=l.parseHost(c))return s;c="",h=Wt}break;case Wt:if(!N(it,a)){if(a===n||"/"===a||"?"===a||"#"===a||"\\"===a&&l.isSpecial()||e){if(""!==c){var w=C(c,10);if(w>65535)return nt;l.port=l.isSpecial()&&w===Lt[l.scheme]?null:w,c=""}if(e)return;h=Gt;continue}return nt}c+=a;break;case Zt:if(l.scheme="file",l.host="","/"===a||"\\"===a)h=Dt;else{if(!r||"file"!==r.scheme){h=Kt;continue}switch(a){case n:l.host=r.host,l.path=S(r.path),l.query=r.query;break;case"?":l.host=r.host,l.path=S(r.path),l.query="",h=Xt;break;case"#":l.host=r.host,l.path=S(r.path),l.query=r.query,l.fragment="",h=Yt;break;default:l.host=r.host,Ot(J(S(o,u),""))||(l.path=S(r.path),l.shortenPath()),h=Kt;continue}}break;case Dt:if("/"===a||"\\"===a){h=Qt;break}r&&"file"===r.scheme&&(l.host=r.host,!Ot(J(S(o,u),""))&&_t(r.path[0],!0)&&D(l.path,r.path[0])),h=Kt;continue;case Qt:if(a===n||"/"===a||"\\"===a||"?"===a||"#"===a){if(!e&&_t(c))h=Kt;else if(""===c){if(l.host="",e)return;h=Gt}else{if(s=l.parseHost(c))return s;if("localhost"===l.host&&(l.host=""),e)return;c="",h=Gt}continue}c+=a;break;case Gt:if(l.isSpecial()){if(h=Kt,"/"!==a&&"\\"!==a)continue}else if(e||"?"!==a)if(e||"#"!==a){if(a!==n&&(h=Kt,"/"!==a))continue}else l.fragment="",h=Yt;else l.query="",h=Xt;break;case Kt:if(a===n||"/"===a||"\\"===a&&l.isSpecial()||!e&&("?"===a||"#"===a)){if(It(c)?(l.shortenPath(),"/"===a||"\\"===a&&l.isSpecial()||D(l.path,"")):qt(c)?"/"===a||"\\"===a&&l.isSpecial()||D(l.path,""):("file"===l.scheme&&!l.path.length&&_t(c)&&(null!==l.host&&""!==l.host&&(l.host=""),c=z(c,0)+":"),D(l.path,c)),c="","file"===l.scheme&&(a===n||"?"===a||"#"===a))for(;l.path.length>1&&""===l.path[0];)G(l.path);"?"===a?(l.query="",h=Xt):"#"===a&&(l.fragment="",h=Yt)}else c+=Ht(a,Ut);break;case Vt:"?"===a?(l.query="",h=Xt):"#"===a?(l.fragment="",h=Yt):a!==n&&(l.path[0]+=" "===a?"?"===o[u+1]||"#"===o[u+1]?"%20":" ":Ht(a,St));break;case Xt:e||"#"!==a?a!==n&&(l.query+=Ht(a,l.isSpecial()?kt:Pt)):(l.fragment="",h=Yt);break;case Yt:a!==n&&(l.fragment+=Ht(a,Rt))}u++}},parseHost:function(t){var e,r,n;if("["===z(t,0)){if("]"!==z(t,t.length-1))return rt;if(e=function(t){var e,r,n,o,a,i,s,l=[0,0,0,0,0,0,0,0],h=0,u=null,c=0,f=function(){return z(t,c)};if(":"===f()){if(":"!==z(t,1))return;c+=2,u=++h}for(;f();){if(8===h)return;if(":"!==f()){for(e=r=0;r<4&&N(ut,f());)e=16*e+C(f(),16),c++,r++;if("."===f()){if(0===r)return;if(c-=r,h>6)return;for(n=0;f();){if(o=null,n>0){if(!("."===f()&&n<4))return;c++}if(!N(it,f()))return;for(;N(it,f());){if(a=C(f(),10),null===o)o=a;else{if(0===o)return;o=10*o+a}if(o>255)return;c++}l[h]=256*l[h]+o,2!==++n&&4!==n||h++}if(4!==n)return;break}if(":"===f()){if(c++,!f())return}else if(f())return;l[h++]=e}else{if(null!==u)return;c++,u=++h}}if(null!==u)for(i=h-u,h=7;0!==h&&i>0;)s=l[h],l[h--]=l[u+i-1],l[u+--i]=s;else if(8!==h)return;return l}(X(t,1,-1)),!e)return rt;this.host=e}else if(this.isSpecial()){if(t=function(t){if(!N(gt,t))return""===t?null:k(t);var e,r,n,o=b(t),a="";for(e=0;e<o.length;e++){if(r=P(o[e],0),yt(r))return null;vt(r)||(a+=(n=wt(r))===r?o[e]:$(n))}return""===a?null:k(a)}(A(t)),null===t||N(ct,t))return rt;if(function(t){var e,r,n=K(t,".");if(""===n[n.length-1]){if(1===n.length)return!1;n.length--}return e=n[n.length-1],!!N(ht,e)||!!N(st,e)&&(""===(r=X(e,2))||!!N(ut,r))}(t)){if(e=function(t){var e,r,n,o,a,i,s,l=K(t,".");if(l.length&&""===l[l.length-1]&&l.length--,(e=l.length)>4)return null;for(r=[],n=0;n<e;n++){if(""===(o=l[n]))return null;if(a=10,o.length>1&&"0"===z(o,0)&&(a=N(st,o)?16:8,o=X(o,8===a?1:2)),""===o)i=0;else{if(!N(10===a?ht:8===a?lt:ut,o))return null;i=C(o,a)}D(r,i)}for(n=0;n<e;n++)if(i=r[n],n===e-1){if(i>=E(256,5-e))return null}else if(i>255)return null;for(s=Z(r),n=0;n<r.length;n++)s+=r[n]*E(256,3-n);return s}(t),null===e)return rt;this.host=e}else this.host=t}else{if(N(ft,t))return rt;for(e="",r=b(t),n=0;n<r.length;n++)e+=Ht(r[n],St);this.host=e}},cannotHaveUsernamePasswordPort:function(){return null===this.host||""===this.host||this.cannotBeABaseURL||"file"===this.scheme},includesCredentials:function(){return""!==this.username||""!==this.password},isSpecial:function(){return y(Lt,this.scheme)},shortenPath:function(){var t=this.path,e=t.length;!e||"file"===this.scheme&&1===e&&_t(t[0],!0)||t.length--},serialize:function(){var t=this,e=t.scheme,r=t.username,n=t.password,o=t.host,a=t.port,i=t.path,s=t.query,l=t.fragment,h=e+":";return null!==o?(h+="//",t.includesCredentials()&&(h+=r+(n?":"+n:"")+"@"),h+=bt(o),null!==a&&(h+=":"+a)):"file"===e&&(h+="//"),null===o&&!t.cannotBeABaseURL&&i.length>1&&""===i[0]&&(h+="/."),h+=t.cannotBeABaseURL?i[0]:i.length?"/"+J(i,"/"):"",null!==s&&(h+="?"+s),null!==l&&(h+="#"+l),h},setHref:function(t){var e=this.parse(t);if(e)throw new T(e);this.searchParams.update()},getOrigin:function(){var t=this.scheme,e=this.port;if("blob"===t)try{return new ee(this.path[0]).origin}catch(t){return"null"}return"file"!==t&&this.isSpecial()?t+"://"+bt(this.host)+(null!==e?":"+e:""):"null"},getProtocol:function(){return this.scheme+":"},setProtocol:function(t){this.parse(U(t)+":",xt)},getUsername:function(){return this.username},setUsername:function(t){var e=b(U(t));if(!this.cannotHaveUsernamePasswordPort()){this.username="";for(var r=0;r<e.length;r++)this.username+=Ht(e[r],Bt)}},getPassword:function(){return this.password},setPassword:function(t){var e=b(U(t));if(!this.cannotHaveUsernamePasswordPort()){this.password="";for(var r=0;r<e.length;r++)this.password+=Ht(e[r],Bt)}},getHost:function(){var t=this.host,e=this.port;return null===t?"":null===e?bt(t):bt(t)+":"+e},setHost:function(t){this.cannotBeABaseURL||this.parse(t,Nt)},getHostname:function(){var t=this.host;return null===t?"":bt(t)},setHostname:function(t){this.cannotBeABaseURL||this.parse(t,Jt)},getPort:function(){var t=this.port;return null===t?"":U(t)},setPort:function(t){this.cannotHaveUsernamePasswordPort()||(""===(t=U(t))?this.port=null:this.parse(t,Wt))},getPathname:function(){var t=this.path;return this.cannotBeABaseURL?t[0]:t.length?"/"+J(t,"/"):""},setPathname:function(t){this.cannotBeABaseURL||(this.path=[],this.parse(t,Gt))},getSearch:function(){var t=this.query;return t?"?"+t:""},setSearch:function(t){""===(t=U(t))?this.query=null:("?"===z(t,0)&&(t=X(t,1)),this.query="",this.parse(t,Xt)),this.searchParams.update()},getSearchParams:function(){return this.searchParams.facade},getHash:function(){var t=this.fragment;return t?"#"+t:""},setHash:function(t){""!==(t=U(t))?("#"===z(t,0)&&(t=X(t,1)),this.fragment="",this.parse(t,Yt)):this.fragment=null},update:function(){this.query=this.searchParams.serialize()||null}};var ee=function(t){var e=v(this,re),r=H(arguments.length,1)>1?arguments[1]:void 0,n=O(e,new te(t,!1,r));u||(e.href=n.serialize(),e.origin=n.getOrigin(),e.protocol=n.getProtocol(),e.username=n.getUsername(),e.password=n.getPassword(),e.host=n.getHost(),e.hostname=n.getHostname(),e.port=n.getPort(),e.pathname=n.getPathname(),e.search=n.getSearch(),e.searchParams=n.getSearchParams(),e.hash=n.getHash())},re=ee.prototype,ne=function(t,e){return{get:function(){return q(this)[t]()},set:e&&function(t){return q(this)[e](t)},configurable:!0,enumerable:!0}};if(u&&(g(re,"href",ne("serialize","setHref")),g(re,"origin",ne("getOrigin")),g(re,"protocol",ne("getProtocol","setProtocol")),g(re,"username",ne("getUsername","setUsername")),g(re,"password",ne("getPassword","setPassword")),g(re,"host",ne("getHost","setHost")),g(re,"hostname",ne("getHostname","setHostname")),g(re,"port",ne("getPort","setPort")),g(re,"pathname",ne("getPathname","setPathname")),g(re,"search",ne("getSearch","setSearch")),g(re,"searchParams",ne("getSearchParams")),g(re,"hash",ne("getHash","setHash"))),m(re,"toJSON",function(){return q(this).serialize()},{enumerable:!0}),m(re,"toString",function(){return q(this).serialize()},{enumerable:!0}),F){var oe=F.createObjectURL,ae=F.revokeObjectURL;oe&&m(ee,"createObjectURL",p(oe,F)),ae&&m(ee,"revokeObjectURL",p(ae,F))}B(ee,"URL"),h({global:!0,constructor:!0,forced:!c,sham:!u},{URL:ee})}),u=r.cw(function(t,e){h()}),c=r.cw(function(t,e){var n=o(),a=r(9565),i=r(4124)("URL","toString");n({target:"URL",proto:!0,enumerable:!0},{toJSON:function(){return a(i,this)}})});function f(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,a,i,s=[],l=!0,h=!1;try{if(a=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=a.call(r)).done)&&(s.push(n.value),s.length!==e);l=!0);}catch(t){h=!0,o=t}finally{try{if(!l&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(h)throw o}}return s}}(t,e)||function(t,e){if(t){if("string"==typeof t)return p(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?p(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}r(9463),r(3792),r(2712),r(7495),r(5440),r(2953),r(8408),r(3921),r(2762),u(),c();class d{constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.bookReaderOptions=t,this.urlSchema=[{name:"page",position:"path",default:"n0"},{name:"mode",position:"path",default:"2up"},{name:"search",position:"path",deprecated_for:"q"},{name:"q",position:"query_param"},{name:"sort",position:"query_param"},{name:"view",position:"query_param"},{name:"admin",position:"query_param"},{name:"focus",position:"query_param",readOnly:!0}],this.urlState={},this.urlMode=this.bookReaderOptions.urlMode||"hash",this.urlHistoryBasePath=this.bookReaderOptions.urlHistoryBasePath||"/",this.urlLocationPollId=null,this.oldLocationHash=null,this.oldUserHash=null}urlStateToUrlString(t){const e=new URLSearchParams,r={};Object.keys(t).forEach(n=>{var o,a,i;let s=this.urlSchema.find(t=>t.name===n);var l,h;null!==(o=s)&&void 0!==o&&o.deprecated_for&&(s=this.urlSchema.find(t=>t.name===s.deprecated_for)),null!==(a=s)&&void 0!==a&&a.readOnly||("path"==(null===(i=s)||void 0===i?void 0:i.position)?r[null===(l=s)||void 0===l?void 0:l.name]=t[n]:e.append((null===(h=s)||void 0===h?void 0:h.name)||n,t[n]))});const n=this.urlSchema.filter(t=>"path"==t.position).map(t=>r[t.name]?"".concat(t.name,"/").concat(encodeURIComponent(r[t.name])):"").join("/"),o="".concat(n.replace(/\/+/g,"/").replace(/\/+$/,"")),a="".concat(o,"?").concat(e.toString());return e.toString()?a:"".concat(o)}urlStringToUrlState(t){const e={},r=new URL(t,"http://example.com"),n=Object.fromEntries(r.searchParams.entries()),o=r.pathname.match(/[^\\/]+\/[^\\/]+/g),a=o?Object.fromEntries(o.map(t=>t.split("/"))):{},i=(t,e)=>Object.keys(t).some(t=>t==e);return this.urlSchema.filter(t=>"path"==t.position).forEach(t=>{const r=i(a,t.name),n=i(t,"deprecated_for")&&r;if(!r&&!n)return;const o=n?t.deprecated_for:t.name;e[o]=decodeURIComponent(a[t.name])}),Object.entries(n).forEach(t=>{let r=f(t,2),n=r[0],o=r[1];e[n]=o}),e}setUrlParam(t,e){this.urlState[t]=e,this.pushToAddressBar()}removeUrlParam(t){delete this.urlState[t],this.pushToAddressBar()}getUrlParam(t){return this.urlState[t]}pushToAddressBar(){const t=this.urlStateToUrlString(this.urlState),e="/"!==t?t:"";if("history"==this.urlMode)if(window.history&&window.history.replaceState){const t="".concat(this.urlHistoryBasePath).concat(e).trim().replace(/(\/+)/g,"/");try{window.history.replaceState({},null,t)}catch(t){this.urlMode="hash"}}else this.options.urlMode="hash";if("hash"==this.urlMode){const t=f(window.location.href.split("#"),1)[0];window.location.replace("".concat(t,"#").concat(e))}this.oldLocationHash=t}listenForHashChanges(){this.oldLocationHash=this.getHash(),this.urlLocationPollId&&(clearInterval(this.urlLocationPollId),this.urlLocationPollId=null),this.urlLocationPollId=setInterval(()=>{const t=this.getHash();t!=this.oldLocationHash&&(this.urlState=this.urlStringToUrlState(t))},500)}pullFromAddressBar(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.location;const e="history"===this.urlMode?t.pathname.substr(this.urlHistoryBasePath.length)+t.search:t.hash.substr(1);this.urlState=this.urlStringToUrlState(e)}getHash(){return window.location.hash.slice(1)}}function m(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}r(1669).extend(BookReader.defaultOptions,{enableUrlPlugin:!0,bookId:"",defaults:null,updateWindowTitle:!1,urlMode:"hash",urlHistoryBasePath:"/",urlTrackedParams:["page","search","mode","region","highlight","view","text"],urlTrackIndex0:!1}),BookReader.prototype.setup=(n=BookReader.prototype.setup,function(t){n.call(this,t),this.bookId=t.bookId,this.defaults=t.defaults,this.locationPollId=null,this.oldLocationHash=null,this.oldUserHash=null}),BookReader.prototype.init=function(t){return function(){this.options.enableUrlPlugin&&(this.bind(BookReader.eventNames.PostInit,()=>{const t=this.options,e=t.updateWindowTitle,r=t.urlMode;e&&(document.title=this.shortTitle(this.bookTitle,50)),"hash"===r&&this.urlStartLocationPolling()}),this.bind(BookReader.eventNames.fragmentChange,this.urlUpdateFragment.bind(this))),t.call(this)}}(BookReader.prototype.init),BookReader.prototype.shortTitle=function(t){return this.bookTitle.length<t?this.bookTitle:"".concat(this.bookTitle.substr(0,t-3),"...")},BookReader.prototype.urlStartLocationPolling=function(){this.oldLocationHash=this.urlReadFragment(),this.locationPollId&&(clearInterval(this.locationPollId),this.locationPollId=null),this.locationPollId=setInterval(()=>{const t=this.urlReadFragment();if(t==this.oldLocationHash||t==this.oldUserHash)return;const e=this.paramsFromFragment(t),r=()=>this.updateFromParams(e);var n;this.trigger(BookReader.eventNames.stop),this.animating?(null===(n=this.plugins.autoplay)||void 0===n||n.stop(),this.animationFinishedCallback=r):r(),this.oldUserHash=t},500)},BookReader.prototype.urlUpdateFragment=function(){const t=this.paramsFromCurrent(),e=this.options,r=e.urlTrackIndex0,n=e.urlTrackedParams;r||void 0===t.index||0!==t.index||(delete t.index,delete t.page);const o=n.reduce((e,r)=>(r in t&&(e[r]=t[r]),e),{}),a=this.fragmentFromParams(o,this.options.urlMode),i=""===a?"":"/".concat(a),s=this.urlReadFragment(),l=this.getLocationSearch(),h=this.queryStringFromParams(o,l,this.options.urlMode);if(s!==a||l!==h){if("history"===this.options.urlMode)if(window.history&&window.history.replaceState){const t=this.options.urlHistoryBasePath.replace(/\/+$/,""),e="".concat(t).concat(i).concat(h);try{window.history.replaceState({},null,e),this.oldLocationHash=a+h}catch(c){this.options.urlMode="hash"}}else this.options.urlMode="hash";if("hash"===this.options.urlMode){const t=this.urlParamsFiltersOnlySearch(this.readQueryString()),e=(u=window.location.href.split("#"),c=1,function(t){if(Array.isArray(t))return t}(u)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,a,i,s=[],l=!0,h=!1;try{if(a=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=a.call(r)).done)&&(s.push(n.value),s.length!==e);l=!0);}catch(t){h=!0,o=t}finally{try{if(!l&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(h)throw o}}return s}}(u,c)||function(t,e){if(t){if("string"==typeof t)return m(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?m(t,e):void 0}}(u,c)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0];window.location.replace("".concat(e,"#").concat(a).concat(t)),this.oldLocationHash=a+t}}var u,c},BookReader.prototype.urlParamsFiltersOnlySearch=function(t){const e=new URLSearchParams(t);return e.has("q")?"?".concat(new URLSearchParams({q:e.get("q")})):""},BookReader.prototype.urlReadFragment=function(){const t=this.options,e=t.urlMode,r=t.urlHistoryBasePath;return"history"===e?window.location.pathname.substr(r.length):this.urlPlugin.getHash()},BookReader.prototype.urlReadHashFragment=function(){return window.location.hash.substr(1)};class g extends BookReader{init(){this.options.enableUrlPlugin&&(this.urlPlugin=new d(this.options),this.on(BookReader.eventNames.PostInit,()=>{"hash"===this.options.urlMode&&this.urlPlugin.listenForHashChanges()})),super.init()}}window.BookReader=g;const v=g}};import{__webpack_require__ as t}from"../ia-bookreader.js";t.C({__webpack_esm_ids__,__webpack_esm_modules__});var e=t(3679);const r=e.Z,n=e.A;export{r as BookreaderUrlPlugin,n as default};
|
|
2
|
+
//# sourceMappingURL=plugin.url.js.map
|